| // Copyright 2017 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package x86csv |
| |
| import ( |
| "reflect" |
| "strings" |
| "testing" |
| ) |
| |
| // This test makes it harder to break Reader unintentionally. |
| // |
| // Deeper testing is probably not required because 99% of the job is |
| // done by csv.Reader. |
| func TestReader(t *testing.T) { |
| input := `# x86.csv v0.2 |
| "ADDSUBPD xmm1, xmm2/m128","ADDSUBPD xmm2/m128, xmm1","addsubpd xmm2/m128, xmm1","66 0F D0 /r","V","V","SSE3","","rw,r","","" |
| "VPEXTRQ r/m64, xmm1, imm8","VPEXTRQ imm8, xmm1, r/m64","vpextrq imm8, xmm1, r/m64","VEX.128.66.0F3A.W1 16 /r ib","I","V","AVX","","w,r,r","","" |
| "XOR r8, r/m8","XORB r/m8, r8","xorb r/m8, r8","REX 32 /r","N.E.","V","","pseudo64","rw,r","Y","8" |
| ` |
| want := []Inst{ |
| { |
| Intel: "ADDSUBPD xmm1, xmm2/m128", |
| Go: "ADDSUBPD xmm2/m128, xmm1", |
| GNU: "addsubpd xmm2/m128, xmm1", |
| Encoding: "66 0F D0 /r", |
| Mode32: "V", |
| Mode64: "V", |
| CPUID: "SSE3", |
| Action: "rw,r", |
| }, |
| { |
| Intel: "VPEXTRQ r/m64, xmm1, imm8", |
| Go: "VPEXTRQ imm8, xmm1, r/m64", |
| GNU: "vpextrq imm8, xmm1, r/m64", |
| Encoding: "VEX.128.66.0F3A.W1 16 /r ib", |
| Mode32: "I", |
| Mode64: "V", |
| CPUID: "AVX", |
| Action: "w,r,r", |
| }, |
| { |
| Intel: "XOR r8, r/m8", |
| Go: "XORB r/m8, r8", |
| GNU: "xorb r/m8, r8", |
| Encoding: "REX 32 /r", |
| Mode32: "N.E.", |
| Mode64: "V", |
| Tags: "pseudo64", |
| Action: "rw,r", |
| Multisize: "Y", |
| DataSize: "8", |
| }, |
| } |
| |
| r := NewReader(strings.NewReader(input)) |
| inst, err := r.Read() |
| if err != nil { |
| t.Fatalf("Read(): %v", err) |
| } |
| restInsts, err := r.ReadAll() |
| if err != nil { |
| t.Fatalf("ReadAll(): %v", err) |
| } |
| if remainder, err := r.ReadAll(); remainder != nil || err != nil { |
| t.Errorf("ReadAll() on exhausted r failed") |
| } |
| have := append([]*Inst{inst}, restInsts...) |
| |
| if len(want) != len(have) { |
| t.Fatalf("len(have) is %d, want %d\n", len(have), len(want)) |
| } |
| lines := strings.Split(input, "\n") |
| lines = lines[1:] // Drop comment line |
| for i := range want { |
| if want[i] != *have[i] { |
| t.Errorf("%s:\nhave: %v\nwant: %v", lines[i], have[i], want[i]) |
| } |
| } |
| } |
| |
| func TestSyntaxSplit(t *testing.T) { |
| tests := []struct { |
| syntax string |
| opcode string |
| args []string |
| }{ |
| {"RET", "RET", nil}, |
| {"CALLW* r/m16", "CALLW*", []string{"r/m16"}}, |
| {"JMP_FAR m16:16", "JMP_FAR", []string{"m16:16"}}, |
| {"movl CR0-CR7, rmr32", "movl", []string{"CR0-CR7", "rmr32"}}, |
| {"VFMSUBADD132PD xmm1, xmmV, xmm2/m128", "VFMSUBADD132PD", []string{"xmm1", "xmmV", "xmm2/m128"}}, |
| } |
| |
| for _, tt := range tests { |
| op, args := instOpcode(tt.syntax), instArgs(tt.syntax) |
| if op != tt.opcode { |
| t.Errorf("%s: opcode mismatch (have `%s`, want `%s`)", |
| tt.syntax, op, tt.opcode) |
| } |
| if !reflect.DeepEqual(args, tt.args) { |
| t.Errorf("%s: args mismatch (have %v, want %s)", |
| tt.syntax, args, tt.args) |
| } |
| } |
| } |