| // 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 main |
| |
| import ( |
| "bytes" |
| "regexp" |
| "strings" |
| "testing" |
| |
| "golang.org/x/arch/x86/x86csv" |
| ) |
| |
| func TestYtabKey(t *testing.T) { |
| type testCase struct { |
| insts []*x86csv.Inst |
| key string |
| } |
| test := func(key string, goSyntaxes ...string) testCase { |
| insts := make([]*x86csv.Inst, len(goSyntaxes)) |
| for i, stx := range goSyntaxes { |
| insts[i] = &x86csv.Inst{Go: stx} |
| } |
| return testCase{insts: insts, key: key} |
| } |
| tests := []testCase{ |
| test("", "VZEROALL"), |
| test("i8,x/m,x", "VAESKEYGENASSIST imm8, xmm2/m128, xmm1"), |
| test("x/m,xV,x;y/m,yV,y", "VADDPD xmm2/m128, xmmV, xmm1", "VADDPD ymm2/m256, ymmV, ymm1"), |
| test("x/m,xV,x", "VADDSD xmm2/m64, xmmV, xmm1"), |
| test("x/m,x", "VAESIMC xmm2/m128, xmm1"), |
| test("r/m,i8;r/m,i8;r/m,i8;r/m,i8", "XOR r/m16, imm8", "XOR r/m32, imm8", "XOR r/m64, imm8", "XOR r/m8, imm8"), |
| test("xV,yV", "OP1 xmm1V, ymm2V "), |
| test("x,y", "OP2 xmm, ymm"), |
| test("x/m,r/m", "OP3 xmm3/m32,r/m32"), |
| } |
| for _, test := range tests { |
| op := test.insts[0].GoOpcode() |
| key := ytabKey(op, test.insts) |
| if key != test.key { |
| t.Errorf("ytabKey(%s, ...)\nwant: '%s'\nhave: '%s'", op, key, test.key) |
| } |
| } |
| } |
| |
| func TestVexExpr(t *testing.T) { |
| tests := map[string]string{ |
| "VEX.NDS.256.0F.WIG": "vexNDS|vex256|vex0F|vexWIG", |
| "VEX.256.66.0F.WIG": "vexNOVSR|vex256|vex66|vex0F|vexWIG", |
| "VEX.128.66.0F38.WIG": "vexNOVSR|vex128|vex66|vex0F38|vexWIG", |
| "VEX.NDS.LIG.F2.0F.WIG": "vexNDS|vexLIG|vexF2|vex0F|vexWIG", |
| "VEX.NDD.LIG.F2.0F.WIG": "vexNDD|vexLIG|vexF2|vex0F|vexWIG", |
| "VEX.DDS.LIG.F2.0F.WIG": "vexDDS|vexLIG|vexF2|vex0F|vexWIG", |
| "VEX.NDS.0F": "vexNDS|vex0F", |
| "VEX.0F": "vexNOVSR|vex0F", |
| "VEX.0F.W0": "vexNOVSR|vex0F|vexW0", |
| "VEX.66.0F.W1": "vexNOVSR|vex66|vex0F|vexW1", |
| } |
| |
| for input, want := range tests { |
| have := vexExpr(input) |
| if have != want { |
| t.Errorf("vexPrefixExpr(%q)\nwant: %#v\nhave: %#v", input, want, have) |
| } |
| } |
| } |
| |
| func TestParseEncoding(t *testing.T) { |
| tests := map[string]encoding{ |
| "VEX.LZ.0F38.W0 F2 /r": { |
| vex: "VEX.LZ.0F38.W0", |
| opbyte: "F2", |
| }, |
| "VEX.NDD.LZ.0F38.W0 F3 /1": { |
| vex: "VEX.NDD.LZ.0F38.W0", |
| opbyte: "F3", |
| opdigit: "1", |
| }, |
| "VEX.NDS.128.66.0F3A.W0 4B /r /is4": { |
| vex: "VEX.NDS.128.66.0F3A.W0", |
| opbyte: "4B", |
| }, |
| } |
| |
| for input, want := range tests { |
| have := parseEncoding(input) |
| if have != want { |
| t.Errorf("vexPrefixExpr(%q)\nwant: %#v\nhave: %#v", input, want, have) |
| } |
| } |
| } |
| |
| func TestGenerateAenum(t *testing.T) { |
| input := `// Code generated by x86avxgen; DO NOT EDIT. |
| package eax |
| |
| const ( |
| unrelatedOne = iota |
| unrelatedTwo |
| ) |
| |
| /* |
| Leading multiline comment; |
| Line 2. |
| */ |
| //go:generate go run ../stringer.go -i $GOFILE -o anames.go -p x86 |
| const ( |
| AAAA = iota + 4*iota // AAAA comment. |
| ACCC // ACCC comment. |
| ABBB |
| AFFF // AFFF comment. |
| ALAST // ALAST comment. |
| ) |
| |
| // Top-level floating comment. |
| ` |
| |
| expected := `// Code generated by x86avxgen; DO NOT EDIT. |
| package eax |
| |
| const ( |
| unrelatedOne = iota |
| unrelatedTwo |
| ) |
| |
| // Top-level floating comment. |
| |
| /* |
| Leading multiline comment; |
| Line 2. |
| */ |
| //go:generate go run ../stringer.go -i $GOFILE -o anames.go -p x86 |
| const ( |
| AAAA = iota + 4*iota // AAAA comment. |
| ABBB |
| ACCC // ACCC comment. |
| ADDD |
| AEEE |
| AFFF // AFFF comment. |
| AZZZ |
| ALAST // ALAST comment. |
| ) |
| ` |
| r := strings.NewReader(input) |
| var buf bytes.Buffer |
| err := generateAenum(r, &buf, []string{ |
| "ZZZ", |
| "EEE", |
| "DDD", |
| }) |
| if err != nil { |
| t.Fatal(err) |
| } |
| output := buf.String() |
| if expected != output { |
| t.Errorf("output mismatch:\nwant: %s\nhave: %s", |
| expected, output) |
| } |
| } |
| |
| func TestUncommentTestLine(t *testing.T) { |
| // Note that is should also fix XMM0 to X0. |
| input := ` |
| //TODO: ADCXL (BX), DX // 660f38f613 |
| //TODO: ADCXL (R11), DX // 66410f38f613 |
| //TODO: ADDSUBPD (BX), X2 // 660fd013 |
| //TODO: BLENDVPD XMM0, (BX), X2 // 660f381513` |
| want := ` |
| ADCXL (BX), DX // 660f38f613 |
| ADCXL (R11), DX // 66410f38f613 |
| ADDSUBPD (BX), X2 // 660fd013 |
| BLENDVPD X0, (BX), X2 // 660f381513` |
| |
| lines := strings.Split(input, "\n") |
| for i := range lines { |
| if len(lines[i]) > 10 { |
| lines[i] = uncommentedTestLine(lines[i]) |
| } |
| } |
| have := strings.Join(lines, "\n") |
| if want != have { |
| t.Errorf("output mismatch:\nwant: `%s`\nhave: `%s`", |
| want, have) |
| } |
| } |
| |
| func TestOutput(t *testing.T) { |
| // Using already existing AVX optabs to check generated output. |
| // This does not cover new instructions though. |
| |
| // These lines can be retrieved by: |
| // $ grep ', Pvex,' src/cmd/internal/obj/x86/asm6.go |
| existingOptabs := ` |
| {AANDNL, yvex_r3, Pvex, [23]uint8{VEX_NDS_LZ_0F38_W0, 0xF2}}, |
| {AANDNQ, yvex_r3, Pvex, [23]uint8{VEX_NDS_LZ_0F38_W1, 0xF2}}, |
| {ABEXTRL, yvex_vmr3, Pvex, [23]uint8{VEX_NDS_LZ_0F38_W0, 0xF7}}, |
| {ABEXTRQ, yvex_vmr3, Pvex, [23]uint8{VEX_NDS_LZ_0F38_W1, 0xF7}}, |
| {ABZHIL, yvex_vmr3, Pvex, [23]uint8{VEX_NDS_LZ_0F38_W0, 0xF5}}, |
| {ABZHIQ, yvex_vmr3, Pvex, [23]uint8{VEX_NDS_LZ_0F38_W1, 0xF5}}, |
| {AMULXL, yvex_r3, Pvex, [23]uint8{VEX_NDD_LZ_F2_0F38_W0, 0xF6}}, |
| {AMULXQ, yvex_r3, Pvex, [23]uint8{VEX_NDD_LZ_F2_0F38_W1, 0xF6}}, |
| {APDEPL, yvex_r3, Pvex, [23]uint8{VEX_NDS_LZ_F2_0F38_W0, 0xF5}}, |
| {APDEPQ, yvex_r3, Pvex, [23]uint8{VEX_NDS_LZ_F2_0F38_W1, 0xF5}}, |
| {APEXTL, yvex_r3, Pvex, [23]uint8{VEX_NDS_LZ_F3_0F38_W0, 0xF5}}, |
| {APEXTQ, yvex_r3, Pvex, [23]uint8{VEX_NDS_LZ_F3_0F38_W1, 0xF5}}, |
| {ASARXL, yvex_vmr3, Pvex, [23]uint8{VEX_NDS_LZ_F3_0F38_W0, 0xF7}}, |
| {ASARXQ, yvex_vmr3, Pvex, [23]uint8{VEX_NDS_LZ_F3_0F38_W1, 0xF7}}, |
| {ASHLXL, yvex_vmr3, Pvex, [23]uint8{VEX_NDS_LZ_66_0F38_W0, 0xF7}}, |
| {ASHLXQ, yvex_vmr3, Pvex, [23]uint8{VEX_NDS_LZ_66_0F38_W1, 0xF7}}, |
| {ASHRXL, yvex_vmr3, Pvex, [23]uint8{VEX_NDS_LZ_F2_0F38_W0, 0xF7}}, |
| {ASHRXQ, yvex_vmr3, Pvex, [23]uint8{VEX_NDS_LZ_F2_0F38_W1, 0xF7}}, |
| {AVMOVDQU, yvex_vmovdqa, Pvex, [23]uint8{VEX_NOVSR_128_F3_0F_WIG, 0x6F, VEX_NOVSR_128_F3_0F_WIG, 0x7F, VEX_NOVSR_256_F3_0F_WIG, 0x6F, VEX_NOVSR_256_F3_0F_WIG, 0x7F}}, |
| {AVMOVDQA, yvex_vmovdqa, Pvex, [23]uint8{VEX_NOVSR_128_66_0F_WIG, 0x6F, VEX_NOVSR_128_66_0F_WIG, 0x7F, VEX_NOVSR_256_66_0F_WIG, 0x6F, VEX_NOVSR_256_66_0F_WIG, 0x7F}}, |
| {AVMOVNTDQ, yvex_vmovntdq, Pvex, [23]uint8{VEX_NOVSR_128_66_0F_WIG, 0xE7, VEX_NOVSR_256_66_0F_WIG, 0xE7}}, |
| {AVPCMPEQB, yvex_xy3, Pvex, [23]uint8{VEX_NDS_128_66_0F_WIG, 0x74, VEX_NDS_256_66_0F_WIG, 0x74}}, |
| {AVPXOR, yvex_xy3, Pvex, [23]uint8{VEX_NDS_128_66_0F_WIG, 0xEF, VEX_NDS_256_66_0F_WIG, 0xEF}}, |
| {AVPMOVMSKB, yvex_xyr2, Pvex, [23]uint8{VEX_NOVSR_128_66_0F_WIG, 0xD7, VEX_NOVSR_256_66_0F_WIG, 0xD7}}, |
| {AVPAND, yvex_xy3, Pvex, [23]uint8{VEX_NDS_128_66_0F_WIG, 0xDB, VEX_NDS_256_66_0F_WIG, 0xDB}}, |
| {AVPBROADCASTB, yvex_vpbroadcast, Pvex, [23]uint8{VEX_NOVSR_128_66_0F38_W0, 0x78, VEX_NOVSR_256_66_0F38_W0, 0x78}}, |
| {AVPTEST, yvex_xy2, Pvex, [23]uint8{VEX_NOVSR_128_66_0F38_WIG, 0x17, VEX_NOVSR_256_66_0F38_WIG, 0x17}}, |
| {AVPSHUFB, yvex_xy3, Pvex, [23]uint8{VEX_NDS_128_66_0F38_WIG, 0x00, VEX_NDS_256_66_0F38_WIG, 0x00}}, |
| {AVPSHUFD, yvex_xyi3, Pvex, [23]uint8{VEX_NOVSR_128_66_0F_WIG, 0x70, VEX_NOVSR_256_66_0F_WIG, 0x70, VEX_NOVSR_128_66_0F_WIG, 0x70, VEX_NOVSR_256_66_0F_WIG, 0x70}}, |
| {AVPOR, yvex_xy3, Pvex, [23]uint8{VEX_NDS_128_66_0F_WIG, 0xeb, VEX_NDS_256_66_0F_WIG, 0xeb}}, |
| {AVPADDQ, yvex_xy3, Pvex, [23]uint8{VEX_NDS_128_66_0F_WIG, 0xd4, VEX_NDS_256_66_0F_WIG, 0xd4}}, |
| {AVPADDD, yvex_xy3, Pvex, [23]uint8{VEX_NDS_128_66_0F_WIG, 0xfe, VEX_NDS_256_66_0F_WIG, 0xfe}}, |
| {AVADDSD, yvex_x3, Pvex, [23]uint8{VEX_NDS_128_F2_0F_WIG, 0x58}}, |
| {AVSUBSD, yvex_x3, Pvex, [23]uint8{VEX_NDS_128_F2_0F_WIG, 0x5c}}, |
| {AVFMADD213SD, yvex_x3, Pvex, [23]uint8{VEX_DDS_LIG_66_0F38_W1, 0xa9}}, |
| {AVFMADD231SD, yvex_x3, Pvex, [23]uint8{VEX_DDS_LIG_66_0F38_W1, 0xb9}}, |
| {AVFNMADD213SD, yvex_x3, Pvex, [23]uint8{VEX_DDS_LIG_66_0F38_W1, 0xad}}, |
| {AVFNMADD231SD, yvex_x3, Pvex, [23]uint8{VEX_DDS_LIG_66_0F38_W1, 0xbd}}, |
| {AVPSLLD, yvex_shift, Pvex, [23]uint8{VEX_NDS_128_66_0F_WIG, 0x72, 0xf0, VEX_NDS_256_66_0F_WIG, 0x72, 0xf0, VEX_NDD_128_66_0F_WIG, 0xf2, VEX_NDD_256_66_0F_WIG, 0xf2}}, |
| {AVPSLLQ, yvex_shift, Pvex, [23]uint8{VEX_NDD_128_66_0F_WIG, 0x73, 0xf0, VEX_NDD_256_66_0F_WIG, 0x73, 0xf0, VEX_NDS_128_66_0F_WIG, 0xf3, VEX_NDS_256_66_0F_WIG, 0xf3}}, |
| {AVPSRLD, yvex_shift, Pvex, [23]uint8{VEX_NDD_128_66_0F_WIG, 0x72, 0xd0, VEX_NDD_256_66_0F_WIG, 0x72, 0xd0, VEX_NDD_128_66_0F_WIG, 0xd2, VEX_NDD_256_66_0F_WIG, 0xd2}}, |
| {AVPSRLQ, yvex_shift, Pvex, [23]uint8{VEX_NDD_128_66_0F_WIG, 0x73, 0xd0, VEX_NDD_256_66_0F_WIG, 0x73, 0xd0, VEX_NDS_128_66_0F_WIG, 0xd3, VEX_NDS_256_66_0F_WIG, 0xd3}}, |
| {AVPSRLDQ, yvex_shift_dq, Pvex, [23]uint8{VEX_NDD_128_66_0F_WIG, 0x73, 0xd8, VEX_NDD_256_66_0F_WIG, 0x73, 0xd8}}, |
| {AVPSLLDQ, yvex_shift_dq, Pvex, [23]uint8{VEX_NDD_128_66_0F_WIG, 0x73, 0xf8, VEX_NDD_256_66_0F_WIG, 0x73, 0xf8}}, |
| {AVPERM2F128, yvex_yyi4, Pvex, [23]uint8{VEX_NDS_256_66_0F3A_W0, 0x06}}, |
| {AVPALIGNR, yvex_yyi4, Pvex, [23]uint8{VEX_NDS_256_66_0F3A_WIG, 0x0f}}, |
| {AVPBLENDD, yvex_yyi4, Pvex, [23]uint8{VEX_NDS_256_66_0F3A_WIG, 0x02}}, |
| {AVINSERTI128, yvex_xyi4, Pvex, [23]uint8{VEX_NDS_256_66_0F3A_WIG, 0x38}}, |
| {AVPERM2I128, yvex_yyi4, Pvex, [23]uint8{VEX_NDS_256_66_0F3A_WIG, 0x46}}, |
| {ARORXL, yvex_ri3, Pvex, [23]uint8{VEX_NOVSR_LZ_F2_0F3A_W0, 0xf0}}, |
| {ARORXQ, yvex_ri3, Pvex, [23]uint8{VEX_NOVSR_LZ_F2_0F3A_W1, 0xf0}}, |
| {AVBROADCASTSD, yvex_vpbroadcast_sd, Pvex, [23]uint8{VEX_NOVSR_256_66_0F38_W0, 0x19}}, |
| {AVBROADCASTSS, yvex_vpbroadcast, Pvex, [23]uint8{VEX_NOVSR_128_66_0F38_W0, 0x18, VEX_NOVSR_256_66_0F38_W0, 0x18}}, |
| {AVMOVDDUP, yvex_xy2, Pvex, [23]uint8{VEX_NOVSR_128_F2_0F_WIG, 0x12, VEX_NOVSR_256_F2_0F_WIG, 0x12}}, |
| {AVMOVSHDUP, yvex_xy2, Pvex, [23]uint8{VEX_NOVSR_128_F3_0F_WIG, 0x16, VEX_NOVSR_256_F3_0F_WIG, 0x16}}, |
| {AVMOVSLDUP, yvex_xy2, Pvex, [23]uint8{VEX_NOVSR_128_F3_0F_WIG, 0x12, VEX_NOVSR_256_F3_0F_WIG, 0x12}},` |
| |
| // Preprocess "existingOptabs" to make generated output comparable. |
| { |
| // 1. Inline prefix byte expressions. |
| // $ egrep 'VEX_[_A-Z0-9]+\s*=' src/cmd/internal/obj/x86/asm6.go |
| prefixFixer := strings.NewReplacer( |
| "VEX_DDS_LIG_66_0F38_W1", "vexDDS | vexLIG | vex66 | vex0F38 | vexW1", |
| "VEX_NDD_128_66_0F_WIG", "vexNDD | vex128 | vex66 | vex0F | vexWIG", |
| "VEX_NDD_256_66_0F_WIG", "vexNDD | vex256 | vex66 | vex0F | vexWIG", |
| "VEX_NDD_LZ_F2_0F38_W0", "vexNDD | vexLZ | vexF2 | vex0F38 | vexW0", |
| "VEX_NDD_LZ_F2_0F38_W1", "vexNDD | vexLZ | vexF2 | vex0F38 | vexW1", |
| "VEX_NDS_128_66_0F_WIG", "vexNDS | vex128 | vex66 | vex0F | vexWIG", |
| "VEX_NDS_128_66_0F38_WIG", "vexNDS | vex128 | vex66 | vex0F38 | vexWIG", |
| "VEX_NDS_128_F2_0F_WIG", "vexNDS | vex128 | vexF2 | vex0F | vexWIG", |
| "VEX_NDS_256_66_0F_WIG", "vexNDS | vex256 | vex66 | vex0F | vexWIG", |
| "VEX_NDS_256_66_0F38_WIG", "vexNDS | vex256 | vex66 | vex0F38 | vexWIG", |
| "VEX_NDS_256_66_0F3A_W0", "vexNDS | vex256 | vex66 | vex0F3A | vexW0", |
| "VEX_NDS_256_66_0F3A_WIG", "vexNDS | vex256 | vex66 | vex0F3A | vexWIG", |
| "VEX_NDS_LZ_0F38_W0", "vexNDS | vexLZ | vex0F38 | vexW0", |
| "VEX_NDS_LZ_0F38_W1", "vexNDS | vexLZ | vex0F38 | vexW1", |
| "VEX_NDS_LZ_66_0F38_W0", "vexNDS | vexLZ | vex66 | vex0F38 | vexW0", |
| "VEX_NDS_LZ_66_0F38_W1", "vexNDS | vexLZ | vex66 | vex0F38 | vexW1", |
| "VEX_NDS_LZ_F2_0F38_W0", "vexNDS | vexLZ | vexF2 | vex0F38 | vexW0", |
| "VEX_NDS_LZ_F2_0F38_W1", "vexNDS | vexLZ | vexF2 | vex0F38 | vexW1", |
| "VEX_NDS_LZ_F3_0F38_W0", "vexNDS | vexLZ | vexF3 | vex0F38 | vexW0", |
| "VEX_NDS_LZ_F3_0F38_W1", "vexNDS | vexLZ | vexF3 | vex0F38 | vexW1", |
| "VEX_NOVSR_128_66_0F_WIG", "vexNOVSR | vex128 | vex66 | vex0F | vexWIG", |
| "VEX_NOVSR_128_66_0F38_W0", "vexNOVSR | vex128 | vex66 | vex0F38 | vexW0", |
| "VEX_NOVSR_128_66_0F38_WIG", "vexNOVSR | vex128 | vex66 | vex0F38 | vexWIG", |
| "VEX_NOVSR_128_F2_0F_WIG", "vexNOVSR | vex128 | vexF2 | vex0F | vexWIG", |
| "VEX_NOVSR_128_F3_0F_WIG", "vexNOVSR | vex128 | vexF3 | vex0F | vexWIG", |
| "VEX_NOVSR_256_66_0F_WIG", "vexNOVSR | vex256 | vex66 | vex0F | vexWIG", |
| "VEX_NOVSR_256_66_0F38_W0", "vexNOVSR | vex256 | vex66 | vex0F38 | vexW0", |
| "VEX_NOVSR_256_66_0F38_WIG", "vexNOVSR | vex256 | vex66 | vex0F38 | vexWIG", |
| "VEX_NOVSR_256_F2_0F_WIG", "vexNOVSR | vex256 | vexF2 | vex0F | vexWIG", |
| "VEX_NOVSR_256_F3_0F_WIG", "vexNOVSR | vex256 | vexF3 | vex0F | vexWIG", |
| "VEX_NOVSR_LZ_F2_0F3A_W0", "vexNOVSR | vexLZ | vexF2 | vex0F3A | vexW0", |
| "VEX_NOVSR_LZ_F2_0F3A_W1", "vexNOVSR | vexLZ | vexF2 | vex0F3A | vexW1", |
| ) |
| existingOptabs = prefixFixer.Replace(existingOptabs) |
| |
| // 2. Normalize hex literals. |
| // Some optabs use 0xaa style, others use 0xAA. |
| // Generated optabs always use upper case style (as in x86.csv). |
| rxHexLit := regexp.MustCompile(` 0x[0-9a-f]{2}`) |
| existingOptabs = rxHexLit.ReplaceAllStringFunc(existingOptabs, func(m string) string { |
| return " 0x" + strings.ToUpper(m[len(" 0x"):]) |
| }) |
| } |
| |
| r, err := specRowReader("../" + specFile) |
| if err != nil { |
| t.Fatalf("open row reader: %v", err) |
| } |
| var newOptabs bytes.Buffer |
| _, err = doGenerateVexOptabs(r, &newOptabs) |
| if err != nil { |
| t.Fatalf("generate vex optabs: %v", err) |
| } |
| |
| rxOptabID := regexp.MustCompile(`[A-Z_][A-Z_0-9]*`) |
| linesToMap := func(lines []string) map[string]string { |
| m := make(map[string]string, len(lines)) |
| for _, l := range lines { |
| name := rxOptabID.FindString(l) |
| if name != "" { |
| m[name] = l |
| } |
| } |
| return m |
| } |
| |
| expectedChanges := map[string]string{ |
| // Before: 256/Y variant. |
| // Now: 256/Y + 128/X variants. |
| "AVPALIGNR": "{AVPALIGNR, yvex_vpalignr, Pvex, [23]uint8{vexNDS | vex128 | vex66 | vex0F3A | vexWIG, 0x0F, vexNDS | vex256 | vex66 | vex0F3A | vexWIG, 0x0F}}", |
| "AVPBLENDD": "{AVPBLENDD, yvex_vpalignr, Pvex, [23]uint8{vexNDS | vex128 | vex66 | vex0F3A | vexW0, 0x02, vexNDS | vex256 | vex66 | vex0F3A | vexW0, 0x02}}", |
| |
| // Before: R+R variants. |
| // Now: R+R and R+M variants. |
| "AVBROADCASTSS": "{AVBROADCASTSS, yvex_vpbroadcast_ss, Pvex, [23]uint8{vexNOVSR | vex128 | vex66 | vex0F38 | vexW0, 0x18, vexNOVSR | vex128 | vex66 | vex0F38 | vexW0, 0x18, vexNOVSR | vex256 | vex66 | vex0F38 | vexW0, 0x18, vexNOVSR | vex256 | vex66 | vex0F38 | vexW0, 0x18}}", |
| "AVBROADCASTSD": "{AVBROADCASTSD, yvex_vpbroadcast_sd, Pvex, [23]uint8{vexNOVSR | vex256 | vex66 | vex0F38 | vexW0, 0x19, vexNOVSR | vex256 | vex66 | vex0F38 | vexW0, 0x19}}", |
| |
| // Before: VEX.L=128 (vex128). |
| // Now: VEX.L=IGNORE (vexLIG); as in "x86.csv". |
| "AVSUBSD": "{AVSUBSD, yvex_x3, Pvex, [23]uint8{vexNDS | vexLIG | vexF2 | vex0F | vexWIG, 0x5C}}", |
| "AVADDSD": "{AVADDSD, yvex_x3, Pvex, [23]uint8{vexNDS | vexLIG | vexF2 | vex0F | vexWIG, 0x58}}", |
| |
| // Before: VEX.W=IGNORE (vexWIG). |
| // Now: VEX.W=W0 (vexW0); as in "x86.csv". |
| "AVINSERTI128": "{AVINSERTI128, yvex_xyi4, Pvex, [23]uint8{vexNDS | vex256 | vex66 | vex0F3A | vexW0, 0x38}}", |
| "AVPERM2I128": "{AVPERM2I128, yvex_yyi4, Pvex, [23]uint8{vexNDS | vex256 | vex66 | vex0F3A | vexW0, 0x46}}", |
| } |
| |
| reportError := func(name, want, have string) { |
| t.Errorf("%s: output mismatch\n\twant:'%s'\n\thave:'%s'", |
| name, want, have) |
| } |
| |
| // Perform check. |
| haveLines := linesToMap(strings.Split(newOptabs.String(), "\n")) |
| wantLines := linesToMap(strings.Split(existingOptabs, "\n")) |
| for name, wantLine := range wantLines { |
| haveLine := haveLines[name] |
| |
| haveLine = strings.Trim(haveLine, " \t,") |
| wantLine = strings.Trim(wantLine, " \t,") |
| |
| if haveLine == "" { |
| t.Errorf("%s: not found", name) |
| continue |
| } |
| |
| if line := expectedChanges[name]; line != "" { |
| if line != haveLine { |
| reportError(name, line, haveLine) |
| } |
| continue |
| } |
| |
| if !strings.Contains(haveLine, wantLine) { |
| reportError(name, wantLine, haveLine) |
| } |
| } |
| } |