// |jit-test| skip-if: !hasDisassembler() || wasmCompileMode() != "ion" || !getBuildConfiguration("loong64"); include:codegen-loong64-test.js const WasmTrapIns = `break 0x6`; const NopIns = `andi \\$zero, \\$zero, 0x0`; // Signed 32-bit division with constants. const i32_div_s = [ // Division by zero. { divisor: 0, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 ${WasmTrapIns}`, }, // Power of two divisor { divisor: 1, expected: `slli\\.w \\$a0, \\$a0, 0x0`, }, { divisor: 2, expected: `srli\\.w \\$a1, \\$a0, 0x1f add\\.w \\$a1, \\$a1, \\$a0 srai\\.w \\$a0, \\$a1, 0x1`, }, { divisor: 4, expected: `srai\\.w \\$a1, \\$a0, 0x1f srli\\.w \\$a1, \\$a1, 0x1e add\\.w \\$a1, \\$a1, \\$a0 srai\\.w \\$a0, \\$a1, 0x2`, }, // Division by -1 needs an overflow check. { divisor: -1, expected: `lu12i\\.w \\$t6, -524288 bne \\$a0, \\$t6, 24 -> ${HEX}+ ${NopIns} bge \\$zero, \\$zero, 12 -> ${HEX}+ ${NopIns} ${NopIns} ${WasmTrapIns} sub\\.w \\$a0, \\$zero, \\$a0`, }, // Other divisors. { divisor: 3, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 lu12i\\.w \\$t6, 349525 ori \\$t6, \\$t6, 0x556 mulh\\.w \\$a0, \\$a1, \\$t6 srai\\.w \\$t6, \\$a1, 0x1f sub\\.w \\$a0, \\$a0, \\$t6`, }, { divisor: 5, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 lu12i\\.w \\$t6, 419430 ori \\$t6, \\$t6, 0x667 mulh\\.w \\$a0, \\$a1, \\$t6 srai\\.w \\$a0, \\$a0, 0x1 srai\\.w \\$t6, \\$a1, 0x1f sub\\.w \\$a0, \\$a0, \\$t6`, }, { divisor: 7, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 lu12i\\.w \\$t6, -449390 ori \\$t6, \\$t6, 0x493 mulh\\.w \\$a0, \\$a1, \\$t6 add\\.w \\$a0, \\$a0, \\$a1 srai\\.w \\$a0, \\$a0, 0x2 srai\\.w \\$t6, \\$a1, 0x1f sub\\.w \\$a0, \\$a0, \\$t6`, }, { divisor: 9, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 lu12i\\.w \\$t6, 233016 ori \\$t6, \\$t6, 0xe39 mulh\\.w \\$a0, \\$a1, \\$t6 srai\\.w \\$a0, \\$a0, 0x1 srai\\.w \\$t6, \\$a1, 0x1f sub\\.w \\$a0, \\$a0, \\$t6`, }, ]; for (let {divisor, expected} of i32_div_s) { let divs32 = `(module (func (export "f") (param i32) (result i32) (i32.div_s (local.get 0) (i32.const ${divisor}))))`; codegenTestLOONG64_adhoc(divs32, "f", expected); // Test negative divisors, too. if (divisor > 1) { let divs32 = `(module (func (export "f") (param i32) (result i32) (i32.div_s (local.get 0) (i32.const -${divisor}))))`; codegenTestLOONG64_adhoc(divs32, "f", expected + ` sub\\.w \\$a0, \\$zero, \\$a0`); } } // Unsigned 32-bit division with constants. const i32_div_u = [ // Division by zero. { divisor: 0, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 ${WasmTrapIns}`, }, // Power of two divisor { divisor: 1, expected: `slli\\.w \\$a0, \\$a0, 0x0`, }, { divisor: 2, expected: `srli\\.w \\$a0, \\$a0, 0x1`, }, { divisor: 4, expected: `srli\\.w \\$a0, \\$a0, 0x2`, }, // Other divisors. { divisor: 3, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 lu12i\\.w \\$t6, -349526 ori \\$t6, \\$t6, 0xaab mulh\\.wu \\$a0, \\$a1, \\$t6 srli\\.w \\$a0, \\$a0, 0x1`, }, { divisor: 5, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 lu12i\\.w \\$t6, -209716 ori \\$t6, \\$t6, 0xccd mulh\\.wu \\$a0, \\$a1, \\$t6 srli\\.w \\$a0, \\$a0, 0x2`, }, { divisor: 7, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 lu12i\\.w \\$t6, 149796 ori \\$t6, \\$t6, 0x925 mulh\\.wu \\$a0, \\$a1, \\$t6 sub\\.w \\$t6, \\$a1, \\$a0 srli\\.w \\$t6, \\$t6, 0x1 add\\.w \\$a0, \\$a0, \\$t6 srli\\.w \\$a0, \\$a0, 0x2`, }, { divisor: 9, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 lu12i\\.w \\$t6, 233016 ori \\$t6, \\$t6, 0xe39 mulh\\.wu \\$a0, \\$a1, \\$t6 srli\\.w \\$a0, \\$a0, 0x1`, }, // Special case: Zero (additional) shift amount. { divisor: 641, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 lu12i\\.w \\$t6, 1635 ori \\$t6, \\$t6, 0xd81 mulh\\.wu \\$a0, \\$a1, \\$t6`, }, ]; for (let {divisor, expected} of i32_div_u) { let divu32 = `(module (func (export "f") (param i32) (result i32) (i32.div_u (local.get 0) (i32.const ${divisor}))))`; codegenTestLOONG64_adhoc(divu32, "f", expected); } // Signed 64-bit division with constants. const i64_div_s = [ // Division by zero. { divisor: 0, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero ${WasmTrapIns}`, }, // Power of two divisor { divisor: 1, expected: `or \\$a0, \\$a0, \\$zero`, }, { divisor: 2, expected: `srli\\.d \\$t6, \\$a0, 0x3f add\\.d \\$t6, \\$t6, \\$a0 srai\\.d \\$a0, \\$t6, 0x1`, }, { divisor: 4, expected: `srai\\.d \\$t6, \\$a0, 0x3f srli\\.d \\$t6, \\$t6, 0x3e add\\.d \\$t6, \\$t6, \\$a0 srai\\.d \\$a0, \\$t6, 0x2`, }, { divisor: 0x1_0000_0000, expected: `srai\\.d \\$t6, \\$a0, 0x3f srli\\.d \\$t6, \\$t6, 0x20 add\\.d \\$t6, \\$t6, \\$a0 srai\\.d \\$a0, \\$t6, 0x20`, }, // Division by -1 needs an overflow check. { divisor: -1, expected: `lu52i\\.d \\$t6, \\$zero, -2048 bne \\$a0, \\$t6, 24 -> ${HEX}+ ${NopIns} bge \\$zero, \\$zero, 12 -> ${HEX}+ ${NopIns} ${NopIns} ${WasmTrapIns} sub\\.d \\$a0, \\$zero, \\$a0`, }, // Other divisors. { divisor: 3, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, 349525 lu32i\\.d \\$t6, 349525 lu52i\\.d \\$t6, \\$t6, 1365 ori \\$t6, \\$t6, 0x556 mulh\\.d \\$a0, \\$a1, \\$t6 srai\\.d \\$t6, \\$a1, 0x3f sub\\.d \\$a0, \\$a0, \\$t6`, }, { divisor: 5, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, 419430 lu32i\\.d \\$t6, 419430 lu52i\\.d \\$t6, \\$t6, 1638 ori \\$t6, \\$t6, 0x667 mulh\\.d \\$a0, \\$a1, \\$t6 srai\\.d \\$a0, \\$a0, 0x1 srai\\.d \\$t6, \\$a1, 0x3f sub\\.d \\$a0, \\$a0, \\$t6`, }, { divisor: 7, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, 149796 lu32i\\.d \\$t6, 299593 lu52i\\.d \\$t6, \\$t6, 1170 ori \\$t6, \\$t6, 0x925 mulh\\.d \\$a0, \\$a1, \\$t6 srai\\.d \\$a0, \\$a0, 0x1 srai\\.d \\$t6, \\$a1, 0x3f sub\\.d \\$a0, \\$a0, \\$t6`, }, { divisor: 9, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, 466033 lu32i\\.d \\$t6, 116508 lu52i\\.d \\$t6, \\$t6, 455 ori \\$t6, \\$t6, 0xc72 mulh\\.d \\$a0, \\$a1, \\$t6 srai\\.d \\$t6, \\$a1, 0x3f sub\\.d \\$a0, \\$a0, \\$t6`, }, { divisor: 0x3_0000_0000, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, -349526 lu32i\\.d \\$t6, -349526 lu52i\\.d \\$t6, \\$t6, 682 ori \\$t6, \\$t6, 0xaab mulh\\.d \\$a0, \\$a1, \\$t6 srai\\.d \\$a0, \\$a0, 0x1f srai\\.d \\$t6, \\$a1, 0x3f sub\\.d \\$a0, \\$a0, \\$t6`, }, ]; for (let {divisor, expected} of i64_div_s) { let divs64 = `(module (func (export "f") (param i64) (result i64) (i64.div_s (local.get 0) (i64.const ${divisor}))))`; codegenTestLOONG64_adhoc(divs64, "f", expected); // Test negative divisors, too. if (divisor > 1) { let divs64 = `(module (func (export "f") (param i64) (result i64) (i64.div_s (local.get 0) (i64.const -${divisor}))))`; codegenTestLOONG64_adhoc(divs64, "f", expected + ` sub\\.d \\$a0, \\$zero, \\$a0`); } } // Unsigned 64-bit division with constants. const i64_div_u = [ // Division by zero. { divisor: 0, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero ${WasmTrapIns}`, }, // Power of two divisor { divisor: 1, expected: `or \\$a0, \\$a0, \\$zero`, }, { divisor: 2, expected: `srli\\.d \\$a0, \\$a0, 0x1`, }, { divisor: 4, expected: `srli\\.d \\$a0, \\$a0, 0x2`, }, { divisor: 0x1_0000_0000, expected: `srli\\.d \\$a0, \\$a0, 0x20`, }, // Other divisors. { divisor: 3, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, -349526 lu32i\\.d \\$t6, -349526 lu52i\\.d \\$t6, \\$t6, -1366 ori \\$t6, \\$t6, 0xaab mulh\\.du \\$a0, \\$a1, \\$t6 srli\\.d \\$a0, \\$a0, 0x1`, }, { divisor: 5, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, -209716 lu32i\\.d \\$t6, -209716 lu52i\\.d \\$t6, \\$t6, -820 ori \\$t6, \\$t6, 0xccd mulh\\.du \\$a0, \\$a1, \\$t6 srli\\.d \\$a0, \\$a0, 0x2`, }, { divisor: 7, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, -449390 lu32i\\.d \\$t6, 149796 lu52i\\.d \\$t6, \\$t6, 585 ori \\$t6, \\$t6, 0x493 mulh\\.du \\$a0, \\$a1, \\$t6 sub\\.d \\$t6, \\$a1, \\$a0 srli\\.d \\$t6, \\$t6, 0x1 add\\.d \\$a0, \\$a0, \\$t6 srli\\.d \\$a0, \\$a0, 0x2`, }, { divisor: 9, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, -466034 lu32i\\.d \\$t6, -116509 lu52i\\.d \\$t6, \\$t6, -456 ori \\$t6, \\$t6, 0x38f mulh\\.du \\$a0, \\$a1, \\$t6 srli\\.d \\$a0, \\$a0, 0x3`, }, { divisor: 0x3_0000_0000, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, -349526 lu32i\\.d \\$t6, -349526 lu52i\\.d \\$t6, \\$t6, -1366 ori \\$t6, \\$t6, 0xaab mulh\\.du \\$a0, \\$a1, \\$t6 srli\\.d \\$a0, \\$a0, 0x21`, }, // Special case: Zero shift amount. { divisor: 274177, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, -58931 lu32i\\.d \\$t6, 15664 ori \\$t6, \\$t6, 0x101 mulh\\.du \\$a0, \\$a1, \\$t6`, }, ]; for (let {divisor, expected} of i64_div_u) { let divu64 = `(module (func (export "f") (param i64) (result i64) (i64.div_u (local.get 0) (i64.const ${divisor}))))`; codegenTestLOONG64_adhoc(divu64, "f", expected); } ////////////// function i32RemPowTwoExpected(msb) { return `blt \\$a0, \\$zero, 20 -> ${HEX}+ ${NopIns} bstrpick\\.w \\$a0, \\$a0, ${msb}, 0x0 beq \\$zero, \\$zero, 20 -> ${HEX}+ ${NopIns} sub\\.w \\$a0, \\$zero, \\$a0 bstrpick\\.w \\$a0, \\$a0, ${msb}, 0x0 sub\\.w \\$a0, \\$zero, \\$a0`; } // Signed 32-bit remainder with constants. const i32_rem_s = [ // Division by zero. { divisor: 0, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 ${WasmTrapIns}`, }, // Power of two divisor { divisor: 1, expected: `addi\\.w \\$a0, \\$zero, 0`, }, { divisor: 2, expected: i32RemPowTwoExpected("0x0"), }, { divisor: 4, expected: i32RemPowTwoExpected("0x1"), }, { divisor: 0x100, expected: i32RemPowTwoExpected("0x7"), }, { divisor: 0x10000, expected: i32RemPowTwoExpected("0xf"), }, { divisor: 0x8000_0000, expected: i32RemPowTwoExpected("0x1e"), }, ]; for (let {divisor, expected} of i32_rem_s) { let rems32 = `(module (func (export "f") (param i32) (result i32) (i32.rem_s (local.get 0) (i32.const ${divisor}))))`; codegenTestLOONG64_adhoc(rems32, "f", expected); // Test negative divisors, too. if (divisor > 0) { let rems32 = `(module (func (export "f") (param i32) (result i32) (i32.rem_s (local.get 0) (i32.const -${divisor}))))`; codegenTestLOONG64_adhoc(rems32, "f", expected); } } // Unigned 32-bit remainder with constants. const i32_rem_u = [ // Division by zero. { divisor: 0, expected: `slli\\.w \\$a2, \\$a0, 0x0 slli\\.w \\$a1, \\$a2, 0x0 ${WasmTrapIns}`, }, // Power of two divisor { divisor: 1, expected: `addi\\.w \\$a0, \\$zero, 0`, }, { divisor: 2, expected: `bstrpick\\.w \\$a0, \\$a0, 0x0, 0x0`, }, { divisor: 4, expected: `bstrpick\\.w \\$a0, \\$a0, 0x1, 0x0`, }, { divisor: 0x100, expected: `bstrpick\\.w \\$a0, \\$a0, 0x7, 0x0`, }, { divisor: 0x10000, expected: `bstrpick\\.w \\$a0, \\$a0, 0xf, 0x0`, }, { divisor: 0x8000_0000, expected: `bstrpick\\.w \\$a0, \\$a0, 0x1e, 0x0`, }, ]; for (let {divisor, expected} of i32_rem_u) { let remu32 = `(module (func (export "f") (param i32) (result i32) (i32.rem_u (local.get 0) (i32.const ${divisor}))))`; codegenTestLOONG64_adhoc(remu32, "f", expected); } function i64RemPowTwoExpected(msb) { return `blt \\$a0, \\$zero, 20 -> ${HEX}+ ${NopIns} bstrpick\\.d \\$a0, \\$a0, ${msb}, 0x0 beq \\$zero, \\$zero, 20 -> ${HEX}+ ${NopIns} sub\\.d \\$a0, \\$zero, \\$a0 bstrpick\\.d \\$a0, \\$a0, ${msb}, 0x0 sub\\.d \\$a0, \\$zero, \\$a0`; } // Signed 64-bit remainder with constants. const i64_rem_s = [ // Division by zero. { divisor: 0, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero ${WasmTrapIns}`, }, // Power of two divisor { divisor: 1, expected: `or \\$a0, \\$zero, \\$zero`, }, { divisor: 2, expected: i64RemPowTwoExpected("0x0"), }, { divisor: 4, expected: i64RemPowTwoExpected("0x1"), }, { divisor: 0x100, expected: i64RemPowTwoExpected("0x7"), }, { divisor: 0x10000, expected: i64RemPowTwoExpected("0xf"), }, { divisor: 0x8000_0000, expected: i64RemPowTwoExpected("0x1e"), }, { divisor: 0x1_0000_0000, expected: i64RemPowTwoExpected("0x1f"), }, { divisor: 0x8000_0000_0000_0000n, expected: i64RemPowTwoExpected("0x3e"), }, // Other divisors. { divisor: 0x3_0000_0000, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, -349526 lu32i\\.d \\$t6, -349526 lu52i\\.d \\$t6, \\$t6, 682 ori \\$t6, \\$t6, 0xaab mulh\\.d \\$a0, \\$a1, \\$t6 srai\\.d \\$a0, \\$a0, 0x1f srai\\.d \\$t6, \\$a1, 0x3f sub\\.d \\$a0, \\$a0, \\$t6 lu12i\\.w \\$t6, 0 lu32i\\.d \\$t6, 3 mul\\.d \\$a0, \\$a0, \\$t6 sub\\.d \\$a0, \\$a1, \\$a0`, negative: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, -349526 lu32i\\.d \\$t6, -349526 lu52i\\.d \\$t6, \\$t6, 682 ori \\$t6, \\$t6, 0xaab mulh\\.d \\$a0, \\$a1, \\$t6 srai\\.d \\$a0, \\$a0, 0x1f srai\\.d \\$t6, \\$a1, 0x3f sub\\.d \\$a0, \\$a0, \\$t6 sub\\.d \\$a0, \\$zero, \\$a0 lu12i\\.w \\$t6, 0 lu32i\\.d \\$t6, -3 mul\\.d \\$a0, \\$a0, \\$t6 sub\\.d \\$a0, \\$a1, \\$a0`, }, ]; for (let {divisor, expected, negative = expected} of i64_rem_s) { let rems64 = `(module (func (export "f") (param i64) (result i64) (i64.rem_s (local.get 0) (i64.const ${divisor}))))`; codegenTestLOONG64_adhoc(rems64, "f", expected); // Test negative divisors, too. if (divisor > 0) { let rems64 = `(module (func (export "f") (param i64) (result i64) (i64.rem_s (local.get 0) (i64.const -${divisor}))))`; codegenTestLOONG64_adhoc(rems64, "f", negative); } } // Unsigned 64-bit remainder with constants. const i64_rem_u = [ { divisor: 0, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero ${WasmTrapIns}`, }, { divisor: 1, expected: `or \\$a0, \\$zero, \\$zero`, }, { divisor: 2, expected: `bstrpick\\.d \\$a0, \\$a0, 0x0, 0x0`, }, { divisor: 4, expected: `bstrpick\\.d \\$a0, \\$a0, 0x1, 0x0`, }, { divisor: 0x100, expected: `bstrpick\\.d \\$a0, \\$a0, 0x7, 0x0`, }, { divisor: 0x10000, expected: `bstrpick\\.d \\$a0, \\$a0, 0xf, 0x0`, }, { divisor: 0x8000_0000, expected: `bstrpick\\.d \\$a0, \\$a0, 0x1e, 0x0`, }, { divisor: 0x1_0000_0000, expected: `bstrpick\\.d \\$a0, \\$a0, 0x1f, 0x0`, }, { divisor: 0x8000_0000_0000_0000n, expected: `bstrpick\\.d \\$a0, \\$a0, 0x3e, 0x0`, }, // Other divisors. { divisor: 0x3_0000_0000, expected: `or \\$a2, \\$a0, \\$zero or \\$a1, \\$a2, \\$zero lu12i\\.w \\$t6, -349526 lu32i\\.d \\$t6, -349526 lu52i\\.d \\$t6, \\$t6, -1366 ori \\$t6, \\$t6, 0xaab mulh\\.du \\$a0, \\$a1, \\$t6 srli\\.d \\$a0, \\$a0, 0x21 lu12i\\.w \\$t6, 0 lu32i\\.d \\$t6, 3 mul\\.d \\$a0, \\$a0, \\$t6 sub\\.d \\$a0, \\$a1, \\$a0`, }, ]; for (let {divisor, expected} of i64_rem_u) { let remu64 = `(module (func (export "f") (param i64) (result i64) (i64.rem_u (local.get 0) (i64.const ${divisor}))))`; codegenTestLOONG64_adhoc(remu64, "f", expected); }