diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 64ca42ea50..efb9569865 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -99,6 +99,7 @@ static void SetHostRoundingMode(u32 rn) namespace ppu_recompiler_llvm { class Compiler; + class RecompilationEngine; } class ppu_llvm_test_class; @@ -108,6 +109,7 @@ class PPUInterpreter : public PPUOpcodes #ifdef PPU_LLVM_RECOMPILER friend class ppu_recompiler_llvm::Compiler; friend class ppu_llvm_test_class; + friend class ppu_recompiler_llvm::RecompilationEngine; #endif private: PPUThread& CPU; @@ -236,13 +238,13 @@ private: } } - void TWI(u32 to, u32 ra, s32 simm16) + static void TWI_impl(PPUThread *CPU, u32 to, u32 ra, s32 simm16) { - s32 a = (s32)CPU.GPR[ra]; + s32 a = (s32)CPU->GPR[ra]; - if( (a < simm16 && (to & 0x10)) || - (a > simm16 && (to & 0x8)) || - (a == simm16 && (to & 0x4)) || + if ((a < simm16 && (to & 0x10)) || + (a > simm16 && (to & 0x8)) || + (a == simm16 && (to & 0x4)) || ((u32)a < (u32)simm16 && (to & 0x2)) || ((u32)a > (u32)simm16 && (to & 0x1)) ) { @@ -250,6 +252,11 @@ private: } } + void TWI(u32 to, u32 ra, s32 simm16) + { + TWI_impl(&CPU, to, ra, simm16); + } + void MFVSCR(u32 vd) //nf { CPU.VPR[vd].clear(); @@ -2198,47 +2205,85 @@ private: CPU.VPR[vd]._u32[2] = CPU.VPR[va]._u32[2] ^ CPU.VPR[vb]._u32[2]; CPU.VPR[vd]._u32[3] = CPU.VPR[va]._u32[3] ^ CPU.VPR[vb]._u32[3]; } + static void MULLI_impl(PPUThread *CPU, u32 rd, u32 ra, s32 simm16) + { + CPU->GPR[rd] = (s64)CPU->GPR[ra] * simm16; + } void MULLI(u32 rd, u32 ra, s32 simm16) { - CPU.GPR[rd] = (s64)CPU.GPR[ra] * simm16; + MULLI_impl(&CPU, rd, ra, simm16); + } + static void SUBFIC_impl(PPUThread *CPU, u32 rd, u32 ra, s32 simm16) + { + const u64 RA = CPU->GPR[ra]; + const u64 IMM = (s64)simm16; + CPU->GPR[rd] = ~RA + IMM + 1; + + CPU->XER.CA = CPU->IsCarry(~RA, IMM, 1); } void SUBFIC(u32 rd, u32 ra, s32 simm16) { - const u64 RA = CPU.GPR[ra]; - const u64 IMM = (s64)simm16; - CPU.GPR[rd] = ~RA + IMM + 1; + SUBFIC_impl(&CPU, rd, ra, simm16); + } - CPU.XER.CA = CPU.IsCarry(~RA, IMM, 1); - } - void CMPLI(u32 crfd, u32 l, u32 ra, u32 uimm16) + static void CMPLI_impl(PPUThread *CPU, u32 crfd, u32 l, u32 ra, u32 uimm16) { - CPU.UpdateCRnU(l, crfd, CPU.GPR[ra], uimm16); + CPU->UpdateCRnU(l, crfd, CPU->GPR[ra], uimm16); } - void CMPI(u32 crfd, u32 l, u32 ra, s32 simm16) + void CMPLI(u32 crfd, u32 l, u32 ra, u32 uimm16) override { - CPU.UpdateCRnS(l, crfd, CPU.GPR[ra], simm16); + CMPLI_impl(&CPU, crfd, l, ra, uimm16); + } + + static void CMPI_impl(PPUThread *CPU, u32 crfd, u32 l, u32 ra, s32 simm16) + { + CPU->UpdateCRnS(l, crfd, CPU->GPR[ra], simm16); + } + void CMPI(u32 crfd, u32 l, u32 ra, s32 simm16) override + { + CMPI_impl(&CPU, crfd, l, ra, simm16); + } + + static void ADDIC_impl(PPUThread *CPU, u32 rd, u32 ra, s32 simm16) + { + const u64 RA = CPU->GPR[ra]; + CPU->GPR[rd] = RA + simm16; + CPU->XER.CA = CPU->IsCarry(RA, simm16); } void ADDIC(u32 rd, u32 ra, s32 simm16) { - const u64 RA = CPU.GPR[ra]; - CPU.GPR[rd] = RA + simm16; - CPU.XER.CA = CPU.IsCarry(RA, simm16); + ADDIC_impl(&CPU, rd, ra, simm16); + } + static void ADDIC__impl(PPUThread *CPU, u32 rd, u32 ra, s32 simm16) + { + const u64 RA = CPU->GPR[ra]; + CPU->GPR[rd] = RA + simm16; + CPU->XER.CA = CPU->IsCarry(RA, simm16); + CPU->UpdateCR0(CPU->GPR[rd]); } void ADDIC_(u32 rd, u32 ra, s32 simm16) { - const u64 RA = CPU.GPR[ra]; - CPU.GPR[rd] = RA + simm16; - CPU.XER.CA = CPU.IsCarry(RA, simm16); - CPU.UpdateCR0(CPU.GPR[rd]); + ADDIC__impl(&CPU, rd, ra, simm16); } - void ADDI(u32 rd, u32 ra, s32 simm16) + + static void ADDI_impl(PPUThread *CPU, u32 rd, u32 ra, s32 simm16) { - CPU.GPR[rd] = ra ? ((s64)CPU.GPR[ra] + simm16) : simm16; + CPU->GPR[rd] = ra ? ((s64)CPU->GPR[ra] + simm16) : simm16; } - void ADDIS(u32 rd, u32 ra, s32 simm16) + void ADDI(u32 rd, u32 ra, s32 simm16) override { - CPU.GPR[rd] = ra ? ((s64)CPU.GPR[ra] + (simm16 << 16)) : (simm16 << 16); + ADDI_impl(&CPU, rd, ra, simm16); } + + static void ADDIS_impl(PPUThread *CPU, u32 rd, u32 ra, s32 simm16) + { + CPU->GPR[rd] = ra ? ((s64)CPU->GPR[ra] + (simm16 << 16)) : (simm16 << 16); + } + void ADDIS(u32 rd, u32 ra, s32 simm16) override + { + ADDIS_impl(&CPU, rd, ra, simm16); + } + void BC(u32 bo, u32 bi, s32 bd, u32 aa, u32 lk) { if (CheckCondition(bo, bi)) @@ -2272,9 +2317,13 @@ private: CPU.PC = branchTarget(aa ? 0 : CPU.PC, ll) - 4; if(lk) CPU.LR = nextLR; } + static void MCRF_impl(PPUThread *CPU, u32 crfd, u32 crfs) + { + CPU->SetCR(crfd, CPU->GetCR(crfs)); + } void MCRF(u32 crfd, u32 crfs) { - CPU.SetCR(crfd, CPU.GetCR(crfs)); + MCRF_impl(&CPU, crfd, crfs); } void BCLR(u32 bo, u32 bi, u32 bh, u32 lk) { @@ -2285,49 +2334,81 @@ private: if(lk) CPU.LR = nextLR; } } + static void CRNOR_impl(PPUThread *CPU, u32 crbd, u32 crba, u32 crbb) + { + const u8 v = 1 ^ (CPU->IsCR(crba) | CPU->IsCR(crbb)); + CPU->SetCRBit2(crbd, v & 0x1); + } void CRNOR(u32 crbd, u32 crba, u32 crbb) { - const u8 v = 1 ^ (CPU.IsCR(crba) | CPU.IsCR(crbb)); - CPU.SetCRBit2(crbd, v & 0x1); + CRNOR_impl(&CPU, crbd, crba, crbb); + } + static void CRANDC_impl(PPUThread *CPU, u32 crbd, u32 crba, u32 crbb) + { + const u8 v = CPU->IsCR(crba) & (1 ^ CPU->IsCR(crbb)); + CPU->SetCRBit2(crbd, v & 0x1); } void CRANDC(u32 crbd, u32 crba, u32 crbb) { - const u8 v = CPU.IsCR(crba) & (1 ^ CPU.IsCR(crbb)); - CPU.SetCRBit2(crbd, v & 0x1); + CRANDC_impl(&CPU, crbd, crba, crbb); } void ISYNC() { _mm_mfence(); } + static void CRXOR_impl(PPUThread *CPU, u32 crbd, u32 crba, u32 crbb) + { + const u8 v = CPU->IsCR(crba) ^ CPU->IsCR(crbb); + CPU->SetCRBit2(crbd, v & 0x1); + } void CRXOR(u32 crbd, u32 crba, u32 crbb) { - const u8 v = CPU.IsCR(crba) ^ CPU.IsCR(crbb); - CPU.SetCRBit2(crbd, v & 0x1); + CRXOR_impl(&CPU, crbd, crba, crbb); + } + static void CRNAND_impl(PPUThread *CPU, u32 crbd, u32 crba, u32 crbb) + { + const u8 v = 1 ^ (CPU->IsCR(crba) & CPU->IsCR(crbb)); + CPU->SetCRBit2(crbd, v & 0x1); } void CRNAND(u32 crbd, u32 crba, u32 crbb) { - const u8 v = 1 ^ (CPU.IsCR(crba) & CPU.IsCR(crbb)); - CPU.SetCRBit2(crbd, v & 0x1); + CRNAND_impl(&CPU, crbd, crba, crbb); + } + static void CRAND_impl(PPUThread *CPU, u32 crbd, u32 crba, u32 crbb) + { + const u8 v = CPU->IsCR(crba) & CPU->IsCR(crbb); + CPU->SetCRBit2(crbd, v & 0x1); } void CRAND(u32 crbd, u32 crba, u32 crbb) { - const u8 v = CPU.IsCR(crba) & CPU.IsCR(crbb); - CPU.SetCRBit2(crbd, v & 0x1); + CRAND_impl(&CPU, crbd, crba, crbb); + } + static void CREQV_impl(PPUThread *CPU, u32 crbd, u32 crba, u32 crbb) + { + const u8 v = 1 ^ (CPU->IsCR(crba) ^ CPU->IsCR(crbb)); + CPU->SetCRBit2(crbd, v & 0x1); } void CREQV(u32 crbd, u32 crba, u32 crbb) { - const u8 v = 1 ^ (CPU.IsCR(crba) ^ CPU.IsCR(crbb)); - CPU.SetCRBit2(crbd, v & 0x1); + CREQV_impl(&CPU, crbd, crba, crbb); + } + static void CRORC_impl(PPUThread *CPU, u32 crbd, u32 crba, u32 crbb) + { + const u8 v = CPU->IsCR(crba) | (1 ^ CPU->IsCR(crbb)); + CPU->SetCRBit2(crbd, v & 0x1); } void CRORC(u32 crbd, u32 crba, u32 crbb) { - const u8 v = CPU.IsCR(crba) | (1 ^ CPU.IsCR(crbb)); - CPU.SetCRBit2(crbd, v & 0x1); + CRORC_impl(&CPU, crbd, crba, crbb); + } + static void CROR_impl(PPUThread *CPU, u32 crbd, u32 crba, u32 crbb) + { + const u8 v = CPU->IsCR(crba) | CPU->IsCR(crbb); + CPU->SetCRBit2(crbd, v & 0x1); } void CROR(u32 crbd, u32 crba, u32 crbb) { - const u8 v = CPU.IsCR(crba) | CPU.IsCR(crbb); - CPU.SetCRBit2(crbd, v & 0x1); + CROR_impl(&CPU, crbd, crba, crbb); } void BCCTR(u32 bo, u32 bi, u32 bh, u32 lk) { @@ -2338,84 +2419,153 @@ private: if(lk) CPU.LR = nextLR; } } - void RLWIMI(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, u32 rc) + static void RLWIMI_impl(PPUThread *CPU, u32 ra, u32 rs, u32 sh, u32 mb, u32 me, u32 rc) { const u64 mask = rotate_mask[32 + mb][32 + me]; - CPU.GPR[ra] = (CPU.GPR[ra] & ~mask) | (rotl32(CPU.GPR[rs], sh) & mask); - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + CPU->GPR[ra] = (CPU->GPR[ra] & ~mask) | (rotl32(CPU->GPR[rs], sh) & mask); + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); } - void RLWINM(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, u32 rc) + void RLWIMI(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, u32 rc) { - CPU.GPR[ra] = rotl32(CPU.GPR[rs], sh) & rotate_mask[32 + mb][32 + me]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + RLWIMI_impl(&CPU, ra, rs, sh, mb, me, rc); + } + + static void RLWINM_impl(PPUThread *CPU, u32 ra, u32 rs, u32 sh, u32 mb, u32 me, u32 rc) + { + CPU->GPR[ra] = rotl32(CPU->GPR[rs], sh) & rotate_mask[32 + mb][32 + me]; + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); + } + void RLWINM(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, u32 rc) override + { + RLWINM_impl(&CPU, ra, rs, sh, mb, me, rc); + } + static void RLWNM_impl(PPUThread *CPU, u32 ra, u32 rs, u32 rb, u32 mb, u32 me, u32 rc) + { + CPU->GPR[ra] = rotl32(CPU->GPR[rs], CPU->GPR[rb] & 0x1f) & rotate_mask[32 + mb][32 + me]; + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); } void RLWNM(u32 ra, u32 rs, u32 rb, u32 mb, u32 me, u32 rc) { - CPU.GPR[ra] = rotl32(CPU.GPR[rs], CPU.GPR[rb] & 0x1f) & rotate_mask[32 + mb][32 + me]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + RLWNM_impl(&CPU, ra, rs, rb, mb, me, rc); + } + + static void ORI_impl(PPUThread *CPU, u32 ra, u32 rs, u32 uimm16) + { + CPU->GPR[ra] = CPU->GPR[rs] | uimm16; } void ORI(u32 ra, u32 rs, u32 uimm16) { - CPU.GPR[ra] = CPU.GPR[rs] | uimm16; + ORI_impl(&CPU, ra, rs, uimm16); + } + static void ORIS_impl(PPUThread *CPU, u32 ra, u32 rs, u32 uimm16) + { + CPU->GPR[ra] = CPU->GPR[rs] | ((u64)uimm16 << 16); } void ORIS(u32 ra, u32 rs, u32 uimm16) { - CPU.GPR[ra] = CPU.GPR[rs] | ((u64)uimm16 << 16); + ORIS_impl(&CPU, ra, rs, uimm16); + } + static void XORI_impl(PPUThread *CPU, u32 ra, u32 rs, u32 uimm16) + { + CPU->GPR[ra] = CPU->GPR[rs] ^ uimm16; } void XORI(u32 ra, u32 rs, u32 uimm16) { - CPU.GPR[ra] = CPU.GPR[rs] ^ uimm16; + XORI_impl(&CPU, ra, rs, uimm16); + } + static void XORIS_impl(PPUThread *CPU, u32 ra, u32 rs, u32 uimm16) + { + CPU->GPR[ra] = CPU->GPR[rs] ^ ((u64)uimm16 << 16); } void XORIS(u32 ra, u32 rs, u32 uimm16) { - CPU.GPR[ra] = CPU.GPR[rs] ^ ((u64)uimm16 << 16); + XORIS_impl(&CPU, ra, rs, uimm16); + } + static void ANDI__impl(PPUThread *CPU, u32 ra, u32 rs, u32 uimm16) + { + CPU->GPR[ra] = CPU->GPR[rs] & uimm16; + CPU->UpdateCR0(CPU->GPR[ra]); } void ANDI_(u32 ra, u32 rs, u32 uimm16) { - CPU.GPR[ra] = CPU.GPR[rs] & uimm16; - CPU.UpdateCR0(CPU.GPR[ra]); + ANDI__impl(&CPU, ra, rs, uimm16); + } + static void ANDIS__impl(PPUThread *CPU, u32 ra, u32 rs, u32 uimm16) + { + CPU->GPR[ra] = CPU->GPR[rs] & ((u64)uimm16 << 16); + CPU->UpdateCR0(CPU->GPR[ra]); } void ANDIS_(u32 ra, u32 rs, u32 uimm16) { - CPU.GPR[ra] = CPU.GPR[rs] & ((u64)uimm16 << 16); - CPU.UpdateCR0(CPU.GPR[ra]); + ANDIS__impl(&CPU, ra, rs, uimm16); } - void RLDICL(u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) + + static + void RLDICL_impl(PPUThread *CPU, u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) { - CPU.GPR[ra] = rotl64(CPU.GPR[rs], sh) & rotate_mask[mb][63]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + CPU->GPR[ra] = rotl64(CPU->GPR[rs], sh) & rotate_mask[mb][63]; + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); } + void RLDICL(u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) override + { + RLDICL_impl(&CPU, ra, rs, sh, mb, rc); + } + + static + void RLDICR_impl(PPUThread *CPU, u32 ra, u32 rs, u32 sh, u32 me, u32 rc) + { + CPU->GPR[ra] = rotl64(CPU->GPR[rs], sh) & rotate_mask[0][me]; + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); + } + void RLDICR(u32 ra, u32 rs, u32 sh, u32 me, u32 rc) { - CPU.GPR[ra] = rotl64(CPU.GPR[rs], sh) & rotate_mask[0][me]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + RLDICR_impl(&CPU, ra, rs, sh, me, rc); + } + static void RLDIC_impl(PPUThread *CPU, u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) + { + CPU->GPR[ra] = rotl64(CPU->GPR[rs], sh) & rotate_mask[mb][63 - sh]; + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); } void RLDIC(u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) { - CPU.GPR[ra] = rotl64(CPU.GPR[rs], sh) & rotate_mask[mb][63-sh]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + RLDIC_impl(&CPU, ra, rs, sh, mb, rc); + } + static void RLDIMI_impl(PPUThread *CPU, u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) + { + const u64 mask = rotate_mask[mb][63 - sh]; + CPU->GPR[ra] = (CPU->GPR[ra] & ~mask) | (rotl64(CPU->GPR[rs], sh) & mask); + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); } void RLDIMI(u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) { - const u64 mask = rotate_mask[mb][63-sh]; - CPU.GPR[ra] = (CPU.GPR[ra] & ~mask) | (rotl64(CPU.GPR[rs], sh) & mask); - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + RLDIMI_impl(&CPU, ra, rs, sh, mb, rc); } - void RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, u32 is_r, u32 rc) + static void RLDC_LR_impl(PPUThread *CPU, u32 ra, u32 rs, u32 rb, u32 m_eb, u32 is_r, u32 rc) { if (is_r) // rldcr { - RLDICR(ra, rs, (u32)(CPU.GPR[rb] & 0x3F), m_eb, rc); + RLDICR_impl(CPU, ra, rs, (u32)(CPU->GPR[rb] & 0x3F), m_eb, rc); } else // rldcl { - RLDICL(ra, rs, (u32)(CPU.GPR[rb] & 0x3F), m_eb, rc); + RLDICL_impl(CPU, ra, rs, (u32)(CPU->GPR[rb] & 0x3F), m_eb, rc); } } - void CMP(u32 crfd, u32 l, u32 ra, u32 rb) + void RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, u32 is_r, u32 rc) { - CPU.UpdateCRnS(l, crfd, CPU.GPR[ra], CPU.GPR[rb]); + RLDC_LR_impl(&CPU, ra, rs, rb, m_eb, is_r, rc); } + + static void CMP_impl(PPUThread *CPU, u32 crfd, u32 l, u32 ra, u32 rb) + { + CPU->UpdateCRnS(l, crfd, CPU->GPR[ra], CPU->GPR[rb]); + } + void CMP(u32 crfd, u32 l, u32 ra, u32 rb) override + { + CMP_impl(&CPU, crfd, l, ra, rb); + } + void TW(u32 to, u32 ra, u32 rb) { s32 a = (s32)CPU.GPR[ra]; @@ -2493,18 +2643,27 @@ private: CPU.GPR[rd] = ((u64)a * (u64)b) >> 32; if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - void MFOCRF(u32 a, u32 rd, u32 crm) + + static void MFOCRF_impl(PPUThread *CPU, u32 a, u32 rd, u32 crm) { - CPU.GPR[rd] = CPU.CR.CR; + CPU->GPR[rd] = CPU->CR.CR; } - void LWARX(u32 rd, u32 ra, u32 rb) + void MFOCRF(u32 a, u32 rd, u32 crm) override { - const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; + MFOCRF_impl(&CPU, a, rd, crm); + } + static void LWARX_impl(PPUThread *CPU, u32 rd, u32 ra, u32 rb) + { + const u64 addr = ra ? CPU->GPR[ra] + CPU->GPR[rb] : CPU->GPR[rb]; be_t value; vm::reservation_acquire(&value, VM_CAST(addr), sizeof(value)); - CPU.GPR[rd] = value; + CPU->GPR[rd] = value; + } + void LWARX(u32 rd, u32 ra, u32 rb) + { + LWARX_impl(&CPU, rd, ra, rb); } void LDX(u32 rd, u32 ra, u32 rb) { @@ -2547,15 +2706,26 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[ra]); } - void AND(u32 ra, u32 rs, u32 rb, u32 rc) + + static void AND_impl(PPUThread *CPU, u32 ra, u32 rs, u32 rb, u32 rc) { - CPU.GPR[ra] = CPU.GPR[rs] & CPU.GPR[rb]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + CPU->GPR[ra] = CPU->GPR[rs] & CPU->GPR[rb]; + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); } - void CMPL(u32 crfd, u32 l, u32 ra, u32 rb) + void AND(u32 ra, u32 rs, u32 rb, u32 rc) override { - CPU.UpdateCRnU(l, crfd, CPU.GPR[ra], CPU.GPR[rb]); + AND_impl(&CPU, ra, rs, rb, rc); } + + static void CMPL_impl(PPUThread *CPU, u32 crfd, u32 l, u32 ra, u32 rb) + { + CPU->UpdateCRnU(l, crfd, CPU->GPR[ra], CPU->GPR[rb]); + } + void CMPL(u32 crfd, u32 l, u32 ra, u32 rb) override + { + CMPL_impl(&CPU, crfd, l, ra, rb); + } + void LVSR(u32 vd, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; @@ -2589,14 +2759,20 @@ private: CPU.VPR[vd]._u16[7 - ((addr >> 1) & 0x7)] = vm::ps3::read16(VM_CAST(addr)); // It's bad idea to read 128 bit there } - void SUBF(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) + + static void SUBF_impl(PPUThread *CPU, u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { - const u64 RA = CPU.GPR[ra]; - const u64 RB = CPU.GPR[rb]; - CPU.GPR[rd] = RB - RA; - if(oe) CPU.SetOV((~RA>>63 == RB>>63) && (~RA>>63 != CPU.GPR[rd]>>63)); - if(rc) CPU.UpdateCR0(CPU.GPR[rd]); + const u64 RA = CPU->GPR[ra]; + const u64 RB = CPU->GPR[rb]; + CPU->GPR[rd] = RB - RA; + if(oe) CPU->SetOV((~RA >> 63 == RB >> 63) && (~RA >> 63 != CPU->GPR[rd] >> 63)); + if(rc) CPU->UpdateCR0(CPU->GPR[rd]); } + void SUBF(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) override + { + SUBF_impl(&CPU, rd, ra, rb, oe, rc); + } + void LDUX(u32 rd, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; @@ -2672,13 +2848,19 @@ private: const u64 addr = (ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]) & ~0xfull; CPU.VPR[vd] = vm::ps3::_ref(VM_CAST(addr)); } - void NEG(u32 rd, u32 ra, u32 oe, u32 rc) + + static void NEG_impl(PPUThread *CPU, u32 rd, u32 ra, u32 oe, u32 rc) { - const u64 RA = CPU.GPR[ra]; - CPU.GPR[rd] = 0 - RA; - if(oe) CPU.SetOV((~RA>>63 == 0) && (~RA>>63 != CPU.GPR[rd]>>63)); - if(rc) CPU.UpdateCR0(CPU.GPR[rd]); + const u64 RA = CPU->GPR[ra]; + CPU->GPR[rd] = 0 - RA; + if(oe) CPU->SetOV((~RA >> 63 == 0) && (~RA >> 63 != CPU->GPR[rd] >> 63)); + if(rc) CPU->UpdateCR0(CPU->GPR[rd]); } + void NEG(u32 rd, u32 ra, u32 oe, u32 rc) override + { + NEG_impl(&CPU, rd, ra, oe, rc); + } + void LBZUX(u32 rd, u32 ra, u32 rb) { const u64 addr = CPU.GPR[ra] + CPU.GPR[rb]; @@ -2730,14 +2912,15 @@ private: if(oe) CPU.SetOV((RA>>63 == RB>>63) && (RA>>63 != CPU.GPR[rd]>>63)); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - void MTOCRF(u32 l, u32 crm, u32 rs) + + static void MTOCRF_impl(PPUThread *CPU, u32 l, u32 crm, u32 rs) { if(l) { u32 n = 0, count = 0; for(u32 i=0; i<8; ++i) { - if(crm & (1 << i)) + if (crm & (1 << i)) { n = i; count++; @@ -2747,10 +2930,10 @@ private: if(count == 1) { //CR[4*n : 4*n+3] = RS[32+4*n : 32+4*n+3]; - CPU.SetCR(7 - n, (CPU.GPR[rs] >> (4*n)) & 0xf); + CPU->SetCR(7 - n, (CPU->GPR[rs] >> (4 * n)) & 0xf); } else - CPU.CR.CR = 0; + CPU->CR.CR = 0; } else { @@ -2758,22 +2941,31 @@ private: { if(crm & (1 << i)) { - CPU.SetCR(7 - i, (CPU.GPR[rs] >> (i * 4)) & 0xf); + CPU->SetCR(7 - i, (CPU->GPR[rs] >> (i * 4)) & 0xf); } } } } + void MTOCRF(u32 l, u32 crm, u32 rs) override + { + MTOCRF_impl(&CPU, l, crm, rs); + } + void STDX(u32 rs, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; vm::ps3::write64(VM_CAST(addr), CPU.GPR[rs]); } + static void STWCX__impl(PPUThread* CPU, u32 rs, u32 ra, u32 rb) + { + const u64 addr = ra ? CPU->GPR[ra] + CPU->GPR[rb] : CPU->GPR[rb]; + + const be_t value = (u32)CPU->GPR[rs]; + CPU->SetCR_EQ(0, vm::reservation_update(VM_CAST(addr), &value, sizeof(value))); + } void STWCX_(u32 rs, u32 ra, u32 rb) { - const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; - - const be_t value = (u32)CPU.GPR[rs]; - CPU.SetCR_EQ(0, vm::reservation_update(VM_CAST(addr), &value, sizeof(value))); + STWCX__impl(&CPU, rs, ra, rb); } void STWX(u32 rs, u32 ra, u32 rb) { @@ -2866,12 +3058,18 @@ private: if(oe) CPU.SetOV((u64(RA)>>63 == 1) && (u64(RA)>>63 != CPU.GPR[rd]>>63)); if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - void MULLW(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) + + static void MULLW_impl(PPUThread *CPU, u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { - CPU.GPR[rd] = (s64)((s64)(s32)CPU.GPR[ra] * (s64)(s32)CPU.GPR[rb]); - if(oe) CPU.SetOV(s64(CPU.GPR[rd]) < s64(-1)<<31 || s64(CPU.GPR[rd]) >= s64(1)<<31); - if(rc) CPU.UpdateCR0(CPU.GPR[rd]); + CPU->GPR[rd] = (s64)((s64)(s32)CPU->GPR[ra] * (s64)(s32)CPU->GPR[rb]); + if(oe) CPU->SetOV(s64(CPU->GPR[rd]) < s64(-1) << 31 || s64(CPU->GPR[rd]) >= s64(1) << 31); + if(rc) CPU->UpdateCR0(CPU->GPR[rd]); } + void MULLW(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) override + { + MULLW_impl(&CPU, rd, ra, rb, oe, rc); + } + void DCBTST(u32 ra, u32 rb, u32 th) { } @@ -2881,14 +3079,20 @@ private: vm::write8(VM_CAST(addr), (u8)CPU.GPR[rs]); CPU.GPR[ra] = addr; } - void ADD(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) + + static void ADD_impl(PPUThread *CPU, u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { - const u64 RA = CPU.GPR[ra]; - const u64 RB = CPU.GPR[rb]; - CPU.GPR[rd] = RA + RB; - if(oe) CPU.SetOV((RA>>63 == RB>>63) && (RA>>63 != CPU.GPR[rd]>>63)); - if(rc) CPU.UpdateCR0(CPU.GPR[rd]); + const u64 RA = CPU->GPR[ra]; + const u64 RB = CPU->GPR[rb]; + CPU->GPR[rd] = RA + RB; + if(oe) CPU->SetOV((RA >> 63 == RB >> 63) && (RA >> 63 != CPU->GPR[rd] >> 63)); + if(rc) CPU->UpdateCR0(CPU->GPR[rd]); } + void ADD(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) override + { + ADD_impl(&CPU, rd, ra, rb, oe, rc); + } + void DCBT(u32 ra, u32 rb, u32 th) { } @@ -2986,11 +3190,17 @@ private: vm::ps3::write16(VM_CAST(addr), (u16)CPU.GPR[rs]); CPU.GPR[ra] = addr; } - void OR(u32 ra, u32 rs, u32 rb, u32 rc) + + static void OR_impl(PPUThread *CPU, u32 ra, u32 rs, u32 rb, u32 rc) { - CPU.GPR[ra] = CPU.GPR[rs] | CPU.GPR[rb]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + CPU->GPR[ra] = CPU->GPR[rs] | CPU->GPR[rb]; + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); } + void OR(u32 ra, u32 rs, u32 rb, u32 rc) override + { + OR_impl(&CPU, ra, rs, rb, rc); + } + void DIVDU(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { const u64 RA = CPU.GPR[ra]; @@ -3009,24 +3219,30 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - void DIVWU(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) + + static void DIVWU_impl(PPUThread *CPU, u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { - const u32 RA = (u32)CPU.GPR[ra]; - const u32 RB = (u32)CPU.GPR[rb]; + const u32 RA = (u32)CPU->GPR[ra]; + const u32 RB = (u32)CPU->GPR[rb]; if(RB == 0) { - if(oe) CPU.SetOV(true); - CPU.GPR[rd] = 0; + if(oe) CPU->SetOV(true); + CPU->GPR[rd] = 0; } else { - if(oe) CPU.SetOV(false); - CPU.GPR[rd] = RA / RB; + if(oe) CPU->SetOV(false); + CPU->GPR[rd] = RA / RB; } - if(rc) CPU.UpdateCR0(CPU.GPR[rd]); + if(rc) CPU->UpdateCR0(CPU->GPR[rd]); } + void DIVWU(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) override + { + DIVWU_impl(&CPU, rd, ra, rb, oe, rc); + } + void MTSPR(u32 spr, u32 rs) { WriteSPR(spr, CPU.GPR[rs]); @@ -3063,24 +3279,30 @@ private: if(rc) CPU.UpdateCR0(CPU.GPR[rd]); } - void DIVW(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) + + static void DIVW_impl(PPUThread *CPU, u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { - const s32 RA = (s32)CPU.GPR[ra]; - const s32 RB = (s32)CPU.GPR[rb]; + const s32 RA = (s32)CPU->GPR[ra]; + const s32 RB = (s32)CPU->GPR[rb]; if (RB == 0 || ((u32)RA == (1 << 31) && RB == -1)) { - if(oe) CPU.SetOV(true); - CPU.GPR[rd] = /*(((u32)RA & (1 << 31)) && RB == 0) ? -1 :*/ 0; + if(oe) CPU->SetOV(true); + CPU->GPR[rd] = /*(((u32)RA & (1 << 31)) && RB == 0) ? -1 :*/ 0; } else { - if(oe) CPU.SetOV(false); - CPU.GPR[rd] = (u32)(RA / RB); + if(oe) CPU->SetOV(false); + CPU->GPR[rd] = (u32)(RA / RB); } - if(rc) CPU.UpdateCR0(CPU.GPR[rd]); + if(rc) CPU->UpdateCR0(CPU->GPR[rd]); } + void DIVW(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) override + { + DIVW_impl(&CPU, rd, ra, rb, oe, rc); + } + void LVLX(u32 vd, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; @@ -3388,14 +3610,20 @@ private: void DSS(u32 strm, u32 a) { } - void SRAWI(u32 ra, u32 rs, u32 sh, u32 rc) - { - s32 RS = (u32)CPU.GPR[rs]; - CPU.GPR[ra] = RS >> sh; - CPU.XER.CA = (RS < 0) & ((u32)(CPU.GPR[ra] << sh) != RS); - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + static void SRAWI_impl(PPUThread *CPU, u32 ra, u32 rs, u32 sh, u32 rc) + { + s32 RS = (u32)CPU->GPR[rs]; + CPU->GPR[ra] = RS >> sh; + CPU->XER.CA = (RS < 0) & ((u32)(CPU->GPR[ra] << sh) != RS); + + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); } + void SRAWI(u32 ra, u32 rs, u32 sh, u32 rc) override + { + SRAWI_impl(&CPU, ra, rs, sh, rc); + } + void SRADI1(u32 ra, u32 rs, u32 sh, u32 rc) { s64 RS = CPU.GPR[rs]; @@ -3436,21 +3664,33 @@ private: for (u32 i = 16 - eb; i < 16; ++i) vm::write8(VM_CAST(addr + i - 16), CPU.VPR[vs]._u8[15 - i]); } - void EXTSB(u32 ra, u32 rs, u32 rc) + + static void EXTSB_impl(PPUThread *CPU, u32 ra, u32 rs, u32 rc) { - CPU.GPR[ra] = (s64)(s8)CPU.GPR[rs]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + CPU->GPR[ra] = (s64)(s8)CPU->GPR[rs]; + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); } + void EXTSB(u32 ra, u32 rs, u32 rc) override + { + EXTSB_impl(&CPU, ra, rs, rc); + } + void STFIWX(u32 frs, u32 ra, u32 rb) { const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb]; vm::ps3::write32(VM_CAST(addr), (u32&)CPU.FPR[frs]); } - void EXTSW(u32 ra, u32 rs, u32 rc) + + static void EXTSW_impl(PPUThread *CPU, u32 ra, u32 rs, u32 rc) { - CPU.GPR[ra] = (s64)(s32)CPU.GPR[rs]; - if(rc) CPU.UpdateCR0(CPU.GPR[ra]); + CPU->GPR[ra] = (s64)(s32)CPU->GPR[rs]; + if(rc) CPU->UpdateCR0(CPU->GPR[ra]); } + void EXTSW(u32 ra, u32 rs, u32 rc) override + { + EXTSW_impl(&CPU, ra, rs, rc); + } + void ICBI(u32 ra, u32 rs) { // Clear jit for the specified block? Nothing to do in the interpreter. @@ -3461,33 +3701,51 @@ private: std::memset(vm::base(VM_CAST(addr) & ~127), 0, 128); } - void LWZ(u32 rd, u32 ra, s32 d) + + static void LWZ_impl(PPUThread *CPU, u32 rd, u32 ra, s32 d) { - const u64 addr = ra ? CPU.GPR[ra] + d : d; - CPU.GPR[rd] = vm::ps3::read32(VM_CAST(addr)); + const u64 addr = ra ? CPU->GPR[ra] + d : d; + CPU->GPR[rd] = vm::ps3::read32(VM_CAST(addr)); } + void LWZ(u32 rd, u32 ra, s32 d) override + { + LWZ_impl(&CPU, rd, ra, d); + } + void LWZU(u32 rd, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; CPU.GPR[rd] = vm::ps3::read32(VM_CAST(addr)); CPU.GPR[ra] = addr; } - void LBZ(u32 rd, u32 ra, s32 d) + + static void LBZ_impl(PPUThread *CPU, u32 rd, u32 ra, s32 d) { - const u64 addr = ra ? CPU.GPR[ra] + d : d; - CPU.GPR[rd] = vm::read8(VM_CAST(addr)); + const u64 addr = ra ? CPU->GPR[ra] + d : d; + CPU->GPR[rd] = vm::read8(VM_CAST(addr)); } + void LBZ(u32 rd, u32 ra, s32 d) override + { + LBZ_impl(&CPU, rd, ra, d); + } + void LBZU(u32 rd, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; CPU.GPR[rd] = vm::read8(VM_CAST(addr)); CPU.GPR[ra] = addr; } + + static void STW_impl(PPUThread *CPU, u32 rs, u32 ra, s32 d) + { + const u64 addr = ra ? CPU->GPR[ra] + d : d; + vm::ps3::write32(VM_CAST(addr), (u32)CPU->GPR[rs]); + } void STW(u32 rs, u32 ra, s32 d) { - const u64 addr = ra ? CPU.GPR[ra] + d : d; - vm::ps3::write32(VM_CAST(addr), (u32)CPU.GPR[rs]); + STW_impl(&CPU, rs, ra, d); } + void STWU(u32 rs, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; @@ -3505,10 +3763,14 @@ private: vm::write8(VM_CAST(addr), (u8)CPU.GPR[rs]); CPU.GPR[ra] = addr; } + static void LHZ_impl(PPUThread *CPU, u32 rd, u32 ra, s32 d) + { + const u64 addr = ra ? CPU->GPR[ra] + d : d; + CPU->GPR[rd] = vm::ps3::read16(VM_CAST(addr)); + } void LHZ(u32 rd, u32 ra, s32 d) { - const u64 addr = ra ? CPU.GPR[ra] + d : d; - CPU.GPR[rd] = vm::ps3::read16(VM_CAST(addr)); + LHZ_impl(&CPU, rd, ra, d); } void LHZU(u32 rd, u32 ra, s32 d) { @@ -3554,20 +3816,26 @@ private: vm::ps3::write32(VM_CAST(addr), (u32)CPU.GPR[i]); } } - void LFS(u32 frd, u32 ra, s32 d) + + static void LFS_impl(PPUThread *CPU, u32 frd, u32 ra, s32 d) { - const u64 addr = ra ? CPU.GPR[ra] + d : d; + const u64 addr = ra ? CPU->GPR[ra] + d : d; const f32 val = vm::ps3::_ref(VM_CAST(addr)); if (!FPRdouble::IsNaN(val)) { - CPU.FPR[frd] = val; + CPU->FPR[frd] = val; } else { u64 bits = (u32&)val; - (u64&)CPU.FPR[frd] = (bits & 0x80000000) << 32 | 7ULL << 60 | (bits & 0x7fffffff) << 29; + (u64&)CPU->FPR[frd] = (bits & 0x80000000) << 32 | 7ULL << 60 | (bits & 0x7fffffff) << 29; } } + void LFS(u32 frd, u32 ra, s32 d) override + { + LFS_impl(&CPU, frd, ra, d); + } + void LFSU(u32 frd, u32 ra, s32 ds) { const u64 addr = CPU.GPR[ra] + ds; @@ -3594,10 +3862,11 @@ private: CPU.FPR[frd]._double = vm::ps3::_ref(VM_CAST(addr)); CPU.GPR[ra] = addr; } - void STFS(u32 frs, u32 ra, s32 d) + + static void STFS_impl(PPUThread *CPU, u32 frs, u32 ra, s32 d) { - const u64 addr = ra ? CPU.GPR[ra] + d : d; - double val = CPU.FPR[frs]; + const u64 addr = ra ? CPU->GPR[ra] + d : d; + double val = CPU->FPR[frs]; if (!FPRdouble::IsNaN(val)) { vm::ps3::_ref(VM_CAST(addr)) = (float)val; @@ -3609,6 +3878,11 @@ private: vm::ps3::_ref(VM_CAST(addr)) = bits32; } } + void STFS(u32 frs, u32 ra, s32 d) override + { + STFS_impl(&CPU, frs, ra, d); + } + void STFSU(u32 frs, u32 ra, s32 d) { const u64 addr = CPU.GPR[ra] + d; @@ -3636,11 +3910,17 @@ private: vm::ps3::_ref(VM_CAST(addr)) = CPU.FPR[frs]; CPU.GPR[ra] = addr; } - void LD(u32 rd, u32 ra, s32 ds) + + static void LD_impl(PPUThread *CPU, u32 rd, u32 ra, s32 ds) { - const u64 addr = ra ? CPU.GPR[ra] + ds : ds; - CPU.GPR[rd] = vm::ps3::read64(VM_CAST(addr)); + const u64 addr = ra ? CPU->GPR[ra] + ds : ds; + CPU->GPR[rd] = vm::ps3::read64(VM_CAST(addr)); } + void LD(u32 rd, u32 ra, s32 ds) override + { + LD_impl(&CPU, rd, ra, ds); + } + void LDU(u32 rd, u32 ra, s32 ds) { const u64 addr = CPU.GPR[ra] + ds; @@ -3701,17 +3981,30 @@ private: void FMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, u32 rc) {FMADD(frd, fra, frc, frb, rc, false, true, true);} void FNMSUBS(u32 frd, u32 fra, u32 frc, u32 frb, u32 rc) {FMADD(frd, fra, frc, frb, rc, true, true, true);} void FNMADDS(u32 frd, u32 fra, u32 frc, u32 frb, u32 rc) {FMADD(frd, fra, frc, frb, rc, true, false, true);} - void STD(u32 rs, u32 ra, s32 d) + + static void STD_impl(PPUThread *CPU, u32 rs, u32 ra, s32 d) { - const u64 addr = ra ? CPU.GPR[ra] + d : d; - vm::ps3::write64(VM_CAST(addr), CPU.GPR[rs]); + const u64 addr = ra ? CPU->GPR[ra] + d : d; + vm::ps3::write64(VM_CAST(addr), CPU->GPR[rs]); } - void STDU(u32 rs, u32 ra, s32 ds) + + void STD(u32 rs, u32 ra, s32 d) override { - const u64 addr = CPU.GPR[ra] + ds; - vm::ps3::write64(VM_CAST(addr), CPU.GPR[rs]); - CPU.GPR[ra] = addr; + STD_impl(&CPU, rs, ra, d); } + + static void STDU_impl(PPUThread *CPU, u32 rs, u32 ra, s32 ds) + { + const u64 addr = CPU->GPR[ra] + ds; + vm::ps3::write64(VM_CAST(addr), CPU->GPR[rs]); + CPU->GPR[ra] = addr; + } + + void STDU(u32 rs, u32 ra, s32 ds) override + { + STDU_impl(&CPU, rs, ra, ds); + } + void MTFSB1(u32 crbd, u32 rc) { u32 mask = 1 << (31 - crbd); diff --git a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp index 9b65fd25a7..3e251c6ca8 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompiler.cpp @@ -376,6 +376,16 @@ std::pair RecompilationEngine::compile(cons function_ptrs["wrappedExecutePPUFuncByIndex"] = reinterpret_cast(wrappedExecutePPUFuncByIndex); function_ptrs["wrappedDoSyscall"] = reinterpret_cast(wrappedDoSyscall); +#define REGISTER_FUNCTION_PTR(name) \ + function_ptrs[#name] = reinterpret_cast(PPUInterpreter::name##_impl); + + MACRO_PPU_INST_MAIN_EXPANDERS(REGISTER_FUNCTION_PTR) + MACRO_PPU_INST_G_13_EXPANDERS(REGISTER_FUNCTION_PTR) + MACRO_PPU_INST_G_1E_EXPANDERS(REGISTER_FUNCTION_PTR) + MACRO_PPU_INST_G_1F_EXPANDERS(REGISTER_FUNCTION_PTR) + MACRO_PPU_INST_G_3A_EXPANDERS(REGISTER_FUNCTION_PTR) + MACRO_PPU_INST_G_3E_EXPANDERS(REGISTER_FUNCTION_PTR) + Compiler(&m_llvm_context, &m_ir_builder, function_ptrs) .translate_to_llvm_ir(module.get(), name, start_address, instruction_count); diff --git a/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp b/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp index 5ce08772d9..789791724e 100644 --- a/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp +++ b/rpcs3/Emu/Cell/PPULLVMRecompilerCore.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #ifdef LLVM_AVAILABLE +#include "Emu/state.h" #include "Emu/System.h" #include "Emu/Cell/PPULLVMRecompiler.h" #include "Emu/Memory/Memory.h" @@ -28,6 +29,13 @@ #pragma warning(pop) #endif +#define USE_INTERP_IF_REQUESTED(inst, ...) \ + if (!rpcs3::state.config.core.llvm.enable_##inst.value()) \ + { \ + Call(#inst, m_state.args[CompileTaskState::Args::State], __VA_ARGS__); \ + return; \ + } + using namespace llvm; using namespace ppu_recompiler_llvm; @@ -1668,12 +1676,16 @@ void Compiler::VXOR(u32 vd, u32 va, u32 vb) { } void Compiler::MULLI(u32 rd, u32 ra, s32 simm16) { + USE_INTERP_IF_REQUESTED(MULLI, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(simm16)); + auto ra_i64 = GetGpr(ra); auto res_i64 = m_ir_builder->CreateMul(ra_i64, m_ir_builder->getInt64((s64)simm16)); SetGpr(rd, res_i64); } void Compiler::SUBFIC(u32 rd, u32 ra, s32 simm16) { + USE_INTERP_IF_REQUESTED(SUBFIC, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(simm16)) + auto ra_i64 = GetGpr(ra); ra_i64 = m_ir_builder->CreateNeg(ra_i64); // simpler way of doing ~ra + 1 auto res_s = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::uadd_with_overflow, m_ir_builder->getInt64Ty()), ra_i64, m_ir_builder->getInt64((s64)simm16)); @@ -1686,6 +1698,8 @@ void Compiler::SUBFIC(u32 rd, u32 ra, s32 simm16) { } void Compiler::CMPLI(u32 crfd, u32 l, u32 ra, u32 uimm16) { + USE_INTERP_IF_REQUESTED(CMPLI, m_ir_builder->getInt32(crfd), m_ir_builder->getInt32(l), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(uimm16)); + Value * ra_i64; if (l == 0) { ra_i64 = m_ir_builder->CreateZExt(GetGpr(ra, 32), m_ir_builder->getInt64Ty()); @@ -1698,6 +1712,8 @@ void Compiler::CMPLI(u32 crfd, u32 l, u32 ra, u32 uimm16) { } void Compiler::CMPI(u32 crfd, u32 l, u32 ra, s32 simm16) { + USE_INTERP_IF_REQUESTED(CMPI, m_ir_builder->getInt32(crfd), m_ir_builder->getInt32(l), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(simm16)); + Value * ra_i64; if (l == 0) { ra_i64 = m_ir_builder->CreateSExt(GetGpr(ra, 32), m_ir_builder->getInt64Ty()); @@ -1710,6 +1726,8 @@ void Compiler::CMPI(u32 crfd, u32 l, u32 ra, s32 simm16) { } void Compiler::ADDIC(u32 rd, u32 ra, s32 simm16) { + USE_INTERP_IF_REQUESTED(ADDIC, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(simm16)); + auto ra_i64 = GetGpr(ra); auto res_s = m_ir_builder->CreateCall2(Intrinsic::getDeclaration(m_module, Intrinsic::uadd_with_overflow, m_ir_builder->getInt64Ty()), m_ir_builder->getInt64((s64)simm16), ra_i64); auto sum_i64 = m_ir_builder->CreateExtractValue(res_s, { 0 }); @@ -1719,11 +1737,15 @@ void Compiler::ADDIC(u32 rd, u32 ra, s32 simm16) { } void Compiler::ADDIC_(u32 rd, u32 ra, s32 simm16) { + USE_INTERP_IF_REQUESTED(ADDIC_, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(simm16)); + ADDIC(rd, ra, simm16); SetCrFieldSignedCmp(0, GetGpr(rd), m_ir_builder->getInt64(0)); } void Compiler::ADDI(u32 rd, u32 ra, s32 simm16) { + USE_INTERP_IF_REQUESTED(ADDI, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(simm16)); + if (ra == 0) { SetGpr(rd, m_ir_builder->getInt64((s64)simm16)); } @@ -1735,6 +1757,8 @@ void Compiler::ADDI(u32 rd, u32 ra, s32 simm16) { } void Compiler::ADDIS(u32 rd, u32 ra, s32 simm16) { + USE_INTERP_IF_REQUESTED(ADDIS, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(simm16)); + if (ra == 0) { SetGpr(rd, m_ir_builder->getInt64((s64)simm16 << 16)); } @@ -1806,6 +1830,8 @@ void Compiler::B(s32 ll, u32 aa, u32 lk) { } void Compiler::MCRF(u32 crfd, u32 crfs) { + USE_INTERP_IF_REQUESTED(MCRF, m_ir_builder->getInt32(crfd), m_ir_builder->getInt32(crfs)); + if (crfd != crfs) { auto cr_i32 = GetCr(); auto crf_i32 = GetNibble(cr_i32, crfs); @@ -1822,6 +1848,8 @@ void Compiler::BCLR(u32 bo, u32 bi, u32 bh, u32 lk) { } void Compiler::CRNOR(u32 crbd, u32 crba, u32 crbb) { + USE_INTERP_IF_REQUESTED(CRNOR, m_ir_builder->getInt32(crbd), m_ir_builder->getInt32(crba), m_ir_builder->getInt32(crbb)); + auto cr_i32 = GetCr(); auto ba_i32 = GetBit(cr_i32, crba); auto bb_i32 = GetBit(cr_i32, crbb); @@ -1832,6 +1860,8 @@ void Compiler::CRNOR(u32 crbd, u32 crba, u32 crbb) { } void Compiler::CRANDC(u32 crbd, u32 crba, u32 crbb) { + USE_INTERP_IF_REQUESTED(CRANDC, m_ir_builder->getInt32(crbd), m_ir_builder->getInt32(crba), m_ir_builder->getInt32(crbb)); + auto cr_i32 = GetCr(); auto ba_i32 = GetBit(cr_i32, crba); auto bb_i32 = GetBit(cr_i32, crbb); @@ -1846,6 +1876,8 @@ void Compiler::ISYNC() { } void Compiler::CRXOR(u32 crbd, u32 crba, u32 crbb) { + USE_INTERP_IF_REQUESTED(CRXOR, m_ir_builder->getInt32(crbd), m_ir_builder->getInt32(crba), m_ir_builder->getInt32(crbb)); + auto cr_i32 = GetCr(); auto ba_i32 = GetBit(cr_i32, crba); auto bb_i32 = GetBit(cr_i32, crbb); @@ -1860,6 +1892,8 @@ void Compiler::DCBI(u32 ra, u32 rb) { } void Compiler::CRNAND(u32 crbd, u32 crba, u32 crbb) { + USE_INTERP_IF_REQUESTED(CRNAND, m_ir_builder->getInt32(crbd), m_ir_builder->getInt32(crba), m_ir_builder->getInt32(crbb)); + auto cr_i32 = GetCr(); auto ba_i32 = GetBit(cr_i32, crba); auto bb_i32 = GetBit(cr_i32, crbb); @@ -1870,6 +1904,8 @@ void Compiler::CRNAND(u32 crbd, u32 crba, u32 crbb) { } void Compiler::CRAND(u32 crbd, u32 crba, u32 crbb) { + USE_INTERP_IF_REQUESTED(CRAND, m_ir_builder->getInt32(crbd), m_ir_builder->getInt32(crba), m_ir_builder->getInt32(crbb)); + auto cr_i32 = GetCr(); auto ba_i32 = GetBit(cr_i32, crba); auto bb_i32 = GetBit(cr_i32, crbb); @@ -1879,6 +1915,8 @@ void Compiler::CRAND(u32 crbd, u32 crba, u32 crbb) { } void Compiler::CREQV(u32 crbd, u32 crba, u32 crbb) { + USE_INTERP_IF_REQUESTED(CREQV, m_ir_builder->getInt32(crbd), m_ir_builder->getInt32(crba), m_ir_builder->getInt32(crbb)); + auto cr_i32 = GetCr(); auto ba_i32 = GetBit(cr_i32, crba); auto bb_i32 = GetBit(cr_i32, crbb); @@ -1889,6 +1927,8 @@ void Compiler::CREQV(u32 crbd, u32 crba, u32 crbb) { } void Compiler::CRORC(u32 crbd, u32 crba, u32 crbb) { + USE_INTERP_IF_REQUESTED(CRORC, m_ir_builder->getInt32(crbd), m_ir_builder->getInt32(crba), m_ir_builder->getInt32(crbb)); + auto cr_i32 = GetCr(); auto ba_i32 = GetBit(cr_i32, crba); auto bb_i32 = GetBit(cr_i32, crbb); @@ -1899,6 +1939,8 @@ void Compiler::CRORC(u32 crbd, u32 crba, u32 crbb) { } void Compiler::CROR(u32 crbd, u32 crba, u32 crbb) { + USE_INTERP_IF_REQUESTED(CROR, m_ir_builder->getInt32(crbd), m_ir_builder->getInt32(crba), m_ir_builder->getInt32(crbb)); + auto cr_i32 = GetCr(); auto ba_i32 = GetBit(cr_i32, crba); auto bb_i32 = GetBit(cr_i32, crbb); @@ -1915,6 +1957,8 @@ void Compiler::BCCTR(u32 bo, u32 bi, u32 bh, u32 lk) { } void Compiler::RLWIMI(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, u32 rc) { + USE_INTERP_IF_REQUESTED(RLWIMI, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(sh), m_ir_builder->getInt32(mb), m_ir_builder->getInt32(me), m_ir_builder->getInt32(rc)); + auto rs_i32 = GetGpr(rs, 32); auto rs_i64 = m_ir_builder->CreateZExt(rs_i32, m_ir_builder->getInt64Ty()); auto rsh_i64 = m_ir_builder->CreateShl(rs_i64, 32); @@ -1939,6 +1983,8 @@ void Compiler::RLWIMI(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, u32 rc) { } void Compiler::RLWINM(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, u32 rc) { + USE_INTERP_IF_REQUESTED(RLWINM, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(sh), m_ir_builder->getInt32(mb), m_ir_builder->getInt32(me), m_ir_builder->getInt32(rc)); + auto rs_i32 = GetGpr(rs, 32); auto rs_i64 = m_ir_builder->CreateZExt(rs_i32, m_ir_builder->getInt64Ty()); auto rsh_i64 = m_ir_builder->CreateShl(rs_i64, 32); @@ -1959,6 +2005,8 @@ void Compiler::RLWINM(u32 ra, u32 rs, u32 sh, u32 mb, u32 me, u32 rc) { } void Compiler::RLWNM(u32 ra, u32 rs, u32 rb, u32 mb, u32 me, u32 rc) { + USE_INTERP_IF_REQUESTED(RLWNM, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(rb), m_ir_builder->getInt32(mb), m_ir_builder->getInt32(me), m_ir_builder->getInt32(rc)); + auto rs_i32 = GetGpr(rs, 32); auto rs_i64 = m_ir_builder->CreateZExt(rs_i32, m_ir_builder->getInt64Ty()); auto rsh_i64 = m_ir_builder->CreateShl(rs_i64, 32); @@ -1978,30 +2026,40 @@ void Compiler::RLWNM(u32 ra, u32 rs, u32 rb, u32 mb, u32 me, u32 rc) { } void Compiler::ORI(u32 ra, u32 rs, u32 uimm16) { + USE_INTERP_IF_REQUESTED(ORI, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(uimm16)); + auto rs_i64 = GetGpr(rs); auto res_i64 = m_ir_builder->CreateOr(rs_i64, uimm16); SetGpr(ra, res_i64); } void Compiler::ORIS(u32 ra, u32 rs, u32 uimm16) { + USE_INTERP_IF_REQUESTED(ORIS, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(uimm16)); + auto rs_i64 = GetGpr(rs); auto res_i64 = m_ir_builder->CreateOr(rs_i64, (u64)uimm16 << 16); SetGpr(ra, res_i64); } void Compiler::XORI(u32 ra, u32 rs, u32 uimm16) { + USE_INTERP_IF_REQUESTED(XORI, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(uimm16)); + auto rs_i64 = GetGpr(rs); auto res_i64 = m_ir_builder->CreateXor(rs_i64, uimm16); SetGpr(ra, res_i64); } void Compiler::XORIS(u32 ra, u32 rs, u32 uimm16) { + USE_INTERP_IF_REQUESTED(XORIS, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(uimm16)); + auto rs_i64 = GetGpr(rs); auto res_i64 = m_ir_builder->CreateXor(rs_i64, (u64)uimm16 << 16); SetGpr(ra, res_i64); } void Compiler::ANDI_(u32 ra, u32 rs, u32 uimm16) { + USE_INTERP_IF_REQUESTED(ANDI_, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(uimm16)); + auto rs_i64 = GetGpr(rs); auto res_i64 = m_ir_builder->CreateAnd(rs_i64, uimm16); SetGpr(ra, res_i64); @@ -2009,6 +2067,8 @@ void Compiler::ANDI_(u32 ra, u32 rs, u32 uimm16) { } void Compiler::ANDIS_(u32 ra, u32 rs, u32 uimm16) { + USE_INTERP_IF_REQUESTED(ANDIS_, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(uimm16)); + auto rs_i64 = GetGpr(rs); auto res_i64 = m_ir_builder->CreateAnd(rs_i64, (u64)uimm16 << 16); SetGpr(ra, res_i64); @@ -2016,6 +2076,8 @@ void Compiler::ANDIS_(u32 ra, u32 rs, u32 uimm16) { } void Compiler::RLDICL(u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) { + USE_INTERP_IF_REQUESTED(RLDICL, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(sh), m_ir_builder->getInt32(mb), m_ir_builder->getInt32(rc)); + auto rs_i64 = GetGpr(rs); auto res_i64 = rs_i64; if (sh) { @@ -2033,6 +2095,8 @@ void Compiler::RLDICL(u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) { } void Compiler::RLDICR(u32 ra, u32 rs, u32 sh, u32 me, u32 rc) { + USE_INTERP_IF_REQUESTED(RLDICR, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(sh), m_ir_builder->getInt32(me), m_ir_builder->getInt32(rc)); + auto rs_i64 = GetGpr(rs); auto res_i64 = rs_i64; if (sh) { @@ -2050,6 +2114,8 @@ void Compiler::RLDICR(u32 ra, u32 rs, u32 sh, u32 me, u32 rc) { } void Compiler::RLDIC(u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) { + USE_INTERP_IF_REQUESTED(RLDIC, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(sh), m_ir_builder->getInt32(mb), m_ir_builder->getInt32(rc)); + auto rs_i64 = GetGpr(rs); auto res_i64 = rs_i64; if (sh) { @@ -2067,6 +2133,8 @@ void Compiler::RLDIC(u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) { } void Compiler::RLDIMI(u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) { + USE_INTERP_IF_REQUESTED(RLDIMI, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(sh), m_ir_builder->getInt32(mb), m_ir_builder->getInt32(rc)); + auto rs_i64 = GetGpr(rs); auto ra_i64 = GetGpr(ra); auto res_i64 = rs_i64; @@ -2088,6 +2156,8 @@ void Compiler::RLDIMI(u32 ra, u32 rs, u32 sh, u32 mb, u32 rc) { } void Compiler::RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, u32 is_r, u32 rc) { + USE_INTERP_IF_REQUESTED(RLDC_LR, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(rb), m_ir_builder->getInt32(m_eb), m_ir_builder->getInt32(is_r), m_ir_builder->getInt32(rc)); + auto rs_i64 = GetGpr(rs); auto rb_i64 = GetGpr(rb); auto shl_i64 = m_ir_builder->CreateAnd(rb_i64, 0x3F); @@ -2111,6 +2181,8 @@ void Compiler::RLDC_LR(u32 ra, u32 rs, u32 rb, u32 m_eb, u32 is_r, u32 rc) { } void Compiler::CMP(u32 crfd, u32 l, u32 ra, u32 rb) { + USE_INTERP_IF_REQUESTED(CMP, m_ir_builder->getInt32(crfd), m_ir_builder->getInt32(l), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rb)); + Value * ra_i64; Value * rb_i64; if (l == 0) { @@ -2245,12 +2317,16 @@ void Compiler::MULHWU(u32 rd, u32 ra, u32 rb, u32 rc) { } void Compiler::MFOCRF(u32 a, u32 rd, u32 crm) { + USE_INTERP_IF_REQUESTED(MFOCRF, m_ir_builder->getInt32(a), m_ir_builder->getInt32(rd), m_ir_builder->getInt32(crm)); + auto cr_i32 = GetCr(); auto cr_i64 = m_ir_builder->CreateZExt(cr_i32, m_ir_builder->getInt64Ty()); SetGpr(rd, cr_i64); } void Compiler::LWARX(u32 rd, u32 ra, u32 rb) { + USE_INTERP_IF_REQUESTED(LWARX, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rb)); + auto addr_i64 = GetGpr(rb); if (ra) { auto ra_i64 = GetGpr(ra); @@ -2333,6 +2409,8 @@ void Compiler::SLD(u32 ra, u32 rs, u32 rb, u32 rc) { } void Compiler::AND(u32 ra, u32 rs, u32 rb, u32 rc) { + USE_INTERP_IF_REQUESTED(AND, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(rb), m_ir_builder->getInt32(rc)); + auto rs_i64 = GetGpr(rs); auto rb_i64 = GetGpr(rb); auto res_i64 = m_ir_builder->CreateAnd(rs_i64, rb_i64); @@ -2344,6 +2422,8 @@ void Compiler::AND(u32 ra, u32 rs, u32 rb, u32 rc) { } void Compiler::CMPL(u32 crfd, u32 l, u32 ra, u32 rb) { + USE_INTERP_IF_REQUESTED(CMPL, m_ir_builder->getInt32(crfd), m_ir_builder->getInt32(l), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rb)); + Value * ra_i64; Value * rb_i64; if (l == 0) { @@ -2409,6 +2489,8 @@ void Compiler::LVEHX(u32 vd, u32 ra, u32 rb) { } void Compiler::SUBF(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { + USE_INTERP_IF_REQUESTED(SUBF, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rb), m_ir_builder->getInt32(oe), m_ir_builder->getInt32(rc)); + auto ra_i64 = GetGpr(ra); auto rb_i64 = GetGpr(rb); auto diff_i64 = m_ir_builder->CreateSub(rb_i64, ra_i64); @@ -2568,6 +2650,8 @@ void Compiler::LVX(u32 vd, u32 ra, u32 rb) { } void Compiler::NEG(u32 rd, u32 ra, u32 oe, u32 rc) { + USE_INTERP_IF_REQUESTED(NEG, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(oe), m_ir_builder->getInt32(rc)); + auto ra_i64 = GetGpr(ra); auto diff_i64 = m_ir_builder->CreateSub(m_ir_builder->getInt64(0), ra_i64); SetGpr(rd, diff_i64); @@ -2669,6 +2753,8 @@ void Compiler::ADDE(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { } void Compiler::MTOCRF(u32 l, u32 crm, u32 rs) { + USE_INTERP_IF_REQUESTED(MTOCRF, m_ir_builder->getInt32(l), m_ir_builder->getInt32(crm), m_ir_builder->getInt32(rs)); + auto rs_i32 = GetGpr(rs, 32); auto cr_i32 = GetCr(); u32 mask = 0; @@ -2699,6 +2785,8 @@ void Compiler::STDX(u32 rs, u32 ra, u32 rb) { } void Compiler::STWCX_(u32 rs, u32 ra, u32 rb) { + USE_INTERP_IF_REQUESTED(STWCX_, m_ir_builder->getInt32(rs), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rb)); + auto addr_i64 = GetGpr(rb); if (ra) { auto ra_i64 = GetGpr(ra); @@ -2922,6 +3010,8 @@ void Compiler::ADDME(u32 rd, u32 ra, u32 oe, u32 rc) { } void Compiler::MULLW(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { + USE_INTERP_IF_REQUESTED(MULLW, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rb), m_ir_builder->getInt32(oe), m_ir_builder->getInt32(rc)); + auto ra_i32 = GetGpr(ra, 32); auto rb_i32 = GetGpr(rb, 32); auto ra_i64 = m_ir_builder->CreateSExt(ra_i32, m_ir_builder->getInt64Ty()); @@ -2954,6 +3044,8 @@ void Compiler::STBUX(u32 rs, u32 ra, u32 rb) { } void Compiler::ADD(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { + USE_INTERP_IF_REQUESTED(ADD, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rb), m_ir_builder->getInt32(oe), m_ir_builder->getInt32(rc)); + auto ra_i64 = GetGpr(ra); auto rb_i64 = GetGpr(rb); auto sum_i64 = m_ir_builder->CreateAdd(ra_i64, rb_i64); @@ -3179,6 +3271,8 @@ void Compiler::STHUX(u32 rs, u32 ra, u32 rb) { } void Compiler::OR(u32 ra, u32 rs, u32 rb, u32 rc) { + USE_INTERP_IF_REQUESTED(OR, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(rb), m_ir_builder->getInt32(rc)); + auto rs_i64 = GetGpr(rs); auto rb_i64 = GetGpr(rb); auto res_i64 = m_ir_builder->CreateOr(rs_i64, rb_i64); @@ -3208,6 +3302,8 @@ void Compiler::DIVDU(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { } void Compiler::DIVWU(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { + USE_INTERP_IF_REQUESTED(DIVWU, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rb), m_ir_builder->getInt32(oe), m_ir_builder->getInt32(rc)); + auto ra_i32 = GetGpr(ra, 32); auto rb_i32 = GetGpr(rb, 32); auto res_i32 = m_ir_builder->CreateUDiv(ra_i32, rb_i32); @@ -3284,6 +3380,8 @@ void Compiler::DIVD(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { } void Compiler::DIVW(u32 rd, u32 ra, u32 rb, u32 oe, u32 rc) { + USE_INTERP_IF_REQUESTED(DIVW, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rb), m_ir_builder->getInt32(oe), m_ir_builder->getInt32(rc)); + auto ra_i32 = GetGpr(ra, 32); auto rb_i32 = GetGpr(rb, 32); auto res_i32 = m_ir_builder->CreateSDiv(ra_i32, rb_i32); @@ -3682,6 +3780,8 @@ void Compiler::DSS(u32 strm, u32 a) { } void Compiler::SRAWI(u32 ra, u32 rs, u32 sh, u32 rc) { + USE_INTERP_IF_REQUESTED(SRAWI, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(sh), m_ir_builder->getInt32(rc)); + auto rs_i32 = GetGpr(rs, 32); auto rs_i64 = m_ir_builder->CreateZExt(rs_i32, m_ir_builder->getInt64Ty()); rs_i64 = m_ir_builder->CreateShl(rs_i64, 32); @@ -3757,6 +3857,8 @@ void Compiler::STVRXL(u32 vs, u32 ra, u32 rb) { } void Compiler::EXTSB(u32 ra, u32 rs, u32 rc) { + USE_INTERP_IF_REQUESTED(EXTSB, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(rc)); + auto rs_i8 = GetGpr(rs, 8); auto rs_i64 = m_ir_builder->CreateSExt(rs_i8, m_ir_builder->getInt64Ty()); SetGpr(ra, rs_i64); @@ -3779,6 +3881,8 @@ void Compiler::STFIWX(u32 frs, u32 ra, u32 rb) { } void Compiler::EXTSW(u32 ra, u32 rs, u32 rc) { + USE_INTERP_IF_REQUESTED(EXTSW, m_ir_builder->getInt32(ra), m_ir_builder->getInt32(rs), m_ir_builder->getInt32(rc)); + auto rs_i32 = GetGpr(rs, 32); auto rs_i64 = m_ir_builder->CreateSExt(rs_i32, m_ir_builder->getInt64Ty()); SetGpr(ra, rs_i64); @@ -3810,6 +3914,8 @@ void Compiler::DCBZ(u32 ra, u32 rb) { } void Compiler::LWZ(u32 rd, u32 ra, s32 d) { + USE_INTERP_IF_REQUESTED(LWZ, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(d)); + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); if (ra) { auto ra_i64 = GetGpr(ra); @@ -3833,6 +3939,8 @@ void Compiler::LWZU(u32 rd, u32 ra, s32 d) { } void Compiler::LBZ(u32 rd, u32 ra, s32 d) { + USE_INTERP_IF_REQUESTED(LBZ, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(d)); + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); if (ra) { auto ra_i64 = GetGpr(ra); @@ -3856,6 +3964,8 @@ void Compiler::LBZU(u32 rd, u32 ra, s32 d) { } void Compiler::STW(u32 rs, u32 ra, s32 d) { + USE_INTERP_IF_REQUESTED(STW, m_ir_builder->getInt32(rs), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(d)); + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); if (ra) { auto ra_i64 = GetGpr(ra); @@ -3894,6 +4004,8 @@ void Compiler::STBU(u32 rs, u32 ra, s32 d) { } void Compiler::LHZ(u32 rd, u32 ra, s32 d) { + USE_INTERP_IF_REQUESTED(LHZ, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(d)); + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); if (ra) { auto ra_i64 = GetGpr(ra); @@ -3986,6 +4098,8 @@ void Compiler::STMW(u32 rs, u32 ra, s32 d) { } void Compiler::LFS(u32 frd, u32 ra, s32 d) { + USE_INTERP_IF_REQUESTED(LFS, m_ir_builder->getInt32(frd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(d)); + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); if (ra) { auto ra_i64 = GetGpr(ra); @@ -4027,6 +4141,8 @@ void Compiler::LFDU(u32 frd, u32 ra, s32 ds) { } void Compiler::STFS(u32 frs, u32 ra, s32 d) { + USE_INTERP_IF_REQUESTED(STFS, m_ir_builder->getInt32(frs), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(d)); + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); if (ra) { auto ra_i64 = GetGpr(ra); @@ -4069,6 +4185,8 @@ void Compiler::STFDU(u32 frs, u32 ra, s32 d) { } void Compiler::LD(u32 rd, u32 ra, s32 ds) { + USE_INTERP_IF_REQUESTED(LD, m_ir_builder->getInt32(rd), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(ds)); + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)ds); if (ra) { auto ra_i64 = GetGpr(ra); @@ -4132,6 +4250,7 @@ void Compiler::FSUBS(u32 frd, u32 fra, u32 frb, u32 rc) { } void Compiler::FADDS(u32 frd, u32 fra, u32 frb, u32 rc) { + auto ra_f64 = GetFpr(fra); auto rb_f64 = GetFpr(frb); auto res_f64 = m_ir_builder->CreateFAdd(ra_f64, rb_f64); @@ -4258,6 +4377,8 @@ void Compiler::FNMADDS(u32 frd, u32 fra, u32 frc, u32 frb, u32 rc) { } void Compiler::STD(u32 rs, u32 ra, s32 d) { + USE_INTERP_IF_REQUESTED(STD, m_ir_builder->getInt32(rs), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(d)); + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)d); if (ra) { auto ra_i64 = GetGpr(ra); @@ -4268,6 +4389,8 @@ void Compiler::STD(u32 rs, u32 ra, s32 d) { } void Compiler::STDU(u32 rs, u32 ra, s32 ds) { + USE_INTERP_IF_REQUESTED(STDU, m_ir_builder->getInt32(rs), m_ir_builder->getInt32(ra), m_ir_builder->getInt32(ds)); + auto addr_i64 = (Value *)m_ir_builder->getInt64((s64)ds); auto ra_i64 = GetGpr(ra); addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64); diff --git a/rpcs3/config.h b/rpcs3/config.h index 571c834a08..2ed632a31a 100644 --- a/rpcs3/config.h +++ b/rpcs3/config.h @@ -590,6 +590,247 @@ namespace rpcs3 entry min_id { this, "Excluded block range min", 200 }; entry max_id { this, "Excluded block range max", 250 }; entry threshold { this, "Compilation threshold", 1000 }; + +#define MACRO_PPU_INST_MAIN_EXPANDERS(MACRO) \ + /*MACRO(HACK)*/ \ + /*MACRO(TDI)*/ \ + MACRO(TWI) \ + MACRO(MULLI) \ + MACRO(SUBFIC) \ + MACRO(CMPLI) \ + MACRO(CMPI) \ + MACRO(ADDIC) \ + MACRO(ADDIC_) \ + MACRO(ADDI) \ + MACRO(ADDIS) \ + /*MACRO(BC)*/ \ + /*MACRO(SC)*/ \ + /*MACRO(B)*/ \ + MACRO(RLWIMI) \ + MACRO(RLWINM) \ + MACRO(RLWNM) \ + MACRO(ORI) \ + MACRO(ORIS) \ + MACRO(XORI) \ + MACRO(XORIS) \ + MACRO(ANDI_) \ + MACRO(ANDIS_) \ + MACRO(LWZ) \ + /*MACRO(LWZU)*/ \ + MACRO(LBZ) \ + /*MACRO(LBZU)*/ \ + MACRO(STW) \ + /*MACRO(STWU)*/ \ + /*MACRO(STB)*/ \ + /*MACRO(STBU)*/ \ + MACRO(LHZ) \ + /*MACRO(LHZU)*/ \ + /*MACRO(LHA)*/ \ + /*MACRO(LHAU)*/ \ + /*MACRO(STH)*/ \ + /*MACRO(STHU)*/ \ + /*MACRO(LMW)*/ \ + /*MACRO(STMW)*/ \ + MACRO(LFS) \ + /*MACRO(LFSU)*/ \ + /*MACRO(LFD)*/ \ + /*MACRO(LFDU)*/ \ + MACRO(STFS) \ + /*MACRO(STFSU)*/ \ + /*MACRO(STFD)*/ \ + /*MACRO(STFDU)*/ \ + /*MACRO(LFQ)*/ \ + /*MACRO(LFQU)*/ + +#define MACRO_PPU_INST_G_13_EXPANDERS(MACRO) \ + MACRO(MCRF) \ + /*MACRO(BCLR)*/ \ + MACRO(CRNOR) \ + MACRO(CRANDC) \ + /*MACRO(ISYNC)*/ \ + MACRO(CRXOR) \ + MACRO(CRNAND) \ + MACRO(CRAND) \ + MACRO(CREQV) \ + MACRO(CRORC) \ + MACRO(CROR) \ + /*MACRO(BCCTR)*/ + +#define MACRO_PPU_INST_G_1E_EXPANDERS(MACRO) \ + MACRO(RLDICL) \ + MACRO(RLDICR) \ + MACRO(RLDIC) \ + MACRO(RLDIMI) \ + MACRO(RLDC_LR) + +#define MACRO_PPU_INST_G_1F_EXPANDERS(MACRO) \ + MACRO(CMP) \ + /*MACRO(TW)*/ \ + /*MACRO(LVSL)*/ \ + /*MACRO(LVEBX)*/ \ + /*MACRO(SUBFC)*/ \ + /*MACRO(MULHDU)*/ \ + /*MACRO(ADDC)*/ \ + /*MACRO(MULHWU)*/ \ + MACRO(MFOCRF) \ + MACRO(LWARX) \ + /*MACRO(LDX)*/ \ + /*MACRO(LWZX)*/ \ + /*MACRO(CNTLZW)*/ \ + /*MACRO(SLD)*/ \ + MACRO(AND) \ + MACRO(CMPL) \ + /*MACRO(LVSR)*/ \ + /*MACRO(LVEHX)*/ \ + MACRO(SUBF) \ + /*MACRO(LDUX)*/ \ + /*MACRO(DCBST)*/ \ + /*MACRO(LWZUX)*/ \ + /*MACRO(CNTLZD)*/ \ + /*MACRO(ANDC)*/ \ + /*MACRO(TD)*/ \ + /*MACRO(LVEWX)*/ \ + /*MACRO(MULHD) \ + MACRO(MULHW) \ + MACRO(LDARX) \ + MACRO(DCBF) \ + MACRO(LBZX) \ + MACRO(LVX)*/ \ + MACRO(NEG) \ + /*MACRO(LBZUX) \ + MACRO(NOR) \ + MACRO(STVEBX) \ + MACRO(SUBFE) \ + MACRO(ADDE)*/ \ + MACRO(MTOCRF) \ + /*MACRO(STDX)*/ \ + MACRO(STWCX_) \ + /*MACRO(STWX) \ + MACRO(STVEHX) \ + MACRO(STDUX) \ + MACRO(STWUX) \ + MACRO(STVEWX) \ + MACRO(SUBFZE) \ + MACRO(ADDZE) \ + MACRO(STDCX_) \ + MACRO(STBX) \ + MACRO(STVX) \ + MACRO(SUBFME) \ + MACRO(MULLD) \ + MACRO(ADDME)*/ \ + MACRO(MULLW) \ + /*MACRO(DCBTST) \ + MACRO(STBUX) \ + MACRO(DOZ)*/ \ + MACRO(ADD) \ + /*MACRO(DCBT) \ + MACRO(LHZX) \ + MACRO(EQV) \ + MACRO(ECIWX) \ + MACRO(LHZUX) \ + MACRO(XOR)*/ \ + /*MACRO(MFSPR)*/ \ + /*MACRO(LWAX) \ + MACRO(DST) \ + MACRO(LHAX) \ + MACRO(LVXL) \ + MACRO(MFTB) \ + MACRO(LWAUX) \ + MACRO(DSTST) \ + MACRO(LHAUX) \ + MACRO(STHX) \ + MACRO(ORC) \ + MACRO(ECOWX) \ + MACRO(STHUX)*/ \ + MACRO(OR) \ + /*MACRO(DIVDU)*/ \ + MACRO(DIVWU) \ + /*MACRO(MTSPR)*/ \ + /*MACRO(DCBI) \ + MACRO(NAND) \ + MACRO(STVXL) \ + MACRO(DIVD)*/ \ + MACRO(DIVW) \ + /*MACRO(LVLX) \ + MACRO(SUBFCO) \ + MACRO(ADDCO) \ + MACRO(LDBRX) \ + MACRO(LSWX) \ + MACRO(SRW) \ + MACRO(SRD) \ + MACRO(LVRX) \ + MACRO(SUBFO) \ + MACRO(LFSUX) \ + MACRO(LSWI) \ + MACRO(SYNC) \ + MACRO(LFDX) \ + MACRO(NEGO) \ + MACRO(LFDUX) \ + MACRO(STVLX) \ + MACRO(SUBFEO) \ + MACRO(ADDEO) \ + MACRO(STDBRX) \ + MACRO(STSWX) \ + MACRO(STWBRX) \ + MACRO(STFSX) \ + MACRO(STVRX) \ + MACRO(STFSUX) \ + MACRO(SUBFZEO) \ + MACRO(ADDZEO) \ + MACRO(STSWI) \ + MACRO(STFDX) \ + MACRO(SUBFMEO) \ + MACRO(MULLDO) \ + MACRO(ADDMEO) \ + MACRO(MULLWO) \ + MACRO(STFDUX) \ + MACRO(LVLXL) \ + MACRO(ADDO) \ + MACRO(LHBRX) \ + MACRO(SRAW) \ + MACRO(SRAD) \ + MACRO(LVRXL) \ + MACRO(DSS)*/ \ + MACRO(SRAWI) \ + /*MACRO(SRADI1) \ + MACRO(SRADI2) \ + MACRO(EIEIO) \ + MACRO(STVLXL) \ + MACRO(STHBRX) \ + MACRO(EXTSH) \ + MACRO(STVRXL)*/ \ + MACRO(EXTSB) \ + /*MACRO(DIVDUO) \ + MACRO(DIVWUO) \ + MACRO(STFIWX)*/ \ + MACRO(EXTSW) \ + /*MACRO(ICBI) \ + MACRO(DIVDO) \ + MACRO(DIVWO) \ + MACRO(DCBZ)*/ + +#define MACRO_PPU_INST_G_3A_EXPANDERS(MACRO) \ + MACRO(LD) \ + /*MACRO(LDU)*/ \ + /*MACRO(LWA)*/ + +#define MACRO_PPU_INST_G_3E_EXPANDERS(MACRO) \ + MACRO(STD) \ + MACRO(STDU) + + + + +#define INSTRUCTION_ENTRY(inst) \ + entry enable_##inst { this, "Enable instruction " #inst, true}; + + MACRO_PPU_INST_MAIN_EXPANDERS(INSTRUCTION_ENTRY) + MACRO_PPU_INST_G_13_EXPANDERS(INSTRUCTION_ENTRY) + MACRO_PPU_INST_G_1E_EXPANDERS(INSTRUCTION_ENTRY) + MACRO_PPU_INST_G_1F_EXPANDERS(INSTRUCTION_ENTRY) + MACRO_PPU_INST_G_3A_EXPANDERS(INSTRUCTION_ENTRY) + MACRO_PPU_INST_G_3E_EXPANDERS(INSTRUCTION_ENTRY) + } llvm{ this }; entry ppu_decoder { this, "PPU Decoder", ppu_decoder_type::interpreter };