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 fd06ba3184..1c67f3cb16 100644 --- a/js/src/jit-test/tests/basic/loongarch-minimal-jit.js +++ b/js/src/jit-test/tests/basic/loongarch-minimal-jit.js @@ -64,6 +64,22 @@ function invertBits(a) { return ~a; } +function negate(a) { + return -a; +} + +function leftShift(a, b) { + return a << b; +} + +function rightShift(a, b) { + return a >> b; +} + +function unsignedRightShift(a, b) { + return a >>> b; +} + function assignArg(a, b) { a = a < b; return a; @@ -125,6 +141,15 @@ assertEq(boolLooseNe(2, 3), false); assertEq(boolLooseNe(3, 2), true); assertEq(bitMix(6, 3), (6 & 3) ^ (6 | 8)); assertEq(invertBits(6), ~6); +assertEq(negate(3), -3); +assertEq(negate(-4), 4); +assertEq(1 / negate(0), -Infinity); +assertEq(negate(-2147483648), 2147483648); +assertEq(leftShift(3, 2), 12); +assertEq(leftShift(1, 33), 2); +assertEq(rightShift(-8, 1), -4); +assertEq(unsignedRightShift(-1, 1), 2147483647); +assertEq(unsignedRightShift(-1, 0), 4294967295); 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 88a5c3192a..962e65c185 100644 --- a/js/src/jit/LoongArchMinimalJit.cpp +++ b/js/src/jit/LoongArchMinimalJit.cpp @@ -318,6 +318,37 @@ class MinimalLoongArchCompiler return emitSltui(out, src, 1); } + bool emitNeg(LoongArchReg src, LoongArchReg out) { + if (!emit(EncodeThreeReg(0x00110000, out, zero, src))) + return false; + if (!emitEq(out, src, WideScratch, false)) + return false; + if (!emitMove(NarrowScratch, zero)) + return false; + return emitFailureBranch(); + } + + bool emitShift(JSOp op, LoongArchReg lhs, LoongArchReg rhs, LoongArchReg out) { + switch (op) { + case JSOP_LSH: + return emit(EncodeThreeReg(0x00170000, out, lhs, rhs)); + case JSOP_RSH: + return emit(EncodeThreeReg(0x00180000, out, lhs, rhs)); + case JSOP_URSH: + if (!emit(EncodeThreeReg(0x00178000, out, lhs, rhs))) + return false; + if (!emit(EncodeThreeReg(0x00120000, WideScratch, out, zero))) + return false; + if (!emitMove(NarrowScratch, zero)) + return false; + return emitFailureBranch(); + default: + break; + } + + MOZ_CRASH("bad shift opcode"); + } + bool emitBranch(BranchKind kind, LoongArchReg reg, uint32_t targetPcOffset) { BranchPatch patch = { wordCount_, targetPcOffset, kind, reg }; if (!branchPatches_.append(patch)) @@ -649,6 +680,13 @@ class MinimalLoongArchCompiler stack_[stackDepth_++] = { out, MinimalValueKind::Boolean }; break; } + case JSOP_NEG: + if (!stackDepth_ || !IsNumericKind(stack_[stackDepth_ - 1].kind)) + return false; + if (!emitNeg(stack_[stackDepth_ - 1].reg, stack_[stackDepth_ - 1].reg)) + return false; + stack_[stackDepth_ - 1].kind = MinimalValueKind::Int32; + break; case JSOP_NOT: { StackValue input; if (!pop(&input)) @@ -659,6 +697,21 @@ class MinimalLoongArchCompiler stack_[stackDepth_++] = { out, MinimalValueKind::Boolean }; break; } + case JSOP_LSH: + case JSOP_RSH: + case JSOP_URSH: { + StackValue rhs; + StackValue lhs; + if (!pop(&rhs) || !pop(&lhs)) + return false; + if (!IsNumericKind(lhs.kind) || !IsNumericKind(rhs.kind)) + return false; + LoongArchReg out = allocStackReg(); + if (!emitShift(op, lhs.reg, rhs.reg, out)) + return false; + stack_[stackDepth_++] = { out, MinimalValueKind::Int32 }; + break; + } case JSOP_BITAND: case JSOP_BITOR: case JSOP_BITXOR: {