summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/lib/codegen-x86-test.js
blob: edf3e916fb7b9ecb20a880ff2e3648b17b27fbc0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
// Scaffolding for testing x86 Ion code generation patterns .  See
// codegen-x64-test.js in this directory for more information.

load(libdir + "codegen-test-common.js");

// Note that Zydis disassembles x86 absolute addresses as relative, so
// the binary encoding and the text encoding may not correspond precisely.

// Absolute address (disp32) following the instruction mnemonic.
var ABS = `0x${HEXES}`;

// Absolute address (disp32) in the binary encoding.
var ABSADDR = `${HEX}{2} ${HEX}{2} ${HEX}{2} ${HEX}{2}`;

// End of prologue.  The mov to eax is debug code, inserted by the register
// allocator to clobber eax before a move group.  But it is only present if
// there is a move group there.
//
// -0x21524111 is 0xDEADBEEF.
var x86_prefix = `
8b ec            mov %esp, %ebp(
b8 ef be ad de   mov \\$-0x21524111, %eax)?
`

// `.bp` because zydis chooses 'rbp' even on 32-bit systems
var x86_loadarg0 = `
f3 0f 6f 45 ${HEX}{2}            movdqux 0x${HEXES}\\(%.bp\\), %xmm0
`;

// Start of epilogue.  `.bp` for the same reason as above.
var x86_suffix = `5d      pop %.bp`;

// v128 OP literal -> v128
// inputs: [[complete-opname, rhs-literal, expected-pattern], ...]
function codegenTestX86_v128xLITERAL_v128(inputs, options = {}) {
    for ( let [op, literal, expected] of inputs ) {
        codegenTestX86_adhoc(wrap(options, `
    (func (export "f") (param v128) (result v128)
      (${op} (local.get 0) ${literal}))`),
                             'f',
                             x86_loadarg0 + expected,
                             options)
    }
}

// For when nothing else applies: `module_text` is the complete source text of
// the module, `export_name` is the name of the function to be tested,
// `expected` is the non-preprocessed pattern, and options is an options bag,
// described above.
function codegenTestX86_adhoc(module_text, export_name, expected, options = {}) {
    assertEq(hasDisassembler(), true);

    let ins = wasmEvalText(module_text);
    let output = wasmDis(ins.exports[export_name], {tier:"ion", asString:true});

    const expected_initial = expected;
    if (!options.no_prefix)
        expected = x86_prefix + '\n' + expected;
    if (!options.no_suffix)
        expected = expected + '\n' + x86_suffix;
    expected = fixlines(expected);

    const output_matches_expected = output.match(new RegExp(expected)) != null;
    if (!output_matches_expected) {
        print("---- codegen-x86-test.js: TEST FAILED ----");
    }
    if (options.log && output_matches_expected) {
        print("---- codegen-x86-test.js: TEST PASSED ----");
    }
    if (options.log || !output_matches_expected) {
        print("---- module text");
        print(module_text);
        print("---- actual");
        print(output);
        print("---- expected (initial)");
        print(expected_initial);
        print("---- expected (as used)");
        print(expected);
        print("----");
    }

    assertEq(output_matches_expected, true);
}