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