github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/asm/alu.go (about)

     1  package asm
     2  
     3  //go:generate go run golang.org/x/tools/cmd/stringer@latest -output alu_string.go -type=Source,Endianness,ALUOp
     4  
     5  // Source of ALU / ALU64 / Branch operations
     6  //
     7  //	msb              lsb
     8  //	+------------+-+---+
     9  //	|     op     |S|cls|
    10  //	+------------+-+---+
    11  type Source uint16
    12  
    13  const sourceMask OpCode = 0x0008
    14  
    15  // Source bitmask
    16  const (
    17  	// InvalidSource is returned by getters when invoked
    18  	// on non ALU / branch OpCodes.
    19  	InvalidSource Source = 0xffff
    20  	// ImmSource src is from constant
    21  	ImmSource Source = 0x0000
    22  	// RegSource src is from register
    23  	RegSource Source = 0x0008
    24  )
    25  
    26  // The Endianness of a byte swap instruction.
    27  type Endianness uint8
    28  
    29  const endianMask = sourceMask
    30  
    31  // Endian flags
    32  const (
    33  	InvalidEndian Endianness = 0xff
    34  	// Convert to little endian
    35  	LE Endianness = 0x00
    36  	// Convert to big endian
    37  	BE Endianness = 0x08
    38  )
    39  
    40  // ALUOp are ALU / ALU64 operations
    41  //
    42  //	msb              lsb
    43  //	+-------+----+-+---+
    44  //	|  EXT  | OP |s|cls|
    45  //	+-------+----+-+---+
    46  type ALUOp uint16
    47  
    48  const aluMask OpCode = 0x3ff0
    49  
    50  const (
    51  	// InvalidALUOp is returned by getters when invoked
    52  	// on non ALU OpCodes
    53  	InvalidALUOp ALUOp = 0xffff
    54  	// Add - addition
    55  	Add ALUOp = 0x0000
    56  	// Sub - subtraction
    57  	Sub ALUOp = 0x0010
    58  	// Mul - multiplication
    59  	Mul ALUOp = 0x0020
    60  	// Div - division
    61  	Div ALUOp = 0x0030
    62  	// SDiv - signed division
    63  	SDiv ALUOp = Div + 0x0100
    64  	// Or - bitwise or
    65  	Or ALUOp = 0x0040
    66  	// And - bitwise and
    67  	And ALUOp = 0x0050
    68  	// LSh - bitwise shift left
    69  	LSh ALUOp = 0x0060
    70  	// RSh - bitwise shift right
    71  	RSh ALUOp = 0x0070
    72  	// Neg - sign/unsign signing bit
    73  	Neg ALUOp = 0x0080
    74  	// Mod - modulo
    75  	Mod ALUOp = 0x0090
    76  	// SMod - signed modulo
    77  	SMod ALUOp = Mod + 0x0100
    78  	// Xor - bitwise xor
    79  	Xor ALUOp = 0x00a0
    80  	// Mov - move value from one place to another
    81  	Mov ALUOp = 0x00b0
    82  	// MovSX8 - move lower 8 bits, sign extended upper bits of target
    83  	MovSX8 ALUOp = Mov + 0x0100
    84  	// MovSX16 - move lower 16 bits, sign extended upper bits of target
    85  	MovSX16 ALUOp = Mov + 0x0200
    86  	// MovSX32 - move lower 32 bits, sign extended upper bits of target
    87  	MovSX32 ALUOp = Mov + 0x0300
    88  	// ArSh - arithmetic shift
    89  	ArSh ALUOp = 0x00c0
    90  	// Swap - endian conversions
    91  	Swap ALUOp = 0x00d0
    92  )
    93  
    94  // HostTo converts from host to another endianness.
    95  func HostTo(endian Endianness, dst Register, size Size) Instruction {
    96  	var imm int64
    97  	switch size {
    98  	case Half:
    99  		imm = 16
   100  	case Word:
   101  		imm = 32
   102  	case DWord:
   103  		imm = 64
   104  	default:
   105  		return Instruction{OpCode: InvalidOpCode}
   106  	}
   107  
   108  	return Instruction{
   109  		OpCode:   OpCode(ALUClass).SetALUOp(Swap).SetSource(Source(endian)),
   110  		Dst:      dst,
   111  		Constant: imm,
   112  	}
   113  }
   114  
   115  // BSwap unconditionally reverses the order of bytes in a register.
   116  func BSwap(dst Register, size Size) Instruction {
   117  	var imm int64
   118  	switch size {
   119  	case Half:
   120  		imm = 16
   121  	case Word:
   122  		imm = 32
   123  	case DWord:
   124  		imm = 64
   125  	default:
   126  		return Instruction{OpCode: InvalidOpCode}
   127  	}
   128  
   129  	return Instruction{
   130  		OpCode:   OpCode(ALU64Class).SetALUOp(Swap),
   131  		Dst:      dst,
   132  		Constant: imm,
   133  	}
   134  }
   135  
   136  // Op returns the OpCode for an ALU operation with a given source.
   137  func (op ALUOp) Op(source Source) OpCode {
   138  	return OpCode(ALU64Class).SetALUOp(op).SetSource(source)
   139  }
   140  
   141  // Reg emits `dst (op) src`.
   142  func (op ALUOp) Reg(dst, src Register) Instruction {
   143  	return Instruction{
   144  		OpCode: op.Op(RegSource),
   145  		Dst:    dst,
   146  		Src:    src,
   147  	}
   148  }
   149  
   150  // Imm emits `dst (op) value`.
   151  func (op ALUOp) Imm(dst Register, value int32) Instruction {
   152  	return Instruction{
   153  		OpCode:   op.Op(ImmSource),
   154  		Dst:      dst,
   155  		Constant: int64(value),
   156  	}
   157  }
   158  
   159  // Op32 returns the OpCode for a 32-bit ALU operation with a given source.
   160  func (op ALUOp) Op32(source Source) OpCode {
   161  	return OpCode(ALUClass).SetALUOp(op).SetSource(source)
   162  }
   163  
   164  // Reg32 emits `dst (op) src`, zeroing the upper 32 bit of dst.
   165  func (op ALUOp) Reg32(dst, src Register) Instruction {
   166  	return Instruction{
   167  		OpCode: op.Op32(RegSource),
   168  		Dst:    dst,
   169  		Src:    src,
   170  	}
   171  }
   172  
   173  // Imm32 emits `dst (op) value`, zeroing the upper 32 bit of dst.
   174  func (op ALUOp) Imm32(dst Register, value int32) Instruction {
   175  	return Instruction{
   176  		OpCode:   op.Op32(ImmSource),
   177  		Dst:      dst,
   178  		Constant: int64(value),
   179  	}
   180  }