diff options
| -rw-r--r-- | src/ARMJIT_A64/ARMJIT_ALU.cpp | 88 | ||||
| -rw-r--r-- | src/dolphin/Arm64Emitter.cpp | 16 | ||||
| -rw-r--r-- | src/dolphin/Arm64Emitter.h | 2 | 
3 files changed, 67 insertions, 39 deletions
diff --git a/src/ARMJIT_A64/ARMJIT_ALU.cpp b/src/ARMJIT_A64/ARMJIT_ALU.cpp index 6f1f99c..1bd427f 100644 --- a/src/ARMJIT_A64/ARMJIT_ALU.cpp +++ b/src/ARMJIT_A64/ARMJIT_ALU.cpp @@ -324,16 +324,29 @@ void Compiler::Comp_Arithmetic(int op, bool S, ARM64Reg rd, ARM64Reg rn, Op2 op2          UBFX(W2, RCPSR, 29, 1);          if (S)          { -            CVInGPR = true; -            ADDS(W1, rn, W2); -            CSET(W2, CC_CS); -            CSET(W3, CC_VS);              if (op2.IsImm) -                ADDSI2R(rd, W1, op2.Imm, W0); +            { +                CVInGPR = true; +                ADDS(W1, rn, W2); +                CSET(W2, CC_CS); +                CSET(W3, CC_VS); +                if (op2.IsImm) +                    ADDSI2R(rd, W1, op2.Imm, W0); +                else +                    ADDS(rd, W1, op2.Reg.Rm, op2.ToArithOption()); +                CSINC(W2, W2, WZR, CC_CC); +                CSINC(W3, W3, WZR, CC_VC); +            }              else -                ADDS(rd, W1, op2.Reg.Rm, op2.ToArithOption()); -            CSINC(W2, W2, WZR, CC_CC); -            CSINC(W3, W3, WZR, CC_VC); +            { +                if (op2.Reg.ShiftAmount > 0) +                { +                    MOV(W0, op2.Reg.Rm, op2.ToArithOption()); +                    op2 = Op2(W0, ST_LSL, 0); +                } +                CMP(W2, 1); +                ADCS(rd, rn, op2.Reg.Rm); +            }          }          else          { @@ -346,25 +359,38 @@ void Compiler::Comp_Arithmetic(int op, bool S, ARM64Reg rd, ARM64Reg rn, Op2 op2          break;      case 0x6: // SBC          UBFX(W2, RCPSR, 29, 1); -        // W1 = -op2 - 1 -        if (op2.IsImm) -            MOVI2R(W1, ~op2.Imm); -        else -            ORN(W1, WZR, op2.Reg.Rm, op2.ToArithOption()); -        if (S) +        if (S && !op2.IsImm)          { -            CVInGPR = true; -            ADDS(W1, W2, W1); -            CSET(W2, CC_CS); -            CSET(W3, CC_VS); -            ADDS(rd, rn, W1); -            CSINC(W2, W2, WZR, CC_CC); -            CSINC(W3, W3, WZR, CC_VC); +            if (op2.Reg.ShiftAmount > 0) +            { +                MOV(W0, op2.Reg.Rm, op2.ToArithOption()); +                op2 = Op2(W0, ST_LSL, 0); +            } +            CMP(W2, 1); +            SBCS(rd, rn, op2.Reg.Rm);          }          else          { -            ADD(W1, W2, W1); -            ADD(rd, rn, W1); +            // W1 = -op2 - 1 +            if (op2.IsImm) +                MOVI2R(W1, ~op2.Imm); +            else +                ORN(W1, WZR, op2.Reg.Rm, op2.ToArithOption()); +            if (S) +            { +                CVInGPR = true; +                ADDS(W1, W2, W1); +                CSET(W2, CC_CS); +                CSET(W3, CC_VS); +                ADDS(rd, rn, W1); +                CSINC(W2, W2, WZR, CC_CC); +                CSINC(W3, W3, WZR, CC_VC); +            } +            else +            { +                ADD(W1, W2, W1); +                ADD(rd, rn, W1); +            }          }          break;      case 0x7: // RSC @@ -533,21 +559,7 @@ void Compiler::A_Comp_ALUMovOp()          }          else          { -            // ORR with shifted operand has cycles latency -            if (op2.Reg.ShiftAmount > 0) -            { -                switch (op2.Reg.ShiftType) -                { -                case ST_LSL: LSL(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break; -                case ST_LSR: LSR(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break; -                case ST_ASR: ASR(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break; -                case ST_ROR: ROR(rd, op2.Reg.Rm, op2.Reg.ShiftAmount); break; -                } -            } -            else -            { -                MOV(rd, op2.Reg.Rm, op2.ToArithOption()); -            } +            MOV(rd, op2.Reg.Rm, op2.ToArithOption());          }      } diff --git a/src/dolphin/Arm64Emitter.cpp b/src/dolphin/Arm64Emitter.cpp index 408411c..47e97b1 100644 --- a/src/dolphin/Arm64Emitter.cpp +++ b/src/dolphin/Arm64Emitter.cpp @@ -1607,7 +1607,21 @@ void ARM64XEmitter::BICS(ARM64Reg Rd, ARM64Reg Rn, ARM64Reg Rm, ArithOption Shif  void ARM64XEmitter::MOV(ARM64Reg Rd, ARM64Reg Rm, ArithOption Shift)  { -  ORR(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, Shift); +  if (Shift.GetType() == ArithOption::TYPE_SHIFTEDREG) +  { +    switch (Shift.GetShiftType()) +    { +    case ST_LSL: LSL(Rd, Rm, Shift.GetShiftAmount()); break; +    case ST_LSR: LSR(Rd, Rm, Shift.GetShiftAmount()); break; +    case ST_ASR: ASR(Rd, Rm, Shift.GetShiftAmount()); break; +    case ST_ROR: ROR(Rd, Rm, Shift.GetShiftAmount()); break; +    default: ASSERT_MSG(DYNA_REC, false, "Invalid shift type"); break; +    } +  } +  else +  { +    ORR(Rd, Is64Bit(Rd) ? ZR : WZR, Rm, Shift); +  }  }  void ARM64XEmitter::MOV(ARM64Reg Rd, ARM64Reg Rm) diff --git a/src/dolphin/Arm64Emitter.h b/src/dolphin/Arm64Emitter.h index 3da3912..0b066de 100644 --- a/src/dolphin/Arm64Emitter.h +++ b/src/dolphin/Arm64Emitter.h @@ -469,6 +469,8 @@ public:    }    TypeSpecifier GetType() const { return m_type; }    ARM64Reg GetReg() const { return m_destReg; } +  ShiftType GetShiftType() const { return m_shifttype; } +  u32 GetShiftAmount() const { return m_shift; }    u32 GetData() const    {      switch (m_type)  |