summaryrefslogtreecommitdiff
path: root/vendor/github.com/cilium/ebpf/asm/alu.go
blob: 70ccc4d1518dcc4e9a5af58cda24b10f8e93ecb4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package asm

//go:generate stringer -output alu_string.go -type=Source,Endianness,ALUOp

// Source of ALU / ALU64 / Branch operations
//
//    msb      lsb
//    +----+-+---+
//    |op  |S|cls|
//    +----+-+---+
type Source uint8

const sourceMask OpCode = 0x08

// Source bitmask
const (
	// InvalidSource is returned by getters when invoked
	// on non ALU / branch OpCodes.
	InvalidSource Source = 0xff
	// ImmSource src is from constant
	ImmSource Source = 0x00
	// RegSource src is from register
	RegSource Source = 0x08
)

// The Endianness of a byte swap instruction.
type Endianness uint8

const endianMask = sourceMask

// Endian flags
const (
	InvalidEndian Endianness = 0xff
	// Convert to little endian
	LE Endianness = 0x00
	// Convert to big endian
	BE Endianness = 0x08
)

// ALUOp are ALU / ALU64 operations
//
//    msb      lsb
//    +----+-+---+
//    |OP  |s|cls|
//    +----+-+---+
type ALUOp uint8

const aluMask OpCode = 0xf0

const (
	// InvalidALUOp is returned by getters when invoked
	// on non ALU OpCodes
	InvalidALUOp ALUOp = 0xff
	// Add - addition
	Add ALUOp = 0x00
	// Sub - subtraction
	Sub ALUOp = 0x10
	// Mul - multiplication
	Mul ALUOp = 0x20
	// Div - division
	Div ALUOp = 0x30
	// Or - bitwise or
	Or ALUOp = 0x40
	// And - bitwise and
	And ALUOp = 0x50
	// LSh - bitwise shift left
	LSh ALUOp = 0x60
	// RSh - bitwise shift right
	RSh ALUOp = 0x70
	// Neg - sign/unsign signing bit
	Neg ALUOp = 0x80
	// Mod - modulo
	Mod ALUOp = 0x90
	// Xor - bitwise xor
	Xor ALUOp = 0xa0
	// Mov - move value from one place to another
	Mov ALUOp = 0xb0
	// ArSh - arithmatic shift
	ArSh ALUOp = 0xc0
	// Swap - endian conversions
	Swap ALUOp = 0xd0
)

// HostTo converts from host to another endianness.
func HostTo(endian Endianness, dst Register, size Size) Instruction {
	var imm int64
	switch size {
	case Half:
		imm = 16
	case Word:
		imm = 32
	case DWord:
		imm = 64
	default:
		return Instruction{OpCode: InvalidOpCode}
	}

	return Instruction{
		OpCode:   OpCode(ALUClass).SetALUOp(Swap).SetSource(Source(endian)),
		Dst:      dst,
		Constant: imm,
	}
}

// Op returns the OpCode for an ALU operation with a given source.
func (op ALUOp) Op(source Source) OpCode {
	return OpCode(ALU64Class).SetALUOp(op).SetSource(source)
}

// Reg emits `dst (op) src`.
func (op ALUOp) Reg(dst, src Register) Instruction {
	return Instruction{
		OpCode: op.Op(RegSource),
		Dst:    dst,
		Src:    src,
	}
}

// Imm emits `dst (op) value`.
func (op ALUOp) Imm(dst Register, value int32) Instruction {
	return Instruction{
		OpCode:   op.Op(ImmSource),
		Dst:      dst,
		Constant: int64(value),
	}
}

// Op32 returns the OpCode for a 32-bit ALU operation with a given source.
func (op ALUOp) Op32(source Source) OpCode {
	return OpCode(ALUClass).SetALUOp(op).SetSource(source)
}

// Reg32 emits `dst (op) src`, zeroing the upper 32 bit of dst.
func (op ALUOp) Reg32(dst, src Register) Instruction {
	return Instruction{
		OpCode: op.Op32(RegSource),
		Dst:    dst,
		Src:    src,
	}
}

// Imm32 emits `dst (op) value`, zeroing the upper 32 bit of dst.
func (op ALUOp) Imm32(dst Register, value int32) Instruction {
	return Instruction{
		OpCode:   op.Op32(ImmSource),
		Dst:      dst,
		Constant: int64(value),
	}
}