1package asm 2 3//go:generate stringer -output load_store_string.go -type=Mode,Size 4 5// Mode for load and store operations 6// 7// msb lsb 8// +---+--+---+ 9// |MDE|sz|cls| 10// +---+--+---+ 11type Mode uint8 12 13const modeMask OpCode = 0xe0 14 15const ( 16 // InvalidMode is returned by getters when invoked 17 // on non load / store OpCodes 18 InvalidMode Mode = 0xff 19 // ImmMode - immediate value 20 ImmMode Mode = 0x00 21 // AbsMode - immediate value + offset 22 AbsMode Mode = 0x20 23 // IndMode - indirect (imm+src) 24 IndMode Mode = 0x40 25 // MemMode - load from memory 26 MemMode Mode = 0x60 27 // XAddMode - add atomically across processors. 28 XAddMode Mode = 0xc0 29) 30 31// Size of load and store operations 32// 33// msb lsb 34// +---+--+---+ 35// |mde|SZ|cls| 36// +---+--+---+ 37type Size uint8 38 39const sizeMask OpCode = 0x18 40 41const ( 42 // InvalidSize is returned by getters when invoked 43 // on non load / store OpCodes 44 InvalidSize Size = 0xff 45 // DWord - double word; 64 bits 46 DWord Size = 0x18 47 // Word - word; 32 bits 48 Word Size = 0x00 49 // Half - half-word; 16 bits 50 Half Size = 0x08 51 // Byte - byte; 8 bits 52 Byte Size = 0x10 53) 54 55// Sizeof returns the size in bytes. 56func (s Size) Sizeof() int { 57 switch s { 58 case DWord: 59 return 8 60 case Word: 61 return 4 62 case Half: 63 return 2 64 case Byte: 65 return 1 66 default: 67 return -1 68 } 69} 70 71// LoadMemOp returns the OpCode to load a value of given size from memory. 72func LoadMemOp(size Size) OpCode { 73 return OpCode(LdXClass).SetMode(MemMode).SetSize(size) 74} 75 76// LoadMem emits `dst = *(size *)(src + offset)`. 77func LoadMem(dst, src Register, offset int16, size Size) Instruction { 78 return Instruction{ 79 OpCode: LoadMemOp(size), 80 Dst: dst, 81 Src: src, 82 Offset: offset, 83 } 84} 85 86// LoadImmOp returns the OpCode to load an immediate of given size. 87// 88// As of kernel 4.20, only DWord size is accepted. 89func LoadImmOp(size Size) OpCode { 90 return OpCode(LdClass).SetMode(ImmMode).SetSize(size) 91} 92 93// LoadImm emits `dst = (size)value`. 94// 95// As of kernel 4.20, only DWord size is accepted. 96func LoadImm(dst Register, value int64, size Size) Instruction { 97 return Instruction{ 98 OpCode: LoadImmOp(size), 99 Dst: dst, 100 Constant: value, 101 } 102} 103 104// LoadMapPtr stores a pointer to a map in dst. 105func LoadMapPtr(dst Register, fd int) Instruction { 106 if fd < 0 { 107 return Instruction{OpCode: InvalidOpCode} 108 } 109 110 return Instruction{ 111 OpCode: LoadImmOp(DWord), 112 Dst: dst, 113 Src: PseudoMapFD, 114 Constant: int64(fd), 115 } 116} 117 118// LoadMapValue stores a pointer to the value at a certain offset of a map. 119func LoadMapValue(dst Register, fd int, offset uint32) Instruction { 120 if fd < 0 { 121 return Instruction{OpCode: InvalidOpCode} 122 } 123 124 fdAndOffset := (uint64(offset) << 32) | uint64(uint32(fd)) 125 return Instruction{ 126 OpCode: LoadImmOp(DWord), 127 Dst: dst, 128 Src: PseudoMapValue, 129 Constant: int64(fdAndOffset), 130 } 131} 132 133// LoadIndOp returns the OpCode for loading a value of given size from an sk_buff. 134func LoadIndOp(size Size) OpCode { 135 return OpCode(LdClass).SetMode(IndMode).SetSize(size) 136} 137 138// LoadInd emits `dst = ntoh(*(size *)(((sk_buff *)R6)->data + src + offset))`. 139func LoadInd(dst, src Register, offset int32, size Size) Instruction { 140 return Instruction{ 141 OpCode: LoadIndOp(size), 142 Dst: dst, 143 Src: src, 144 Constant: int64(offset), 145 } 146} 147 148// LoadAbsOp returns the OpCode for loading a value of given size from an sk_buff. 149func LoadAbsOp(size Size) OpCode { 150 return OpCode(LdClass).SetMode(AbsMode).SetSize(size) 151} 152 153// LoadAbs emits `r0 = ntoh(*(size *)(((sk_buff *)R6)->data + offset))`. 154func LoadAbs(offset int32, size Size) Instruction { 155 return Instruction{ 156 OpCode: LoadAbsOp(size), 157 Dst: R0, 158 Constant: int64(offset), 159 } 160} 161 162// StoreMemOp returns the OpCode for storing a register of given size in memory. 163func StoreMemOp(size Size) OpCode { 164 return OpCode(StXClass).SetMode(MemMode).SetSize(size) 165} 166 167// StoreMem emits `*(size *)(dst + offset) = src` 168func StoreMem(dst Register, offset int16, src Register, size Size) Instruction { 169 return Instruction{ 170 OpCode: StoreMemOp(size), 171 Dst: dst, 172 Src: src, 173 Offset: offset, 174 } 175} 176 177// StoreImmOp returns the OpCode for storing an immediate of given size in memory. 178func StoreImmOp(size Size) OpCode { 179 return OpCode(StClass).SetMode(MemMode).SetSize(size) 180} 181 182// StoreImm emits `*(size *)(dst + offset) = value`. 183func StoreImm(dst Register, offset int16, value int64, size Size) Instruction { 184 return Instruction{ 185 OpCode: StoreImmOp(size), 186 Dst: dst, 187 Offset: offset, 188 Constant: value, 189 } 190} 191 192// StoreXAddOp returns the OpCode to atomically add a register to a value in memory. 193func StoreXAddOp(size Size) OpCode { 194 return OpCode(StXClass).SetMode(XAddMode).SetSize(size) 195} 196 197// StoreXAdd atomically adds src to *dst. 198func StoreXAdd(dst, src Register, size Size) Instruction { 199 return Instruction{ 200 OpCode: StoreXAddOp(size), 201 Dst: dst, 202 Src: src, 203 } 204} 205