diff --git a/Common/Arm64Emitter.cpp b/Common/Arm64Emitter.cpp index 1c4984653..ad834e187 100644 --- a/Common/Arm64Emitter.cpp +++ b/Common/Arm64Emitter.cpp @@ -3664,14 +3664,10 @@ void ARM64FloatEmitter::ABI_PopRegisters(uint32_t registers, uint32_t fp_registe } void ARM64XEmitter::ANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { - unsigned int n, imm_s, imm_r; + // It's probably okay to AND by extra bits. if (!Is64Bit(Rn)) imm &= 0xFFFFFFFF; - if (IsImmLogical(imm, Is64Bit(Rn) ? 64 : 32, &n, &imm_s, &imm_r)) { - AND(Rd, Rn, imm_r, imm_s, n != 0); - } else if (imm == 0) { - MOVI2R(Rd, 0); - } else { + if (!TryANDI2R(Rd, Rn, imm)) { _assert_msg_(JIT, scratch != INVALID_REG, "ANDI2R - failed to construct logical immediate value from %08x, need scratch", (u32)imm); MOVI2R(scratch, imm); AND(Rd, Rn, scratch); @@ -3679,14 +3675,8 @@ void ARM64XEmitter::ANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) } void ARM64XEmitter::ORRI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { - unsigned int n, imm_s, imm_r; - if (IsImmLogical(imm, Is64Bit(Rn) ? 64 : 32, &n, &imm_s, &imm_r)) { - ORR(Rd, Rn, imm_r, imm_s, n != 0); - } else if (imm == 0) { - if (Rd != Rn) { - MOV(Rd, Rn); - } - } else { + _assert_msg_(JIT, Is64Bit(Rn) || (imm & 0xFFFFFFFF00000000UL) == 0, "ORRI2R - more bits in imm than Rn"); + if (!TryORRI2R(Rd, Rn, imm)) { _assert_msg_(JIT, scratch != INVALID_REG, "ORRI2R - failed to construct logical immediate value from %08x, need scratch", (u32)imm); MOVI2R(scratch, imm); ORR(Rd, Rn, scratch); @@ -3694,14 +3684,8 @@ void ARM64XEmitter::ORRI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) } void ARM64XEmitter::EORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { - unsigned int n, imm_s, imm_r; - if (IsImmLogical(imm, Is64Bit(Rn) ? 64 : 32, &n, &imm_s, &imm_r)) { - EOR(Rd, Rn, imm_r, imm_s, n != 0); - } else if (imm == 0) { - if (Rd != Rn) { - MOV(Rd, Rn); - } - } else { + _assert_msg_(JIT, Is64Bit(Rn) || (imm & 0xFFFFFFFF00000000UL) == 0, "EORI2R - more bits in imm than Rn"); + if (!TryEORI2R(Rd, Rn, imm)) { _assert_msg_(JIT, scratch != INVALID_REG, "EORI2R - failed to construct logical immediate value from %08x, need scratch", (u32)imm); MOVI2R(scratch, imm); EOR(Rd, Rn, scratch); @@ -3709,11 +3693,13 @@ void ARM64XEmitter::EORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) } void ARM64XEmitter::ANDSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { + if (!Is64Bit(Rn)) + imm &= 0xFFFFFFFF; unsigned int n, imm_s, imm_r; if (IsImmLogical(imm, Is64Bit(Rn) ? 64 : 32, &n, &imm_s, &imm_r)) { ANDS(Rd, Rn, imm_r, imm_s, n != 0); } else if (imm == 0) { - ANDS(Rd, Rn, Is64Bit(Rn) ? ZR : WZR, ArithOption(Rd, ST_LSL, 0)); + ANDS(Rd, Rn, Is64Bit(Rn) ? ZR : WZR); } else { _assert_msg_(JIT, scratch != INVALID_REG, "ANDSI2R - failed to construct logical immediate value from %08x, need scratch", (u32)imm); MOVI2R(scratch, imm); @@ -3722,11 +3708,7 @@ void ARM64XEmitter::ANDSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) } void ARM64XEmitter::ADDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { - u32 val; - bool shift; - if (IsImmArithmetic(imm, &val, &shift)) { - ADD(Rd, Rn, val, shift); - } else { + if (!TryADDI2R(Rd, Rn, imm)) { _assert_msg_(JIT, scratch != INVALID_REG, "ADDI2R - failed to construct arithmetic immediate value from %08x, need scratch", (u32)imm); MOVI2R(scratch, imm); ADD(Rd, Rn, scratch); @@ -3734,11 +3716,7 @@ void ARM64XEmitter::ADDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) } void ARM64XEmitter::SUBI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) { - u32 val; - bool shift; - if (IsImmArithmetic(imm, &val, &shift)) { - SUB(Rd, Rn, val, shift); - } else { + if (!TrySUBI2R(Rd, Rn, imm)) { _assert_msg_(JIT, scratch != INVALID_REG, "SUBI2R - failed to construct arithmetic immediate value from %08x, need scratch", (u32)imm); MOVI2R(scratch, imm); SUB(Rd, Rn, scratch); @@ -3746,18 +3724,14 @@ void ARM64XEmitter::SUBI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch) } void ARM64XEmitter::CMPI2R(ARM64Reg Rn, u64 imm, ARM64Reg scratch) { - u32 val; - bool shift; - if (IsImmArithmetic(imm, &val, &shift)) { - CMP(Rn, val, shift); - } else { + if (!TryCMPI2R(Rn, imm)) { _assert_msg_(JIT, scratch != INVALID_REG, "CMPI2R - failed to construct arithmetic immediate value from %08x, need scratch", (u32)imm); MOVI2R(scratch, imm); CMP(Rn, scratch); } } -bool ARM64XEmitter::TryADDI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) { +bool ARM64XEmitter::TryADDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm) { u32 val; bool shift; if (IsImmArithmetic(imm, &val, &shift)) { @@ -3768,7 +3742,7 @@ bool ARM64XEmitter::TryADDI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) { } } -bool ARM64XEmitter::TrySUBI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) { +bool ARM64XEmitter::TrySUBI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm) { u32 val; bool shift; if (IsImmArithmetic(imm, &val, &shift)) { @@ -3779,7 +3753,7 @@ bool ARM64XEmitter::TrySUBI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) { } } -bool ARM64XEmitter::TryCMPI2R(ARM64Reg Rn, u32 imm) { +bool ARM64XEmitter::TryCMPI2R(ARM64Reg Rn, u64 imm) { u32 val; bool shift; if (IsImmArithmetic(imm, &val, &shift)) { @@ -3790,9 +3764,11 @@ bool ARM64XEmitter::TryCMPI2R(ARM64Reg Rn, u32 imm) { } } -bool ARM64XEmitter::TryANDI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) { +bool ARM64XEmitter::TryANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm) { + if (!Is64Bit(Rn)) + imm &= 0xFFFFFFFF; u32 n, imm_r, imm_s; - if (IsImmLogical(imm, 32, &n, &imm_s, &imm_r)) { + if (IsImmLogical(imm, Is64Bit(Rn) ? 64 : 32, &n, &imm_s, &imm_r)) { AND(Rd, Rn, imm_r, imm_s, n != 0); return true; } else if (imm == 0) { @@ -3802,9 +3778,10 @@ bool ARM64XEmitter::TryANDI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) { return false; } } -bool ARM64XEmitter::TryORRI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) { +bool ARM64XEmitter::TryORRI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm) { + _assert_msg_(JIT, Is64Bit(Rn) || (imm & 0xFFFFFFFF00000000UL) == 0, "TryORRI2R - more bits in imm than Rn"); u32 n, imm_r, imm_s; - if (IsImmLogical(imm, 32, &n, &imm_s, &imm_r)) { + if (IsImmLogical(imm, Is64Bit(Rn) ? 64 : 32, &n, &imm_s, &imm_r)) { ORR(Rd, Rn, imm_r, imm_s, n != 0); return true; } else if (imm == 0) { @@ -3816,9 +3793,10 @@ bool ARM64XEmitter::TryORRI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) { return false; } } -bool ARM64XEmitter::TryEORI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm) { +bool ARM64XEmitter::TryEORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm) { + _assert_msg_(JIT, Is64Bit(Rn) || (imm & 0xFFFFFFFF00000000UL) == 0, "TryEORI2R - more bits in imm than Rn"); u32 n, imm_r, imm_s; - if (IsImmLogical(imm, 32, &n, &imm_s, &imm_r)) { + if (IsImmLogical(imm, Is64Bit(Rn) ? 64 : 32, &n, &imm_s, &imm_r)) { EOR(Rd, Rn, imm_r, imm_s, n != 0); return true; } else if (imm == 0) { diff --git a/Common/Arm64Emitter.h b/Common/Arm64Emitter.h index 4a05b9564..097d82a85 100644 --- a/Common/Arm64Emitter.h +++ b/Common/Arm64Emitter.h @@ -714,13 +714,13 @@ public: void SUBI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG); void SUBSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch = INVALID_REG); - bool TryADDI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm); - bool TrySUBI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm); - bool TryCMPI2R(ARM64Reg Rn, u32 imm); + bool TryADDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm); + bool TrySUBI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm); + bool TryCMPI2R(ARM64Reg Rn, u64 imm); - bool TryANDI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm); - bool TryORRI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm); - bool TryEORI2R(ARM64Reg Rd, ARM64Reg Rn, u32 imm); + bool TryANDI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm); + bool TryORRI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm); + bool TryEORI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm); // Pseudo-instruction for convenience. PUSH pushes 16 bytes even though we only push a single register. // This is so the stack pointer is always 16-byte aligned, which is checked by hardware! diff --git a/Core/MIPS/ARM64/Arm64CompALU.cpp b/Core/MIPS/ARM64/Arm64CompALU.cpp index dfa1d8b0d..2bda62502 100644 --- a/Core/MIPS/ARM64/Arm64CompALU.cpp +++ b/Core/MIPS/ARM64/Arm64CompALU.cpp @@ -57,7 +57,7 @@ static u32 EvalAnd(u32 a, u32 b) { return a & b; } static u32 EvalAdd(u32 a, u32 b) { return a + b; } static u32 EvalSub(u32 a, u32 b) { return a - b; } -void Arm64Jit::CompImmLogic(MIPSGPReg rs, MIPSGPReg rt, u32 uimm, void (ARM64XEmitter::*arith)(ARM64Reg dst, ARM64Reg src, ARM64Reg src2), bool (ARM64XEmitter::*tryArithI2R)(ARM64Reg dst, ARM64Reg src, u32 val), u32 (*eval)(u32 a, u32 b)) { +void Arm64Jit::CompImmLogic(MIPSGPReg rs, MIPSGPReg rt, u32 uimm, void (ARM64XEmitter::*arith)(ARM64Reg dst, ARM64Reg src, ARM64Reg src2), bool (ARM64XEmitter::*tryArithI2R)(ARM64Reg dst, ARM64Reg src, u64 val), u32 (*eval)(u32 a, u32 b)) { if (gpr.IsImm(rs)) { gpr.SetImm(rt, (*eval)(gpr.GetImm(rs), uimm)); } else { @@ -119,7 +119,7 @@ void Arm64Jit::Comp_IType(MIPSOpcode op) { break; } gpr.MapDirtyIn(rt, rs); - if (!TryCMPI2R(gpr.R(rs), simm)) { + if (!TryCMPI2R(gpr.R(rs), (u32)simm)) { gpr.SetRegImm(SCRATCH1, simm); CMP(gpr.R(rs), SCRATCH1); } @@ -196,7 +196,7 @@ void Arm64Jit::Comp_RType2(MIPSOpcode op) { } } -void Arm64Jit::CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARM64XEmitter::*arith)(ARM64Reg dst, ARM64Reg rm, ARM64Reg rn), bool (ARM64XEmitter::*tryArithI2R)(ARM64Reg dst, ARM64Reg rm, u32 val), u32(*eval)(u32 a, u32 b), bool symmetric) { +void Arm64Jit::CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARM64XEmitter::*arith)(ARM64Reg dst, ARM64Reg rm, ARM64Reg rn), bool (ARM64XEmitter::*tryArithI2R)(ARM64Reg dst, ARM64Reg rm, u64 val), u32(*eval)(u32 a, u32 b), bool symmetric) { if (gpr.IsImm(rs) && gpr.IsImm(rt)) { gpr.SetImm(rd, (*eval)(gpr.GetImm(rs), gpr.GetImm(rt))); return; diff --git a/Core/MIPS/ARM64/Arm64Jit.h b/Core/MIPS/ARM64/Arm64Jit.h index e8874fa0b..545de5846 100644 --- a/Core/MIPS/ARM64/Arm64Jit.h +++ b/Core/MIPS/ARM64/Arm64Jit.h @@ -220,8 +220,8 @@ private: void BranchRSRTComp(MIPSOpcode op, CCFlags cc, bool likely); // Utilities to reduce duplicated code - void CompImmLogic(MIPSGPReg rs, MIPSGPReg rt, u32 uimm, void (ARM64XEmitter::*arith)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg src, Arm64Gen::ARM64Reg src2), bool (ARM64XEmitter::*tryArithI2R)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg src, u32 val), u32 (*eval)(u32 a, u32 b)); - void CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARM64XEmitter::*arithOp2)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg rm, Arm64Gen::ARM64Reg rn), bool (ARM64XEmitter::*tryArithI2R)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg rm, u32 val), u32 (*eval)(u32 a, u32 b), bool symmetric = false); + void CompImmLogic(MIPSGPReg rs, MIPSGPReg rt, u32 uimm, void (ARM64XEmitter::*arith)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg src, Arm64Gen::ARM64Reg src2), bool (ARM64XEmitter::*tryArithI2R)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg src, u64 val), u32 (*eval)(u32 a, u32 b)); + void CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARM64XEmitter::*arithOp2)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg rm, Arm64Gen::ARM64Reg rn), bool (ARM64XEmitter::*tryArithI2R)(Arm64Gen::ARM64Reg dst, Arm64Gen::ARM64Reg rm, u64 val), u32 (*eval)(u32 a, u32 b), bool symmetric = false); void CompShiftImm(MIPSOpcode op, Arm64Gen::ShiftType shiftType, int sa); void CompShiftVar(MIPSOpcode op, Arm64Gen::ShiftType shiftType); void CompVrotShuffle(u8 *dregs, int imm, VectorSize sz, bool negSin);