operands.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. //
  2. // Copyright 2024 CloudWeGo Authors
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. package x86_64
  17. import (
  18. "errors"
  19. "fmt"
  20. "math"
  21. "reflect"
  22. "strconv"
  23. "strings"
  24. "sync/atomic"
  25. )
  26. // RelativeOffset represents an RIP-relative offset.
  27. type RelativeOffset int32
  28. // String implements the fmt.Stringer interface.
  29. func (self RelativeOffset) String() string {
  30. if self == 0 {
  31. return "(%rip)"
  32. } else {
  33. return fmt.Sprintf("%d(%%rip)", self)
  34. }
  35. }
  36. // RoundingControl represents a floating-point rounding option.
  37. type RoundingControl uint8
  38. const (
  39. // RN_SAE represents "Round Nearest", which is the default rounding option.
  40. RN_SAE RoundingControl = iota
  41. // RD_SAE represents "Round Down".
  42. RD_SAE
  43. // RU_SAE represents "Round Up".
  44. RU_SAE
  45. // RZ_SAE represents "Round towards Zero".
  46. RZ_SAE
  47. )
  48. var _RC_NAMES = map[RoundingControl]string{
  49. RN_SAE: "rn-sae",
  50. RD_SAE: "rd-sae",
  51. RU_SAE: "ru-sae",
  52. RZ_SAE: "rz-sae",
  53. }
  54. func (self RoundingControl) String() string {
  55. if v, ok := _RC_NAMES[self]; ok {
  56. return v
  57. } else {
  58. panic("invalid RoundingControl value")
  59. }
  60. }
  61. // ExceptionControl represents the "Suppress All Exceptions" flag.
  62. type ExceptionControl uint8
  63. const (
  64. // SAE represents the flag "Suppress All Exceptions" for floating point operations.
  65. SAE ExceptionControl = iota
  66. )
  67. func (ExceptionControl) String() string {
  68. return "sae"
  69. }
  70. // AddressType indicates which kind of value that an Addressable object contains.
  71. type AddressType uint
  72. const (
  73. // None indicates the Addressable does not contain any addressable value.
  74. None AddressType = iota
  75. // Memory indicates the Addressable contains a memory address.
  76. Memory
  77. // Offset indicates the Addressable contains an RIP-relative offset.
  78. Offset
  79. // Reference indicates the Addressable contains a label reference.
  80. Reference
  81. )
  82. // Disposable is a type of object that can be Free'd manually.
  83. type Disposable interface {
  84. Free()
  85. }
  86. // Label represents a location within the program.
  87. type Label struct {
  88. refs int64
  89. Name string
  90. Dest *Instruction
  91. }
  92. func (self *Label) offset(p uintptr, n int) RelativeOffset {
  93. if self.Dest == nil {
  94. panic("unresolved label: " + self.Name)
  95. } else {
  96. return RelativeOffset(self.Dest.pc - p - uintptr(n))
  97. }
  98. }
  99. // Free decreases the reference count of a Label, if the
  100. // refcount drops to 0, the Label will be recycled.
  101. func (self *Label) Free() {
  102. if atomic.AddInt64(&self.refs, -1) == 0 {
  103. //freeLabel(self)
  104. }
  105. }
  106. // String implements the fmt.Stringer interface.
  107. func (self *Label) String() string {
  108. if self.Dest == nil {
  109. return fmt.Sprintf("%s(%%rip)", self.Name)
  110. } else {
  111. return fmt.Sprintf("%s(%%rip)@%#x", self.Name, self.Dest.pc)
  112. }
  113. }
  114. // Retain increases the reference count of a Label.
  115. func (self *Label) Retain() *Label {
  116. atomic.AddInt64(&self.refs, 1)
  117. return self
  118. }
  119. // Evaluate implements the interface expr.Term.
  120. func (self *Label) Evaluate() (int64, error) {
  121. if self.Dest != nil {
  122. return int64(self.Dest.pc), nil
  123. } else {
  124. return 0, errors.New("unresolved label: " + self.Name)
  125. }
  126. }
  127. // Addressable is a union to represent an addressable operand.
  128. type Addressable struct {
  129. Type AddressType
  130. Memory MemoryAddress
  131. Offset RelativeOffset
  132. Reference *Label
  133. }
  134. // String implements the fmt.Stringer interface.
  135. func (self *Addressable) String() string {
  136. switch self.Type {
  137. case None:
  138. return "(not addressable)"
  139. case Memory:
  140. return self.Memory.String()
  141. case Offset:
  142. return self.Offset.String()
  143. case Reference:
  144. return self.Reference.String()
  145. default:
  146. return "(invalid addressable)"
  147. }
  148. }
  149. // MemoryOperand represents a memory operand for an instruction.
  150. type MemoryOperand struct {
  151. refs int64
  152. Size int
  153. Addr Addressable
  154. Mask RegisterMask
  155. Masked bool
  156. Broadcast uint8
  157. }
  158. const (
  159. _Sizes = 0b10000000100010111 // bit-mask for valid sizes (0, 1, 2, 4, 8, 16)
  160. )
  161. func (self *MemoryOperand) isVMX(evex bool) bool {
  162. return self.Addr.Type == Memory && self.Addr.Memory.isVMX(evex)
  163. }
  164. func (self *MemoryOperand) isVMY(evex bool) bool {
  165. return self.Addr.Type == Memory && self.Addr.Memory.isVMY(evex)
  166. }
  167. func (self *MemoryOperand) isVMZ() bool {
  168. return self.Addr.Type == Memory && self.Addr.Memory.isVMZ()
  169. }
  170. func (self *MemoryOperand) isMem() bool {
  171. if (_Sizes & (1 << self.Broadcast)) == 0 {
  172. return false
  173. } else if self.Addr.Type == Memory {
  174. return self.Addr.Memory.isMem()
  175. } else if self.Addr.Type == Offset {
  176. return true
  177. } else if self.Addr.Type == Reference {
  178. return true
  179. } else {
  180. return false
  181. }
  182. }
  183. func (self *MemoryOperand) isSize(n int) bool {
  184. return self.Size == 0 || self.Size == n
  185. }
  186. func (self *MemoryOperand) isBroadcast(n int, b uint8) bool {
  187. return self.Size == n && self.Broadcast == b
  188. }
  189. func (self *MemoryOperand) formatMask() string {
  190. if !self.Masked {
  191. return ""
  192. } else {
  193. return self.Mask.String()
  194. }
  195. }
  196. func (self *MemoryOperand) formatBroadcast() string {
  197. if self.Broadcast == 0 {
  198. return ""
  199. } else {
  200. return fmt.Sprintf("{1to%d}", self.Broadcast)
  201. }
  202. }
  203. func (self *MemoryOperand) ensureAddrValid() {
  204. switch self.Addr.Type {
  205. case None:
  206. break
  207. case Memory:
  208. self.Addr.Memory.EnsureValid()
  209. case Offset:
  210. break
  211. case Reference:
  212. break
  213. default:
  214. panic("invalid address type")
  215. }
  216. }
  217. func (self *MemoryOperand) ensureSizeValid() {
  218. if (_Sizes & (1 << self.Size)) == 0 {
  219. panic("invalid memory operand size")
  220. }
  221. }
  222. func (self *MemoryOperand) ensureBroadcastValid() {
  223. if (_Sizes & (1 << self.Broadcast)) == 0 {
  224. panic("invalid memory operand broadcast")
  225. }
  226. }
  227. // Free decreases the reference count of a MemoryOperand, if the
  228. // refcount drops to 0, the Label will be recycled.
  229. func (self *MemoryOperand) Free() {
  230. if atomic.AddInt64(&self.refs, -1) == 0 {
  231. //freeMemoryOperand(self)
  232. }
  233. }
  234. // String implements the fmt.Stringer interface.
  235. func (self *MemoryOperand) String() string {
  236. return self.Addr.String() + self.formatMask() + self.formatBroadcast()
  237. }
  238. // Retain increases the reference count of a MemoryOperand.
  239. func (self *MemoryOperand) Retain() *MemoryOperand {
  240. atomic.AddInt64(&self.refs, 1)
  241. return self
  242. }
  243. // EnsureValid checks if the memory operand is valid, if not, it panics.
  244. func (self *MemoryOperand) EnsureValid() {
  245. self.ensureAddrValid()
  246. self.ensureSizeValid()
  247. self.ensureBroadcastValid()
  248. }
  249. // MemoryAddress represents a memory address.
  250. type MemoryAddress struct {
  251. Base Register
  252. Index Register
  253. Scale uint8
  254. Displacement int32
  255. }
  256. const (
  257. _Scales = 0b100010111 // bit-mask for valid scales (0, 1, 2, 4, 8)
  258. )
  259. func (self *MemoryAddress) isVMX(evex bool) bool {
  260. return self.isMemBase() && (self.Index == nil || isXMM(self.Index) || (evex && isEVEXXMM(self.Index)))
  261. }
  262. func (self *MemoryAddress) isVMY(evex bool) bool {
  263. return self.isMemBase() && (self.Index == nil || isYMM(self.Index) || (evex && isEVEXYMM(self.Index)))
  264. }
  265. func (self *MemoryAddress) isVMZ() bool {
  266. return self.isMemBase() && (self.Index == nil || isZMM(self.Index))
  267. }
  268. func (self *MemoryAddress) isMem() bool {
  269. return self.isMemBase() && (self.Index == nil || isReg64(self.Index))
  270. }
  271. func (self *MemoryAddress) isMemBase() bool {
  272. return (self.Base == nil || isReg64(self.Base)) && // `Base` must be 64-bit if present
  273. (self.Scale == 0) == (self.Index == nil) && // `Scale` and `Index` depends on each other
  274. (_Scales&(1<<self.Scale)) != 0 // `Scale` can only be 0, 1, 2, 4 or 8
  275. }
  276. // String implements the fmt.Stringer interface.
  277. func (self *MemoryAddress) String() string {
  278. var dp int
  279. var sb strings.Builder
  280. /* the displacement part */
  281. if dp = int(self.Displacement); dp != 0 {
  282. sb.WriteString(strconv.Itoa(dp))
  283. }
  284. /* the base register */
  285. if sb.WriteByte('('); self.Base != nil {
  286. sb.WriteByte('%')
  287. sb.WriteString(self.Base.String())
  288. }
  289. /* index is optional */
  290. if self.Index != nil {
  291. sb.WriteString(",%")
  292. sb.WriteString(self.Index.String())
  293. /* scale is also optional */
  294. if self.Scale >= 2 {
  295. sb.WriteByte(',')
  296. sb.WriteString(strconv.Itoa(int(self.Scale)))
  297. }
  298. }
  299. /* close the bracket */
  300. sb.WriteByte(')')
  301. return sb.String()
  302. }
  303. // EnsureValid checks if the memory address is valid, if not, it panics.
  304. func (self *MemoryAddress) EnsureValid() {
  305. if !self.isMemBase() || (self.Index != nil && !isIndexable(self.Index)) {
  306. panic("not a valid memory address")
  307. }
  308. }
  309. // Ref constructs a memory reference to a label.
  310. func Ref(ref *Label) (v *MemoryOperand) {
  311. v = CreateMemoryOperand()
  312. v.Addr.Type = Reference
  313. v.Addr.Reference = ref
  314. return
  315. }
  316. // Abs construct a simple memory address that represents absolute addressing.
  317. func Abs(disp int32) *MemoryOperand {
  318. return Sib(nil, nil, 0, disp)
  319. }
  320. // Ptr constructs a simple memory operand with base and displacement.
  321. func Ptr(base Register, disp int32) *MemoryOperand {
  322. return Sib(base, nil, 0, disp)
  323. }
  324. // Sib constructs a simple memory operand that represents a complete memory address.
  325. func Sib(base Register, index Register, scale uint8, disp int32) (v *MemoryOperand) {
  326. v = CreateMemoryOperand()
  327. v.Addr.Type = Memory
  328. v.Addr.Memory.Base = base
  329. v.Addr.Memory.Index = index
  330. v.Addr.Memory.Scale = scale
  331. v.Addr.Memory.Displacement = disp
  332. v.EnsureValid()
  333. return
  334. }
  335. /** Operand Matching Helpers **/
  336. const _IntMask = (1 << reflect.Int) |
  337. (1 << reflect.Int8) |
  338. (1 << reflect.Int16) |
  339. (1 << reflect.Int32) |
  340. (1 << reflect.Int64) |
  341. (1 << reflect.Uint) |
  342. (1 << reflect.Uint8) |
  343. (1 << reflect.Uint16) |
  344. (1 << reflect.Uint32) |
  345. (1 << reflect.Uint64) |
  346. (1 << reflect.Uintptr)
  347. func isInt(k reflect.Kind) bool {
  348. return (_IntMask & (1 << k)) != 0
  349. }
  350. func asInt64(v interface{}) (int64, bool) {
  351. if isSpecial(v) {
  352. return 0, false
  353. } else if x := efaceOf(v); isInt(x.kind()) {
  354. return x.toInt64(), true
  355. } else {
  356. return 0, false
  357. }
  358. }
  359. func inRange(v interface{}, low int64, high int64) bool {
  360. x, ok := asInt64(v)
  361. return ok && x >= low && x <= high
  362. }
  363. func isSpecial(v interface{}) bool {
  364. switch v.(type) {
  365. case Register8:
  366. return true
  367. case Register16:
  368. return true
  369. case Register32:
  370. return true
  371. case Register64:
  372. return true
  373. case KRegister:
  374. return true
  375. case MMRegister:
  376. return true
  377. case XMMRegister:
  378. return true
  379. case YMMRegister:
  380. return true
  381. case ZMMRegister:
  382. return true
  383. case RelativeOffset:
  384. return true
  385. case RoundingControl:
  386. return true
  387. case ExceptionControl:
  388. return true
  389. default:
  390. return false
  391. }
  392. }
  393. func isIndexable(v interface{}) bool {
  394. return isZMM(v) || isReg64(v) || isEVEXXMM(v) || isEVEXYMM(v)
  395. }
  396. func isImm4(v interface{}) bool { return inRange(v, 0, 15) }
  397. func isImm8(v interface{}) bool { return inRange(v, math.MinInt8, math.MaxUint8) }
  398. func isImm16(v interface{}) bool { return inRange(v, math.MinInt16, math.MaxUint16) }
  399. func isImm32(v interface{}) bool { return inRange(v, math.MinInt32, math.MaxUint32) }
  400. func isImm64(v interface{}) bool { _, r := asInt64(v); return r }
  401. func isConst1(v interface{}) bool { x, r := asInt64(v); return r && x == 1 }
  402. func isConst3(v interface{}) bool { x, r := asInt64(v); return r && x == 3 }
  403. func isRel8(v interface{}) bool {
  404. x, r := v.(RelativeOffset)
  405. return r && x >= math.MinInt8 && x <= math.MaxInt8
  406. }
  407. func isRel32(v interface{}) bool { _, r := v.(RelativeOffset); return r }
  408. func isLabel(v interface{}) bool { _, r := v.(*Label); return r }
  409. func isReg8(v interface{}) bool { _, r := v.(Register8); return r }
  410. func isReg8REX(v interface{}) bool {
  411. x, r := v.(Register8)
  412. return r && (x&0x80) == 0 && x >= SPL
  413. }
  414. func isReg16(v interface{}) bool { _, r := v.(Register16); return r }
  415. func isReg32(v interface{}) bool { _, r := v.(Register32); return r }
  416. func isReg64(v interface{}) bool { _, r := v.(Register64); return r }
  417. func isMM(v interface{}) bool { _, r := v.(MMRegister); return r }
  418. func isXMM(v interface{}) bool { x, r := v.(XMMRegister); return r && x <= XMM15 }
  419. func isEVEXXMM(v interface{}) bool { _, r := v.(XMMRegister); return r }
  420. func isXMMk(v interface{}) bool {
  421. x, r := v.(MaskedRegister)
  422. return isXMM(v) || (r && isXMM(x.Reg) && !x.Mask.Z)
  423. }
  424. func isXMMkz(v interface{}) bool {
  425. x, r := v.(MaskedRegister)
  426. return isXMM(v) || (r && isXMM(x.Reg))
  427. }
  428. func isYMM(v interface{}) bool { x, r := v.(YMMRegister); return r && x <= YMM15 }
  429. func isEVEXYMM(v interface{}) bool { _, r := v.(YMMRegister); return r }
  430. func isYMMk(v interface{}) bool {
  431. x, r := v.(MaskedRegister)
  432. return isYMM(v) || (r && isYMM(x.Reg) && !x.Mask.Z)
  433. }
  434. func isYMMkz(v interface{}) bool {
  435. x, r := v.(MaskedRegister)
  436. return isYMM(v) || (r && isYMM(x.Reg))
  437. }
  438. func isZMM(v interface{}) bool { _, r := v.(ZMMRegister); return r }
  439. func isZMMk(v interface{}) bool {
  440. x, r := v.(MaskedRegister)
  441. return isZMM(v) || (r && isZMM(x.Reg) && !x.Mask.Z)
  442. }
  443. func isZMMkz(v interface{}) bool {
  444. x, r := v.(MaskedRegister)
  445. return isZMM(v) || (r && isZMM(x.Reg))
  446. }
  447. func isK(v interface{}) bool { _, r := v.(KRegister); return r }
  448. func isKk(v interface{}) bool {
  449. x, r := v.(MaskedRegister)
  450. return isK(v) || (r && isK(x.Reg) && !x.Mask.Z)
  451. }
  452. func isM(v interface{}) bool {
  453. x, r := v.(*MemoryOperand)
  454. return r && x.isMem() && x.Broadcast == 0 && !x.Masked
  455. }
  456. func isMk(v interface{}) bool {
  457. x, r := v.(*MemoryOperand)
  458. return r && x.isMem() && x.Broadcast == 0 && !(x.Masked && x.Mask.Z)
  459. }
  460. func isMkz(v interface{}) bool {
  461. x, r := v.(*MemoryOperand)
  462. return r && x.isMem() && x.Broadcast == 0
  463. }
  464. func isM8(v interface{}) bool {
  465. x, r := v.(*MemoryOperand)
  466. return r && isM(v) && x.isSize(1)
  467. }
  468. func isM16(v interface{}) bool {
  469. x, r := v.(*MemoryOperand)
  470. return r && isM(v) && x.isSize(2)
  471. }
  472. func isM16kz(v interface{}) bool {
  473. x, r := v.(*MemoryOperand)
  474. return r && isMkz(v) && x.isSize(2)
  475. }
  476. func isM32(v interface{}) bool {
  477. x, r := v.(*MemoryOperand)
  478. return r && isM(v) && x.isSize(4)
  479. }
  480. func isM32k(v interface{}) bool {
  481. x, r := v.(*MemoryOperand)
  482. return r && isMk(v) && x.isSize(4)
  483. }
  484. func isM32kz(v interface{}) bool {
  485. x, r := v.(*MemoryOperand)
  486. return r && isMkz(v) && x.isSize(4)
  487. }
  488. func isM64(v interface{}) bool {
  489. x, r := v.(*MemoryOperand)
  490. return r && isM(v) && x.isSize(8)
  491. }
  492. func isM64k(v interface{}) bool {
  493. x, r := v.(*MemoryOperand)
  494. return r && isMk(v) && x.isSize(8)
  495. }
  496. func isM64kz(v interface{}) bool {
  497. x, r := v.(*MemoryOperand)
  498. return r && isMkz(v) && x.isSize(8)
  499. }
  500. func isM128(v interface{}) bool {
  501. x, r := v.(*MemoryOperand)
  502. return r && isM(v) && x.isSize(16)
  503. }
  504. func isM128kz(v interface{}) bool {
  505. x, r := v.(*MemoryOperand)
  506. return r && isMkz(v) && x.isSize(16)
  507. }
  508. func isM256(v interface{}) bool {
  509. x, r := v.(*MemoryOperand)
  510. return r && isM(v) && x.isSize(32)
  511. }
  512. func isM256kz(v interface{}) bool {
  513. x, r := v.(*MemoryOperand)
  514. return r && isMkz(v) && x.isSize(32)
  515. }
  516. func isM512(v interface{}) bool {
  517. x, r := v.(*MemoryOperand)
  518. return r && isM(v) && x.isSize(64)
  519. }
  520. func isM512kz(v interface{}) bool {
  521. x, r := v.(*MemoryOperand)
  522. return r && isMkz(v) && x.isSize(64)
  523. }
  524. func isM64M32bcst(v interface{}) bool {
  525. x, r := v.(*MemoryOperand)
  526. return isM64(v) || (r && x.isBroadcast(4, 2))
  527. }
  528. func isM128M32bcst(v interface{}) bool {
  529. x, r := v.(*MemoryOperand)
  530. return isM128(v) || (r && x.isBroadcast(4, 4))
  531. }
  532. func isM256M32bcst(v interface{}) bool {
  533. x, r := v.(*MemoryOperand)
  534. return isM256(v) || (r && x.isBroadcast(4, 8))
  535. }
  536. func isM512M32bcst(v interface{}) bool {
  537. x, r := v.(*MemoryOperand)
  538. return isM512(v) || (r && x.isBroadcast(4, 16))
  539. }
  540. func isM128M64bcst(v interface{}) bool {
  541. x, r := v.(*MemoryOperand)
  542. return isM128(v) || (r && x.isBroadcast(8, 2))
  543. }
  544. func isM256M64bcst(v interface{}) bool {
  545. x, r := v.(*MemoryOperand)
  546. return isM256(v) || (r && x.isBroadcast(8, 4))
  547. }
  548. func isM512M64bcst(v interface{}) bool {
  549. x, r := v.(*MemoryOperand)
  550. return isM512(v) || (r && x.isBroadcast(8, 8))
  551. }
  552. func isVMX(v interface{}) bool {
  553. x, r := v.(*MemoryOperand)
  554. return r && x.isVMX(false) && !x.Masked
  555. }
  556. func isEVEXVMX(v interface{}) bool {
  557. x, r := v.(*MemoryOperand)
  558. return r && x.isVMX(true) && !x.Masked
  559. }
  560. func isVMXk(v interface{}) bool { x, r := v.(*MemoryOperand); return r && x.isVMX(true) }
  561. func isVMY(v interface{}) bool {
  562. x, r := v.(*MemoryOperand)
  563. return r && x.isVMY(false) && !x.Masked
  564. }
  565. func isEVEXVMY(v interface{}) bool {
  566. x, r := v.(*MemoryOperand)
  567. return r && x.isVMY(true) && !x.Masked
  568. }
  569. func isVMYk(v interface{}) bool { x, r := v.(*MemoryOperand); return r && x.isVMY(true) }
  570. func isVMZ(v interface{}) bool {
  571. x, r := v.(*MemoryOperand)
  572. return r && x.isVMZ() && !x.Masked
  573. }
  574. func isVMZk(v interface{}) bool { x, r := v.(*MemoryOperand); return r && x.isVMZ() }
  575. func isSAE(v interface{}) bool { _, r := v.(ExceptionControl); return r }
  576. func isER(v interface{}) bool { _, r := v.(RoundingControl); return r }
  577. func isImmExt(v interface{}, ext int, min int64, max int64) bool {
  578. if x, ok := asInt64(v); !ok {
  579. return false
  580. } else if m := int64(1) << (8 * ext); x < m && x >= m+min {
  581. return true
  582. } else {
  583. return x <= max && x >= min
  584. }
  585. }
  586. func isImm8Ext(v interface{}, ext int) bool {
  587. return isImmExt(v, ext, math.MinInt8, math.MaxInt8)
  588. }
  589. func isImm32Ext(v interface{}, ext int) bool {
  590. return isImmExt(v, ext, math.MinInt32, math.MaxInt32)
  591. }