#endif
#include "psxcommon.h"
-#include "psxmem.h"
-#include "psxcounters.h"
-#include "psxbios.h"
-enum {
+enum R3000Aexception {
+ R3000E_Int = 0, // Interrupt
+ R3000E_AdEL = 4, // Address error (on load/I-fetch)
+ R3000E_AdES = 5, // Address error (on store)
+ R3000E_IBE = 6, // Bus error (instruction fetch)
+ R3000E_DBE = 7, // Bus error (data load/store)
+ R3000E_Syscall = 8, // syscall instruction
+ R3000E_Bp = 9, // Breakpoint - a break instruction
+ R3000E_RI = 10, // reserved instruction
+ R3000E_CpU = 11, // Co-Processor unusable
+ R3000E_Ov = 12 // arithmetic overflow
+};
+
+enum R3000Anote {
R3000ACPU_NOTIFY_CACHE_ISOLATED = 0,
R3000ACPU_NOTIFY_CACHE_UNISOLATED = 1,
- R3000ACPU_NOTIFY_DMA3_EXE_LOAD = 2
+ R3000ACPU_NOTIFY_BEFORE_SAVE, // data arg - hle if non-null
+ R3000ACPU_NOTIFY_AFTER_LOAD,
+};
+
+enum blockExecCaller {
+ EXEC_CALLER_BOOT,
+ EXEC_CALLER_HLE,
};
typedef struct {
int (*Init)();
void (*Reset)();
- void (*Execute)(); /* executes up to a break */
- void (*ExecuteBlock)(); /* executes up to a jump */
+ void (*Execute)();
+ void (*ExecuteBlock)(enum blockExecCaller caller); /* executes up to a jump */
void (*Clear)(u32 Addr, u32 Size);
- void (*Notify)(int note, void *data);
+ void (*Notify)(enum R3000Anote note, void *data);
void (*ApplyConfig)();
void (*Shutdown)();
} R3000Acpu;
extern R3000Acpu psxRec;
typedef union {
-#if defined(__BIGENDIAN__)
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
struct { u8 h3, h2, h, l; } b;
struct { s8 h3, h2, h, l; } sb;
struct { u16 h, l; } w;
u32 r0, at, v0, v1, a0, a1, a2, a3,
t0, t1, t2, t3, t4, t5, t6, t7,
s0, s1, s2, s3, s4, s5, s6, s7,
- t8, t9, k0, k1, gp, sp, s8, ra, lo, hi;
+ t8, t9, k0, k1, gp, sp, fp, ra, lo, hi;
} n;
u32 r[34]; /* Lo, Hi in r[32] and r[33] */
PAIR p[34];
} psxGPRRegs;
-typedef union {
+typedef union psxCP0Regs_ {
struct {
- u32 Index, Random, EntryLo0, EntryLo1,
- Context, PageMask, Wired, Reserved0,
- BadVAddr, Count, EntryHi, Compare,
- Status, Cause, EPC, PRid,
- Config, LLAddr, WatchLO, WatchHI,
- XContext, Reserved1, Reserved2, Reserved3,
- Reserved4, Reserved5, ECC, CacheErr,
- TagLo, TagHi, ErrorEPC, Reserved6;
+ u32 Reserved0, Reserved1, Reserved2, BPC,
+ Reserved4, BDA, Target, DCIC,
+ BadVAddr, BDAM, Reserved10, BPCM,
+ SR, Cause, EPC, PRid,
+ Reserved16[16];
} n;
u32 r[32];
PAIR p[32];
PAIR p[32];
} psxCP2Ctrl;
-enum {
- PSXINT_SIO = 0,
- PSXINT_CDR,
- PSXINT_CDREAD,
- PSXINT_GPUDMA,
- PSXINT_MDECOUTDMA,
- PSXINT_SPUDMA,
- PSXINT_GPUBUSY,
- PSXINT_MDECINDMA,
- PSXINT_GPUOTCDMA,
- PSXINT_CDRDMA,
- PSXINT_NEWDRC_CHECK,
- PSXINT_RCNT,
- PSXINT_CDRLID,
- PSXINT_CDRPLAY,
- PSXINT_SPU_UPDATE,
- PSXINT_COUNT
+enum R3000Abdt {
+ // corresponds to bits 31,30 of Cause reg
+ R3000A_BRANCH_TAKEN = 3,
+ R3000A_BRANCH_NOT_TAKEN = 2,
+ // none or tells that there was an exception in DS back to doBranch
+ R3000A_BRANCH_NONE_OR_EXCEPTION = 0,
};
typedef struct psxCP2Regs {
} psxCP2Regs;
typedef struct {
+ // note: some cores like lightrec don't keep their data here,
+ // so use R3000ACPU_NOTIFY_BEFORE_SAVE to sync
psxGPRRegs GPR; /* General Purpose Registers */
psxCP0Regs CP0; /* Coprocessor0 Registers */
union {
};
psxCP2Regs CP2;
};
- u32 pc; /* Program counter */
- u32 code; /* The instruction */
+ u32 pc; /* Program counter */
+ u32 code; /* The instruction */
u32 cycle;
u32 interrupt;
struct { u32 sCycle, cycle; } intCycle[32];
u32 gteBusyCycle;
u32 muldivBusyCycle;
+ u32 subCycle; /* interpreter cycle counting */
+ u32 subCycleStep;
+ u32 biuReg;
+ u8 branching; /* interp. R3000A_BRANCH_TAKEN / not, 0 if not branch */
+ u8 dloadSel; /* interp. delay load state */
+ u8 dloadReg[2];
+ u32 dloadVal[2];
+ u32 biosBranchCheck;
+ u32 cpuInRecursion;
+ u32 gpuIdleAfter;
+ u32 reserved[1];
// warning: changing anything in psxRegisters requires update of all
- // asm in libpcsxcore/new_dynarec/, but this member can be replaced
- u32 reserved[2];
+ // asm in libpcsxcore/new_dynarec/
} psxRegisters;
extern psxRegisters psxRegs;
/* new_dynarec stuff */
-extern u32 event_cycles[PSXINT_COUNT];
-extern u32 next_interupt;
-
-void new_dyna_before_save(void);
-void new_dyna_after_save(void);
void new_dyna_freeze(void *f, int mode);
-#define new_dyna_set_event(e, c) { \
- s32 c_ = c; \
- u32 abs_ = psxRegs.cycle + c_; \
- s32 odi_ = next_interupt - psxRegs.cycle; \
- event_cycles[e] = abs_; \
- if (c_ < odi_) { \
- /*printf("%u: next_interupt %d -> %d (%u)\n", psxRegs.cycle, odi_, c_, abs_);*/ \
- next_interupt = abs_; \
- } \
-}
-
-#if defined(__BIGENDIAN__)
-
-#define _i32(x) *(s32 *)&x
-#define _u32(x) x
-
-#define _i16(x) (((short *)&x)[1])
-#define _u16(x) (((unsigned short *)&x)[1])
-
-#define _i8(x) (((char *)&x)[3])
-#define _u8(x) (((unsigned char *)&x)[3])
-
-#else
-
-#define _i32(x) *(s32 *)&x
-#define _u32(x) x
-
-#define _i16(x) *(short *)&x
-#define _u16(x) *(unsigned short *)&x
-
-#define _i8(x) *(char *)&x
-#define _u8(x) *(unsigned char *)&x
-
-#endif
-
-/**** R3000A Instruction Macros ****/
-#define _PC_ psxRegs.pc // The next PC to be executed
-
-#define _fOp_(code) ((code >> 26) ) // The opcode part of the instruction register
-#define _fFunct_(code) ((code ) & 0x3F) // The funct part of the instruction register
-#define _fRd_(code) ((code >> 11) & 0x1F) // The rd part of the instruction register
-#define _fRt_(code) ((code >> 16) & 0x1F) // The rt part of the instruction register
-#define _fRs_(code) ((code >> 21) & 0x1F) // The rs part of the instruction register
-#define _fSa_(code) ((code >> 6) & 0x1F) // The sa part of the instruction register
-#define _fIm_(code) ((u16)code) // The immediate part of the instruction register
-#define _fTarget_(code) (code & 0x03ffffff) // The target part of the instruction register
-
-#define _fImm_(code) ((s16)code) // sign-extended immediate
-#define _fImmU_(code) (code&0xffff) // zero-extended immediate
-
-#define _Op_ _fOp_(psxRegs.code)
-#define _Funct_ _fFunct_(psxRegs.code)
-#define _Rd_ _fRd_(psxRegs.code)
-#define _Rt_ _fRt_(psxRegs.code)
-#define _Rs_ _fRs_(psxRegs.code)
-#define _Sa_ _fSa_(psxRegs.code)
-#define _Im_ _fIm_(psxRegs.code)
-#define _Target_ _fTarget_(psxRegs.code)
-
-#define _Imm_ _fImm_(psxRegs.code)
-#define _ImmU_ _fImmU_(psxRegs.code)
-
-#define _rRs_ psxRegs.GPR.r[_Rs_] // Rs register
-#define _rRt_ psxRegs.GPR.r[_Rt_] // Rt register
-#define _rRd_ psxRegs.GPR.r[_Rd_] // Rd register
-#define _rSa_ psxRegs.GPR.r[_Sa_] // Sa register
-#define _rFs_ psxRegs.CP0.r[_Rd_] // Fs register
-
-#define _c2dRs_ psxRegs.CP2D.r[_Rs_] // Rs cop2 data register
-#define _c2dRt_ psxRegs.CP2D.r[_Rt_] // Rt cop2 data register
-#define _c2dRd_ psxRegs.CP2D.r[_Rd_] // Rd cop2 data register
-#define _c2dSa_ psxRegs.CP2D.r[_Sa_] // Sa cop2 data register
-
-#define _rHi_ psxRegs.GPR.n.hi // The HI register
-#define _rLo_ psxRegs.GPR.n.lo // The LO register
-
-#define _JumpTarget_ ((_Target_ * 4) + (_PC_ & 0xf0000000)) // Calculates the target during a jump instruction
-#define _BranchTarget_ ((s16)_Im_ * 4 + _PC_) // Calculates the target during a branch instruction
-
-#define _SetLink(x) psxRegs.GPR.r[x] = _PC_ + 4; // Sets the return address in the link register
-
int psxInit();
void psxReset();
void psxShutdown();
-void psxException(u32 code, u32 bd);
+void psxException(u32 code, enum R3000Abdt bdt, psxCP0Regs *cp0);
void psxBranchTest();
void psxExecuteBios();
-int psxTestLoadDelay(int reg, u32 tmp);
-void psxDelayTest(int reg, u32 bpc);
-void psxTestSWInts();
void psxJumpTest();
+void irq10Interrupt();
+void psxScheduleIrq10(int irq_count, int x_cycles, int y);
+
#ifdef __cplusplus
}
#endif