operands.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. package x86_64
  2. import (
  3. `errors`
  4. `fmt`
  5. `math`
  6. `reflect`
  7. `strconv`
  8. `strings`
  9. `sync/atomic`
  10. )
  11. // RelativeOffset represents an RIP-relative offset.
  12. type RelativeOffset int32
  13. // String implements the fmt.Stringer interface.
  14. func (self RelativeOffset) String() string {
  15. if self == 0 {
  16. return "(%rip)"
  17. } else {
  18. return fmt.Sprintf("%d(%%rip)", self)
  19. }
  20. }
  21. // RoundingControl represents a floating-point rounding option.
  22. type RoundingControl uint8
  23. const (
  24. // RN_SAE represents "Round Nearest", which is the default rounding option.
  25. RN_SAE RoundingControl = iota
  26. // RD_SAE represents "Round Down".
  27. RD_SAE
  28. // RU_SAE represents "Round Up".
  29. RU_SAE
  30. // RZ_SAE represents "Round towards Zero".
  31. RZ_SAE
  32. )
  33. var _RC_NAMES = map[RoundingControl]string {
  34. RN_SAE: "rn-sae",
  35. RD_SAE: "rd-sae",
  36. RU_SAE: "ru-sae",
  37. RZ_SAE: "rz-sae",
  38. }
  39. func (self RoundingControl) String() string {
  40. if v, ok := _RC_NAMES[self]; ok {
  41. return v
  42. } else {
  43. panic("invalid RoundingControl value")
  44. }
  45. }
  46. // ExceptionControl represents the "Suppress All Exceptions" flag.
  47. type ExceptionControl uint8
  48. const (
  49. // SAE represents the flag "Suppress All Exceptions" for floating point operations.
  50. SAE ExceptionControl = iota
  51. )
  52. func (ExceptionControl) String() string {
  53. return "sae"
  54. }
  55. // AddressType indicates which kind of value that an Addressable object contains.
  56. type AddressType uint
  57. const (
  58. // None indicates the Addressable does not contain any addressable value.
  59. None AddressType = iota
  60. // Memory indicates the Addressable contains a memory address.
  61. Memory
  62. // Offset indicates the Addressable contains an RIP-relative offset.
  63. Offset
  64. // Reference indicates the Addressable contains a label reference.
  65. Reference
  66. )
  67. // Disposable is a type of object that can be Free'd manually.
  68. type Disposable interface {
  69. Free()
  70. }
  71. // Label represents a location within the program.
  72. type Label struct {
  73. refs int64
  74. Name string
  75. Dest *Instruction
  76. }
  77. func (self *Label) offset(p uintptr, n int) RelativeOffset {
  78. if self.Dest == nil {
  79. panic("unresolved label: " + self.Name)
  80. } else {
  81. return RelativeOffset(self.Dest.pc - p - uintptr(n))
  82. }
  83. }
  84. // Free decreases the reference count of a Label, if the
  85. // refcount drops to 0, the Label will be recycled.
  86. func (self *Label) Free() {
  87. if atomic.AddInt64(&self.refs, -1) == 0 {
  88. freeLabel(self)
  89. }
  90. }
  91. // String implements the fmt.Stringer interface.
  92. func (self *Label) String() string {
  93. if self.Dest == nil {
  94. return fmt.Sprintf("%s(%%rip)", self.Name)
  95. } else {
  96. return fmt.Sprintf("%s(%%rip)@%#x", self.Name, self.Dest.pc)
  97. }
  98. }
  99. // Retain increases the reference count of a Label.
  100. func (self *Label) Retain() *Label {
  101. atomic.AddInt64(&self.refs, 1)
  102. return self
  103. }
  104. // Evaluate implements the interface expr.Term.
  105. func (self *Label) Evaluate() (int64, error) {
  106. if self.Dest != nil {
  107. return int64(self.Dest.pc), nil
  108. } else {
  109. return 0, errors.New("unresolved label: " + self.Name)
  110. }
  111. }
  112. // Addressable is a union to represent an addressable operand.
  113. type Addressable struct {
  114. Type AddressType
  115. Memory MemoryAddress
  116. Offset RelativeOffset
  117. Reference *Label
  118. }
  119. // String implements the fmt.Stringer interface.
  120. func (self *Addressable) String() string {
  121. switch self.Type {
  122. case None : return "(not addressable)"
  123. case Memory : return self.Memory.String()
  124. case Offset : return self.Offset.String()
  125. case Reference : return self.Reference.String()
  126. default : return "(invalid addressable)"
  127. }
  128. }
  129. // MemoryOperand represents a memory operand for an instruction.
  130. type MemoryOperand struct {
  131. refs int64
  132. Size int
  133. Addr Addressable
  134. Mask RegisterMask
  135. Masked bool
  136. Broadcast uint8
  137. }
  138. const (
  139. _Sizes = 0b10000000100010111 // bit-mask for valid sizes (0, 1, 2, 4, 8, 16)
  140. )
  141. func (self *MemoryOperand) isVMX(evex bool) bool {
  142. return self.Addr.Type == Memory && self.Addr.Memory.isVMX(evex)
  143. }
  144. func (self *MemoryOperand) isVMY(evex bool) bool {
  145. return self.Addr.Type == Memory && self.Addr.Memory.isVMY(evex)
  146. }
  147. func (self *MemoryOperand) isVMZ() bool {
  148. return self.Addr.Type == Memory && self.Addr.Memory.isVMZ()
  149. }
  150. func (self *MemoryOperand) isMem() bool {
  151. if (_Sizes & (1 << self.Broadcast)) == 0 {
  152. return false
  153. } else if self.Addr.Type == Memory {
  154. return self.Addr.Memory.isMem()
  155. } else if self.Addr.Type == Offset {
  156. return true
  157. } else if self.Addr.Type == Reference {
  158. return true
  159. } else {
  160. return false
  161. }
  162. }
  163. func (self *MemoryOperand) isSize(n int) bool {
  164. return self.Size == 0 || self.Size == n
  165. }
  166. func (self *MemoryOperand) isBroadcast(n int, b uint8) bool {
  167. return self.Size == n && self.Broadcast == b
  168. }
  169. func (self *MemoryOperand) formatMask() string {
  170. if !self.Masked {
  171. return ""
  172. } else {
  173. return self.Mask.String()
  174. }
  175. }
  176. func (self *MemoryOperand) formatBroadcast() string {
  177. if self.Broadcast == 0 {
  178. return ""
  179. } else {
  180. return fmt.Sprintf("{1to%d}", self.Broadcast)
  181. }
  182. }
  183. func (self *MemoryOperand) ensureAddrValid() {
  184. switch self.Addr.Type {
  185. case None : break
  186. case Memory : self.Addr.Memory.EnsureValid()
  187. case Offset : break
  188. case Reference : break
  189. default : panic("invalid address type")
  190. }
  191. }
  192. func (self *MemoryOperand) ensureSizeValid() {
  193. if (_Sizes & (1 << self.Size)) == 0 {
  194. panic("invalid memory operand size")
  195. }
  196. }
  197. func (self *MemoryOperand) ensureBroadcastValid() {
  198. if (_Sizes & (1 << self.Broadcast)) == 0 {
  199. panic("invalid memory operand broadcast")
  200. }
  201. }
  202. // Free decreases the reference count of a MemoryOperand, if the
  203. // refcount drops to 0, the Label will be recycled.
  204. func (self *MemoryOperand) Free() {
  205. if atomic.AddInt64(&self.refs, -1) == 0 {
  206. freeMemoryOperand(self)
  207. }
  208. }
  209. // String implements the fmt.Stringer interface.
  210. func (self *MemoryOperand) String() string {
  211. return self.Addr.String() + self.formatMask() + self.formatBroadcast()
  212. }
  213. // Retain increases the reference count of a MemoryOperand.
  214. func (self *MemoryOperand) Retain() *MemoryOperand {
  215. atomic.AddInt64(&self.refs, 1)
  216. return self
  217. }
  218. // EnsureValid checks if the memory operand is valid, if not, it panics.
  219. func (self *MemoryOperand) EnsureValid() {
  220. self.ensureAddrValid()
  221. self.ensureSizeValid()
  222. self.ensureBroadcastValid()
  223. }
  224. // MemoryAddress represents a memory address.
  225. type MemoryAddress struct {
  226. Base Register
  227. Index Register
  228. Scale uint8
  229. Displacement int32
  230. }
  231. const (
  232. _Scales = 0b100010111 // bit-mask for valid scales (0, 1, 2, 4, 8)
  233. )
  234. func (self *MemoryAddress) isVMX(evex bool) bool {
  235. return self.isMemBase() && (self.Index == nil || isXMM(self.Index) || (evex && isEVEXXMM(self.Index)))
  236. }
  237. func (self *MemoryAddress) isVMY(evex bool) bool {
  238. return self.isMemBase() && (self.Index == nil || isYMM(self.Index) || (evex && isEVEXYMM(self.Index)))
  239. }
  240. func (self *MemoryAddress) isVMZ() bool {
  241. return self.isMemBase() && (self.Index == nil || isZMM(self.Index))
  242. }
  243. func (self *MemoryAddress) isMem() bool {
  244. return self.isMemBase() && (self.Index == nil || isReg64(self.Index))
  245. }
  246. func (self *MemoryAddress) isMemBase() bool {
  247. return (self.Base == nil || isReg64(self.Base)) && // `Base` must be 64-bit if present
  248. (self.Scale == 0) == (self.Index == nil) && // `Scale` and `Index` depends on each other
  249. (_Scales & (1 << self.Scale)) != 0 // `Scale` can only be 0, 1, 2, 4 or 8
  250. }
  251. // String implements the fmt.Stringer interface.
  252. func (self *MemoryAddress) String() string {
  253. var dp int
  254. var sb strings.Builder
  255. /* the displacement part */
  256. if dp = int(self.Displacement); dp != 0 {
  257. sb.WriteString(strconv.Itoa(dp))
  258. }
  259. /* the base register */
  260. if sb.WriteByte('('); self.Base != nil {
  261. sb.WriteByte('%')
  262. sb.WriteString(self.Base.String())
  263. }
  264. /* index is optional */
  265. if self.Index != nil {
  266. sb.WriteString(",%")
  267. sb.WriteString(self.Index.String())
  268. /* scale is also optional */
  269. if self.Scale >= 2 {
  270. sb.WriteByte(',')
  271. sb.WriteString(strconv.Itoa(int(self.Scale)))
  272. }
  273. }
  274. /* close the bracket */
  275. sb.WriteByte(')')
  276. return sb.String()
  277. }
  278. // EnsureValid checks if the memory address is valid, if not, it panics.
  279. func (self *MemoryAddress) EnsureValid() {
  280. if !self.isMemBase() || (self.Index != nil && !isIndexable(self.Index)) {
  281. panic("not a valid memory address")
  282. }
  283. }
  284. // Ref constructs a memory reference to a label.
  285. func Ref(ref *Label) (v *MemoryOperand) {
  286. v = CreateMemoryOperand()
  287. v.Addr.Type = Reference
  288. v.Addr.Reference = ref
  289. return
  290. }
  291. // Abs construct a simple memory address that represents absolute addressing.
  292. func Abs(disp int32) *MemoryOperand {
  293. return Sib(nil, nil, 0, disp)
  294. }
  295. // Ptr constructs a simple memory operand with base and displacement.
  296. func Ptr(base Register, disp int32) *MemoryOperand {
  297. return Sib(base, nil, 0, disp)
  298. }
  299. // Sib constructs a simple memory operand that represents a complete memory address.
  300. func Sib(base Register, index Register, scale uint8, disp int32) (v *MemoryOperand) {
  301. v = CreateMemoryOperand()
  302. v.Addr.Type = Memory
  303. v.Addr.Memory.Base = base
  304. v.Addr.Memory.Index = index
  305. v.Addr.Memory.Scale = scale
  306. v.Addr.Memory.Displacement = disp
  307. v.EnsureValid()
  308. return
  309. }
  310. /** Operand Matching Helpers **/
  311. const _IntMask =
  312. (1 << reflect.Int ) |
  313. (1 << reflect.Int8 ) |
  314. (1 << reflect.Int16 ) |
  315. (1 << reflect.Int32 ) |
  316. (1 << reflect.Int64 ) |
  317. (1 << reflect.Uint ) |
  318. (1 << reflect.Uint8 ) |
  319. (1 << reflect.Uint16 ) |
  320. (1 << reflect.Uint32 ) |
  321. (1 << reflect.Uint64 ) |
  322. (1 << reflect.Uintptr)
  323. func isInt(k reflect.Kind) bool {
  324. return (_IntMask & (1 << k)) != 0
  325. }
  326. func asInt64(v interface{}) (int64, bool) {
  327. if isSpecial(v) {
  328. return 0, false
  329. } else if x := efaceOf(v); isInt(x.kind()) {
  330. return x.toInt64(), true
  331. } else {
  332. return 0, false
  333. }
  334. }
  335. func inRange(v interface{}, low int64, high int64) bool {
  336. x, ok := asInt64(v)
  337. return ok && x >= low && x <= high
  338. }
  339. func isSpecial(v interface{}) bool {
  340. switch v.(type) {
  341. case Register8 : return true
  342. case Register16 : return true
  343. case Register32 : return true
  344. case Register64 : return true
  345. case KRegister : return true
  346. case MMRegister : return true
  347. case XMMRegister : return true
  348. case YMMRegister : return true
  349. case ZMMRegister : return true
  350. case RelativeOffset : return true
  351. case RoundingControl : return true
  352. case ExceptionControl : return true
  353. default : return false
  354. }
  355. }
  356. func isIndexable(v interface{}) bool {
  357. return isZMM(v) || isReg64(v) || isEVEXXMM(v) || isEVEXYMM(v)
  358. }
  359. func isImm4 (v interface{}) bool { return inRange(v, 0, 15) }
  360. func isImm8 (v interface{}) bool { return inRange(v, math.MinInt8, math.MaxUint8) }
  361. func isImm16 (v interface{}) bool { return inRange(v, math.MinInt16, math.MaxUint16) }
  362. func isImm32 (v interface{}) bool { return inRange(v, math.MinInt32, math.MaxUint32) }
  363. func isImm64 (v interface{}) bool { _, r := asInt64(v) ; return r }
  364. func isConst1 (v interface{}) bool { x, r := asInt64(v) ; return r && x == 1 }
  365. func isConst3 (v interface{}) bool { x, r := asInt64(v) ; return r && x == 3 }
  366. func isRel8 (v interface{}) bool { x, r := v.(RelativeOffset) ; return r && x >= math.MinInt8 && x <= math.MaxInt8 }
  367. func isRel32 (v interface{}) bool { _, r := v.(RelativeOffset) ; return r }
  368. func isLabel (v interface{}) bool { _, r := v.(*Label) ; return r }
  369. func isReg8 (v interface{}) bool { _, r := v.(Register8) ; return r }
  370. func isReg8REX (v interface{}) bool { x, r := v.(Register8) ; return r && (x & 0x80) == 0 && x >= SPL }
  371. func isReg16 (v interface{}) bool { _, r := v.(Register16) ; return r }
  372. func isReg32 (v interface{}) bool { _, r := v.(Register32) ; return r }
  373. func isReg64 (v interface{}) bool { _, r := v.(Register64) ; return r }
  374. func isMM (v interface{}) bool { _, r := v.(MMRegister) ; return r }
  375. func isXMM (v interface{}) bool { x, r := v.(XMMRegister) ; return r && x <= XMM15 }
  376. func isEVEXXMM (v interface{}) bool { _, r := v.(XMMRegister) ; return r }
  377. func isXMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isXMM(v) || (r && isXMM(x.Reg) && !x.Mask.Z) }
  378. func isXMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isXMM(v) || (r && isXMM(x.Reg)) }
  379. func isYMM (v interface{}) bool { x, r := v.(YMMRegister) ; return r && x <= YMM15 }
  380. func isEVEXYMM (v interface{}) bool { _, r := v.(YMMRegister) ; return r }
  381. func isYMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isYMM(v) || (r && isYMM(x.Reg) && !x.Mask.Z) }
  382. func isYMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isYMM(v) || (r && isYMM(x.Reg)) }
  383. func isZMM (v interface{}) bool { _, r := v.(ZMMRegister) ; return r }
  384. func isZMMk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isZMM(v) || (r && isZMM(x.Reg) && !x.Mask.Z) }
  385. func isZMMkz (v interface{}) bool { x, r := v.(MaskedRegister) ; return isZMM(v) || (r && isZMM(x.Reg)) }
  386. func isK (v interface{}) bool { _, r := v.(KRegister) ; return r }
  387. func isKk (v interface{}) bool { x, r := v.(MaskedRegister) ; return isK(v) || (r && isK(x.Reg) && !x.Mask.Z) }
  388. func isM (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 && !x.Masked }
  389. func isMk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 && !(x.Masked && x.Mask.Z) }
  390. func isMkz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isMem() && x.Broadcast == 0 }
  391. func isM8 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(1) }
  392. func isM16 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(2) }
  393. func isM16kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(2) }
  394. func isM32 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(4) }
  395. func isM32k (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMk(v) && x.isSize(4) }
  396. func isM32kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(4) }
  397. func isM64 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(8) }
  398. func isM64k (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMk(v) && x.isSize(8) }
  399. func isM64kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(8) }
  400. func isM128 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(16) }
  401. func isM128kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(16) }
  402. func isM256 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(32) }
  403. func isM256kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(32) }
  404. func isM512 (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isM(v) && x.isSize(64) }
  405. func isM512kz (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && isMkz(v) && x.isSize(64) }
  406. func isM64M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM64(v) || (r && x.isBroadcast(4, 2)) }
  407. func isM128M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM128(v) || (r && x.isBroadcast(4, 4)) }
  408. func isM256M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM256(v) || (r && x.isBroadcast(4, 8)) }
  409. func isM512M32bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM512(v) || (r && x.isBroadcast(4, 16)) }
  410. func isM128M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM128(v) || (r && x.isBroadcast(8, 2)) }
  411. func isM256M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM256(v) || (r && x.isBroadcast(8, 4)) }
  412. func isM512M64bcst (v interface{}) bool { x, r := v.(*MemoryOperand) ; return isM512(v) || (r && x.isBroadcast(8, 8)) }
  413. func isVMX (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(false) && !x.Masked }
  414. func isEVEXVMX (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(true) && !x.Masked }
  415. func isVMXk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMX(true) }
  416. func isVMY (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(false) && !x.Masked }
  417. func isEVEXVMY (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(true) && !x.Masked }
  418. func isVMYk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMY(true) }
  419. func isVMZ (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMZ() && !x.Masked }
  420. func isVMZk (v interface{}) bool { x, r := v.(*MemoryOperand) ; return r && x.isVMZ() }
  421. func isSAE (v interface{}) bool { _, r := v.(ExceptionControl) ; return r }
  422. func isER (v interface{}) bool { _, r := v.(RoundingControl) ; return r }
  423. func isImmExt(v interface{}, ext int, min int64, max int64) bool {
  424. if x, ok := asInt64(v); !ok {
  425. return false
  426. } else if m := int64(1) << (8 * ext); x < m && x >= m + min {
  427. return true
  428. } else {
  429. return x <= max && x >= min
  430. }
  431. }
  432. func isImm8Ext(v interface{}, ext int) bool {
  433. return isImmExt(v, ext, math.MinInt8, math.MaxInt8)
  434. }
  435. func isImm32Ext(v interface{}, ext int) bool {
  436. return isImmExt(v, ext, math.MinInt32, math.MaxInt32)
  437. }