load_store.go (4913B)
1 package 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 // +---+--+---+ 11 type Mode uint8 12 13 const modeMask OpCode = 0xe0 14 15 const ( 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 // +---+--+---+ 37 type Size uint8 38 39 const sizeMask OpCode = 0x18 40 41 const ( 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. 56 func (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. 72 func LoadMemOp(size Size) OpCode { 73 return OpCode(LdXClass).SetMode(MemMode).SetSize(size) 74 } 75 76 // LoadMem emits `dst = *(size *)(src + offset)`. 77 func 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. 89 func 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. 96 func 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. 105 func 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(uint32(fd)), 115 } 116 } 117 118 // LoadMapValue stores a pointer to the value at a certain offset of a map. 119 func 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. 134 func 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))`. 139 func 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. 149 func 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))`. 154 func 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. 163 func StoreMemOp(size Size) OpCode { 164 return OpCode(StXClass).SetMode(MemMode).SetSize(size) 165 } 166 167 // StoreMem emits `*(size *)(dst + offset) = src` 168 func 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. 178 func StoreImmOp(size Size) OpCode { 179 return OpCode(StClass).SetMode(MemMode).SetSize(size) 180 } 181 182 // StoreImm emits `*(size *)(dst + offset) = value`. 183 func 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. 193 func StoreXAddOp(size Size) OpCode { 194 return OpCode(StXClass).SetMode(XAddMode).SetSize(size) 195 } 196 197 // StoreXAdd atomically adds src to *dst. 198 func StoreXAdd(dst, src Register, size Size) Instruction { 199 return Instruction{ 200 OpCode: StoreXAddOp(size), 201 Dst: dst, 202 Src: src, 203 } 204 }