1 package x86_64
2
3 import (
4 `encoding/binary`
5 `math`
6 )
7
8
9
10 func imml(v interface{}) byte {
11 return byte(toImmAny(v) & 0x0f)
12 }
13
14 func relv(v interface{}) int64 {
15 switch r := v.(type) {
16 case *Label : return 0
17 case RelativeOffset : return int64(r)
18 default : panic("invalid relative offset")
19 }
20 }
21
22 func addr(v interface{}) interface{} {
23 switch a := v.(*MemoryOperand).Addr; a.Type {
24 case Memory : return a.Memory
25 case Offset : return a.Offset
26 case Reference : return a.Reference
27 default : panic("invalid memory operand type")
28 }
29 }
30
31 func bcode(v interface{}) byte {
32 if m, ok := v.(*MemoryOperand); !ok {
33 panic("v is not a memory operand")
34 } else if m.Broadcast == 0 {
35 return 0
36 } else {
37 return 1
38 }
39 }
40
41 func vcode(v interface{}) byte {
42 switch r := v.(type) {
43 case XMMRegister : return byte(r)
44 case YMMRegister : return byte(r)
45 case ZMMRegister : return byte(r)
46 case MaskedRegister : return vcode(r.Reg)
47 default : panic("v is not a vector register")
48 }
49 }
50
51 func kcode(v interface{}) byte {
52 switch r := v.(type) {
53 case KRegister : return byte(r)
54 case XMMRegister : return 0
55 case YMMRegister : return 0
56 case ZMMRegister : return 0
57 case RegisterMask : return byte(r.K)
58 case MaskedRegister : return byte(r.Mask.K)
59 case *MemoryOperand : return toKcodeMem(r)
60 default : panic("v is not a maskable operand")
61 }
62 }
63
64 func zcode(v interface{}) byte {
65 switch r := v.(type) {
66 case KRegister : return 0
67 case XMMRegister : return 0
68 case YMMRegister : return 0
69 case ZMMRegister : return 0
70 case RegisterMask : return toZcodeRegM(r)
71 case MaskedRegister : return toZcodeRegM(r.Mask)
72 case *MemoryOperand : return toZcodeMem(r)
73 default : panic("v is not a maskable operand")
74 }
75 }
76
77 func lcode(v interface{}) byte {
78 switch r := v.(type) {
79 case Register8 : return byte(r & 0x07)
80 case Register16 : return byte(r & 0x07)
81 case Register32 : return byte(r & 0x07)
82 case Register64 : return byte(r & 0x07)
83 case KRegister : return byte(r & 0x07)
84 case MMRegister : return byte(r & 0x07)
85 case XMMRegister : return byte(r & 0x07)
86 case YMMRegister : return byte(r & 0x07)
87 case ZMMRegister : return byte(r & 0x07)
88 case MaskedRegister : return lcode(r.Reg)
89 default : panic("v is not a register")
90 }
91 }
92
93 func hcode(v interface{}) byte {
94 switch r := v.(type) {
95 case Register8 : return byte(r >> 3) & 1
96 case Register16 : return byte(r >> 3) & 1
97 case Register32 : return byte(r >> 3) & 1
98 case Register64 : return byte(r >> 3) & 1
99 case KRegister : return byte(r >> 3) & 1
100 case MMRegister : return byte(r >> 3) & 1
101 case XMMRegister : return byte(r >> 3) & 1
102 case YMMRegister : return byte(r >> 3) & 1
103 case ZMMRegister : return byte(r >> 3) & 1
104 case MaskedRegister : return hcode(r.Reg)
105 default : panic("v is not a register")
106 }
107 }
108
109 func ecode(v interface{}) byte {
110 switch r := v.(type) {
111 case Register8 : return byte(r >> 4) & 1
112 case Register16 : return byte(r >> 4) & 1
113 case Register32 : return byte(r >> 4) & 1
114 case Register64 : return byte(r >> 4) & 1
115 case KRegister : return byte(r >> 4) & 1
116 case MMRegister : return byte(r >> 4) & 1
117 case XMMRegister : return byte(r >> 4) & 1
118 case YMMRegister : return byte(r >> 4) & 1
119 case ZMMRegister : return byte(r >> 4) & 1
120 case MaskedRegister : return ecode(r.Reg)
121 default : panic("v is not a register")
122 }
123 }
124
125 func hlcode(v interface{}) byte {
126 switch r := v.(type) {
127 case Register8 : return toHLcodeReg8(r)
128 case Register16 : return byte(r & 0x0f)
129 case Register32 : return byte(r & 0x0f)
130 case Register64 : return byte(r & 0x0f)
131 case KRegister : return byte(r & 0x0f)
132 case MMRegister : return byte(r & 0x0f)
133 case XMMRegister : return byte(r & 0x0f)
134 case YMMRegister : return byte(r & 0x0f)
135 case ZMMRegister : return byte(r & 0x0f)
136 case MaskedRegister : return hlcode(r.Reg)
137 default : panic("v is not a register")
138 }
139 }
140
141 func ehcode(v interface{}) byte {
142 switch r := v.(type) {
143 case Register8 : return byte(r >> 3) & 0x03
144 case Register16 : return byte(r >> 3) & 0x03
145 case Register32 : return byte(r >> 3) & 0x03
146 case Register64 : return byte(r >> 3) & 0x03
147 case KRegister : return byte(r >> 3) & 0x03
148 case MMRegister : return byte(r >> 3) & 0x03
149 case XMMRegister : return byte(r >> 3) & 0x03
150 case YMMRegister : return byte(r >> 3) & 0x03
151 case ZMMRegister : return byte(r >> 3) & 0x03
152 case MaskedRegister : return ehcode(r.Reg)
153 default : panic("v is not a register")
154 }
155 }
156
157 func toImmAny(v interface{}) int64 {
158 if x, ok := asInt64(v); ok {
159 return x
160 } else {
161 panic("value is not an integer")
162 }
163 }
164
165 func toHcodeOpt(v interface{}) byte {
166 if v == nil {
167 return 0
168 } else {
169 return hcode(v)
170 }
171 }
172
173 func toEcodeVMM(v interface{}, x byte) byte {
174 switch r := v.(type) {
175 case XMMRegister : return ecode(r)
176 case YMMRegister : return ecode(r)
177 case ZMMRegister : return ecode(r)
178 default : return x
179 }
180 }
181
182 func toKcodeMem(v *MemoryOperand) byte {
183 if !v.Masked {
184 return 0
185 } else {
186 return byte(v.Mask.K)
187 }
188 }
189
190 func toZcodeMem(v *MemoryOperand) byte {
191 if !v.Masked || v.Mask.Z {
192 return 0
193 } else {
194 return 1
195 }
196 }
197
198 func toZcodeRegM(v RegisterMask) byte {
199 if v.Z {
200 return 1
201 } else {
202 return 0
203 }
204 }
205
206 func toHLcodeReg8(v Register8) byte {
207 switch v {
208 case AH: fallthrough
209 case BH: fallthrough
210 case CH: fallthrough
211 case DH: panic("ah/bh/ch/dh registers never use 4-bit encoding")
212 default: return byte(v & 0x0f)
213 }
214 }
215
216
217
218 const (
219 _N_inst = 16
220 )
221
222 const (
223 _F_rel1 = 1 << iota
224 _F_rel4
225 )
226
227 type _Encoding struct {
228 len int
229 flags int
230 bytes [_N_inst]byte
231 encoder func(m *_Encoding, v []interface{})
232 }
233
234
235 func (self *_Encoding) buf(n int) []byte {
236 if i := self.len; i + n > _N_inst {
237 panic("instruction too long")
238 } else {
239 return self.bytes[i:]
240 }
241 }
242
243
244 func (self *_Encoding) emit(v byte) {
245 self.buf(1)[0] = v
246 self.len++
247 }
248
249
250 func (self *_Encoding) imm1(v int64) {
251 self.emit(byte(v))
252 }
253
254
255 func (self *_Encoding) imm2(v int64) {
256 binary.LittleEndian.PutUint16(self.buf(2), uint16(v))
257 self.len += 2
258 }
259
260
261 func (self *_Encoding) imm4(v int64) {
262 binary.LittleEndian.PutUint32(self.buf(4), uint32(v))
263 self.len += 4
264 }
265
266
267 func (self *_Encoding) imm8(v int64) {
268 binary.LittleEndian.PutUint64(self.buf(8), uint64(v))
269 self.len += 8
270 }
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297 func (self *_Encoding) vex2(lpp byte, r byte, rm interface{}, vvvv byte) {
298 var b byte
299 var x byte
300
301
302 if r > 1 {
303 panic("VEX.R must be a 1-bit mask")
304 }
305
306
307 if lpp &^ 0b111 != 0 {
308 panic("VEX.Lpp must be a 3-bit mask")
309 }
310
311
312 if vvvv &^ 0b1111 != 0 {
313 panic("VEX.vvvv must be a 4-bit mask")
314 }
315
316
317 if rm != nil {
318 switch v := rm.(type) {
319 case *Label : break
320 case Register : b = hcode(v)
321 case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
322 case RelativeOffset : break
323 default : panic("rm is expected to be a register or a memory address")
324 }
325 }
326
327
328 if x == 0 && b == 0 {
329 self.emit(0xc5)
330 self.emit(0xf8 ^ (r << 7) ^ (vvvv << 3) ^ lpp)
331 } else {
332 self.emit(0xc4)
333 self.emit(0xe1 ^ (r << 7) ^ (x << 6) ^ (b << 5))
334 self.emit(0x78 ^ (vvvv << 3) ^ lpp)
335 }
336 }
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353 func (self *_Encoding) vex3(esc byte, mmmmm byte, wlpp byte, r byte, rm interface{}, vvvv byte) {
354 var b byte
355 var x byte
356
357
358 if r > 1 {
359 panic("VEX.R must be a 1-bit mask")
360 }
361
362
363 if vvvv &^ 0b1111 != 0 {
364 panic("VEX.vvvv must be a 4-bit mask")
365 }
366
367
368 if esc != 0xc4 && esc != 0x8f {
369 panic("escape must be a 3-byte VEX (0xc4) or XOP (0x8f) prefix")
370 }
371
372
373 if wlpp &^ 0b10000111 != 0 {
374 panic("VEX.W____Lpp is expected to have no bits set except 0, 1, 2 and 7")
375 }
376
377
378 if mmmmm &^ 0b11111 != 0 {
379 panic("VEX.m-mmmm is expected to be a 5-bit mask")
380 }
381
382
383 switch v := rm.(type) {
384 case *Label : break
385 case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
386 case RelativeOffset : break
387 default : panic("rm is expected to be a register or a memory address")
388 }
389
390
391 self.emit(esc)
392 self.emit(0xe0 ^ (r << 7) ^ (x << 6) ^ (b << 5) ^ mmmmm)
393 self.emit(0x78 ^ (vvvv << 3) ^ wlpp)
394 }
395
396
397 func (self *_Encoding) evex(mm byte, w1pp byte, ll byte, rr byte, rm interface{}, vvvvv byte, aaa byte, zz byte, bb byte) {
398 var b byte
399 var x byte
400
401
402 if bb > 1 {
403 panic("EVEX.b must be a 1-bit mask")
404 }
405
406
407 if zz > 1 {
408 panic("EVEX.z must be a 1-bit mask")
409 }
410
411
412 if mm &^ 0b11 != 0 {
413 panic("EVEX.mm must be a 2-bit mask")
414 }
415
416
417 if ll &^ 0b11 != 0 {
418 panic("EVEX.L'L must be a 2-bit mask")
419 }
420
421
422 if rr &^ 0b11 != 0 {
423 panic("EVEX.R'R must be a 2-bit mask")
424 }
425
426
427 if aaa &^ 0b111 != 0 {
428 panic("EVEX.aaa must be a 3-bit mask")
429 }
430
431
432 if vvvvv &^ 0b11111 != 0 {
433 panic("EVEX.v'vvvv must be a 5-bit mask")
434 }
435
436
437 if w1pp &^ 0b10000011 != 0b100 {
438 panic("EVEX.W____1pp is expected to have no bits set except 0, 1, 2, and 7")
439 }
440
441
442 r1, r0 := rr >> 1, rr & 1
443 v1, v0 := vvvvv >> 4, vvvvv & 0b1111
444
445
446 if rm != nil {
447 switch m := rm.(type) {
448 case *Label : break
449 case Register : b, x = hcode(m), ecode(m)
450 case MemoryAddress : b, x, v1 = toHcodeOpt(m.Base), toHcodeOpt(m.Index), toEcodeVMM(m.Index, v1)
451 case RelativeOffset : break
452 default : panic("rm is expected to be a register or a memory address")
453 }
454 }
455
456
457 p0 := (r0 << 7) | (x << 6) | (b << 5) | (r1 << 4) | mm
458 p1 := (v0 << 3) | w1pp
459 p2 := (zz << 7) | (ll << 5) | (b << 4) | (v1 << 3) | aaa
460
461
464 self.emit(0x62)
465 self.emit(p0 ^ 0xf0)
466 self.emit(p1 ^ 0x78)
467 self.emit(p2 ^ 0x08)
468 }
469
470
471 func (self *_Encoding) rexm(w byte, r byte, rm interface{}) {
472 var b byte
473 var x byte
474
475
476 if r != 0 && r != 1 {
477 panic("REX.R must be 0 or 1")
478 }
479
480
481 if w != 0 && w != 1 {
482 panic("REX.W must be 0 or 1")
483 }
484
485
486 switch v := rm.(type) {
487 case *Label : break
488 case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
489 case RelativeOffset : break
490 default : panic("rm is expected to be a register or a memory address")
491 }
492
493
494 self.emit(0x40 | (w << 3) | (r << 2) | (x << 1) | b)
495 }
496
497
498 func (self *_Encoding) rexo(r byte, rm interface{}, force bool) {
499 var b byte
500 var x byte
501
502
503 if r != 0 && r != 1 {
504 panic("REX.R must be 0 or 1")
505 }
506
507
508 switch v := rm.(type) {
509 case *Label : break
510 case Register : b = hcode(v)
511 case MemoryAddress : b, x = toHcodeOpt(v.Base), toHcodeOpt(v.Index)
512 case RelativeOffset : break
513 default : panic("rm is expected to be a register or a memory address")
514 }
515
516
517 if force || r != 0 || x != 0 || b != 0 {
518 self.emit(0x40 | (r << 2) | (x << 1) | b)
519 }
520 }
521
522
523
524
525
526
527
528
529
530
531
532
533
534 func (self *_Encoding) mrsd(reg byte, rm interface{}, disp8v int32) {
535 var ok bool
536 var mm MemoryAddress
537 var ro RelativeOffset
538
539
540 if reg > 7 {
541 panic("invalid register bits")
542 }
543
544
545 switch disp8v {
546 case 1: break
547 case 2: break
548 case 4: break
549 case 8: break
550 case 16: break
551 case 32: break
552 case 64: break
553 default: panic("invalid displacement size")
554 }
555
556
557 if _, ok = rm.(*Label); ok {
558 self.emit(0x05 | (reg << 3))
559 self.imm4(0)
560 return
561 }
562
563
565 if ro, ok = rm.(RelativeOffset); ok {
566 self.emit(0x05 | (reg << 3))
567 self.imm4(int64(ro))
568 return
569 }
570
571
572 if mm, ok = rm.(MemoryAddress); !ok {
573 panic("rm must be a memory address")
574 }
575
576
577 if mm.Base == nil && mm.Index == nil {
578 self.emit(0x04 | (reg << 3))
579 self.emit(0x25)
580 self.imm4(int64(mm.Displacement))
581 return
582 }
583
584
585 if mm.Index == nil && lcode(mm.Base) != 0b100 {
586 cc := lcode(mm.Base)
587 dv := mm.Displacement
588
589
590 if dv == 0 && mm.Base != RBP && mm.Base != R13 {
591 if cc == 0b101 {
592 panic("rbp/r13 is not encodable as a base register (interpreted as disp32 address)")
593 } else {
594 self.emit((reg << 3) | cc)
595 return
596 }
597 }
598
599
600 if dq := dv / disp8v; dq >= math.MinInt8 && dq <= math.MaxInt8 && dv % disp8v == 0 {
601 self.emit(0x40 | (reg << 3) | cc)
602 self.imm1(int64(dq))
603 return
604 }
605
606
607 self.emit(0x80 | (reg << 3) | cc)
608 self.imm4(int64(mm.Displacement))
609 return
610 }
611
612
613 if mm.Index == RSP {
614 panic("rsp is not encodable as an index register (interpreted as no index)")
615 }
616
617
618 var scale byte
619 var index byte = 0x04
620
621
622 if mm.Scale != 0 {
623 switch mm.Scale {
624 case 1 : scale = 0
625 case 2 : scale = 1
626 case 4 : scale = 2
627 case 8 : scale = 3
628 default : panic("invalid scale value")
629 }
630 }
631
632
633 if mm.Index != nil {
634 index = lcode(mm.Index)
635 }
636
637
638 if mm.Base == nil {
639 self.emit((reg << 3) | 0b100)
640 self.emit((scale << 6) | (index << 3) | 0b101)
641 self.imm4(int64(mm.Displacement))
642 return
643 }
644
645
646 cc := lcode(mm.Base)
647 dv := mm.Displacement
648
649
650 if dv == 0 && cc != 0b101 {
651 self.emit((reg << 3) | 0b100)
652 self.emit((scale << 6) | (index << 3) | cc)
653 return
654 }
655
656
657 if dq := dv / disp8v; dq >= math.MinInt8 && dq <= math.MaxInt8 && dv % disp8v == 0 {
658 self.emit(0x44 | (reg << 3))
659 self.emit((scale << 6) | (index << 3) | cc)
660 self.imm1(int64(dq))
661 return
662 }
663
664
665 self.emit(0x84 | (reg << 3))
666 self.emit((scale << 6) | (index << 3) | cc)
667 self.imm4(int64(mm.Displacement))
668 }
669
670
671 func (self *_Encoding) encode(v []interface{}) int {
672 self.len = 0
673 self.encoder(self, v)
674 return self.len
675 }
676
View as plain text