From 3faf2d124906caae80809192a0d8305ebfa88f45 Mon Sep 17 00:00:00 2001 From: Basilisk-Dev Date: Wed, 22 Apr 2026 23:39:10 -0400 Subject: [PATCH] Issue #3049 - Add LoongArch minimal JIT multiply support --- .../tests/basic/loongarch-minimal-jit.js | 13 +++++++ js/src/jit/LoongArchMinimalJit.cpp | 37 +++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) 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 1c67f3cb16..884b7b4ed6 100644 --- a/js/src/jit-test/tests/basic/loongarch-minimal-jit.js +++ b/js/src/jit-test/tests/basic/loongarch-minimal-jit.js @@ -80,6 +80,14 @@ function unsignedRightShift(a, b) { return a >>> b; } +function multiply(a, b) { + return a * b; +} + +function multiplyZero(a) { + return a * 0; +} + function assignArg(a, b) { a = a < b; return a; @@ -150,6 +158,11 @@ assertEq(leftShift(1, 33), 2); assertEq(rightShift(-8, 1), -4); assertEq(unsignedRightShift(-1, 1), 2147483647); assertEq(unsignedRightShift(-1, 0), 4294967295); +assertEq(multiply(6, 7), 42); +assertEq(multiply(-3, 7), -21); +assertEq(multiply(1073741824, 4), 4294967296); +assertEq(multiplyZero(3), 0); +assertEq(1 / multiplyZero(-3), -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 962e65c185..23fe000fdc 100644 --- a/js/src/jit/LoongArchMinimalJit.cpp +++ b/js/src/jit/LoongArchMinimalJit.cpp @@ -349,6 +349,31 @@ class MinimalLoongArchCompiler MOZ_CRASH("bad shift opcode"); } + bool emitMul(LoongArchReg lhs, LoongArchReg rhs, LoongArchReg out) { + if (!emit(EncodeThreeReg(0x001c8000, WideScratch, lhs, rhs))) + return false; + if (!emit(EncodeThreeReg(0x001c0000, out, lhs, rhs))) + return false; + if (!emitLoadImm32(NarrowScratch, 31)) + return false; + if (!emit(EncodeThreeReg(0x00180000, NarrowScratch, out, NarrowScratch))) + return false; + if (!emitFailureBranch()) + return false; + + if (!emitEq(out, zero, WideScratch, false)) + return false; + if (!emit(EncodeThreeReg(0x00150000, NarrowScratch, lhs, rhs))) + return false; + if (!emit(EncodeThreeReg(0x00120000, NarrowScratch, NarrowScratch, 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)) @@ -608,7 +633,8 @@ class MinimalLoongArchCompiler case JSOP_NOP: break; case JSOP_ADD: - case JSOP_SUB: { + case JSOP_SUB: + case JSOP_MUL: { StackValue rhs; StackValue lhs; if (!pop(&rhs) || !pop(&lhs)) @@ -616,8 +642,13 @@ class MinimalLoongArchCompiler if (!IsNumericKind(lhs.kind) || !IsNumericKind(rhs.kind)) return false; LoongArchReg out = allocStackReg(); - if (!emitCheckedBinary(op, lhs.reg, rhs.reg, out)) - return false; + if (op == JSOP_MUL) { + if (!emitMul(lhs.reg, rhs.reg, out)) + return false; + } else { + if (!emitCheckedBinary(op, lhs.reg, rhs.reg, out)) + return false; + } stack_[stackDepth_++] = { out, MinimalValueKind::Int32 }; break; }