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 += 1
416 continue
417 } else {
418 nprefix = pos
419 break ReadPrefixes
420 }
421 case 0xC4:
422 if pos == 0 && pos+2 < len(src) && (mode == 64 || (mode == 32 && src[pos+1]&0xc0 == 0xc0)) {
423 vex = p
424 vexIndex = pos
425 inst.Prefix[pos] = p
426 inst.Prefix[pos+1] = Prefix(src[pos+1])
427 inst.Prefix[pos+2] = Prefix(src[pos+2])
428 pos += 2
429 continue
430 } else {
431 nprefix = pos
432 break ReadPrefixes
433 }
434 }
435
436 if pos >= len(inst.Prefix) {
437 return instPrefix(src[0], mode)
438 }
439
440 inst.Prefix[pos] = p
441 }
442
443
444 if pos < len(src) && mode == 64 && Prefix(src[pos]).IsREX() && vex == 0 {
445 rex = Prefix(src[pos])
446 rexIndex = pos
447 if pos >= len(inst.Prefix) {
448 return instPrefix(src[0], mode)
449 }
450 inst.Prefix[pos] = rex
451 pos++
452 if rex&PrefixREXW != 0 {
453 dataMode = 64
454 if dataSizeIndex >= 0 {
455 inst.Prefix[dataSizeIndex] |= PrefixIgnored
456 }
457 }
458 }
459
460
461
462
463 opshift = 24
464
465
466 var oldPC, prevPC int
467 Decode:
468 for pc := 1; ; {
469 oldPC = prevPC
470 prevPC = pc
471 if trace {
472 println("run", pc)
473 }
474 x := decoder[pc]
475 if decoderCover != nil {
476 decoderCover[pc] = true
477 }
478 pc++
479
480
481 switch decodeOp(x) {
482 case xCondSlashR, xReadSlashR:
483 if haveModrm {
484 return Inst{Len: pos}, errInternal
485 }
486 haveModrm = true
487 if pos >= len(src) {
488 return truncated(src, mode)
489 }
490 modrm = int(src[pos])
491 pos++
492 if opshift >= 0 {
493 inst.Opcode |= uint32(modrm) << uint(opshift)
494 opshift -= 8
495 }
496 mod = modrm >> 6
497 regop = (modrm >> 3) & 07
498 rm = modrm & 07
499 if rex&PrefixREXR != 0 {
500 rexUsed |= PrefixREXR
501 regop |= 8
502 }
503 if addrMode == 16 {
504
505 if mod != 3 {
506 haveMem = true
507 mem = addr16[rm]
508 if rm == 6 && mod == 0 {
509 mem.Base = 0
510 }
511
512
513 if mod == 0 && rm == 6 || mod == 2 {
514 if pos+2 > len(src) {
515 return truncated(src, mode)
516 }
517 mem.Disp = int64(binary.LittleEndian.Uint16(src[pos:]))
518 pos += 2
519 }
520
521
522 if mod == 1 {
523 if pos >= len(src) {
524 return truncated(src, mode)
525 }
526 mem.Disp = int64(int8(src[pos]))
527 pos++
528 }
529 }
530 } else {
531 haveMem = mod != 3
532
533
534
535 if rm == 4 && mod != 3 {
536 haveSIB = true
537 if pos >= len(src) {
538 return truncated(src, mode)
539 }
540 sib = int(src[pos])
541 pos++
542 if opshift >= 0 {
543 inst.Opcode |= uint32(sib) << uint(opshift)
544 opshift -= 8
545 }
546 scale = sib >> 6
547 index = (sib >> 3) & 07
548 base = sib & 07
549 if rex&PrefixREXB != 0 || vex == 0xC4 && inst.Prefix[vexIndex+1]&0x20 == 0 {
550 rexUsed |= PrefixREXB
551 base |= 8
552 }
553 if rex&PrefixREXX != 0 || vex == 0xC4 && inst.Prefix[vexIndex+1]&0x40 == 0 {
554 rexUsed |= PrefixREXX
555 index |= 8
556 }
557
558 mem.Scale = 1 << uint(scale)
559 if index == 4 {
560
561 } else {
562 mem.Index = baseRegForBits(addrMode) + Reg(index)
563 }
564 if base&7 == 5 && mod == 0 {
565
566 } else {
567 mem.Base = baseRegForBits(addrMode) + Reg(base)
568 }
569 } else {
570 if rex&PrefixREXB != 0 {
571 rexUsed |= PrefixREXB
572 rm |= 8
573 }
574 if mod == 0 && rm&7 == 5 || rm&7 == 4 {
575
576 } else if mod != 3 {
577 mem.Base = baseRegForBits(addrMode) + Reg(rm)
578 }
579 }
580
581
582 if mod == 0 && (rm&7 == 5 || haveSIB && base&7 == 5) || mod == 2 {
583 if pos+4 > len(src) {
584 return truncated(src, mode)
585 }
586 dispoff = pos
587 displen = 4
588 mem.Disp = int64(binary.LittleEndian.Uint32(src[pos:]))
589 pos += 4
590 }
591
592
593 if mod == 1 {
594 if pos >= len(src) {
595 return truncated(src, mode)
596 }
597 dispoff = pos
598 displen = 1
599 mem.Disp = int64(int8(src[pos]))
600 pos++
601 }
602
603
604
605 if mode == 64 && mod == 0 && rm&7 == 5 {
606 if addrMode == 32 {
607 mem.Base = EIP
608 } else {
609 mem.Base = RIP
610 }
611 }
612 }
613
614 if segIndex >= 0 {
615 mem.Segment = prefixToSegment(inst.Prefix[segIndex])
616 }
617 }
618
619
620 switch decodeOp(x) {
621 default:
622 println("bad op", x, "at", pc-1, "from", oldPC)
623 return Inst{Len: pos}, errInternal
624
625 case xFail:
626 inst.Op = 0
627 break Decode
628
629 case xMatch:
630 break Decode
631
632 case xJump:
633 pc = int(decoder[pc])
634
635
636
637 case xCondByte:
638 if pos >= len(src) {
639 return truncated(src, mode)
640 }
641 b := src[pos]
642 n := int(decoder[pc])
643 pc++
644 for i := 0; i < n; i++ {
645 xb, xpc := decoder[pc], int(decoder[pc+1])
646 pc += 2
647 if b == byte(xb) {
648 pc = xpc
649 pos++
650 if opshift >= 0 {
651 inst.Opcode |= uint32(b) << uint(opshift)
652 opshift -= 8
653 }
654 continue Decode
655 }
656 }
657
658
659
660
661
662 if decodeOp(decoder[pc]) == xJump {
663 pc = int(decoder[pc+1])
664 }
665 if decodeOp(decoder[pc]) == xFail {
666 pos++
667 }
668
669 case xCondIs64:
670 if mode == 64 {
671 pc = int(decoder[pc+1])
672 } else {
673 pc = int(decoder[pc])
674 }
675
676 case xCondIsMem:
677 mem := haveMem
678 if !haveModrm {
679 if pos >= len(src) {
680 return instPrefix(src[0], mode)
681 }
682 mem = src[pos]>>6 != 3
683 }
684 if mem {
685 pc = int(decoder[pc+1])
686 } else {
687 pc = int(decoder[pc])
688 }
689
690 case xCondDataSize:
691 switch dataMode {
692 case 16:
693 if dataSizeIndex >= 0 {
694 inst.Prefix[dataSizeIndex] |= PrefixImplicit
695 }
696 pc = int(decoder[pc])
697 case 32:
698 if dataSizeIndex >= 0 {
699 inst.Prefix[dataSizeIndex] |= PrefixImplicit
700 }
701 pc = int(decoder[pc+1])
702 case 64:
703 rexUsed |= PrefixREXW
704 pc = int(decoder[pc+2])
705 }
706
707 case xCondAddrSize:
708 switch addrMode {
709 case 16:
710 if addrSizeIndex >= 0 {
711 inst.Prefix[addrSizeIndex] |= PrefixImplicit
712 }
713 pc = int(decoder[pc])
714 case 32:
715 if addrSizeIndex >= 0 {
716 inst.Prefix[addrSizeIndex] |= PrefixImplicit
717 }
718 pc = int(decoder[pc+1])
719 case 64:
720 pc = int(decoder[pc+2])
721 }
722
723 case xCondPrefix:
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
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 n := int(decoder[pc])
794 pc++
795 sawF3 := false
796 for j := 0; j < n; j++ {
797 prefix := Prefix(decoder[pc+2*j])
798 if prefix.IsREX() {
799 rexUsed |= prefix
800 if rex&prefix == prefix {
801 pc = int(decoder[pc+2*j+1])
802 continue Decode
803 }
804 continue
805 }
806 ok := false
807 if prefix == 0 {
808 ok = true
809 } else if prefix.IsREX() {
810 rexUsed |= prefix
811 if rex&prefix == prefix {
812 ok = true
813 }
814 } else if prefix == 0xC5 || prefix == 0xC4 {
815 if vex == prefix {
816 ok = true
817 }
818 } else if vex != 0 && (prefix == 0x0F || prefix == 0x0F38 || prefix == 0x0F3A ||
819 prefix == 0x66 || prefix == 0xF2 || prefix == 0xF3) {
820 var vexM, vexP Prefix
821 if vex == 0xC5 {
822 vexM = 1
823 vexP = inst.Prefix[vexIndex+1]
824 } else {
825 vexM = inst.Prefix[vexIndex+1]
826 vexP = inst.Prefix[vexIndex+2]
827 }
828 switch prefix {
829 case 0x66:
830 ok = vexP&3 == 1
831 case 0xF3:
832 ok = vexP&3 == 2
833 case 0xF2:
834 ok = vexP&3 == 3
835 case 0x0F:
836 ok = vexM&3 == 1
837 case 0x0F38:
838 ok = vexM&3 == 2
839 case 0x0F3A:
840 ok = vexM&3 == 3
841 }
842 } else {
843 if prefix == 0xF3 {
844 sawF3 = true
845 }
846 switch prefix {
847 case PrefixLOCK:
848 if lockIndex >= 0 {
849 inst.Prefix[lockIndex] |= PrefixImplicit
850 ok = true
851 }
852 case PrefixREP, PrefixREPN:
853 if repIndex >= 0 && inst.Prefix[repIndex]&0xFF == prefix {
854 inst.Prefix[repIndex] |= PrefixImplicit
855 ok = true
856 }
857 if gnuCompat && !ok && prefix == 0xF3 && repIndex >= 0 && (j+1 >= n || decoder[pc+2*(j+1)] != 0xF2) {
858
859 for i := repIndex - 1; i >= 0; i-- {
860 if inst.Prefix[i]&0xFF == prefix {
861 inst.Prefix[i] |= PrefixImplicit
862 ok = true
863 }
864 }
865 }
866 if gnuCompat && !ok && prefix == 0xF2 && repIndex >= 0 && !sawF3 && inst.Prefix[repIndex]&0xFF == 0xF3 {
867
868 for i := repIndex - 1; i >= 0; i-- {
869 if inst.Prefix[i]&0xFF == prefix {
870 inst.Prefix[i] |= PrefixImplicit
871 ok = true
872 }
873 }
874 }
875 case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:
876 if segIndex >= 0 && inst.Prefix[segIndex]&0xFF == prefix {
877 inst.Prefix[segIndex] |= PrefixImplicit
878 ok = true
879 }
880 case PrefixDataSize:
881
882
883
884
885
886
887
888
889 if repIndex >= 0 && !gnuCompat {
890 inst.Op = 0
891 break Decode
892 }
893 if dataSizeIndex >= 0 {
894 inst.Prefix[dataSizeIndex] |= PrefixImplicit
895 ok = true
896 }
897 case PrefixAddrSize:
898 if addrSizeIndex >= 0 {
899 inst.Prefix[addrSizeIndex] |= PrefixImplicit
900 ok = true
901 }
902 }
903 }
904 if ok {
905 pc = int(decoder[pc+2*j+1])
906 continue Decode
907 }
908 }
909 inst.Op = 0
910 break Decode
911
912 case xCondSlashR:
913 pc = int(decoder[pc+regop&7])
914
915
916
917 case xReadSlashR:
918
919
920 case xReadIb:
921 if pos >= len(src) {
922 return truncated(src, mode)
923 }
924 imm8 = int8(src[pos])
925 pos++
926
927 case xReadIw:
928 if pos+2 > len(src) {
929 return truncated(src, mode)
930 }
931 imm = int64(binary.LittleEndian.Uint16(src[pos:]))
932 pos += 2
933
934 case xReadId:
935 if pos+4 > len(src) {
936 return truncated(src, mode)
937 }
938 imm = int64(binary.LittleEndian.Uint32(src[pos:]))
939 pos += 4
940
941 case xReadIo:
942 if pos+8 > len(src) {
943 return truncated(src, mode)
944 }
945 imm = int64(binary.LittleEndian.Uint64(src[pos:]))
946 pos += 8
947
948 case xReadCb:
949 if pos >= len(src) {
950 return truncated(src, mode)
951 }
952 immcpos = pos
953 immc = int64(src[pos])
954 pos++
955
956 case xReadCw:
957 if pos+2 > len(src) {
958 return truncated(src, mode)
959 }
960 immcpos = pos
961 immc = int64(binary.LittleEndian.Uint16(src[pos:]))
962 pos += 2
963
964 case xReadCm:
965 immcpos = pos
966 if addrMode == 16 {
967 if pos+2 > len(src) {
968 return truncated(src, mode)
969 }
970 immc = int64(binary.LittleEndian.Uint16(src[pos:]))
971 pos += 2
972 } else if addrMode == 32 {
973 if pos+4 > len(src) {
974 return truncated(src, mode)
975 }
976 immc = int64(binary.LittleEndian.Uint32(src[pos:]))
977 pos += 4
978 } else {
979 if pos+8 > len(src) {
980 return truncated(src, mode)
981 }
982 immc = int64(binary.LittleEndian.Uint64(src[pos:]))
983 pos += 8
984 }
985 case xReadCd:
986 immcpos = pos
987 if pos+4 > len(src) {
988 return truncated(src, mode)
989 }
990 immc = int64(binary.LittleEndian.Uint32(src[pos:]))
991 pos += 4
992
993 case xReadCp:
994 immcpos = pos
995 if pos+6 > len(src) {
996 return truncated(src, mode)
997 }
998 w := binary.LittleEndian.Uint32(src[pos:])
999 w2 := binary.LittleEndian.Uint16(src[pos+4:])
1000 immc = int64(w2)<<32 | int64(w)
1001 pos += 6
1002
1003
1004
1005 case xSetOp:
1006 inst.Op = Op(decoder[pc])
1007 pc++
1008
1009 case xArg1,
1010 xArg3,
1011 xArgAL,
1012 xArgAX,
1013 xArgCL,
1014 xArgCS,
1015 xArgDS,
1016 xArgDX,
1017 xArgEAX,
1018 xArgEDX,
1019 xArgES,
1020 xArgFS,
1021 xArgGS,
1022 xArgRAX,
1023 xArgRDX,
1024 xArgSS,
1025 xArgST,
1026 xArgXMM0:
1027 inst.Args[narg] = fixedArg[x]
1028 narg++
1029
1030 case xArgImm8:
1031 inst.Args[narg] = Imm(imm8)
1032 narg++
1033
1034 case xArgImm8u:
1035 inst.Args[narg] = Imm(uint8(imm8))
1036 narg++
1037
1038 case xArgImm16:
1039 inst.Args[narg] = Imm(int16(imm))
1040 narg++
1041
1042 case xArgImm16u:
1043 inst.Args[narg] = Imm(uint16(imm))
1044 narg++
1045
1046 case xArgImm32:
1047 inst.Args[narg] = Imm(int32(imm))
1048 narg++
1049
1050 case xArgImm64:
1051 inst.Args[narg] = Imm(imm)
1052 narg++
1053
1054 case xArgM,
1055 xArgM128,
1056 xArgM256,
1057 xArgM1428byte,
1058 xArgM16,
1059 xArgM16and16,
1060 xArgM16and32,
1061 xArgM16and64,
1062 xArgM16colon16,
1063 xArgM16colon32,
1064 xArgM16colon64,
1065 xArgM16int,
1066 xArgM2byte,
1067 xArgM32,
1068 xArgM32and32,
1069 xArgM32fp,
1070 xArgM32int,
1071 xArgM512byte,
1072 xArgM64,
1073 xArgM64fp,
1074 xArgM64int,
1075 xArgM8,
1076 xArgM80bcd,
1077 xArgM80dec,
1078 xArgM80fp,
1079 xArgM94108byte,
1080 xArgMem:
1081 if !haveMem {
1082 inst.Op = 0
1083 break Decode
1084 }
1085 inst.Args[narg] = mem
1086 inst.MemBytes = int(memBytes[decodeOp(x)])
1087 if mem.Base == RIP {
1088 inst.PCRel = displen
1089 inst.PCRelOff = dispoff
1090 }
1091 narg++
1092
1093 case xArgPtr16colon16:
1094 inst.Args[narg] = Imm(immc >> 16)
1095 inst.Args[narg+1] = Imm(immc & (1<<16 - 1))
1096 narg += 2
1097
1098 case xArgPtr16colon32:
1099 inst.Args[narg] = Imm(immc >> 32)
1100 inst.Args[narg+1] = Imm(immc & (1<<32 - 1))
1101 narg += 2
1102
1103 case xArgMoffs8, xArgMoffs16, xArgMoffs32, xArgMoffs64:
1104
1105 mem = Mem{Disp: int64(immc)}
1106 if segIndex >= 0 {
1107 mem.Segment = prefixToSegment(inst.Prefix[segIndex])
1108 inst.Prefix[segIndex] |= PrefixImplicit
1109 }
1110 inst.Args[narg] = mem
1111 inst.MemBytes = int(memBytes[decodeOp(x)])
1112 if mem.Base == RIP {
1113 inst.PCRel = displen
1114 inst.PCRelOff = dispoff
1115 }
1116 narg++
1117
1118 case xArgYmm1:
1119 base := baseReg[x]
1120 index := Reg(regop)
1121 if inst.Prefix[vexIndex+1]&0x80 == 0 {
1122 index += 8
1123 }
1124 inst.Args[narg] = base + index
1125 narg++
1126
1127 case xArgR8, xArgR16, xArgR32, xArgR64, xArgXmm, xArgXmm1, xArgDR0dashDR7:
1128 base := baseReg[x]
1129 index := Reg(regop)
1130 if rex != 0 && base == AL && index >= 4 {
1131 rexUsed |= PrefixREX
1132 index -= 4
1133 base = SPB
1134 }
1135 inst.Args[narg] = base + index
1136 narg++
1137
1138 case xArgMm, xArgMm1, xArgTR0dashTR7:
1139 inst.Args[narg] = baseReg[x] + Reg(regop&7)
1140 narg++
1141
1142 case xArgCR0dashCR7:
1143
1144
1145
1146
1147 if lockIndex >= 0 {
1148 inst.Prefix[lockIndex] |= PrefixImplicit
1149 regop += 8
1150 }
1151 inst.Args[narg] = CR0 + Reg(regop)
1152 narg++
1153
1154 case xArgSreg:
1155 regop &= 7
1156 if regop >= 6 {
1157 inst.Op = 0
1158 break Decode
1159 }
1160 inst.Args[narg] = ES + Reg(regop)
1161 narg++
1162
1163 case xArgRmf16, xArgRmf32, xArgRmf64:
1164 base := baseReg[x]
1165 index := Reg(modrm & 07)
1166 if rex&PrefixREXB != 0 {
1167 rexUsed |= PrefixREXB
1168 index += 8
1169 }
1170 inst.Args[narg] = base + index
1171 narg++
1172
1173 case xArgR8op, xArgR16op, xArgR32op, xArgR64op, xArgSTi:
1174 n := inst.Opcode >> uint(opshift+8) & 07
1175 base := baseReg[x]
1176 index := Reg(n)
1177 if rex&PrefixREXB != 0 && decodeOp(x) != xArgSTi {
1178 rexUsed |= PrefixREXB
1179 index += 8
1180 }
1181 if rex != 0 && base == AL && index >= 4 {
1182 rexUsed |= PrefixREX
1183 index -= 4
1184 base = SPB
1185 }
1186 inst.Args[narg] = base + index
1187 narg++
1188 case xArgRM8, xArgRM16, xArgRM32, xArgRM64, xArgR32M16, xArgR32M8, xArgR64M16,
1189 xArgMmM32, xArgMmM64, xArgMm2M64,
1190 xArgXmm2M16, xArgXmm2M32, xArgXmm2M64, xArgXmmM64, xArgXmmM128, xArgXmmM32, xArgXmm2M128,
1191 xArgYmm2M256:
1192 if haveMem {
1193 inst.Args[narg] = mem
1194 inst.MemBytes = int(memBytes[decodeOp(x)])
1195 if mem.Base == RIP {
1196 inst.PCRel = displen
1197 inst.PCRelOff = dispoff
1198 }
1199 } else {
1200 base := baseReg[x]
1201 index := Reg(rm)
1202 switch decodeOp(x) {
1203 case xArgMmM32, xArgMmM64, xArgMm2M64:
1204
1205 index &= 7
1206 case xArgRM8:
1207 if rex != 0 && index >= 4 {
1208 rexUsed |= PrefixREX
1209 index -= 4
1210 base = SPB
1211 }
1212 case xArgYmm2M256:
1213 if vex == 0xC4 && inst.Prefix[vexIndex+1]&0x40 == 0x40 {
1214 index += 8
1215 }
1216 }
1217 inst.Args[narg] = base + index
1218 }
1219 narg++
1220
1221 case xArgMm2:
1222 if haveMem {
1223 inst.Op = 0
1224 break Decode
1225 }
1226 inst.Args[narg] = baseReg[x] + Reg(rm&7)
1227 narg++
1228
1229 case xArgXmm2:
1230 if haveMem {
1231 inst.Op = 0
1232 break Decode
1233 }
1234 inst.Args[narg] = baseReg[x] + Reg(rm)
1235 narg++
1236
1237 case xArgRel8:
1238 inst.PCRelOff = immcpos
1239 inst.PCRel = 1
1240 inst.Args[narg] = Rel(int8(immc))
1241 narg++
1242
1243 case xArgRel16:
1244 inst.PCRelOff = immcpos
1245 inst.PCRel = 2
1246 inst.Args[narg] = Rel(int16(immc))
1247 narg++
1248
1249 case xArgRel32:
1250 inst.PCRelOff = immcpos
1251 inst.PCRel = 4
1252 inst.Args[narg] = Rel(int32(immc))
1253 narg++
1254 }
1255 }
1256
1257 if inst.Op == 0 {
1258
1259 if nprefix > 0 {
1260 return instPrefix(src[0], mode)
1261 }
1262 return Inst{Len: pos}, ErrUnrecognized
1263 }
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273 if inst.Op == XCHG && inst.Opcode>>24 == 0x90 {
1274 if inst.Args[0] == RAX || inst.Args[0] == EAX || inst.Args[0] == AX {
1275 inst.Op = NOP
1276 if dataSizeIndex >= 0 {
1277 inst.Prefix[dataSizeIndex] &^= PrefixImplicit
1278 }
1279 inst.Args[0] = nil
1280 inst.Args[1] = nil
1281 }
1282 if repIndex >= 0 && inst.Prefix[repIndex] == 0xF3 {
1283 inst.Prefix[repIndex] |= PrefixImplicit
1284 inst.Op = PAUSE
1285 inst.Args[0] = nil
1286 inst.Args[1] = nil
1287 } else if gnuCompat {
1288 for i := nprefix - 1; i >= 0; i-- {
1289 if inst.Prefix[i]&0xFF == 0xF3 {
1290 inst.Prefix[i] |= PrefixImplicit
1291 inst.Op = PAUSE
1292 inst.Args[0] = nil
1293 inst.Args[1] = nil
1294 break
1295 }
1296 }
1297 }
1298 }
1299
1300
1301
1302 defaultSeg := func() Reg {
1303 if segIndex >= 0 {
1304 inst.Prefix[segIndex] |= PrefixImplicit
1305 return prefixToSegment(inst.Prefix[segIndex])
1306 }
1307 return DS
1308 }
1309
1310
1311
1312
1313
1314
1315
1316 usedAddrSize := false
1317 switch inst.Op {
1318 case INSB, INSW, INSD:
1319 inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
1320 inst.Args[1] = DX
1321 usedAddrSize = true
1322
1323 case OUTSB, OUTSW, OUTSD:
1324 inst.Args[0] = DX
1325 inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
1326 usedAddrSize = true
1327
1328 case MOVSB, MOVSW, MOVSD, MOVSQ:
1329 inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
1330 inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
1331 usedAddrSize = true
1332
1333 case CMPSB, CMPSW, CMPSD, CMPSQ:
1334 inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
1335 inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
1336 usedAddrSize = true
1337
1338 case LODSB, LODSW, LODSD, LODSQ:
1339 switch inst.Op {
1340 case LODSB:
1341 inst.Args[0] = AL
1342 case LODSW:
1343 inst.Args[0] = AX
1344 case LODSD:
1345 inst.Args[0] = EAX
1346 case LODSQ:
1347 inst.Args[0] = RAX
1348 }
1349 inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}
1350 usedAddrSize = true
1351
1352 case STOSB, STOSW, STOSD, STOSQ:
1353 inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
1354 switch inst.Op {
1355 case STOSB:
1356 inst.Args[1] = AL
1357 case STOSW:
1358 inst.Args[1] = AX
1359 case STOSD:
1360 inst.Args[1] = EAX
1361 case STOSQ:
1362 inst.Args[1] = RAX
1363 }
1364 usedAddrSize = true
1365
1366 case SCASB, SCASW, SCASD, SCASQ:
1367 inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}
1368 switch inst.Op {
1369 case SCASB:
1370 inst.Args[0] = AL
1371 case SCASW:
1372 inst.Args[0] = AX
1373 case SCASD:
1374 inst.Args[0] = EAX
1375 case SCASQ:
1376 inst.Args[0] = RAX
1377 }
1378 usedAddrSize = true
1379
1380 case XLATB:
1381 inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + BX - AX}
1382 usedAddrSize = true
1383 }
1384
1385
1386
1387
1388 if haveMem || usedAddrSize {
1389 if addrSizeIndex >= 0 {
1390 inst.Prefix[addrSizeIndex] |= PrefixImplicit
1391 }
1392 }
1393
1394
1395
1396
1397 if haveMem {
1398 if segIndex >= 0 {
1399 inst.Prefix[segIndex] |= PrefixImplicit
1400 }
1401 }
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411 if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {
1412 PredictLoop:
1413 for i := nprefix - 1; i >= 0; i-- {
1414 p := inst.Prefix[i]
1415 switch p & 0xFF {
1416 case PrefixCS:
1417 inst.Prefix[i] = PrefixPN
1418 break PredictLoop
1419 case PrefixDS:
1420 inst.Prefix[i] = PrefixPT
1421 break PredictLoop
1422 }
1423 }
1424 }
1425
1426
1427
1428
1429
1430
1431
1432
1433 if isCondJmp[inst.Op] || inst.Op == JMP || inst.Op == CALL || inst.Op == RET {
1434 for i := nprefix - 1; i >= 0; i-- {
1435 p := inst.Prefix[i]
1436 if p&^PrefixIgnored == PrefixREPN {
1437 inst.Prefix[i] = PrefixBND
1438 break
1439 }
1440 }
1441 }
1442
1443
1444
1445
1446
1447
1448 hasLock := false
1449 if lockIndex >= 0 && inst.Prefix[lockIndex]&PrefixImplicit == 0 {
1450 switch inst.Op {
1451
1452 case ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCHG8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, XCHG:
1453 if isMem(inst.Args[0]) {
1454 hasLock = true
1455 break
1456 }
1457 fallthrough
1458 default:
1459 inst.Prefix[lockIndex] |= PrefixInvalid
1460 }
1461 }
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471 if isMem(inst.Args[0]) {
1472 if inst.Op == XCHG {
1473 hasLock = true
1474 }
1475
1476 for i := len(inst.Prefix) - 1; i >= 0; i-- {
1477 p := inst.Prefix[i] &^ PrefixIgnored
1478 switch p {
1479 case PrefixREPN:
1480 if hasLock {
1481 inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXACQUIRE
1482 }
1483
1484 case PrefixREP:
1485 if hasLock {
1486 inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE
1487 }
1488
1489 if inst.Op == MOV {
1490 op := (inst.Opcode >> 24) &^ 1
1491 if op == 0x88 || op == 0xC6 {
1492 inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE
1493 }
1494 }
1495 }
1496 }
1497 }
1498
1499
1500 if repIndex >= 0 {
1501 switch inst.Prefix[repIndex] {
1502 case PrefixREP, PrefixREPN:
1503 switch inst.Op {
1504
1505
1506
1507
1508 case INSB, INSW, INSD,
1509 MOVSB, MOVSW, MOVSD, MOVSQ,
1510 OUTSB, OUTSW, OUTSD,
1511 LODSB, LODSW, LODSD, LODSQ,
1512 CMPSB, CMPSW, CMPSD, CMPSQ,
1513 SCASB, SCASW, SCASD, SCASQ,
1514 STOSB, STOSW, STOSD, STOSQ:
1515
1516 default:
1517 inst.Prefix[repIndex] |= PrefixIgnored
1518 }
1519 }
1520 }
1521
1522
1523 if rexIndex >= 0 {
1524 if rexUsed != 0 {
1525 rexUsed |= PrefixREX
1526 }
1527 if rex&^rexUsed == 0 {
1528 inst.Prefix[rexIndex] |= PrefixImplicit
1529 }
1530 }
1531
1532 inst.DataSize = dataMode
1533 inst.AddrSize = addrMode
1534 inst.Mode = mode
1535 inst.Len = pos
1536 return inst, nil
1537 }
1538
1539 var errInternal = errors.New("internal error")
1540
1541
1542 var addr16 = [8]Mem{
1543 {Base: BX, Scale: 1, Index: SI},
1544 {Base: BX, Scale: 1, Index: DI},
1545 {Base: BP, Scale: 1, Index: SI},
1546 {Base: BP, Scale: 1, Index: DI},
1547 {Base: SI},
1548 {Base: DI},
1549 {Base: BP},
1550 {Base: BX},
1551 }
1552
1553
1554 func baseRegForBits(bits int) Reg {
1555 switch bits {
1556 case 8:
1557 return AL
1558 case 16:
1559 return AX
1560 case 32:
1561 return EAX
1562 case 64:
1563 return RAX
1564 }
1565 return 0
1566 }
1567
1568
1569
1570 var baseReg = [...]Reg{
1571 xArgDR0dashDR7: DR0,
1572 xArgMm1: M0,
1573 xArgMm2: M0,
1574 xArgMm2M64: M0,
1575 xArgMm: M0,
1576 xArgMmM32: M0,
1577 xArgMmM64: M0,
1578 xArgR16: AX,
1579 xArgR16op: AX,
1580 xArgR32: EAX,
1581 xArgR32M16: EAX,
1582 xArgR32M8: EAX,
1583 xArgR32op: EAX,
1584 xArgR64: RAX,
1585 xArgR64M16: RAX,
1586 xArgR64op: RAX,
1587 xArgR8: AL,
1588 xArgR8op: AL,
1589 xArgRM16: AX,
1590 xArgRM32: EAX,
1591 xArgRM64: RAX,
1592 xArgRM8: AL,
1593 xArgRmf16: AX,
1594 xArgRmf32: EAX,
1595 xArgRmf64: RAX,
1596 xArgSTi: F0,
1597 xArgTR0dashTR7: TR0,
1598 xArgXmm1: X0,
1599 xArgYmm1: X0,
1600 xArgXmm2: X0,
1601 xArgXmm2M128: X0,
1602 xArgYmm2M256: X0,
1603 xArgXmm2M16: X0,
1604 xArgXmm2M32: X0,
1605 xArgXmm2M64: X0,
1606 xArgXmm: X0,
1607 xArgXmmM128: X0,
1608 xArgXmmM32: X0,
1609 xArgXmmM64: X0,
1610 }
1611
1612
1613
1614 func prefixToSegment(p Prefix) Reg {
1615 switch p &^ PrefixImplicit {
1616 case PrefixCS:
1617 return CS
1618 case PrefixDS:
1619 return DS
1620 case PrefixES:
1621 return ES
1622 case PrefixFS:
1623 return FS
1624 case PrefixGS:
1625 return GS
1626 case PrefixSS:
1627 return SS
1628 }
1629 return 0
1630 }
1631
1632
1633 var fixedArg = [...]Arg{
1634 xArg1: Imm(1),
1635 xArg3: Imm(3),
1636 xArgAL: AL,
1637 xArgAX: AX,
1638 xArgDX: DX,
1639 xArgEAX: EAX,
1640 xArgEDX: EDX,
1641 xArgRAX: RAX,
1642 xArgRDX: RDX,
1643 xArgCL: CL,
1644 xArgCS: CS,
1645 xArgDS: DS,
1646 xArgES: ES,
1647 xArgFS: FS,
1648 xArgGS: GS,
1649 xArgSS: SS,
1650 xArgST: F0,
1651 xArgXMM0: X0,
1652 }
1653
1654
1655
1656 var memBytes = [...]int8{
1657 xArgM128: 128 / 8,
1658 xArgM256: 256 / 8,
1659 xArgM16: 16 / 8,
1660 xArgM16and16: (16 + 16) / 8,
1661 xArgM16colon16: (16 + 16) / 8,
1662 xArgM16colon32: (16 + 32) / 8,
1663 xArgM16int: 16 / 8,
1664 xArgM2byte: 2,
1665 xArgM32: 32 / 8,
1666 xArgM32and32: (32 + 32) / 8,
1667 xArgM32fp: 32 / 8,
1668 xArgM32int: 32 / 8,
1669 xArgM64: 64 / 8,
1670 xArgM64fp: 64 / 8,
1671 xArgM64int: 64 / 8,
1672 xArgMm2M64: 64 / 8,
1673 xArgMmM32: 32 / 8,
1674 xArgMmM64: 64 / 8,
1675 xArgMoffs16: 16 / 8,
1676 xArgMoffs32: 32 / 8,
1677 xArgMoffs64: 64 / 8,
1678 xArgMoffs8: 8 / 8,
1679 xArgR32M16: 16 / 8,
1680 xArgR32M8: 8 / 8,
1681 xArgR64M16: 16 / 8,
1682 xArgRM16: 16 / 8,
1683 xArgRM32: 32 / 8,
1684 xArgRM64: 64 / 8,
1685 xArgRM8: 8 / 8,
1686 xArgXmm2M128: 128 / 8,
1687 xArgYmm2M256: 256 / 8,
1688 xArgXmm2M16: 16 / 8,
1689 xArgXmm2M32: 32 / 8,
1690 xArgXmm2M64: 64 / 8,
1691 xArgXmm: 128 / 8,
1692 xArgXmmM128: 128 / 8,
1693 xArgXmmM32: 32 / 8,
1694 xArgXmmM64: 64 / 8,
1695 }
1696
1697
1698 var isCondJmp = [maxOp + 1]bool{
1699 JA: true,
1700 JAE: true,
1701 JB: true,
1702 JBE: true,
1703 JE: true,
1704 JG: true,
1705 JGE: true,
1706 JL: true,
1707 JLE: true,
1708 JNE: true,
1709 JNO: true,
1710 JNP: true,
1711 JNS: true,
1712 JO: true,
1713 JP: true,
1714 JS: true,
1715 }
1716
1717
1718 var isLoop = [maxOp + 1]bool{
1719 LOOP: true,
1720 LOOPE: true,
1721 LOOPNE: true,
1722 JECXZ: true,
1723 JRCXZ: true,
1724 }
1725
View as plain text