load_store.go 4.8 KB

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