Issue #3049 - Add LoongArch minimal JIT shifts and negation

This commit is contained in:
Basilisk-Dev 2026-04-22 23:37:23 -04:00 committed by wuggy
commit 02eaa0dbc6
2 changed files with 78 additions and 0 deletions

View file

@ -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);

View file

@ -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: {