github.com/akaros/go-akaros@v0.0.0-20181004170632-85005d477eab/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  `)