blob: 6f72605440c9e19cf6bb890e33504fe8a0153652 [file] [log] [blame]
Russ Coxc75f81f2014-09-30 12:28:24 -04001// Copyright 2014 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package x86asm
6
7import (
8 "bytes"
9 "strings"
10 "testing"
11)
12
13func TestObjdump32Manual(t *testing.T) { testObjdump32(t, hexCases(t, objdumpManualTests)) }
14func TestObjdump32Testdata(t *testing.T) { testObjdump32(t, concat(basicPrefixes, testdataCases(t))) }
15func TestObjdump32ModRM(t *testing.T) { testObjdump32(t, concat(basicPrefixes, enumModRM)) }
16func TestObjdump32OneByte(t *testing.T) { testBasic(t, testObjdump32) }
17func TestObjdump320F(t *testing.T) { testBasic(t, testObjdump32, 0x0F) }
18func TestObjdump320F38(t *testing.T) { testBasic(t, testObjdump32, 0x0F, 0x38) }
19func TestObjdump320F3A(t *testing.T) { testBasic(t, testObjdump32, 0x0F, 0x3A) }
20func TestObjdump32Prefix(t *testing.T) { testPrefix(t, testObjdump32) }
21
22func TestObjdump64Manual(t *testing.T) { testObjdump64(t, hexCases(t, objdumpManualTests)) }
23func TestObjdump64Testdata(t *testing.T) { testObjdump64(t, concat(basicPrefixes, testdataCases(t))) }
24func TestObjdump64ModRM(t *testing.T) { testObjdump64(t, concat(basicPrefixes, enumModRM)) }
25func TestObjdump64OneByte(t *testing.T) { testBasic(t, testObjdump64) }
26func TestObjdump640F(t *testing.T) { testBasic(t, testObjdump64, 0x0F) }
27func TestObjdump640F38(t *testing.T) { testBasic(t, testObjdump64, 0x0F, 0x38) }
28func TestObjdump640F3A(t *testing.T) { testBasic(t, testObjdump64, 0x0F, 0x3A) }
29func TestObjdump64Prefix(t *testing.T) { testPrefix(t, testObjdump64) }
30
31func TestObjdump64REXTestdata(t *testing.T) {
32 testObjdump64(t, filter(concat3(basicPrefixes, rexPrefixes, testdataCases(t)), isValidREX))
33}
34func TestObjdump64REXModRM(t *testing.T) {
35 testObjdump64(t, concat3(basicPrefixes, rexPrefixes, enumModRM))
36}
37func TestObjdump64REXOneByte(t *testing.T) { testBasicREX(t, testObjdump64) }
38func TestObjdump64REX0F(t *testing.T) { testBasicREX(t, testObjdump64, 0x0F) }
39func TestObjdump64REX0F38(t *testing.T) { testBasicREX(t, testObjdump64, 0x0F, 0x38) }
40func TestObjdump64REX0F3A(t *testing.T) { testBasicREX(t, testObjdump64, 0x0F, 0x3A) }
41func TestObjdump64REXPrefix(t *testing.T) { testPrefixREX(t, testObjdump64) }
42
43// objdumpManualTests holds test cases that will be run by TestObjdumpManual.
44// If you are debugging a few cases that turned up in a longer run, it can be useful
45// to list them here and then use -run=ObjdumpManual, particularly with tracing enabled.
46var objdumpManualTests = `
47F390
48`
49
50// allowedMismatchObjdump reports whether the mismatch between text and dec
51// should be allowed by the test.
52func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool {
53 if size == 15 && dec.nenc == 15 && contains(text, "truncated") && contains(dec.text, "(bad)") {
54 return true
55 }
56
57 if i := strings.LastIndex(dec.text, " "); isPrefix(dec.text[i+1:]) && size == 1 && isPrefix(text) {
58 return true
59 }
60
61 if size == dec.nenc && contains(dec.text, "movupd") && contains(dec.text, "data32") {
62 s := strings.Replace(dec.text, "data32 ", "", -1)
63 if text == s {
64 return true
65 }
66 }
67
68 // Simplify our invalid instruction text.
69 if text == "error: unrecognized instruction" {
70 text = "BAD"
71 }
72
73 // Invalid instructions for which libopcodes prints %? register.
74 // FF E8 11 22 33 44:
75 // Invalid instructions for which libopcodes prints "internal disassembler error".
76 // Invalid instructions for which libopcodes prints 8087 only (e.g., DB E0)
77 // or prints 287 only (e.g., DB E4).
78 if contains(dec.text, "%?", "<internal disassembler error>", "(8087 only)", "(287 only)") {
79 dec.text = "(bad)"
80 }
81
82 // 0F 19 11, 0F 1C 11, 0F 1D 11, 0F 1E 11, 0F 1F 11: libopcodes says nop,
83 // but the Intel manuals say that the only NOP there is 0F 1F /0.
84 // Perhaps libopcodes is reporting an older encoding.
85 i := bytes.IndexByte(dec.enc[:], 0x0F)
86 if contains(dec.text, "nop") && i >= 0 && i+2 < len(dec.enc) && dec.enc[i+1]&^7 == 0x18 && (dec.enc[i+1] != 0x1F || (dec.enc[i+2]>>3)&7 != 0) {
87 dec.text = "(bad)"
88 }
89
90 // Any invalid instruction.
91 if text == "BAD" && contains(dec.text, "(bad)") {
92 return true
93 }
94
95 // Instructions libopcodes knows but we do not (e.g., 0F 19 11).
96 if (text == "BAD" || size == 1 && isPrefix(text)) && hasPrefix(dec.text, unsupported...) {
97 return true
98 }
99
100 // Instructions we know but libopcodes does not (e.g., 0F D0 11).
101 if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && hasPrefix(text, libopcodesUnsupported...) {
102 return true
103 }
104
105 // Libopcodes rejects F2 90 as NOP. Not sure why.
106 if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && inst.Opcode>>24 == 0x90 && countPrefix(inst, 0xF2) > 0 {
107 return true
108 }
109
110 // 0F 20 11, 0F 21 11, 0F 22 11, 0F 23 11, 0F 24 11:
111 // Moves into and out of some control registers seem to be unsupported by libopcodes.
112 // TODO(rsc): Are they invalid somehow?
113 if (contains(dec.text, "(bad)") || dec.nenc == 1 && isPrefix(dec.text)) && contains(text, "%cr", "%db", "%tr") {
114 return true
115 }
116
117 if contains(dec.text, "fwait") && dec.nenc == 1 && dec.enc[0] != 0x9B {
118 return true
119 }
120
121 // 9B D9 11: libopcodes reports FSTSW instead of FWAIT + FNSTSW.
122 // This is correct in that FSTSW is a pseudo-op for the pair, but it really
123 // is a pair of instructions: execution can stop between them.
124 // Our decoder chooses to separate them.
125 if (text == "fwait" || strings.HasSuffix(text, " fwait")) && dec.nenc >= len(strings.Fields(text)) && dec.enc[len(strings.Fields(text))-1] == 0x9B {
126 return true
127 }
128
129 // 0F 18 77 11:
130 // Invalid instructions for which libopcodes prints "nop/reserved".
131 // Perhaps libopcodes is reporting an older encoding.
132 if text == "BAD" && contains(dec.text, "nop/reserved") {
133 return true
134 }
135
136 // 0F C7 B0 11 22 33 44: libopcodes says vmptrld 0x44332211(%eax); we say rdrand %eax.
137 // TODO(rsc): Fix, since we are probably wrong, but we don't have vmptrld in the manual.
138 if contains(text, "rdrand") && contains(dec.text, "vmptrld", "vmxon", "vmclear") {
139 return true
140 }
141
142 // DD C8: libopcodes says FNOP but the Intel manual is clear FNOP is only D9 D0.
143 // Perhaps libopcodes is reporting an older encoding.
144 if text == "BAD" && contains(dec.text, "fnop") && (dec.enc[0] != 0xD9 || dec.enc[1] != 0xD0) {
145 return true
146 }
147
148 // 66 90: libopcodes says xchg %ax,%ax; we say 'data16 nop'.
149 // The 16-bit swap will preserve the high bits of the register,
150 // so they are the same.
151 if contains(text, "nop") && contains(dec.text, "xchg %ax,%ax") {
152 return true
153 }
154
155 // If there are multiple prefixes, allow libopcodes to use an alternate name.
156 if size == 1 && dec.nenc == 1 && prefixByte[text] > 0 && prefixByte[text] == prefixByte[dec.text] {
157 return true
158 }
159
160 // 26 9B: libopcodes reports "fwait"/1, ignoring segment prefix.
161 // https://sourceware.org/bugzilla/show_bug.cgi?id=16891
162 // F0 82: Decode="lock"/1 but libopcodes="lock (bad)"/2.
163 if size == 1 && dec.nenc >= 1 && prefixByte[text] == dec.enc[0] && contains(dec.text, "(bad)", "fwait", "fnop") {
164 return true
165 }
166
167 // libopcodes interprets 660f801122 as taking a rel16 but
168 // truncating the address at 16 bits. Not sure what is correct.
169 if contains(text, ".+0x2211", ".+0x11") && contains(dec.text, " .-") {
170 return true
171 }
172
173 // 66 F3 0F D6 C5, 66 F2 0F D6 C0: libopcodes reports use of XMM register instead of MMX register,
174 // but only when the instruction has a 66 prefix. Maybe they know something we don't.
175 if countPrefix(inst, 0x66) > 0 && contains(dec.text, "movdq2q", "movq2dq") && !contains(dec.text, "%mm") {
176 return true
177 }
178
179 // 0F 01 F8, 0F 05, 0F 07: these are 64-bit instructions but libopcodes accepts them.
180 if (text == "BAD" || size == 1 && isPrefix(text)) && contains(dec.text, "swapgs", "syscall", "sysret", "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase") {
181 return true
182 }
183
184 return false
185}
186
187// Instructions known to libopcodes (or xed) but not to us.
188// Most of these come from supplementary manuals of one form or another.
189var unsupported = strings.Fields(`
190 bndc
191 bndl
192 bndm
193 bnds
194 clac
195 clgi
196 femms
197 fldln
198 fldz
199 getsec
200 invlpga
201 kmov
202 montmul
203 pavg
204 pf2i
205 pfacc
206 pfadd
207 pfcmp
208 pfmax
209 pfmin
210 pfmul
211 pfna
212 pfpnac
213 pfrc
214 pfrs
215 pfsub
216 phadd
217 phsub
218 pi2f
219 pmulhr
220 prefetch
221 pswap
222 ptest
223 rdseed
224 sha1
225 sha256
226 skinit
227 stac
228 stgi
229 vadd
230 vand
231 vcmp
232 vcomis
233 vcvt
234 vcvt
235 vdiv
236 vhadd
237 vhsub
238 vld
239 vmax
240 vmcall
241 vmfunc
242 vmin
243 vmlaunch
244 vmload
245 vmmcall
246 vmov
247 vmov
248 vmov
249 vmptrld
250 vmptrst
251 vmread
252 vmresume
253 vmrun
254 vmsave
255 vmul
256 vmwrite
257 vmxoff
258 vor
259 vpack
260 vpadd
261 vpand
262 vpavg
263 vpcmp
264 vpcmp
265 vpins
266 vpmadd
267 vpmax
268 vpmin
269 vpmul
270 vpmul
271 vpor
272 vpsad
273 vpshuf
274 vpsll
275 vpsra
276 vpsrad
277 vpsrl
278 vpsub
279 vpunp
280 vpxor
281 vrcp
282 vrsqrt
283 vshuf
284 vsqrt
285 vsub
286 vucomis
287 vunp
288 vxor
289 vzero
290 xcrypt
291 xsha1
292 xsha256
293 xstore-rng
294 insertq
295 extrq
296 vmclear
297 invvpid
298 adox
299 vmxon
300 invept
301 adcx
302 vmclear
303 prefetchwt1
304 enclu
305 encls
306 salc
307 fstpnce
308 fdisi8087_nop
309 fsetpm287_nop
310 feni8087_nop
311 syscall
312 sysret
313`)
314
315// Instructions known to us but not to libopcodes (at least in binutils 2.24).
316var libopcodesUnsupported = strings.Fields(`
317 addsubps
318 aes
319 blend
320 cvttpd2dq
321 dpp
322 extract
323 haddps
324 hsubps
325 insert
326 invpcid
327 lddqu
328 movmsk
329 movnt
330 movq2dq
331 mps
332 pack
333 pblend
334 pclmul
335 pcmp
336 pext
337 phmin
338 pins
339 pmax
340 pmin
341 pmov
342 pmovmsk
343 pmul
344 popcnt
345 pslld
346 psllq
347 psllw
348 psrad
349 psraw
350 psrl
351 ptest
352 punpck
353 round
354 xrstor
355 xsavec
356 xsaves
357 comis
358 ucomis
359 movhps
360 movntps
361 rsqrt
362 rcpp
363 puncpck
364 bsf
365 movq2dq
366 cvttpd2dq
367 movq
368 hsubpd
369 movdqa
370 movhpd
371 addsubpd
372 movd
373 haddpd
374 cvtps2dq
375 bsr
376 cvtdq2ps
377 rdrand
378 maskmov
379 movq2dq
380 movlhps
381 movbe
382 movlpd
383`)