1
2
3
4
5
6
7 package x86asm
8
9 import (
10 "encoding/binary"
11 "errors"
12 "fmt"
13 "runtime"
14 )
15
16
17
18
19 const trace = false
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 type decodeOp uint16
37
38 const (
39 xFail decodeOp = iota
40 xMatch
41 xJump
42
43 xCondByte
44 xCondSlashR
45 xCondPrefix
46 xCondIs64
47 xCondDataSize
48 xCondAddrSize
49 xCondIsMem
50
51 xSetOp
52
53 xReadSlashR
54 xReadIb
55 xReadIw
56 xReadId
57 xReadIo
58 xReadCb
59 xReadCw
60 xReadCd
61 xReadCp
62 xReadCm
63
64 xArg1
65 xArg3
66 xArgAL
67 xArgAX
68 xArgCL
69 xArgCR0dashCR7
70 xArgCS
71 xArgDR0dashDR7
72 xArgDS
73 xArgDX
74 xArgEAX
75 xArgEDX
76 xArgES
77 xArgFS
78 xArgGS
79 xArgImm16
80 xArgImm32
81 xArgImm64
82 xArgImm8
83 xArgImm8u
84 xArgImm16u
85 xArgM
86 xArgM128
87 xArgM256
88 xArgM1428byte
89 xArgM16
90 xArgM16and16
91 xArgM16and32
92 xArgM16and64
93 xArgM16colon16
94 xArgM16colon32
95 xArgM16colon64
96 xArgM16int
97 xArgM2byte
98 xArgM32
99 xArgM32and32
100 xArgM32fp
101 xArgM32int
102 xArgM512byte
103 xArgM64
104 xArgM64fp
105 xArgM64int
106 xArgM8
107 xArgM80bcd
108 xArgM80dec
109 xArgM80fp
110 xArgM94108byte
111 xArgMm
112 xArgMm1
113 xArgMm2
114 xArgMm2M64
115 xArgMmM32
116 xArgMmM64
117 xArgMem
118 xArgMoffs16
119 xArgMoffs32
120 xArgMoffs64
121 xArgMoffs8
122 xArgPtr16colon16
123 xArgPtr16colon32
124 xArgR16
125 xArgR16op
126 xArgR32
127 xArgR32M16
128 xArgR32M8
129 xArgR32op
130 xArgR64
131 xArgR64M16
132 xArgR64op
133 xArgR8
134 xArgR8op
135 xArgRAX
136 xArgRDX
137 xArgRM
138 xArgRM16
139 xArgRM32
140 xArgRM64
141 xArgRM8
142 xArgReg
143 xArgRegM16
144 xArgRegM32
145 xArgRegM8
146 xArgRel16
147 xArgRel32
148 xArgRel8
149 xArgSS
150 xArgST
151 xArgSTi
152 xArgSreg
153 xArgTR0dashTR7
154 xArgXmm
155 xArgXMM0
156 xArgXmm1
157 xArgXmm2
158 xArgXmm2M128
159 xArgYmm2M256
160 xArgXmm2M16
161 xArgXmm2M32
162 xArgXmm2M64
163 xArgXmmM128
164 xArgXmmM32
165 xArgXmmM64
166 xArgYmm1
167 xArgRmf16
168 xArgRmf32
169 xArgRmf64
170 )
171
172
173
174
175 func instPrefix(b byte, mode int) (Inst, error) {
176
177 if trace {
178 _, file, line, _ := runtime.Caller(1)
179 fmt.Printf("%s:%d\n", file, line)
180 }
181 p := Prefix(b)
182 switch p {
183 case PrefixDataSize:
184 if mode == 16 {
185 p = PrefixData32
186 } else {
187 p = PrefixData16
188 }
189 case PrefixAddrSize:
190 if mode == 32 {
191 p = PrefixAddr16
192 } else {
193 p = PrefixAddr32
194 }
195 }
196
197 inst := Inst{Len: 1}
198 inst.Prefix = Prefixes{p}
199 return inst, nil
200 }
201
202
203
204
205 func truncated(src []byte, mode int) (Inst, error) {
206 if len(src) == 0 {
207 return Inst{}, ErrTruncated
208 }
209 return instPrefix(src[0], mode)
210 }
211
212
213 var (
214 ErrInvalidMode = errors.New("invalid x86 mode in Decode")
215 ErrTruncated = errors.New("truncated instruction")
216 ErrUnrecognized = errors.New("unrecognized instruction")
217 )
218
219
220
221 var decoderCover []bool
222
223
224
225
226 func Decode(src []byte, mode int) (inst Inst, err error) {
227 return decode1(src, mode, false)
228 }
229
230
231
232
233
234
235
236
237
238 func decode1(src []byte, mode int, gnuCompat bool) (Inst, error) {
239 switch mode {
240 case 16, 32, 64:
241
242
243 default:
244 return Inst{}, ErrInvalidMode
245 }
246
247
248
249 if len(src) > 15 {
250 src = src[:15]
251 }
252
253 var (
254
255 pos = 0
256 nprefix = 0
257 lockIndex = -1
258 repIndex = -1
259 segIndex = -1
260 dataSizeIndex = -1
261 addrSizeIndex = -1
262 rex Prefix
263 rexUsed Prefix
264 rexIndex = -1
265 vex Prefix
266 vexIndex = -1
267
268 addrMode = mode
269 dataMode = mode
270
271
272 haveModrm bool
273 modrm int
274 mod int
275 regop int
276 rm int
277
278
279 mem Mem
280 haveMem bool
281
282
283 haveSIB bool
284 sib int
285 scale int
286 index int
287 base int
288 displen int
289 dispoff int
290
291
292 imm int64
293 imm8 int8
294 immc int64
295 immcpos int
296
297
298 opshift int
299 inst Inst
300 narg int
301 )
302
303 if mode == 64 {
304 dataMode = 32
305 }
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345 ReadPrefixes:
346 for ; pos < len(src); pos++ {
347 p := Prefix(src[pos])
348 switch p {
349 default:
350 nprefix = pos
351 break ReadPrefixes
352
353
354
355
356 case 0xF0:
357 if lockIndex >= 0 {
358 inst.Prefix[lockIndex] |= PrefixIgnored
359 }
360 lockIndex = pos
361 case 0xF2, 0xF3:
362 if repIndex >= 0 {
363 inst.Prefix[repIndex] |= PrefixIgnored
364 }
365 repIndex = pos
366
367
368 case 0x26, 0x2E, 0x36, 0x3E:
369 if mode == 64 {
370 p |= PrefixIgnored
371 break
372 }
373 fallthrough
374 case 0x64, 0x65:
375 if segIndex >= 0 {
376 inst.Prefix[segIndex] |= PrefixIgnored
377 }
378 segIndex = pos
379
380
381 case 0x66:
382 if mode == 16 {
383 dataMode = 32
384 p = PrefixData32
385 } else {
386 dataMode = 16
387 p = PrefixData16
388 }
389 if dataSizeIndex >= 0 {
390 inst.Prefix[dataSizeIndex] |= PrefixIgnored
391 }
392 dataSizeIndex = pos
393
394
395 case 0x67:
396 if mode == 32 {
397 addrMode = 16
398 p = PrefixAddr16
399 } else {
400 addrMode = 32
401 p = PrefixAddr32
402 }
403 if addrSizeIndex >= 0 {
404 inst.Prefix[addrSizeIndex] |= PrefixIgnored
405 }
406 addrSizeIndex = pos
407
408
409 case 0xC5:
410 if pos == 0 && pos+1 < len(src) && (mode == 64 || (mode == 32 && src[pos+1]&0xc0 == 0xc0)) {
411 vex = p
412 vexIndex = pos
413 inst.Prefix[pos] = p
414 inst.Prefix[pos+1] = Prefix(src[pos+1])
415 pos += 2
416 nprefix = pos
417 break ReadPrefixes
418 } else {
419 nprefix = pos
420 break ReadPrefixes
421 }
422 case 0xC4:
423 if pos == 0 && pos+2 < len(src) && (mode == 64 || (mode == 32 && src[pos+1]&0xc0 == 0xc0)) {
424 vex = p
425 vexIndex = pos
426 inst.Prefix[pos] = p
427 inst.Prefix[pos+1] = Prefix(src[pos+1])
428 inst.Prefix[pos+2] = Prefix(src[pos+2])
429 pos += 3
430 nprefix = pos
431 break ReadPrefixes
432 } else {
433 nprefix = pos
434 break ReadPrefixes
435 }
436
437 case 0x62:
438 if pos == 0 && pos+3 < len(src) && (mode == 64 || (mode == 32 && src[pos+1]&0xc0 == 0xc0)) {
439 vex = p
440 vexIndex = pos
441 inst.Prefix[pos] = p
442 inst.Prefix[pos+1] = Prefix(src[pos+1])
443 inst.Prefix[pos+2] = Prefix(src[pos+2])
444 inst.Prefix[pos+3] = Prefix(src[pos+3])
445 pos += 4
446 nprefix = pos
447 break ReadPrefixes
448 } else {
449 nprefix = pos
450 break ReadPrefixes
451 }
452 }
453
454 if pos >= len(inst.Prefix) {
455 return instPrefix(src[0], mode)
456 }
457
458 inst.Prefix[pos] = p
459 }
460
461
462 if pos < len(src) && mode == 64 && Prefix(src[pos]).IsREX() && vex == 0 {
463 rex = Prefix(src[pos])
464 rexIndex = pos
465 if pos >= len(inst.Prefix) {
466 return instPrefix(src[0], mode)
467 }
468 inst.Prefix[pos] = rex
469 pos++
470 if rex&PrefixREXW != 0 {
471 dataMode = 64
472 if dataSizeIndex >= 0 {
473 inst.Prefix[dataSizeIndex] |= PrefixIgnored
474 }
475 }
476 }
477
478
479
480
481 opshift = 24
482
483 if vex != 0 {
484 return decodeAVX(src, pos, vex, vexIndex, inst, mode)
485 }
486
487
488 var oldPC, prevPC int
489 Decode:
490 for pc := 1; ; {
491 oldPC = prevPC
492 prevPC = pc
493 if trace {
494 println("run", pc)
495 }
496 x := decoder[pc]
497 if decoderCover != nil {
498 decoderCover[pc] = true
499 }
500 pc++
501
502
503 switch decodeOp(x) {
504 case xCondSlashR, xReadSlashR:
505 if haveModrm {
506 return Inst{Len: pos}, errInternal
507 }
508 haveModrm = true
509 if pos >= len(src) {
510 return truncated(src, mode)
511 }
512 modrm = int(src[pos])
513 pos++
514 if opshift >= 0 {
515 inst.Opcode |= uint32(modrm) << uint(opshift)
516 opshift -= 8
517 }
518 mod = modrm >> 6
519 regop = (modrm >> 3) & 07
520 rm = modrm & 07
521 if rex&PrefixREXR != 0 {
522 rexUsed |= PrefixREXR
523 regop |= 8
524 }
525 if addrMode == 16 {
526
527 if mod != 3 {
528 haveMem = true
529 mem = addr16[rm]
530 if rm == 6 && mod == 0 {
531 mem.Base = 0
532 }
533
534
535 if mod == 0 && rm == 6 || mod == 2 {
536 if pos+2 > len(src) {
537 return truncated(src, mode)
538 }
539 mem.Disp = int64(binary.LittleEndian.Uint16(src[pos:]))
540 pos += 2
541 }
542
543
544 if mod == 1 {
545 if pos >= len(src) {
546 return truncated(src, mode)
547 }
548 mem.Disp = int64(int8(src[pos]))
549 pos++
550 }
551 }
552 } else {
553 haveMem = mod != 3
554
555
556
557 if rm == 4 && mod != 3 {
558 haveSIB = true
559 if pos >= len(src) {
560 return truncated(src, mode)
561 }
562 sib = int(src[pos])
563 pos++
564 if opshift >= 0 {
565 inst.Opcode |= uint32(sib) << uint(opshift)
566 opshift -= 8
567 }
568 scale = sib >> 6
569 index = (sib >> 3) & 07
570 base = sib & 07
571 if rex&PrefixREXB != 0 || vex == 0xC4 && inst.Prefix[vexIndex+1]&0x20 == 0 {
572 rexUsed |= PrefixREXB
573 base |= 8
574 }
575 if rex&PrefixREXX != 0 || vex == 0xC4 && inst.Prefix[vexIndex+1]&0x40 == 0 {
576 rexUsed |= PrefixREXX
577 index |= 8
578 }
579
580 mem.Scale = 1 << uint(scale)
581 if index == 4 {
582
583 } else {
584 mem.Index = baseRegForBits(addrMode) + Reg(index)
585 }
586 if base&7 == 5 && mod == 0 {
587
588 } else {
589 mem.Base = baseRegForBits(addrMode) + Reg(base)
590 }
591 } else {
592 if rex&PrefixREXB != 0 {
593 rexUsed |= PrefixREXB
594 rm |= 8
595 }
596 if mod == 0 && rm&7 == 5 || rm&7 == 4 {
597
598 } else if mod != 3 {
599 mem.Base = baseRegForBits(addrMode) + Reg(rm)
600 }
601 }
602
603
604 if mod == 0 && (rm&7 == 5 || haveSIB && base&7 == 5) || mod == 2 {
605 if pos+4 > len(src) {
606 return truncated(src, mode)
607 }
608 dispoff = pos
609 displen = 4
610 mem.Disp = int64(binary.LittleEndian.Uint32(src[pos:]))
611 pos += 4
612 }
613
614
615 if mod == 1 {
616 if pos >= len(src) {
617 return truncated(src, mode)
618 }
619 dispoff = pos
620 displen = 1
621 mem.Disp = int64(int8(src[pos]))
622 pos++
623 }
624
625
626
627 if mode == 64 && mod == 0 && rm&7 == 5 {
628 if addrMode == 32 {
629 mem.Base = EIP
630 } else {
631 mem.Base = RIP
632 }
633 }
634 }
635
636 if segIndex >= 0 {
637 mem.Segment = prefixToSegment(inst.Prefix[segIndex])
638 }
639 }
640
641
642 switch decodeOp(x) {
643 default:
644 println("bad op", x, "at", pc-1, "from", oldPC)
645 return Inst{Len: pos}, errInternal
646
647 case xFail:
648 inst.Op = 0
649 break Decode
650
651 case xMatch:
652 break Decode
653
654 case xJump:
655 pc = int(decoder[pc])
656
657
658
659 case xCondByte:
660 if pos >= len(src) {
661 return truncated(src, mode)
662 }
663 b := src[pos]
664 n := int(decoder[pc])
665 pc++
666 for i := 0; i < n; i++ {
667 xb, xpc := decoder[pc], int(decoder[pc+1])
668 pc += 2
669 if b == byte(xb) {
670 pc = xpc
671 pos++
672 if opshift >= 0 {
673 inst.Opcode |= uint32(b) << uint(opshift)
674 opshift -= 8
675 }
676 continue Decode
677 }
678 }
679
680
681
682
683
684 if decodeOp(decoder[pc]) == xJump {
685 pc = int(decoder[pc+1])
686 }
687 if decodeOp(decoder[pc]) == xFail {
688 pos++
689 }
690
691 case xCondIs64:
692 if mode == 64 {
693 pc = int(decoder[pc+1])
694 } else {
695 pc = int(decoder[pc])
696 }
697
698 case xCondIsMem:
699 mem := haveMem
700 if !haveModrm {
701 if pos >= len(src) {
702 return instPrefix(src[0], mode)
703 }
704 mem = src[pos]>>6 != 3
705 }
706 if mem {
707 pc = int(decoder[pc+1])
708 } else {
709 pc = int(decoder[pc])
710 }
711
712 case xCondDataSize:
713 switch dataMode {
714 case 16:
715 if dataSizeIndex >= 0 {
716 inst.Prefix[dataSizeIndex] |= PrefixImplicit
717 }
718 pc = int(decoder[pc])
719 case 32:
720 if dataSizeIndex >= 0 {
721 inst.Prefix[dataSizeIndex] |= PrefixImplicit
722 }
723 pc = int(decoder[pc+1])
724 case 64:
725 rexUsed |= PrefixREXW
726 pc = int(decoder[pc+2])
727 }
728
729 case xCondAddrSize:
730 switch addrMode {
731 case 16:
732 if addrSizeIndex >= 0 {
733 inst.Prefix[addrSizeIndex] |= PrefixImplicit
734 }
735 pc = int(decoder[pc])
736 case 32:
737 if addrSizeIndex >= 0 {
738 inst.Prefix[addrSizeIndex] |= PrefixImplicit
739 }
740 pc = int(decoder[pc+1])
741 case 64:
742 pc = int(decoder[pc+2])
743 }
744
745 case xCondPrefix:
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815 n := int(decoder[pc])
816 pc++
817 sawF3 := false
818 for j := 0; j < n; j++ {
819 prefix := Prefix(decoder[pc+2*j])
820 if prefix.IsREX() {
821 rexUsed |= prefix
822 if rex&prefix == prefix {
823 pc = int(decoder[pc+2*j+1])
824 continue Decode
825 }
826 continue
827 }
828 ok := false
829 if prefix == 0 {
830 ok = true
831 } else if prefix.IsREX() {
832 rexUsed |= prefix
833 if rex&prefix == prefix {
834 ok = true
835 }
836 } else if prefix == 0xC5 || prefix == 0xC4 {
837 if vex == prefix {
838 ok = true
839 }
840 } else if vex != 0 && (prefix == 0x0F || prefix == 0x0F38 || prefix == 0x0F3A ||
841 prefix == 0x66 || prefix == 0xF2 || prefix == 0xF3) {
842 var vexM, vexP Prefix
843 if vex == 0xC5 {
844 vexM = 1
845 vexP = inst.Prefix[vexIndex+1]
846 } else {
847 vexM = inst.Prefix[vexIndex+1]
848 vexP = inst.Prefix[vexIndex+2]
849 }
850 switch prefix {
851 case 0x66:
852 ok = vexP&3 == 1
853 case 0xF3:
854 ok = vexP&3 == 2
855 case 0xF2:
856 ok = vexP&3 == 3
857 case 0x0F:
858 ok = vexM&3 == 1
859 case 0x0F38:
860 ok = vexM&3 == 2
861 case 0x0F3A:
862 ok = vexM&3 == 3
863 }
864 } else {
865 if prefix == 0xF3 {
866 sawF3 = true
867 }
868 switch prefix {
869 case PrefixLOCK:
870 if lockIndex >= 0 {
871 inst.Prefix[lockIndex] |= PrefixImplicit
872 ok = true
873 }
874 case PrefixREP, PrefixREPN:
875 if repIndex >= 0 && inst.Prefix[repIndex]&0xFF == prefix {
876 inst.Prefix[repIndex] |= PrefixImplicit
877 ok = true
878 }
879 if gnuCompat && !ok && prefix == 0xF3 && repIndex >= 0 && (j+1 >= n || decoder[pc+2*(j+1)] != 0xF2) {
880
881 for i := repIndex - 1; i >= 0; i-- {
882 if inst.Prefix[i]&0xFF == prefix {
883 inst.Prefix[i] |= PrefixImplicit
884 ok = true
885 }
886 }
887 }
888 if gnuCompat && !ok && prefix == 0xF2 && repIndex >= 0 && !sawF3 && inst.Prefix[repIndex]&0xFF == 0xF3 {
889
890 for i := repIndex - 1; i >= 0; i-- {
891 if inst.Prefix[i]&0xFF == prefix {
892 inst.Prefix[i] |= PrefixImplicit
893 ok = true
894 }
895 }
896 }
897 case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
898 if segIndex >= 0 && inst.Prefix[segIndex]&0xFF == prefix {
899 inst.Prefix[segIndex] |= PrefixImplicit
900 ok = true
901 }
902 case PrefixDataSize:
903
904
905
906
907
908
909
910
911 if repIndex >= 0 && !gnuCompat {
912 inst.Op = 0
913 break Decode
914 }
915 if dataSizeIndex >= 0 {
916 inst.Prefix[dataSizeIndex] |= PrefixImplicit
917 ok = true
918 }
919 case PrefixAddrSize:
920 if addrSizeIndex >= 0 {
921 inst.Prefix[addrSizeIndex] |= PrefixImplicit
922 ok = true
923 }
924 }
925 }
926 if ok {
927 pc = int(decoder[pc+2*j+1])
928 continue Decode
929 }
930 }
931 inst.Op = 0
932 break Decode
933
934 case xCondSlashR:
935 pc = int(decoder[pc+regop&7])
936
937
938
939 case xReadSlashR:
940
941
942 case xReadIb:
943 if pos >= len(src) {
944 return truncated(src, mode)
945 }
946 imm8 = int8(src[pos])
947 pos++
948
949 case xReadIw:
950 if pos+2 > len(src) {
951 return truncated(src, mode)
952 }
953 imm = int64(binary.LittleEndian.Uint16(src[pos:]))
954 pos += 2
955
956 case xReadId:
957 if pos+4 > len(src) {
958 return truncated(src, mode)
959 }
960 imm = int64(binary.LittleEndian.Uint32(src[pos:]))
961 pos += 4
962
963 case xReadIo:
964 if pos+8 > len(src) {
965 return truncated(src, mode)
966 }
967 imm = int64(binary.LittleEndian.Uint64(src[pos:]))
968 pos += 8
969
970 case xReadCb:
971 if pos >= len(src) {
972 return truncated(src, mode)
973 }
974 immcpos = pos
975 immc = int64(src[pos])
976 pos++
977
978 case xReadCw:
979 if pos+2 > len(src) {
980 return truncated(src, mode)
981 }
982 immcpos = pos
983 immc = int64(binary.LittleEndian.Uint16(src[pos:]))
984 pos += 2
985
986 case xReadCm:
987 immcpos = pos
988 if addrMode == 16 {
989 if pos+2 > len(src) {
990 return truncated(src, mode)
991 }
992 immc = int64(binary.LittleEndian.Uint16(src[pos:]))
993 pos += 2
994 } else if addrMode == 32 {
995 if pos+4 > len(src) {
996 return truncated(src, mode)
997 }
998 immc = int64(binary.LittleEndian.Uint32(src[pos:]))
999 pos += 4
1000 } else {
1001 if pos+8 > len(src) {
1002 return truncated(src, mode)
1003 }
1004 immc = int64(binary.LittleEndian.Uint64(src[pos:]))
1005 pos += 8
1006 }
1007 case xReadCd:
1008 immcpos = pos
1009 if pos+4 > len(src) {
1010 return truncated(src, mode)
1011 }
1012 immc = int64(binary.LittleEndian.Uint32(src[pos:]))
1013 pos += 4
1014
1015 case xReadCp:
1016 immcpos = pos
1017 if pos+6 > len(src) {
1018 return truncated(src, mode)
1019 }
1020 w := binary.LittleEndian.Uint32(src[pos:])
1021 w2 := binary.LittleEndian.Uint16(src[pos+4:])
1022 immc = int64(w2)<<32 | int64(w)
1023 pos += 6
1024
1025
1026
1027 case xSetOp:
1028 inst.Op = Op(decoder[pc])
1029 pc++
1030
1031 case xArg1,
1032 xArg3,
1033 xArgAL,
1034 xArgAX,
1035 xArgCL,
1036 xArgCS,
1037 xArgDS,
1038 xArgDX,
1039 xArgEAX,
1040 xArgEDX,
1041 xArgES,
1042 xArgFS,
1043 xArgGS,
1044 xArgRAX,
1045 xArgRDX,
1046 xArgSS,
1047 xArgST,
1048 xArgXMM0:
1049 inst.Args[narg] = fixedArg[x]
1050 narg++
1051
1052 case xArgImm8:
1053 inst.Args[narg] = Imm(imm8)
1054 narg++
1055
1056 case xArgImm8u:
1057 inst.Args[narg] = Imm(uint8(imm8))
1058 narg++
1059
1060 case xArgImm16:
1061 inst.Args[narg] = Imm(int16(imm))
1062 narg++
1063
1064 case xArgImm16u:
1065 inst.Args[narg] = Imm(uint16(imm))
1066 narg++
1067
1068 case xArgImm32:
1069 inst.Args[narg] = Imm(int32(imm))
1070 narg++
1071
1072 case xArgImm64:
1073 inst.Args[narg] = Imm(imm)
1074 narg++
1075
1076 case xArgM,
1077 xArgM128,
1078 xArgM256,
1079 xArgM1428byte,
1080 xArgM16,
1081 xArgM16and16,
1082 xArgM16and32,
1083 xArgM16and64,
1084 xArgM16colon16,
1085 xArgM16colon32,
1086 xArgM16colon64,
1087 xArgM16int,
1088 xArgM2byte,
1089 xArgM32,
1090 xArgM32and32,
1091 xArgM32fp,
1092 xArgM32int,
1093 xArgM512byte,
1094 xArgM64,
1095 xArgM64fp,
1096 xArgM64int,
1097 xArgM8,
1098 xArgM80bcd,
1099 xArgM80dec,
1100 xArgM80fp,
1101 xArgM94108byte,
1102 xArgMem:
1103 if !haveMem {
1104 inst.Op = 0
1105 break Decode
1106 }
1107 inst.Args[narg] = mem
1108 inst.MemBytes = int(memBytes[decodeOp(x)])
1109 if mem.Base == RIP {
1110 inst.PCRel = displen
1111 inst.PCRelOff = dispoff
1112 }
1113 narg++
1114
1115 case xArgPtr16colon16:
1116 inst.Args[narg] = Imm(immc >> 16)
1117 inst.Args[narg+1] = Imm(immc & (1<<16 - 1))
1118 narg += 2
1119
1120 case xArgPtr16colon32:
1121 inst.Args[narg] = Imm(immc >> 32)
1122 inst.Args[narg+1] = Imm(immc & (1<<32 - 1))
1123 narg += 2
1124
1125 case xArgMoffs8, xArgMoffs16, xArgMoffs32, xArgMoffs64:
1126
1127 mem = Mem{Disp: int64(immc)}
1128 if segIndex >= 0 {
1129 mem.Segment = prefixToSegment(inst.Prefix[segIndex])
1130 inst.Prefix[segIndex] |= PrefixImplicit
1131 }
1132 inst.Args[narg] = mem
1133 inst.MemBytes = int(memBytes[decodeOp(x)])
1134 if mem.Base == RIP {
1135 inst.PCRel = displen
1136 inst.PCRelOff = dispoff
1137 }
1138 narg++
1139
1140 case xArgYmm1:
1141 base := baseReg[x]
1142 index := Reg(regop)
1143 if inst.Prefix[vexIndex+1]&0x80 == 0 {
1144 index += 8
1145 }
1146 inst.Args[narg] = base + index
1147 narg++
1148
1149 case xArgR8, xArgR16, xArgR32, xArgR64, xArgXmm, xArgXmm1, xArgDR0dashDR7:
1150 base := baseReg[x]
1151 index := Reg(regop)
1152 if rex != 0 && base == AL && index >= 4 {
1153 rexUsed |= PrefixREX
1154 index -= 4
1155 base = SPB
1156 }
1157 inst.Args[narg] = base + index
1158 narg++
1159
1160 case xArgMm, xArgMm1, xArgTR0dashTR7:
1161 inst.Args[narg] = baseReg[x] + Reg(regop&7)
1162 narg++
1163
1164 case xArgCR0dashCR7:
1165
1166
1167
1168
1169 if lockIndex >= 0 {
1170 inst.Prefix[lockIndex] |= PrefixImplicit
1171 regop += 8
1172 }
1173 inst.Args[narg] = CR0 + Reg(regop)
1174 narg++
1175
1176 case xArgSreg:
1177 regop &= 7
1178 if regop >= 6 {
1179 inst.Op = 0
1180 break Decode
1181 }
1182 inst.Args[narg] = ES + Reg(regop)
1183 narg++
1184
1185 case xArgRmf16, xArgRmf32, xArgRmf64:
1186 base := baseReg[x]
1187 index := Reg(modrm & 07)
1188 if rex&PrefixREXB != 0 {
1189 rexUsed |= PrefixREXB
1190 index += 8
1191 }
1192 inst.Args[narg] = base + index
1193 narg++
1194
1195 case xArgR8op, xArgR16op, xArgR32op, xArgR64op, xArgSTi:
1196 n := inst.Opcode >> uint(opshift+8) & 07
1197 base := baseReg[x]
1198 index := Reg(n)
1199 if rex&PrefixREXB != 0 && decodeOp(x) != xArgSTi {
1200 rexUsed |= PrefixREXB
1201 index += 8
1202 }
1203 if rex != 0 && base == AL && index >= 4 {
1204 rexUsed |= PrefixREX
1205 index -= 4
1206 base = SPB
1207 }
1208 inst.Args[narg] = base + index
1209 narg++
1210 case xArgRM8, xArgRM16, xArgRM32, xArgRM64, xArgR32M16, xArgR32M8, xArgR64M16,
1211 xArgMmM32, xArgMmM64, xArgMm2M64,
1212 xArgXmm2M16, xArgXmm2M32, xArgXmm2M64, xArgXmmM64, xArgXmmM128, xArgXmmM32, xArgXmm2M128,
1213 xArgYmm2M256:
1214 if haveMem {
1215 inst.Args[narg] = mem
1216 inst.MemBytes = int(memBytes[decodeOp(x)])
1217 if mem.Base == RIP {
1218 inst.PCRel = displen
1219 inst.PCRelOff = dispoff
1220 }
1221 } else {
1222 base := baseReg[x]
1223 index := Reg(rm)
1224 switch decodeOp(x) {
1225 case xArgMmM32, xArgMmM64, xArgMm2M64:
1226
1227 index &= 7
1228 case xArgRM8:
1229 if rex != 0 && index >= 4 {
1230 rexUsed |= PrefixREX
1231 index -= 4
1232 base = SPB
1233 }
1234 case xArgYmm2M256:
1235 if vex == 0xC4 && inst.Prefix[vexIndex+1]&0x40 == 0x40 {
1236 index += 8
1237 }
1238 }
1239 inst.Args[narg] = base + index
1240 }
1241 narg++
1242
1243 case xArgMm2:
1244 if haveMem {
1245 inst.Op = 0
1246 break Decode
1247 }
1248 inst.Args[narg] = baseReg[x] + Reg(rm&7)
1249 narg++
1250
1251 case xArgXmm2:
1252 if haveMem {
1253 inst.Op = 0
1254 break Decode
1255 }
1256 inst.Args[narg] = baseReg[x] + Reg(rm)
1257 narg++
1258
1259 case xArgRel8:
1260 inst.PCRelOff = immcpos
1261 inst.PCRel = 1
1262 inst.Args[narg] = Rel(int8(immc))
1263 narg++
1264
1265 case xArgRel16:
1266 inst.PCRelOff = immcpos
1267 inst.PCRel = 2
1268 inst.Args[narg] = Rel(int16(immc))
1269 narg++
1270
1271 case xArgRel32:
1272 inst.PCRelOff = immcpos
1273 inst.PCRel = 4
1274 inst.Args[narg] = Rel(int32(immc))
1275 narg++
1276 }
1277 }
1278
1279 if inst.Op == 0 {
1280
1281 if nprefix > 0 {
1282 return instPrefix(src[0], mode)
1283 }
1284 return Inst{Len: pos}, ErrUnrecognized
1285 }
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295 if inst.Op == XCHG && inst.Opcode>>24 == 0x90 {
1296 if inst.Args[0] == RAX || inst.Args[0] == EAX || inst.Args[0] == AX {
1297 inst.Op = NOP
1298 if dataSizeIndex >= 0 {
1299 inst.Prefix[dataSizeIndex] &^= PrefixImplicit
1300 }
1301 inst.Args[0] = nil
1302 inst.Args[1] = nil
1303 }
1304 if repIndex >= 0 && inst.Prefix[repIndex] == 0xF3 {
1305 inst.Prefix[repIndex] |= PrefixImplicit
1306 inst.Op = PAUSE
1307 inst.Args[0] = nil
1308 inst.Args[1] = nil
1309 } else if gnuCompat {
1310 for i := nprefix - 1; i >= 0; i-- {
1311 if inst.Prefix[i]&0xFF == 0xF3 {
1312 inst.Prefix[i] |= PrefixImplicit
1313 inst.Op = PAUSE
1314 inst.Args[0] = nil
1315 inst.Args[1] = nil
1316 break
1317 }
1318 }
1319 }
1320 }
1321
1322
1323
1324 defaultSeg := func() Reg {
1325 if segIndex >= 0 {
1326 inst.Prefix[segIndex] |= PrefixImplicit
1327 return prefixToSegment(inst.Prefix[segIndex])
1328 }
1329 return DS
1330 }
1331
1332
1333
1334
1335
1336
1337
1338 usedAddrSize := false
1339 switch inst.Op {
1340 case INSB, INSW, INSD:
1341 inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
1342 inst.Args[1] = DX
1343 usedAddrSize = true
1344
1345 case OUTSB, OUTSW, OUTSD:
1346 inst.Args[0] = DX
1347 inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
1348 usedAddrSize = true
1349
1350 case MOVSB, MOVSW, MOVSD, MOVSQ:
1351 inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
1352 inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
1353 usedAddrSize = true
1354
1355 case CMPSB, CMPSW, CMPSD, CMPSQ:
1356 inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
1357 inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
1358 usedAddrSize = true
1359
1360 case LODSB, LODSW, LODSD, LODSQ:
1361 switch inst.Op {
1362 case LODSB:
1363 inst.Args[0] = AL
1364 case LODSW:
1365 inst.Args[0] = AX
1366 case LODSD:
1367 inst.Args[0] = EAX
1368 case LODSQ:
1369 inst.Args[0] = RAX
1370 }
1371 inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
1372 usedAddrSize = true
1373
1374 case STOSB, STOSW, STOSD, STOSQ:
1375 inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
1376 switch inst.Op {
1377 case STOSB:
1378 inst.Args[1] = AL
1379 case STOSW:
1380 inst.Args[1] = AX
1381 case STOSD:
1382 inst.Args[1] = EAX
1383 case STOSQ:
1384 inst.Args[1] = RAX
1385 }
1386 usedAddrSize = true
1387
1388 case SCASB, SCASW, SCASD, SCASQ:
1389 inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
1390 switch inst.Op {
1391 case SCASB:
1392 inst.Args[0] = AL
1393 case SCASW:
1394 inst.Args[0] = AX
1395 case SCASD:
1396 inst.Args[0] = EAX
1397 case SCASQ:
1398 inst.Args[0] = RAX
1399 }
1400 usedAddrSize = true
1401
1402 case XLATB:
1403 inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + BX - AX}
1404 usedAddrSize = true
1405 }
1406
1407
1408
1409
1410 if haveMem || usedAddrSize {
1411 if addrSizeIndex >= 0 {
1412 inst.Prefix[addrSizeIndex] |= PrefixImplicit
1413 }
1414 }
1415
1416
1417
1418
1419 if haveMem {
1420 if segIndex >= 0 {
1421 inst.Prefix[segIndex] |= PrefixImplicit
1422 }
1423 }
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433 if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
1434 PredictLoop:
1435 for i := nprefix - 1; i >= 0; i-- {
1436 p := inst.Prefix[i]
1437 switch p & 0xFF {
1438 case PrefixCS:
1439 inst.Prefix[i] = PrefixPN
1440 break PredictLoop
1441 case PrefixDS:
1442 inst.Prefix[i] = PrefixPT
1443 break PredictLoop
1444 }
1445 }
1446 }
1447
1448
1449
1450
1451
1452
1453
1454
1455 if isCondJmp[inst.Op] || inst.Op == JMP || inst.Op == CALL || inst.Op == RET {
1456 for i := nprefix - 1; i >= 0; i-- {
1457 p := inst.Prefix[i]
1458 if p&^PrefixIgnored == PrefixREPN {
1459 inst.Prefix[i] = PrefixBND
1460 break
1461 }
1462 }
1463 }
1464
1465
1466
1467
1468
1469
1470 hasLock := false
1471 if lockIndex >= 0 && inst.Prefix[lockIndex]&PrefixImplicit == 0 {
1472 switch inst.Op {
1473
1474 case ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCHG8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, XCHG:
1475 if isMem(inst.Args[0]) {
1476 hasLock = true
1477 break
1478 }
1479 fallthrough
1480 default:
1481 inst.Prefix[lockIndex] |= PrefixInvalid
1482 }
1483 }
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493 if isMem(inst.Args[0]) {
1494 if inst.Op == XCHG {
1495 hasLock = true
1496 }
1497
1498 for i := len(inst.Prefix) - 1; i >= 0; i-- {
1499 p := inst.Prefix[i] &^ PrefixIgnored
1500 switch p {
1501 case PrefixREPN:
1502 if hasLock {
1503 inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXACQUIRE
1504 }
1505
1506 case PrefixREP:
1507 if hasLock {
1508 inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE
1509 }
1510
1511 if inst.Op == MOV {
1512 op := (inst.Opcode >> 24) &^ 1
1513 if op == 0x88 || op == 0xC6 {
1514 inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE
1515 }
1516 }
1517 }
1518 }
1519 }
1520
1521
1522 if repIndex >= 0 {
1523 switch inst.Prefix[repIndex] {
1524 case PrefixREP, PrefixREPN:
1525 switch inst.Op {
1526
1527
1528
1529
1530 case INSB, INSW, INSD,
1531 MOVSB, MOVSW, MOVSD, MOVSQ,
1532 OUTSB, OUTSW, OUTSD,
1533 LODSB, LODSW, LODSD, LODSQ,
1534 CMPSB, CMPSW, CMPSD, CMPSQ,
1535 SCASB, SCASW, SCASD, SCASQ,
1536 STOSB, STOSW, STOSD, STOSQ:
1537
1538 default:
1539 inst.Prefix[repIndex] |= PrefixIgnored
1540 }
1541 }
1542 }
1543
1544
1545 if rexIndex >= 0 {
1546 if rexUsed != 0 {
1547 rexUsed |= PrefixREX
1548 }
1549 if rex&^rexUsed == 0 {
1550 inst.Prefix[rexIndex] |= PrefixImplicit
1551 }
1552 }
1553
1554 inst.DataSize = dataMode
1555 inst.AddrSize = addrMode
1556 inst.Mode = mode
1557 inst.Len = pos
1558 return inst, nil
1559 }
1560
1561 var errInternal = errors.New("internal error")
1562
1563
1564 var addr16 = [8]Mem{
1565 {Base: BX, Scale: 1, Index: SI},
1566 {Base: BX, Scale: 1, Index: DI},
1567 {Base: BP, Scale: 1, Index: SI},
1568 {Base: BP, Scale: 1, Index: DI},
1569 {Base: SI},
1570 {Base: DI},
1571 {Base: BP},
1572 {Base: BX},
1573 }
1574
1575
1576 func baseRegForBits(bits int) Reg {
1577 switch bits {
1578 case 8:
1579 return AL
1580 case 16:
1581 return AX
1582 case 32:
1583 return EAX
1584 case 64:
1585 return RAX
1586 }
1587 return 0
1588 }
1589
1590
1591
1592 var baseReg = [...]Reg{
1593 xArgDR0dashDR7: DR0,
1594 xArgMm1: M0,
1595 xArgMm2: M0,
1596 xArgMm2M64: M0,
1597 xArgMm: M0,
1598 xArgMmM32: M0,
1599 xArgMmM64: M0,
1600 xArgR16: AX,
1601 xArgR16op: AX,
1602 xArgR32: EAX,
1603 xArgR32M16: EAX,
1604 xArgR32M8: EAX,
1605 xArgR32op: EAX,
1606 xArgR64: RAX,
1607 xArgR64M16: RAX,
1608 xArgR64op: RAX,
1609 xArgR8: AL,
1610 xArgR8op: AL,
1611 xArgRM16: AX,
1612 xArgRM32: EAX,
1613 xArgRM64: RAX,
1614 xArgRM8: AL,
1615 xArgRmf16: AX,
1616 xArgRmf32: EAX,
1617 xArgRmf64: RAX,
1618 xArgSTi: F0,
1619 xArgTR0dashTR7: TR0,
1620 xArgXmm1: X0,
1621 xArgYmm1: X0,
1622 xArgXmm2: X0,
1623 xArgXmm2M128: X0,
1624 xArgYmm2M256: X0,
1625 xArgXmm2M16: X0,
1626 xArgXmm2M32: X0,
1627 xArgXmm2M64: X0,
1628 xArgXmm: X0,
1629 xArgXmmM128: X0,
1630 xArgXmmM32: X0,
1631 xArgXmmM64: X0,
1632 }
1633
1634
1635
1636 func prefixToSegment(p Prefix) Reg {
1637 switch p &^ PrefixImplicit {
1638 case PrefixCS:
1639 return CS
1640 case PrefixDS:
1641 return DS
1642 case PrefixES:
1643 return ES
1644 case PrefixFS:
1645 return FS
1646 case PrefixGS:
1647 return GS
1648 case PrefixSS:
1649 return SS
1650 }
1651 return 0
1652 }
1653
1654
1655 var fixedArg = [...]Arg{
1656 xArg1: Imm(1),
1657 xArg3: Imm(3),
1658 xArgAL: AL,
1659 xArgAX: AX,
1660 xArgDX: DX,
1661 xArgEAX: EAX,
1662 xArgEDX: EDX,
1663 xArgRAX: RAX,
1664 xArgRDX: RDX,
1665 xArgCL: CL,
1666 xArgCS: CS,
1667 xArgDS: DS,
1668 xArgES: ES,
1669 xArgFS: FS,
1670 xArgGS: GS,
1671 xArgSS: SS,
1672 xArgST: F0,
1673 xArgXMM0: X0,
1674 }
1675
1676
1677
1678 var memBytes = [...]int8{
1679 xArgM128: 128 / 8,
1680 xArgM256: 256 / 8,
1681 xArgM16: 16 / 8,
1682 xArgM16and16: (16 + 16) / 8,
1683 xArgM16colon16: (16 + 16) / 8,
1684 xArgM16colon32: (16 + 32) / 8,
1685 xArgM16int: 16 / 8,
1686 xArgM2byte: 2,
1687 xArgM32: 32 / 8,
1688 xArgM32and32: (32 + 32) / 8,
1689 xArgM32fp: 32 / 8,
1690 xArgM32int: 32 / 8,
1691 xArgM64: 64 / 8,
1692 xArgM64fp: 64 / 8,
1693 xArgM64int: 64 / 8,
1694 xArgMm2M64: 64 / 8,
1695 xArgMmM32: 32 / 8,
1696 xArgMmM64: 64 / 8,
1697 xArgMoffs16: 16 / 8,
1698 xArgMoffs32: 32 / 8,
1699 xArgMoffs64: 64 / 8,
1700 xArgMoffs8: 8 / 8,
1701 xArgR32M16: 16 / 8,
1702 xArgR32M8: 8 / 8,
1703 xArgR64M16: 16 / 8,
1704 xArgRM16: 16 / 8,
1705 xArgRM32: 32 / 8,
1706 xArgRM64: 64 / 8,
1707 xArgRM8: 8 / 8,
1708 xArgXmm2M128: 128 / 8,
1709 xArgYmm2M256: 256 / 8,
1710 xArgXmm2M16: 16 / 8,
1711 xArgXmm2M32: 32 / 8,
1712 xArgXmm2M64: 64 / 8,
1713 xArgXmm: 128 / 8,
1714 xArgXmmM128: 128 / 8,
1715 xArgXmmM32: 32 / 8,
1716 xArgXmmM64: 64 / 8,
1717 }
1718
1719
1720 var isCondJmp = [maxOp + 1]bool{
1721 JA: true,
1722 JAE: true,
1723 JB: true,
1724 JBE: true,
1725 JE: true,
1726 JG: true,
1727 JGE: true,
1728 JL: true,
1729 JLE: true,
1730 JNE: true,
1731 JNO: true,
1732 JNP: true,
1733 JNS: true,
1734 JO: true,
1735 JP: true,
1736 JS: true,
1737 }
1738
1739
1740 var isLoop = [maxOp + 1]bool{
1741 LOOP: true,
1742 LOOPE: true,
1743 LOOPNE: true,
1744 JECXZ: true,
1745 JRCXZ: true,
1746 }
1747
View as plain text