1
2
3
4
5 package x86asm
6
7 import (
8 "bytes"
9 "strings"
10 "testing"
11 )
12
13 func TestXed32Manual(t *testing.T) { testXed32(t, hexCases(t, xedManualTests)) }
14 func TestXed32Testdata(t *testing.T) { testXed32(t, concat(basicPrefixes, testdataCases(t))) }
15 func TestXed32ModRM(t *testing.T) { testXed32(t, concat(basicPrefixes, enumModRM)) }
16 func TestXed32OneByte(t *testing.T) { testBasic(t, testXed32) }
17 func TestXed320F(t *testing.T) { testBasic(t, testXed32, 0x0F) }
18 func TestXed320F38(t *testing.T) { testBasic(t, testXed32, 0x0F, 0x38) }
19 func TestXed320F3A(t *testing.T) { testBasic(t, testXed32, 0x0F, 0x3A) }
20 func TestXed32Prefix(t *testing.T) { testPrefix(t, testXed32) }
21
22 func TestXed64Manual(t *testing.T) { testXed64(t, hexCases(t, xedManualTests)) }
23 func TestXed64Testdata(t *testing.T) { testXed64(t, concat(basicPrefixes, testdataCases(t))) }
24 func TestXed64ModRM(t *testing.T) { testXed64(t, concat(basicPrefixes, enumModRM)) }
25 func TestXed64OneByte(t *testing.T) { testBasic(t, testXed64) }
26 func TestXed640F(t *testing.T) { testBasic(t, testXed64, 0x0F) }
27 func TestXed640F38(t *testing.T) { testBasic(t, testXed64, 0x0F, 0x38) }
28 func TestXed640F3A(t *testing.T) { testBasic(t, testXed64, 0x0F, 0x3A) }
29 func TestXed64Prefix(t *testing.T) { testPrefix(t, testXed64) }
30
31 func TestXed64REXTestdata(t *testing.T) {
32 testXed64(t, filter(concat3(basicPrefixes, rexPrefixes, testdataCases(t)), isValidREX))
33 }
34 func TestXed64REXModRM(t *testing.T) { testXed64(t, concat3(basicPrefixes, rexPrefixes, enumModRM)) }
35 func TestXed64REXOneByte(t *testing.T) { testBasicREX(t, testXed64) }
36 func TestXed64REX0F(t *testing.T) { testBasicREX(t, testXed64, 0x0F) }
37 func TestXed64REX0F38(t *testing.T) { testBasicREX(t, testXed64, 0x0F, 0x38) }
38 func TestXed64REX0F3A(t *testing.T) { testBasicREX(t, testXed64, 0x0F, 0x3A) }
39 func TestXed64REXPrefix(t *testing.T) { testPrefixREX(t, testXed64) }
40
41
42
43
44 var xedManualTests = `
45 6690
46 `
47
48
49
50 func allowedMismatchXed(text string, size int, inst *Inst, dec ExtInst) bool {
51 if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "GENERAL_ERROR", "INSTR_TOO_LONG", "BAD_LOCK_PREFIX") {
52 return true
53 }
54
55 if contains(dec.text, "BAD_LOCK_PREFIX") && countExactPrefix(inst, PrefixLOCK|PrefixInvalid) > 0 {
56 return true
57 }
58
59 if contains(dec.text, "BAD_LOCK_PREFIX", "GENERAL_ERROR") && countExactPrefix(inst, PrefixLOCK|PrefixImplicit) > 0 {
60 return true
61 }
62
63 if text == "lock" && size == 1 && contains(dec.text, "BAD_LOCK_PREFIX") {
64 return true
65 }
66
67
68 if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, unsupported...) {
69 return true
70 }
71
72
73 if contains(text, xedUnsupported...) && contains(dec.text, "ERROR") {
74 return true
75 }
76
77 if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "shl ") && (inst.Opcode>>16)&0xEC38 == 0xC030 {
78 return true
79 }
80
81
82
83
84 if (contains(text, "error:") || isPrefix(text) && size == 1) && hasByte(dec.enc[:dec.nenc], 0x82, 0xC0, 0xC1, 0xD0, 0xD1, 0xD2, 0xD3, 0xF6, 0xF7) {
85 return true
86 }
87
88
89 if (text == "rep" && dec.enc[0] == 0xF3 || (text == "repn" || text == "repne") && dec.enc[0] == 0xF2) && (!contains(dec.text, "ins", "outs", "movs", "lods", "cmps", "scas") || contains(dec.text, "xmm")) {
90 return true
91 }
92
93
94
95 if contains(text, "rdrand") && contains(dec.text, "vmptrld", "vmxon", "vmclear") {
96 return true
97 }
98
99
100
101
102 if contains(text, "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase") && contains(dec.text, "ERROR") {
103 return true
104 }
105
106
107
108 if contains(text, "swapgs") {
109 return true
110 }
111
112
113
114 if contains(text, "cr1", "cr5", "cr6", "cr7", "tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7") && contains(dec.text, "ERROR") {
115 return true
116 }
117
118
119
120
121 if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "nop ") && (inst.Opcode>>8)&0xFFFF38 != 0x0F1F00 {
122 return true
123 }
124
125
126 if contains(text, "clflush") && contains(dec.text, "clflushopt") {
127 return true
128 }
129
130
131
132
133
134
135 if text == dec.text && size > dec.nenc && contains(text, " cr", " dr", " tr") {
136 return true
137 }
138
139
140 if contains(dec.text, "fence") && hasByte(dec.enc[:dec.nenc], 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF) {
141 return true
142 }
143
144
145 if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fxch ") && hasByte(dec.enc[:dec.nenc], 0xDD, 0xDF) {
146 return true
147 }
148
149
150 if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fcom ") && hasByte(dec.enc[:dec.nenc], 0xD8, 0xDC) {
151 return true
152 }
153
154
155 if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fcomp ") && hasByte(dec.enc[:dec.nenc], 0xDC, 0xDE) {
156 return true
157 }
158
159
160 if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "fstp ") && hasByte(dec.enc[:dec.nenc], 0xDF) {
161 return true
162 }
163
164 return false
165 }
166
167 func countExactPrefix(inst *Inst, target Prefix) int {
168 n := 0
169 for _, p := range inst.Prefix {
170 if p == target {
171 n++
172 }
173 }
174 return n
175 }
176
177 func hasByte(src []byte, target ...byte) bool {
178 for _, b := range target {
179 if bytes.IndexByte(src, b) >= 0 {
180 return true
181 }
182 }
183 return false
184 }
185
186
187 var xedUnsupported = strings.Fields(`
188 xrstor
189 xsave
190 xsave
191 ud1
192 xgetbv
193 xsetbv
194 fxsave
195 fxrstor
196 clflush
197 lfence
198 mfence
199 sfence
200 rsqrtps
201 rcpps
202 emms
203 ldmxcsr
204 stmxcsr
205 movhpd
206 movnti
207 rdrand
208 movbe
209 movlpd
210 sysret
211 `)
212
View as plain text