static u32 (INT_ATTR *fetch)(u8 **memRLUT, u32 pc) = fetchNoCache;
+// Make the timing events trigger faster as we are currently assuming everything
+// takes one cycle, which is not the case on real hardware.
+// FIXME: count cache misses, memory latencies, stalls to get rid of this
+static inline void addCycle(void)
+{
+ assert(psxRegs.subCycleStep >= 0x10000);
+ psxRegs.subCycle += psxRegs.subCycleStep;
+ psxRegs.cycle += psxRegs.subCycle >> 16;
+ psxRegs.subCycle &= 0xffff;
+}
+
static void delayRead(int reg, u32 bpc) {
u32 rold, rnew;
case 3:
delayWrite(reg, bpc); return;
}
+ // DS
psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code);
branch = 0;
branch = 0;
psxRegs.pc = tar;
- psxRegs.cycle += BIAS;
+ addCycle();
psxBranchTest();
return 1;
}
return psxDelayBranchExec(tar2);
}
debugI();
- psxRegs.cycle += BIAS;
+ addCycle();
/*
* Got a branch at tar1:
return psxDelayBranchExec(tmp1);
}
debugI();
- psxRegs.cycle += BIAS;
+ addCycle();
/*
* Got a branch at tar2:
debugI();
psxRegs.pc += 4;
- psxRegs.cycle += BIAS;
+ addCycle();
// check for load delay
- tmp = psxRegs.code >> 26;
+ tmp = code >> 26;
switch (tmp) {
case 0x10: // COP0
switch (_Rs_) {
break;
}
- psxBSC[psxRegs.code >> 26](&psxRegs, psxRegs.code);
+ psxBSC[code >> 26](&psxRegs, code);
branch = 0;
psxRegs.pc = branchPC;
* Register branch logic *
* Format: OP rs, offset *
*********************************************************/
-#define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
-#define RepZBranchLinki32(op) { _SetLink(31); if(_i32(_rRs_) op 0) { doBranch(_BranchTarget_); } }
+#define RepZBranchi32(op) \
+ if(_i32(_rRs_) op 0) \
+ doBranch(_BranchTarget_);
+#define RepZBranchLinki32(op) { \
+ s32 temp = _i32(_rRs_); \
+ _SetLink(31); \
+ if(temp op 0) \
+ doBranch(_BranchTarget_); \
+}
OP(psxBGEZ) { RepZBranchi32(>=) } // Branch if Rs >= 0
OP(psxBGEZAL) { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
*********************************************************/
OP(psxBREAK) {
regs_->pc -= 4;
- psxException(0x24, branch);
+ psxException(0x24, branch, ®s_->CP0);
}
OP(psxSYSCALL) {
regs_->pc -= 4;
- psxException(0x20, branch);
+ psxException(0x20, branch, ®s_->CP0);
}
static inline void psxTestSWInts(psxRegisters *regs_) {
if (regs_->CP0.n.Cause & regs_->CP0.n.Status & 0x0300 &&
regs_->CP0.n.Status & 0x1) {
regs_->CP0.n.Cause &= ~0x7c;
- psxException(regs_->CP0.n.Cause, branch);
+ psxException(regs_->CP0.n.Cause, branch, ®s_->CP0);
}
}
// SysPrintf("MTC0 %d: %x\n", reg, val);
switch (reg) {
case 12: // Status
- regs_->CP0.r[12] = val;
+ if ((regs_->CP0.n.Status ^ val) & (1 << 16))
+ psxMemOnIsolate((val >> 16) & 1);
+ regs_->CP0.n.Status = val;
psxTestSWInts(regs_);
break;
}
OP(psxREGIMM) {
- switch (_Rt_) {
- case 0x00: psxBLTZ(regs_, code); break;
- case 0x01: psxBGEZ(regs_, code); break;
+ u32 rt = _Rt_;
+ switch (rt) {
case 0x10: psxBLTZAL(regs_, code); break;
case 0x11: psxBGEZAL(regs_, code); break;
- default: psxNULL_(); break;
+ default:
+ if (rt & 1)
+ psxBGEZ(regs_, code);
+ else
+ psxBLTZ(regs_, code);
}
}
}
static void intReset() {
- memset(&ICache, 0xff, sizeof(ICache));
}
static inline void execI_(u8 **memRLUT, psxRegisters *regs_) {
if (Config.Debug) ProcessDebug();
regs_->pc += 4;
- regs_->cycle += BIAS;
+ addCycle();
psxBSC[regs_->code >> 26](regs_, regs_->code);
}
execI_(memRLUT, regs_);
}
-static void intExecuteBlock() {
+void intExecuteBlock(enum blockExecCaller caller) {
psxRegisters *regs_ = &psxRegs;
u8 **memRLUT = psxMemRLUT;
static void intClear(u32 Addr, u32 Size) {
}
-void intNotify (int note, void *data) {
- /* Gameblabla - Only clear the icache if it's isolated */
- if (note == R3000ACPU_NOTIFY_CACHE_ISOLATED)
- {
+static void intNotify(enum R3000Anote note, void *data) {
+ switch (note) {
+ case R3000ACPU_NOTIFY_CACHE_ISOLATED: // Armored Core?
+ case R3000ACPU_NOTIFY_AFTER_LOAD:
memset(&ICache, 0xff, sizeof(ICache));
+ break;
+ case R3000ACPU_NOTIFY_CACHE_UNISOLATED:
+ case R3000ACPU_NOTIFY_BEFORE_SAVE:
+ break;
}
}
void intApplyConfig() {
+ int cycle_mult;
+
assert(psxBSC[18] == psxCOP2 || psxBSC[18] == psxCOP2_stall);
assert(psxBSC[50] == gteLWC2 || psxBSC[50] == gteLWC2_stall);
assert(psxBSC[58] == gteSWC2 || psxBSC[58] == gteSWC2_stall);
fetch = fetchNoCache;
else
fetch = fetchICache;
+
+ cycle_mult = Config.cycle_multiplier_override && Config.cycle_multiplier == CYCLE_MULT_DEFAULT
+ ? Config.cycle_multiplier_override : Config.cycle_multiplier;
+ psxRegs.subCycleStep = 0x10000 * cycle_mult / 100;
}
static void intShutdown() {