github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/src/cmd/internal/rsc.io/x86/x86asm/xed_test.go (about) 1 // 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 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 // xedManualTests holds test cases that will be run by TestXedManual32 and TestXedManual64. 42 // If you are debugging a few cases that turned up in a longer run, it can be useful 43 // to list them here and then use -run=XedManual, particularly with tracing enabled. 44 var xedManualTests = ` 45 6690 46 ` 47 48 // allowedMismatchXed reports whether the mismatch between text and dec 49 // should be allowed by the test. 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 // Instructions not known to us. 68 if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, unsupported...) { 69 return true 70 } 71 72 // Instructions not known to xed. 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 11 22: xed says 'adc byte ptr [ecx], 0x22' but there is no justification in the manuals for that. 82 // C0 30 11: xed says 'shl byte ptr [eax], 0x11' but there is no justification in the manuals for that. 83 // F6 08 11: xed says 'test byte ptr [eax], 0x11' but there is no justification in the manuals for that. 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 // F3 11 22 and many others: xed allows and drops misused rep/repn prefix. 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 // 0F C7 30: xed says vmptrld qword ptr [eax]; we say rdrand eax. 94 // TODO(rsc): Fix, since we are probably wrong, but we don't have vmptrld in the manual. 95 if contains(text, "rdrand") && contains(dec.text, "vmptrld", "vmxon", "vmclear") { 96 return true 97 } 98 99 // F3 0F AE 00: we say 'rdfsbase dword ptr [eax]' but RDFSBASE needs a register. 100 // Also, this is a 64-bit only instruction. 101 // TODO(rsc): Fix to reject this encoding. 102 if contains(text, "rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase") && contains(dec.text, "ERROR") { 103 return true 104 } 105 106 // 0F 01 F8: we say swapgs but that's only valid in 64-bit mode. 107 // TODO(rsc): Fix. 108 if contains(text, "swapgs") { 109 return true 110 } 111 112 // 0F 24 11: 'mov ecx, tr2' except there is no TR2. 113 // Or maybe the MOV to TR registers doesn't use RMF. 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 // 0F 19 11, 0F 1C 11, 0F 1D 11, 0F 1E 11, 0F 1F 11: xed says nop, 119 // but the Intel manuals say that the only NOP there is 0F 1F /0. 120 // Perhaps xed is reporting an older encoding. 121 if (contains(text, "error:") || isPrefix(text) && size == 1) && contains(dec.text, "nop ") && (inst.Opcode>>8)&0xFFFF38 != 0x0F1F00 { 122 return true 123 } 124 125 // 66 0F AE 38: clflushopt but we only know clflush 126 if contains(text, "clflush") && contains(dec.text, "clflushopt") { 127 return true 128 } 129 130 // 0F 20 04 11: MOV SP, CR0 but has mod!=3 despite register argument. 131 // (This encoding ignores the mod bits.) The decoder sees the non-register 132 // mod and reads farther ahead to decode the memory reference that 133 // isn't really there, causing the size to be too large. 134 // TODO(rsc): Fix. 135 if text == dec.text && size > dec.nenc && contains(text, " cr", " dr", " tr") { 136 return true 137 } 138 139 // 0F AE E9: xed says lfence, which is wrong (only 0F AE E8 is lfence). And so on. 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 // DD C9, DF C9: xed says 'fxch st0, st1' but that instruction is D9 C9. 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 // DC D4: xed says 'fcom st0, st4' but that instruction is D8 D4. 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 // DE D4: xed says 'fcomp st0, st4' but that instruction is D8 D4. 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 // DF D4: xed says 'fstp st4, st0' but that instruction is DD D4. 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 // Instructions known to us but not to xed. 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 `)