summaryrefslogtreecommitdiff
path: root/libpcsxcore/r3000a.h
diff options
context:
space:
mode:
authorSND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2011-03-13 08:26:16 +0000
committerSND\weimingzhi_cp <SND\weimingzhi_cp@e17a0e51-4ae3-4d35-97c3-1a29b211df97>2011-03-13 08:26:16 +0000
commit379a8879f7dae1a9074317c0270e12dd203b32c0 (patch)
tree348efb7ecd4f7cbc030f4b5db6683a857f2ae6cf /libpcsxcore/r3000a.h
parentd34b4220bde29d7937d927e9d17a50470a36c500 (diff)
Temporarily reverted r64524 until I (or someone else) find the time to sort out the stuff.
git-svn-id: https://pcsxr.svn.codeplex.com/svn/pcsxr@64536 e17a0e51-4ae3-4d35-97c3-1a29b211df97
Diffstat (limited to 'libpcsxcore/r3000a.h')
-rw-r--r--libpcsxcore/r3000a.h795
1 files changed, 339 insertions, 456 deletions
diff --git a/libpcsxcore/r3000a.h b/libpcsxcore/r3000a.h
index 2c4e57f5..b34a30f2 100644
--- a/libpcsxcore/r3000a.h
+++ b/libpcsxcore/r3000a.h
@@ -1,456 +1,339 @@
-/***************************************************************************
- * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
- ***************************************************************************/
-
-#ifndef __R3000A_H__
-#define __R3000A_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "psxcommon.h"
-#include "psxmem.h"
-#include "psxcounters.h"
-#include "psxbios.h"
-
-typedef struct {
- int (*Init)();
- void (*Reset)();
- void (*Execute)(); /* executes up to a break */
- void (*ExecuteBlock)(); /* executes up to a jump */
- void (*Clear)(u32 Addr, u32 Size);
- void (*Shutdown)();
-} R3000Acpu;
-
-extern R3000Acpu *psxCpu;
-extern R3000Acpu psxInt;
-#if (defined(__x86_64__) || defined(__i386__) || defined(__sh__) || defined(__ppc__)) && !defined(NOPSXREC)
-extern R3000Acpu psxRec;
-#define PSXREC
-#endif
-
-typedef union {
-#if defined(__BIGENDIAN__)
- struct { u8 h3, h2, h, l; } b;
- struct { s8 h3, h2, h, l; } sb;
- struct { u16 h, l; } w;
- struct { s16 h, l; } sw;
-#else
- struct { u8 l, h, h2, h3; } b;
- struct { u16 l, h; } w;
- struct { s8 l, h, h2, h3; } sb;
- struct { s16 l, h; } sw;
-#endif
-} PAIR;
-
-typedef union {
- struct {
- 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;
- } n;
- u32 r[34]; /* Lo, Hi in r[32] and r[33] */
- PAIR p[34];
-} psxGPRRegs;
-
-typedef union {
- struct {
- u32 Index, Random, EntryLo0, BPC,
- Context, BDA, PIDMask, DCIC,
- BadVAddr, BDAM, EntryHi, BPCM,
- Status, Cause, EPC, PRid,
- Config, LLAddr, WatchLO, WatchHI,
- XContext, Reserved1, Reserved2, Reserved3,
- Reserved4, Reserved5, ECC, CacheErr,
- TagLo, TagHi, ErrorEPC, Reserved6;
- } n;
- u32 r[32];
-} psxCP0Regs;
-
-typedef struct {
- short x, y;
-} SVector2D;
-
-typedef struct {
- short z, pad;
-} SVector2Dz;
-
-typedef struct {
- short x, y, z, pad;
-} SVector3D;
-
-typedef struct {
- short x, y, z, pad;
-} LVector3D;
-
-typedef struct {
- unsigned char r, g, b, c;
-} CBGR;
-
-typedef struct {
- short m11, m12, m13, m21, m22, m23, m31, m32, m33, pad;
-} SMatrix3D;
-
-typedef union {
- struct {
- SVector3D v0, v1, v2;
- CBGR rgb;
- s32 otz;
- s32 ir0, ir1, ir2, ir3;
- SVector2D sxy0, sxy1, sxy2, sxyp;
- SVector2Dz sz0, sz1, sz2, sz3;
- CBGR rgb0, rgb1, rgb2;
- s32 reserved;
- s32 mac0, mac1, mac2, mac3;
- u32 irgb, orgb;
- s32 lzcs, lzcr;
- } n;
- u32 r[32];
- PAIR p[32];
-} psxCP2Data;
-
-typedef union {
- struct {
- SMatrix3D rMatrix;
- s32 trX, trY, trZ;
- SMatrix3D lMatrix;
- s32 rbk, gbk, bbk;
- SMatrix3D cMatrix;
- s32 rfc, gfc, bfc;
- s32 ofx, ofy;
- s32 h;
- s32 dqa, dqb;
- s32 zsf3, zsf4;
- s32 flag;
- } n;
- u32 r[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_SPUASYNC,
- PSXINT_CDRDBUF,
- PSXINT_CDRLID,
- PSXINT_CDRPLAY
-};
-
-typedef struct {
- psxGPRRegs GPR; /* General Purpose Registers */
- psxCP0Regs CP0; /* Coprocessor0 Registers */
- psxCP2Data CP2D; /* Cop2 data registers */
- psxCP2Ctrl CP2C; /* Cop2 control registers */
- u32 pc; /* Program counter */
- u32 code; /* The instruction */
- u32 cycle;
- u32 interrupt;
- struct { u32 sCycle, cycle; } intCycle[32];
- u8 ICache_Addr[0x1000];
- u8 ICache_Code[0x1000];
- boolean ICache_valid;
-} psxRegisters;
-
-extern psxRegisters psxRegs;
-
-/*
-Formula One 2001
-- Use old CPU cache code when the RAM location is
- updated with new code (affects in-game racing)
-
-TODO:
-- I-cache / D-cache swapping
-- Isolate D-cache from RAM
-*/
-
-static inline u32 *Read_ICache(u32 pc, boolean isolate) {
- u32 pc_bank, pc_offset, pc_cache;
- u8 *IAddr, *ICode;
-
- pc_bank = pc >> 24;
- pc_offset = pc & 0xffffff;
- pc_cache = pc & 0xfff;
-
- IAddr = psxRegs.ICache_Addr;
- ICode = psxRegs.ICache_Code;
-
- // clear I-cache
- if (!psxRegs.ICache_valid) {
- memset(psxRegs.ICache_Addr, 0xff, sizeof(psxRegs.ICache_Addr));
- memset(psxRegs.ICache_Code, 0xff, sizeof(psxRegs.ICache_Code));
-
- psxRegs.ICache_valid = TRUE;
- }
-
- // uncached
- if (pc_bank >= 0xa0)
- return (u32 *)PSXM(pc);
-
- // cached - RAM
- if (pc_bank == 0x80 || pc_bank == 0x00) {
- if (SWAP32(*(u32 *)(IAddr + pc_cache)) == pc_offset) {
- // Cache hit - return last opcode used
- return (u32 *)(ICode + pc_cache);
- } else {
- // Cache miss - addresses don't match
- // - default: 0xffffffff (not init)
-
- if (!isolate) {
- // cache line is 4 bytes wide
- pc_offset &= ~0xf;
- pc_cache &= ~0xf;
-
- // address line
- *(u32 *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0);
- *(u32 *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4);
- *(u32 *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8);
- *(u32 *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc);
-
- // opcode line
- pc_offset = pc & ~0xf;
- *(u32 *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0);
- *(u32 *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4);
- *(u32 *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8);
- *(u32 *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc);
- }
-
- // normal code
- return (u32 *)PSXM(pc);
- }
- }
-
- /*
- TODO: Probably should add cached BIOS
- */
-
- // default
- return (u32 *)PSXM(pc);
-}
-
-#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 psxBranchTest();
-void psxExecuteBios();
-int psxTestLoadDelay(int reg, u32 tmp);
-void psxDelayTest(int reg, u32 bpc);
-void psxTestSWInts();
-void psxJumpTest();
-
-/* psxinterpreter for rec fallbacks */
-void psxNULL(void);
-void psxSPECIAL(void);
-void psxREGIMM(void);
-void psxJ(void);
-void psxJAL(void);
-void psxBEQ(void);
-void psxBNE(void);
-void psxBLEZ(void);
-void psxBGTZ(void);
-void psxADDI(void);
-void psxADDIU(void);
-void psxSLTI(void);
-void psxSLTIU(void);
-void psxANDI(void);
-void psxORI(void);
-void psxXORI(void);
-void psxLUI(void);
-void psxCOP0(void);
-void psxCOP2(void);
-void psxLB(void);
-void psxLH(void);
-void psxLWL(void);
-void psxLW(void);
-void psxLBU(void);
-void psxLHU(void);
-void psxLWR(void);
-void psxSB(void);
-void psxSH(void);
-void psxSWL(void);
-void psxSW(void);
-void psxSWR(void);
-void psxNULL(void);
-void gteLWC2(void);
-void psxNULL(void);
-void gteSWC2(void);
-void psxHLE(void);
-void psxSLL(void);
-void psxSRL(void);
-void psxSRA(void);
-void psxSLLV(void);
-void psxSRLV(void);
-void psxSRAV(void);
-void psxJR(void);
-void psxJALR(void);
-void psxSYSCALL(void);
-void psxBREAK(void);
-void psxMFHI(void);
-void psxMTHI(void);
-void psxMFLO(void);
-void psxMTLO(void);
-void psxMULT(void);
-void psxMULTU(void);
-void psxDIV(void);
-void psxDIVU(void);
-void psxADD(void);
-void psxADDU(void);
-void psxSUB(void);
-void psxSUBU(void);
-void psxAND(void);
-void psxOR(void);
-void psxXOR(void);
-void psxNOR(void);
-void psxNULL(void);
-void psxSLT(void);
-void psxSLTU(void);
-void psxBLTZ(void);
-void psxBGEZ(void);
-void psxBLTZAL(void);
-void psxBGEZAL(void);
-void psxMFC0(void);
-void psxCFC0(void);
-void psxMTC0(void);
-void psxCTC0(void);
-void psxRFE(void);
-void psxBASIC(void);
-void gteRTPS(void);
-void gteNCLIP(void);
-void psxNULL(void);
-void gteOP(void);
-void gteDPCS(void);
-void gteINTPL(void);
-void gteMVMVA(void);
-void gteNCDS(void);
-void gteCDP(void);
-void gteNCDT(void);
-void psxNULL(void);
-void gteNCCS(void);
-void gteCC(void);
-void gteNCS(void);
-void gteNCT(void);
-void gteSQR(void);
-void gteDCPL(void);
-void gteDPCT(void);
-void gteAVSZ3(void);
-void gteAVSZ4(void);
-void gteRTPT(void);
-void psxNULL(void);
-void gteGPF(void);
-void gteGPL(void);
-void gteNCCT(void);
-void psxMFC2(void);
-void psxCFC2(void);
-void gteMTC2(void);
-void gteCTC2(void);
-extern void (*psxBSC[])();
-
-/* for table-based unaligned access implementations */
-extern u32 LWL_MASK[4];
-extern u32 LWL_SHIFT[4];
-extern u32 LWR_MASK[4];
-extern u32 LWR_SHIFT[4];
-extern u32 SWL_MASK[4];
-extern u32 SWL_SHIFT[4];
-extern u32 SWR_MASK[4];
-extern u32 SWR_SHIFT[4];
-
-#ifdef __cplusplus
-}
-#endif
-#endif
+/***************************************************************************
+ * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
+ ***************************************************************************/
+
+#ifndef __R3000A_H__
+#define __R3000A_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "psxcommon.h"
+#include "psxmem.h"
+#include "psxcounters.h"
+#include "psxbios.h"
+
+typedef struct {
+ int (*Init)();
+ void (*Reset)();
+ void (*Execute)(); /* executes up to a break */
+ void (*ExecuteBlock)(); /* executes up to a jump */
+ void (*Clear)(u32 Addr, u32 Size);
+ void (*Shutdown)();
+} R3000Acpu;
+
+extern R3000Acpu *psxCpu;
+extern R3000Acpu psxInt;
+#if (defined(__x86_64__) || defined(__i386__) || defined(__sh__) || defined(__ppc__)) && !defined(NOPSXREC)
+extern R3000Acpu psxRec;
+#define PSXREC
+#endif
+
+typedef union {
+#if defined(__BIGENDIAN__)
+ struct { u8 h3, h2, h, l; } b;
+ struct { s8 h3, h2, h, l; } sb;
+ struct { u16 h, l; } w;
+ struct { s16 h, l; } sw;
+#else
+ struct { u8 l, h, h2, h3; } b;
+ struct { u16 l, h; } w;
+ struct { s8 l, h, h2, h3; } sb;
+ struct { s16 l, h; } sw;
+#endif
+} PAIR;
+
+typedef union {
+ struct {
+ 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;
+ } n;
+ u32 r[34]; /* Lo, Hi in r[32] and r[33] */
+ PAIR p[34];
+} psxGPRRegs;
+
+typedef union {
+ struct {
+ u32 Index, Random, EntryLo0, BPC,
+ Context, BDA, PIDMask, DCIC,
+ BadVAddr, BDAM, EntryHi, BPCM,
+ Status, Cause, EPC, PRid,
+ Config, LLAddr, WatchLO, WatchHI,
+ XContext, Reserved1, Reserved2, Reserved3,
+ Reserved4, Reserved5, ECC, CacheErr,
+ TagLo, TagHi, ErrorEPC, Reserved6;
+ } n;
+ u32 r[32];
+} psxCP0Regs;
+
+typedef struct {
+ short x, y;
+} SVector2D;
+
+typedef struct {
+ short z, pad;
+} SVector2Dz;
+
+typedef struct {
+ short x, y, z, pad;
+} SVector3D;
+
+typedef struct {
+ short x, y, z, pad;
+} LVector3D;
+
+typedef struct {
+ unsigned char r, g, b, c;
+} CBGR;
+
+typedef struct {
+ short m11, m12, m13, m21, m22, m23, m31, m32, m33, pad;
+} SMatrix3D;
+
+typedef union {
+ struct {
+ SVector3D v0, v1, v2;
+ CBGR rgb;
+ s32 otz;
+ s32 ir0, ir1, ir2, ir3;
+ SVector2D sxy0, sxy1, sxy2, sxyp;
+ SVector2Dz sz0, sz1, sz2, sz3;
+ CBGR rgb0, rgb1, rgb2;
+ s32 reserved;
+ s32 mac0, mac1, mac2, mac3;
+ u32 irgb, orgb;
+ s32 lzcs, lzcr;
+ } n;
+ u32 r[32];
+ PAIR p[32];
+} psxCP2Data;
+
+typedef union {
+ struct {
+ SMatrix3D rMatrix;
+ s32 trX, trY, trZ;
+ SMatrix3D lMatrix;
+ s32 rbk, gbk, bbk;
+ SMatrix3D cMatrix;
+ s32 rfc, gfc, bfc;
+ s32 ofx, ofy;
+ s32 h;
+ s32 dqa, dqb;
+ s32 zsf3, zsf4;
+ s32 flag;
+ } n;
+ u32 r[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_SPUASYNC,
+ PSXINT_CDRDBUF,
+ PSXINT_CDRLID,
+ PSXINT_CDRPLAY
+};
+
+typedef struct {
+ psxGPRRegs GPR; /* General Purpose Registers */
+ psxCP0Regs CP0; /* Coprocessor0 Registers */
+ psxCP2Data CP2D; /* Cop2 data registers */
+ psxCP2Ctrl CP2C; /* Cop2 control registers */
+ u32 pc; /* Program counter */
+ u32 code; /* The instruction */
+ u32 cycle;
+ u32 interrupt;
+ struct { u32 sCycle, cycle; } intCycle[32];
+ u8 ICache_Addr[0x1000];
+ u8 ICache_Code[0x1000];
+ boolean ICache_valid;
+} psxRegisters;
+
+extern psxRegisters psxRegs;
+
+/*
+Formula One 2001
+- Use old CPU cache code when the RAM location is
+ updated with new code (affects in-game racing)
+
+TODO:
+- I-cache / D-cache swapping
+- Isolate D-cache from RAM
+*/
+
+static inline u32 *Read_ICache(u32 pc, boolean isolate) {
+ u32 pc_bank, pc_offset, pc_cache;
+ u8 *IAddr, *ICode;
+
+ pc_bank = pc >> 24;
+ pc_offset = pc & 0xffffff;
+ pc_cache = pc & 0xfff;
+
+ IAddr = psxRegs.ICache_Addr;
+ ICode = psxRegs.ICache_Code;
+
+ // clear I-cache
+ if (!psxRegs.ICache_valid) {
+ memset(psxRegs.ICache_Addr, 0xff, sizeof(psxRegs.ICache_Addr));
+ memset(psxRegs.ICache_Code, 0xff, sizeof(psxRegs.ICache_Code));
+
+ psxRegs.ICache_valid = TRUE;
+ }
+
+ // uncached
+ if (pc_bank >= 0xa0)
+ return (u32 *)PSXM(pc);
+
+ // cached - RAM
+ if (pc_bank == 0x80 || pc_bank == 0x00) {
+ if (SWAP32(*(u32 *)(IAddr + pc_cache)) == pc_offset) {
+ // Cache hit - return last opcode used
+ return (u32 *)(ICode + pc_cache);
+ } else {
+ // Cache miss - addresses don't match
+ // - default: 0xffffffff (not init)
+
+ if (!isolate) {
+ // cache line is 4 bytes wide
+ pc_offset &= ~0xf;
+ pc_cache &= ~0xf;
+
+ // address line
+ *(u32 *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0);
+ *(u32 *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4);
+ *(u32 *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8);
+ *(u32 *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc);
+
+ // opcode line
+ pc_offset = pc & ~0xf;
+ *(u32 *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0);
+ *(u32 *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4);
+ *(u32 *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8);
+ *(u32 *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc);
+ }
+
+ // normal code
+ return (u32 *)PSXM(pc);
+ }
+ }
+
+ /*
+ TODO: Probably should add cached BIOS
+ */
+
+ // default
+ return (u32 *)PSXM(pc);
+}
+
+#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 psxBranchTest();
+void psxExecuteBios();
+int psxTestLoadDelay(int reg, u32 tmp);
+void psxDelayTest(int reg, u32 bpc);
+void psxTestSWInts();
+void psxJumpTest();
+
+#ifdef __cplusplus
+}
+#endif
+#endif