void Jit64::mfspr(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITSystemRegistersOff) u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F); int d = inst.RD; switch (iIndex) { case SPR_WPAR: case SPR_DEC: case SPR_TL: case SPR_TU: case SPR_PMC1: case SPR_PMC2: case SPR_PMC3: case SPR_PMC4: FallBackToInterpreter(inst); return; default: gpr.Lock(d); gpr.BindToRegister(d, false); MOV(32, gpr.R(d), M(&PowerPC::ppcState.spr[iIndex])); gpr.UnlockAll(); break; } }
void Jit64::mtspr(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITSystemRegistersOff) u32 iIndex = (inst.SPRU << 5) | (inst.SPRL & 0x1F); int d = inst.RD; switch (iIndex) { case SPR_DMAU: case SPR_SPRG0: case SPR_SPRG1: case SPR_SPRG2: case SPR_SPRG3: case SPR_SRR0: case SPR_SRR1: // These are safe to do the easy way, see the bottom of this function. break; case SPR_LR: case SPR_CTR: case SPR_XER: // These are safe to do the easy way, see the bottom of this function. break; case SPR_GQR0: case SPR_GQR0 + 1: case SPR_GQR0 + 2: case SPR_GQR0 + 3: case SPR_GQR0 + 4: case SPR_GQR0 + 5: case SPR_GQR0 + 6: case SPR_GQR0 + 7: // These are safe to do the easy way, see the bottom of this function. break; default: FallBackToInterpreter(inst); return; } // OK, this is easy. if (!gpr.R(d).IsImm()) { gpr.Lock(d); gpr.BindToRegister(d, true, false); } MOV(32, M(&PowerPC::ppcState.spr[iIndex]), gpr.R(d)); gpr.UnlockAll(); }
void JitILBase::icbi(UGeckoInstruction inst) { FallBackToInterpreter(inst); ibuild.EmitBranchUncond(ibuild.EmitIntConst(js.compilerPC + 4)); }
void JitArm::icbi(UGeckoInstruction inst) { FallBackToInterpreter(inst); WriteExit(js.compilerPC + 4); }
void Jit64::reg_imm(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITIntegerOff) u32 d = inst.RD, a = inst.RA, s = inst.RS; switch (inst.OPCD) { case 14: // addi // occasionally used as MOV - emulate, with immediate propagation if (gpr.R(a).IsImm() && d != a && a != 0) { gpr.SetImmediate32(d, (u32)gpr.R(a).offset + (u32)(s32)(s16)inst.SIMM_16); } else if (inst.SIMM_16 == 0 && d != a && a != 0) { gpr.Lock(a, d); gpr.BindToRegister(d, false, true); MOV(32, gpr.R(d), gpr.R(a)); gpr.UnlockAll(); } else { regimmop(d, a, false, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD); //addi } break; case 15: if (a == 0) // lis { // Merge with next instruction if loading a 32-bits immediate value (lis + addi, lis + ori) if (!js.isLastInstruction && !Core::g_CoreStartupParameter.bEnableDebugging) { if ((js.next_inst.OPCD == 14) && (js.next_inst.RD == d) && (js.next_inst.RA == d)) // addi { gpr.SetImmediate32(d, ((u32)inst.SIMM_16 << 16) + (u32)(s32)js.next_inst.SIMM_16); js.downcountAmount++; js.skipnext = true; break; } else if ((js.next_inst.OPCD == 24) && (js.next_inst.RA == d) && (js.next_inst.RS == d)) // ori { gpr.SetImmediate32(d, ((u32)inst.SIMM_16 << 16) | (u32)js.next_inst.UIMM); js.downcountAmount++; js.skipnext = true; break; } } // Not merged regimmop(d, a, false, (u32)inst.SIMM_16 << 16, Add, &XEmitter::ADD); } else // addis { regimmop(d, a, false, (u32)inst.SIMM_16 << 16, Add, &XEmitter::ADD); } break; case 24: if (a == 0 && s == 0 && inst.UIMM == 0 && !inst.Rc) //check for nop {NOP(); return;} //make the nop visible in the generated code. not much use but interesting if we see one. regimmop(a, s, true, inst.UIMM, Or, &XEmitter::OR); break; //ori case 25: regimmop(a, s, true, inst.UIMM << 16, Or, &XEmitter::OR, false); break;//oris case 28: regimmop(a, s, true, inst.UIMM, And, &XEmitter::AND, true); break; case 29: regimmop(a, s, true, inst.UIMM << 16, And, &XEmitter::AND, true); break; case 26: regimmop(a, s, true, inst.UIMM, Xor, &XEmitter::XOR, false); break; //xori case 27: regimmop(a, s, true, inst.UIMM << 16, Xor, &XEmitter::XOR, false); break; //xoris case 12: regimmop(d, a, false, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD, false, true); break; //addic case 13: regimmop(d, a, true, (u32)(s32)inst.SIMM_16, Add, &XEmitter::ADD, true, true); break; //addic_rc default: FallBackToInterpreter(inst); break; } }