diff --git a/js/src/jit-test/tests/basic/loongarch-minimal-jit.js b/js/src/jit-test/tests/basic/loongarch-minimal-jit.js index 884b7b4ed6..e24997d73d 100644 --- a/js/src/jit-test/tests/basic/loongarch-minimal-jit.js +++ b/js/src/jit-test/tests/basic/loongarch-minimal-jit.js @@ -88,6 +88,22 @@ function multiplyZero(a) { return a * 0; } +function divide(a, b) { + return a / b; +} + +function divideNegativeZero(a) { + return 0 / a; +} + +function remainder(a, b) { + return a % b; +} + +function remainderNegativeZero(a) { + return a % 2; +} + function assignArg(a, b) { a = a < b; return a; @@ -163,6 +179,14 @@ assertEq(multiply(-3, 7), -21); assertEq(multiply(1073741824, 4), 4294967296); assertEq(multiplyZero(3), 0); assertEq(1 / multiplyZero(-3), -Infinity); +assertEq(divide(8, 2), 4); +assertEq(divide(-9, 3), -3); +assertEq(divide(7, 2), 3.5); +assertEq(1 / divideNegativeZero(-3), -Infinity); +assertEq(divide(-2147483648, -1), 2147483648); +assertEq(remainder(7, 3), 1); +assertEq(remainder(8, 2), 0); +assertEq(1 / remainderNegativeZero(-4), -Infinity); assertEq(assignArg(2, 3), true); assertEq(assignArg(3, 2), false); assertEq(boolToNumeric(2, 3), 1); diff --git a/js/src/jit/LoongArchMinimalJit.cpp b/js/src/jit/LoongArchMinimalJit.cpp index 23fe000fdc..e253639344 100644 --- a/js/src/jit/LoongArchMinimalJit.cpp +++ b/js/src/jit/LoongArchMinimalJit.cpp @@ -374,6 +374,72 @@ class MinimalLoongArchCompiler return emitFailureBranch(); } + bool emitDiv(LoongArchReg lhs, LoongArchReg rhs, LoongArchReg out) { + if (!emitNot(rhs, WideScratch)) + return false; + if (!emitMove(NarrowScratch, zero)) + return false; + if (!emitFailureBranch()) + return false; + + if (!emitNot(lhs, WideScratch)) + return false; + if (!emit(EncodeThreeReg(0x00120000, NarrowScratch, rhs, zero))) + return false; + if (!emit(EncodeThreeReg(0x00148000, WideScratch, WideScratch, NarrowScratch))) + return false; + if (!emitMove(NarrowScratch, zero)) + return false; + if (!emitFailureBranch()) + return false; + + if (!emitLoadImm32(NarrowScratch, -1)) + return false; + if (!emitEq(rhs, NarrowScratch, WideScratch, false)) + return false; + if (!emitLoadImm32(NarrowScratch, INT32_MIN)) + return false; + if (!emit(EncodeThreeReg(0x00158000, NarrowScratch, lhs, NarrowScratch))) + return false; + if (!emitSltui(NarrowScratch, NarrowScratch, 1)) + return false; + if (!emit(EncodeThreeReg(0x00148000, WideScratch, WideScratch, NarrowScratch))) + return false; + if (!emitMove(NarrowScratch, zero)) + return false; + if (!emitFailureBranch()) + return false; + + if (!emit(EncodeThreeReg(0x00200000, out, lhs, rhs))) + return false; + if (!emit(EncodeThreeReg(0x00208000, WideScratch, lhs, rhs))) + return false; + if (!emitMove(NarrowScratch, zero)) + return false; + return emitFailureBranch(); + } + + bool emitMod(LoongArchReg lhs, LoongArchReg rhs, LoongArchReg out) { + if (!emitNot(rhs, WideScratch)) + return false; + if (!emitMove(NarrowScratch, zero)) + return false; + if (!emitFailureBranch()) + return false; + + if (!emit(EncodeThreeReg(0x00208000, out, lhs, rhs))) + return false; + if (!emitNot(out, WideScratch)) + return false; + if (!emit(EncodeThreeReg(0x00120000, NarrowScratch, lhs, zero))) + return false; + if (!emit(EncodeThreeReg(0x00148000, WideScratch, WideScratch, NarrowScratch))) + return false; + if (!emitMove(NarrowScratch, zero)) + return false; + return emitFailureBranch(); + } + bool emitBranch(BranchKind kind, LoongArchReg reg, uint32_t targetPcOffset) { BranchPatch patch = { wordCount_, targetPcOffset, kind, reg }; if (!branchPatches_.append(patch)) @@ -634,7 +700,9 @@ class MinimalLoongArchCompiler break; case JSOP_ADD: case JSOP_SUB: - case JSOP_MUL: { + case JSOP_MUL: + case JSOP_DIV: + case JSOP_MOD: { StackValue rhs; StackValue lhs; if (!pop(&rhs) || !pop(&lhs)) @@ -642,12 +710,23 @@ class MinimalLoongArchCompiler if (!IsNumericKind(lhs.kind) || !IsNumericKind(rhs.kind)) return false; LoongArchReg out = allocStackReg(); - if (op == JSOP_MUL) { + switch (op) { + case JSOP_MUL: if (!emitMul(lhs.reg, rhs.reg, out)) return false; - } else { + break; + case JSOP_DIV: + if (!emitDiv(lhs.reg, rhs.reg, out)) + return false; + break; + case JSOP_MOD: + if (!emitMod(lhs.reg, rhs.reg, out)) + return false; + break; + default: if (!emitCheckedBinary(op, lhs.reg, rhs.reg, out)) return false; + break; } stack_[stackDepth_++] = { out, MinimalValueKind::Int32 }; break;