summaryrefslogtreecommitdiff
path: root/PcsxSrc/ix86/iR3000A.c
diff options
context:
space:
mode:
Diffstat (limited to 'PcsxSrc/ix86/iR3000A.c')
-rw-r--r--PcsxSrc/ix86/iR3000A.c1236
1 files changed, 1236 insertions, 0 deletions
diff --git a/PcsxSrc/ix86/iR3000A.c b/PcsxSrc/ix86/iR3000A.c
new file mode 100644
index 0000000..c6ff128
--- /dev/null
+++ b/PcsxSrc/ix86/iR3000A.c
@@ -0,0 +1,1236 @@
+/* Pcsx - Pc Psx Emulator
+ * Copyright (C) 1999-2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef __WIN32__
+#pragma warning(disable:4244)
+#pragma warning(disable:4761)
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "PsxCommon.h"
+#include "ix86.h"
+
+static u32 *recLUT;
+
+#define PC_REC(x) (recLUT[x >> 16] + (x & 0xffff))
+#define PC_REC8(x) (*(u8 *)PC_REC(x))
+#define PC_REC16(x) (*(u16*)PC_REC(x))
+#define PC_REC32(x) (*(u32*)PC_REC(x))
+
+#define RECMEM_SIZE (8*1024*1024)
+
+static char *recMem; /* the recompiled blocks will be here */
+static char *recRAM; /* and the ptr to the blocks here */
+static char *recROM; /* and here */
+
+static u32 pc; /* recompiler pc */
+static int count; /* recompiler intruction count */
+static int branch; /* set for branch */
+static u32 target; /* branch target */
+
+static void (*recBSC[64])();
+static void (*recSPC[64])();
+static void (*recREG[32])();
+static void (*recCP0[32])();
+static void (*recCP2[64])();
+static void (*recCP2BSC[32])();
+
+/* set a pending branch */
+#define SetBranch() { \
+ branch = 1; \
+ psxRegs.code = PSXMu32(pc); \
+ pc+=4; count++; \
+ recBSC[psxRegs.code>>26](); \
+ \
+ MOV32MtoR(EAX, (u32)&target); \
+ MOV32RtoM((u32)&psxRegs.pc, EAX); \
+ CALLFunc((u32)psxBranchTest); \
+}
+
+#define REC_FUNC(f) \
+void psx##f(); \
+static void rec##f() { \
+ MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \
+ MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \
+ CALLFunc((u32)psx##f); \
+/* branch = 2; */\
+}
+
+#define REC_SYS(f) \
+void psx##f(); \
+static void rec##f() { \
+ MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \
+ MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \
+ CALLFunc((u32)psx##f); \
+ branch = 2; \
+}
+
+#define REC_BRANCH(f) \
+void psx##f(); \
+static void rec##f() { \
+ MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \
+ MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \
+ CALLFunc((u32)psx##f); \
+ branch = 2; \
+ count++; \
+}
+
+static void recRecompile();
+
+static int recInit() {
+ int i;
+
+ recLUT = (u32*) malloc(0x010000 * 4);
+
+ recMem = (char*) malloc(RECMEM_SIZE);
+ recRAM = (char*) malloc(0x200000);
+ recROM = (char*) malloc(0x080000);
+ if (recRAM == NULL || recROM == NULL || recMem == NULL || recLUT == NULL) {
+ SysMessage("Error allocating memory"); return -1;
+ }
+
+ for (i=0; i<0x80; i++) recLUT[i + 0x0000] = (u32)&recRAM[(i & 0x1f) << 16];
+ memcpy(recLUT + 0x8000, recLUT, 0x80 * 4);
+ memcpy(recLUT + 0xa000, recLUT, 0x80 * 4);
+
+ for (i=0; i<0x08; i++) recLUT[i + 0xbfc0] = (u32)&recROM[i << 16];
+
+ return 0;
+}
+
+static void recReset() {
+ memset(recRAM, 0, 0x200000);
+ memset(recROM, 0, 0x080000);
+
+ x86Init(recMem);
+ branch = 0;
+}
+
+static void recShutdown() {
+ if (recMem == NULL) return;
+ free(recLUT);
+ free(recMem);
+ free(recRAM);
+ free(recROM);
+}
+
+static void recError() {
+ SysReset();
+ ClosePlugins();
+ SysMessage("Unrecoverable error while running recompiler\n");
+ SysRunGui();
+}
+
+#define execute() { \
+ void (**recFunc)(); \
+ char *p; \
+ \
+ p = (char*)PC_REC(psxRegs.pc); \
+ if (p != NULL) recFunc = (void (**)()) (u32)p; \
+ else { recError(); return; } \
+ \
+ if (*recFunc == 0) { \
+ recRecompile(); \
+ } \
+ (*recFunc)(); \
+}
+
+static void DumpRegs() {
+ int i, j;
+
+ printf("%lx %lx\n", psxRegs.pc, psxRegs.cycle);
+ for (i=0; i<4; i++) {
+ for (j=0; j<8; j++)
+ printf("%lx ", psxRegs.GPR.r[j*i]);
+ printf("\n");
+ }
+}
+
+static void recExecuteBios() {
+ while (psxRegs.pc != 0x80030000) {
+ execute();
+ }
+}
+
+static void recExecute() {
+ for (;;) execute();
+}
+
+static void recExecuteBlock() {
+ execute();
+}
+
+static void recClear(u32 Addr, u32 Size) {
+ memset((void*)PC_REC(Addr), 0, Size * 4);
+}
+
+static void recNULL() {
+// SysMessage("recUNK: %8.8x\n", psxRegs.code);
+}
+
+/*********************************************************
+* goes to opcodes tables... *
+* Format: table[something....] *
+*********************************************************/
+
+//REC_SYS(SPECIAL);
+static void recSPECIAL() {
+ recSPC[_Funct_]();
+}
+
+static void recREGIMM() {
+ recREG[_Rt_]();
+}
+
+static void recCOP0() {
+ recCP0[_Rs_]();
+}
+
+//REC_SYS(COP2);
+static void recCOP2() {
+ recCP2[_Funct_]();
+}
+
+static void recBASIC() {
+ recCP2BSC[_Rs_]();
+}
+
+//end of Tables opcodes...
+
+/*********************************************************
+* Arithmetic with immediate operand *
+* Format: OP rt, rs, immediate *
+*********************************************************/
+/*
+REC_FUNC(ADDI);
+REC_FUNC(ADDIU);
+REC_FUNC(ANDI);
+REC_FUNC(ORI);
+REC_FUNC(XORI);
+REC_FUNC(SLTI);
+REC_FUNC(SLTIU);
+#if 0*/
+static void recADDIU() {
+// Rt = Rs + Im
+ if (!_Rt_) return;
+
+ if (_Rs_) {
+ if (_Rs_ == _Rt_) {
+ ADD32ItoM((u32)&psxRegs.GPR.r[_Rt_], _Imm_);
+ } else {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ if (_Imm_) ADD32ItoR(EAX, _Imm_);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+ }
+ } else {
+ MOV32ItoM((u32)&psxRegs.GPR.r[_Rt_], _Imm_);
+ }
+}
+
+static void recADDI() {
+// Rt = Rs + Im
+ recADDIU();
+}
+
+static void recSLTI() {
+// Rt = Rs < Im (signed)
+ if (!_Rt_) return;
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ CMP32ItoR(EAX, _Imm_);
+ SETL8R (EAX);
+ AND32ItoR(EAX, 0xff);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+}
+
+static void recSLTIU() {
+// Rt = Rs < Im (unsigned)
+ if (!_Rt_) return;
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ CMP32ItoR(EAX, _Imm_);
+ SETB8R (EAX);
+ AND32ItoR(EAX, 0xff);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+}
+
+static void recANDI() {
+// Rt = Rs And Im
+ if (!_Rt_) return;
+
+ if (_Rs_ && _ImmU_) {
+ if (_Rs_ == _Rt_) {
+ AND32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_);
+ } else {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ AND32ItoR(EAX, _ImmU_);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+ }
+ } else {
+ XOR32RtoR(EAX, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+ }
+}
+
+static void recORI() {
+// Rt = Rs Or Im
+ if (!_Rt_) return;
+
+ if (_Rs_) {
+ if (_Rs_ == _Rt_) {
+ OR32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_);
+ } else {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ if (_ImmU_) OR32ItoR (EAX, _ImmU_);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+ }
+ } else {
+ MOV32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_);
+ }
+}
+
+static void recXORI() {
+// Rt = Rs Xor Im
+ if (!_Rt_) return;
+
+ if (_Rs_) {
+ if (_Rs_ == _Rt_) {
+ XOR32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_);
+ } else {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ XOR32ItoR(EAX, _ImmU_);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+ }
+ } else {
+ MOV32ItoR(EAX, _ImmU_ ^ 0);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+ }
+}
+//#endif
+//end of * Arithmetic with immediate operand
+
+/*********************************************************
+* Load higher 16 bits of the first word in GPR with imm *
+* Format: OP rt, immediate *
+*********************************************************/
+/*REC_FUNC(LUI);
+#if 0*/
+static void recLUI() {
+// Rt = Imm << 16
+ if (!_Rt_) return;
+
+ MOV32ItoM((u32)&psxRegs.GPR.r[_Rt_], psxRegs.code << 16);
+}
+//#endif
+//End of Load Higher .....
+
+
+/*********************************************************
+* Register arithmetic *
+* Format: OP rd, rs, rt *
+*********************************************************/
+/*
+REC_FUNC(ADD);
+REC_FUNC(ADDU);
+REC_FUNC(SUB);
+REC_FUNC(SUBU);
+REC_FUNC(AND);
+REC_FUNC(OR);
+REC_FUNC(XOR);
+REC_FUNC(NOR);
+REC_FUNC(SLT);
+REC_FUNC(SLTU);
+
+#if 0*/
+static void recADDU() {
+// Rd = Rs + Rt
+ if (!_Rd_) return;
+
+ if (_Rs_ && _Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ ADD32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ } else if (_Rs_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ } else if (_Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ } else {
+ XOR32RtoR(EAX, EAX);
+ }
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+
+static void recADD() {
+// Rd = Rs + Rt
+ recADDU();
+}
+
+static void recSUBU() {
+// Rd = Rs - Rt
+ if (!_Rd_) return;
+
+ if (_Rs_ || _Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ SUB32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ } else {
+ XOR32RtoR(EAX, EAX);
+ }
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+
+static void recSUB() {
+// Rd = Rs - Rt
+ recSUBU();
+}
+
+static void recAND() {
+// Rd = Rs And Rt
+ if (!_Rd_) return;
+
+ if (_Rs_ && _Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ AND32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ } else {
+ XOR32RtoR(EAX, EAX);
+ }
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+
+static void recOR() {
+// Rd = Rs Or Rt
+ if (!_Rd_) return;
+
+ if (_Rs_ && _Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ } else if (_Rs_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ } else if (_Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ } else {
+ XOR32RtoR(EAX, EAX);
+ }
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+
+static void recXOR() {
+// Rd = Rs Xor Rt
+ if (!_Rd_) return;
+
+ if (_Rs_ && _Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ XOR32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ } else if (_Rs_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ XOR32ItoR(EAX, 0);
+ } else if (_Rt_) {
+ XOR32RtoR(EAX, EAX);
+ XOR32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ } else {
+ XOR32RtoR(EAX, EAX);
+ }
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+
+static void recNOR() {
+// Rd = Rs Nor Rt
+ if (!_Rd_) return;
+
+ if (_Rs_ && _Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ NOT32R (EAX);
+ } else if (_Rs_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ NOT32R (EAX);
+ } else if (_Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ NOT32R (EAX);
+ } else {
+ MOV32ItoR(EAX, ~0);
+ }
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+
+static void recSLT() {
+// Rd = Rs < Rt (signed)
+ if (!_Rd_) return;
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ SETL8R (EAX);
+ AND32ItoR(EAX, 0xff);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+
+static void recSLTU() {
+// Rd = Rs < Rt (unsigned)
+ if (!_Rd_) return;
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ SBB32RtoR(EAX, EAX);
+ NEG32R (EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+//#endif
+//End of * Register arithmetic
+
+/*********************************************************
+* Register mult/div & Register trap logic *
+* Format: OP rs, rt *
+*********************************************************/
+
+/*REC_FUNC(MULT);
+REC_FUNC(MULTU);
+REC_FUNC(DIV);
+REC_FUNC(DIVU);
+#if 0*/
+static void recMULT() {
+// Lo/Hi = Rs * Rt (signed)
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ IMUL32M ((u32)&psxRegs.GPR.r[_Rt_]);
+ MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX);
+}
+
+static void recMULTU() {
+// Lo/Hi = Rs * Rt (unsigned)
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ MUL32M ((u32)&psxRegs.GPR.r[_Rt_]);
+ MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX);
+}
+
+static void recDIV() {
+// Lo/Hi = Rs / Rt (signed)
+
+ MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
+ CMP32ItoR(ECX, 0);
+ j8Ptr[0] = JE8(0);
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ CDQ();
+ IDIV32R (ECX);
+ MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX);
+ x86SetJ8(j8Ptr[0]);
+}
+
+static void recDIVU() {
+// Lo/Hi = Rs / Rt (unsigned)
+
+ MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
+ CMP32ItoR(ECX, 0);
+ j8Ptr[0] = JE8(0);
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ XOR32RtoR(EDX, EDX);
+ DIV32R (ECX);
+ MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX);
+ x86SetJ8(j8Ptr[0]);
+}
+//#endif
+//End of * Register mult/div & Register trap logic
+
+/*REC_FUNC(LB);
+REC_FUNC(LBU);
+REC_FUNC(LH);
+REC_FUNC(LHU);
+REC_FUNC(LW);
+
+REC_FUNC(SB);
+REC_FUNC(SH);
+REC_FUNC(SW);*/
+
+REC_FUNC(LWL);
+REC_FUNC(LWR);
+REC_FUNC(SWL);
+REC_FUNC(SWR);
+//#if 0
+static void recLB() {
+// Rt = mem[Rs + Im] (signed)
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ if (_Imm_) ADD32ItoR(EAX, _Imm_);
+ PUSH32R (EAX);
+ CALLFunc((u32)psxMemRead8);
+ if (_Rt_) {
+ MOVSX32R8toR(EAX, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+ }
+ ADD32ItoR(ESP, 4);
+}
+
+static void recLBU() {
+// Rt = mem[Rs + Im] (unsigned)
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ if (_Imm_) ADD32ItoR(EAX, _Imm_);
+ PUSH32R (EAX);
+ CALLFunc((u32)psxMemRead8);
+ if (_Rt_) {
+ MOVZX32R8toR(EAX, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+ }
+ ADD32ItoR(ESP, 4);
+}
+
+static void recLH() {
+// Rt = mem[Rs + Im] (signed)
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ if (_Imm_) ADD32ItoR(EAX, _Imm_);
+ PUSH32R (EAX);
+ CALLFunc((u32)psxMemRead16);
+ if (_Rt_) {
+ MOVSX32R16toR(EAX, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+ }
+ ADD32ItoR(ESP, 4);
+}
+
+static void recLHU() {
+// Rt = mem[Rs + Im] (unsigned)
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ if (_Imm_) ADD32ItoR(EAX, _Imm_);
+ PUSH32R (EAX);
+ CALLFunc((u32)psxMemRead16);
+ if (_Rt_) {
+ MOVZX32R16toR(EAX, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+ }
+ ADD32ItoR(ESP, 4);
+}
+
+static void recLW() {
+// Rt = mem[Rs + Im] (unsigned)
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ if (_Imm_) ADD32ItoR(EAX, _Imm_);
+ PUSH32R (EAX);
+ CALLFunc((u32)psxMemRead32);
+ if (_Rt_) {
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+ }
+ ADD32ItoR(ESP, 4);
+}
+/*
+void recLWL() {
+}
+
+void recLWR() {
+}
+*/
+static void recSB() {
+// mem[Rs + Im] = Rt
+
+ PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]);
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ if (_Imm_) ADD32ItoR(EAX, _Imm_);
+ PUSH32R (EAX);
+ CALLFunc((u32)psxMemWrite8);
+ ADD32ItoR(ESP, 8);
+}
+
+static void recSH() {
+// mem[Rs + Im] = Rt
+
+ PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]);
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ if (_Imm_) ADD32ItoR(EAX, _Imm_);
+ PUSH32R (EAX);
+ CALLFunc((u32)psxMemWrite16);
+ ADD32ItoR(ESP, 8);
+}
+
+static void recSW() {
+// mem[Rs + Im] = Rt
+
+ PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]);
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ if (_Imm_) ADD32ItoR(EAX, _Imm_);
+ PUSH32R (EAX);
+ CALLFunc((u32)psxMemWrite32);
+ ADD32ItoR(ESP, 8);
+}
+//#endif
+/*
+void recSWL() {
+}
+
+void recSWR() {
+}
+*/
+/*REC_FUNC(SLL);
+REC_FUNC(SRL);
+REC_FUNC(SRA);
+#if 0*/
+static void recSLL() {
+// Rd = Rt << Sa
+ if (!_Rd_) return;
+
+ if (_Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ if (_Sa_) SHL32ItoR(EAX, _Sa_);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+ } else {
+ XOR32RtoR(EAX, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+ }
+}
+
+static void recSRL() {
+// Rd = Rt >> Sa
+ if (!_Rd_) return;
+
+ if (_Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ if (_Sa_) SHR32ItoR(EAX, _Sa_);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+ } else {
+ XOR32RtoR(EAX, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+ }
+}
+
+static void recSRA() {
+// Rd = Rt >> Sa
+ if (!_Rd_) return;
+
+ if (_Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ if (_Sa_) SAR32ItoR(EAX, _Sa_);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+ } else {
+ XOR32RtoR(EAX, EAX);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+ }
+}
+//#endif
+
+/*REC_FUNC(SLLV);
+REC_FUNC(SRLV);
+REC_FUNC(SRAV);
+#if 0*/
+static void recSLLV() {
+// Rd = Rt << Rs
+ if (!_Rd_) return;
+
+ if (_Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ if (_Rs_) {
+ MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
+ SHL32CLtoR(EAX);
+ }
+ }
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+
+static void recSRLV() {
+// Rd = Rt >> Rs
+ if (!_Rd_) return;
+
+ if (_Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ if (_Rs_) {
+ MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
+ SHR32CLtoR(EAX);
+ }
+ }
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+
+static void recSRAV() {
+// Rd = Rt >> Rs
+ if (!_Rd_) return;
+
+ if (_Rt_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ if (_Rs_) {
+ MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
+ SAR32CLtoR(EAX);
+ }
+ }
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+//#endif
+
+/*REC_SYS(SYSCALL);
+REC_SYS(BREAK);
+
+#if 0*/
+static void recSYSCALL() {
+ MOV32ItoR(EAX, pc - 4);
+ MOV32RtoM((u32)&psxRegs.pc, EAX);
+ PUSH32I (branch == 1 ? 1 : 0);
+ PUSH32I (0x20);
+ CALLFunc ((u32)psxException);
+ ADD32ItoR(ESP, 8);
+
+ if (!branch) branch = 2;
+}
+
+static void recBREAK() {
+}
+//#endif
+/*
+REC_FUNC(MFHI);
+REC_FUNC(MTHI);
+REC_FUNC(MFLO);
+REC_FUNC(MTLO);
+#if 0*/
+static void recMFHI() {
+// Rd = Hi
+ if (!_Rd_) return;
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.n.hi);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+
+static void recMTHI() {
+// Hi = Rs
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
+}
+
+static void recMFLO() {
+// Rd = Lo
+ if (!_Rd_) return;
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.n.lo);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
+}
+
+static void recMTLO() {
+// Lo = Rs
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
+}
+//#endif
+
+/*REC_BRANCH(J);
+REC_BRANCH(JR);
+REC_BRANCH(JAL);
+REC_BRANCH(JALR);
+REC_BRANCH(BLTZ);
+REC_BRANCH(BGTZ);
+REC_BRANCH(BLTZAL);
+REC_BRANCH(BGEZAL);
+REC_BRANCH(BNE);
+REC_BRANCH(BEQ);
+REC_BRANCH(BLEZ);
+REC_BRANCH(BGEZ);
+
+#if 0*/
+static void recBLTZ() {
+// Branch if Rs < 0
+
+ CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
+ j8Ptr[0] = JL8(0);
+
+ MOV32ItoM((u32)&target, pc+4);
+ j8Ptr[1] = JMP8(0);
+
+ x86SetJ8(j8Ptr[0]);
+
+ MOV32ItoM((u32)&target, _Imm_ * 4 + pc);
+
+ x86SetJ8(j8Ptr[1]);
+
+ SetBranch();
+}
+
+static void recBGEZ() {
+// Branch if Rs >= 0
+
+ CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
+ j8Ptr[0] = JGE8(0);
+
+ MOV32ItoM((u32)&target, pc+4);
+ j8Ptr[1] = JMP8(0);
+
+ x86SetJ8(j8Ptr[0]);
+
+ MOV32ItoM((u32)&target, _Imm_ * 4 + pc);
+
+ x86SetJ8(j8Ptr[1]);
+
+ SetBranch();
+}
+
+static void recBLTZAL() {
+// Branch if Rs < 0
+
+ CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
+ j8Ptr[0] = JL8(0);
+
+ MOV32ItoM((u32)&target, pc+4);
+ j8Ptr[1] = JMP8(0);
+
+ x86SetJ8(j8Ptr[0]);
+
+ MOV32ItoM((u32)&target, _Imm_ * 4 + pc);
+ MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4);
+
+ x86SetJ8(j8Ptr[1]);
+
+ SetBranch();
+}
+
+static void recBGEZAL() {
+// Branch if Rs >= 0
+
+ CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
+ j8Ptr[0] = JGE8(0);
+
+ MOV32ItoM((u32)&target, pc+4);
+ j8Ptr[1] = JMP8(0);
+
+ x86SetJ8(j8Ptr[0]);
+
+ MOV32ItoM((u32)&target, _Imm_ * 4 + pc);
+ MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4);
+
+ x86SetJ8(j8Ptr[1]);
+
+ SetBranch();
+}
+
+static void recJ() {
+// j target
+ MOV32ItoM((u32)&target, _Target_ * 4 + (pc & 0xf0000000));
+
+ SetBranch();
+}
+
+static void recJAL() {
+// jal target
+
+ MOV32ItoM((u32)&target, _Target_ * 4 + (pc & 0xf0000000));
+ MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4);
+
+ SetBranch();
+}
+
+static void recJR() {
+// jr Rs
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ MOV32RtoM((u32)&target, EAX);
+
+ SetBranch();
+}
+
+static void recJALR() {
+// jalr Rs
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ MOV32RtoM((u32)&target, EAX);
+
+ if (_Rd_) {
+ MOV32ItoM((u32)&psxRegs.GPR.r[_Rd_], pc + 4);
+ }
+
+ SetBranch();
+}
+
+static void recBEQ() {
+// Branch if Rs == Rt
+
+ if (_Rs_ == _Rt_) {
+ MOV32ItoM((u32)&target, _Imm_ * 4 + pc);
+ } else {
+ if (_Rs_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ } else {
+ XOR32RtoR(EAX, EAX);
+ }
+ CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ j8Ptr[0] = JE8(0);
+
+ MOV32ItoM((u32)&target, pc+4);
+ j8Ptr[1] = JMP8(0);
+
+ x86SetJ8(j8Ptr[0]);
+
+ MOV32ItoM((u32)&target, _Imm_ * 4 + pc);
+
+ x86SetJ8(j8Ptr[1]);
+ }
+
+ SetBranch();
+}
+
+static void recBNE() {
+// Branch if Rs != Rt
+
+ if (_Rs_) {
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
+ } else {
+ XOR32RtoR(EAX, EAX);
+ }
+ CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ j8Ptr[0] = JNE8(0);
+
+ MOV32ItoM((u32)&target, pc+4);
+ j8Ptr[1] = JMP8(0);
+
+ x86SetJ8(j8Ptr[0]);
+
+ MOV32ItoM((u32)&target, _Imm_ * 4 + pc);
+
+ x86SetJ8(j8Ptr[1]);
+
+ SetBranch();
+}
+
+static void recBLEZ() {
+// Branch if Rs <= 0
+
+ CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
+ j8Ptr[0] = JLE8(0);
+
+ MOV32ItoM((u32)&target, pc+4);
+ j8Ptr[1] = JMP8(0);
+
+ x86SetJ8(j8Ptr[0]);
+
+ MOV32ItoM((u32)&target, _Imm_ * 4 + pc);
+
+ x86SetJ8(j8Ptr[1]);
+
+ SetBranch();
+}
+
+static void recBGTZ() {
+// Branch if Rs > 0
+
+ CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
+ j8Ptr[0] = JG8(0);
+
+ MOV32ItoM((u32)&target, pc+4);
+ j8Ptr[1] = JMP8(0);
+
+ x86SetJ8(j8Ptr[0]);
+
+ MOV32ItoM((u32)&target, _Imm_ * 4 + pc);
+
+ x86SetJ8(j8Ptr[1]);
+
+ SetBranch();
+}
+//#endif
+
+/*REC_FUNC(MFC0);
+REC_FUNC(MTC0);
+REC_FUNC(CFC0);
+REC_FUNC(CTC0);
+REC_FUNC(RFE);
+#if 0*/
+static void recMFC0() {
+// Rt = Cop0->Rd
+ if (!_Rt_) return;
+
+ MOV32MtoR(EAX, (u32)&psxRegs.CP0.r[_Rd_]);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+}
+
+static void recCFC0() {
+// Rt = Cop0->Rd
+ if (!_Rt_) return;
+
+ MOV32MtoR(EAX, (u32)&psxRegs.CP0.r[_Rd_]);
+ MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
+}
+
+static void recMTC0() {
+// Cop0->Rd = Rt
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ MOV32RtoM((u32)&psxRegs.CP0.r[_Rd_], EAX);
+}
+
+static void recCTC0() {
+// Cop0->Rd = Rt
+
+ MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
+ MOV32RtoM((u32)&psxRegs.CP0.r[_Rd_], EAX);
+}
+
+static void recRFE() {
+ MOV32MtoR(EAX, (u32)&psxRegs.CP0.n.Status);
+ MOV32RtoR(ECX, EAX);
+ AND32ItoR(EAX, 0xfffffff0);
+ AND32ItoR(ECX, 0x3c);
+ SHR32ItoR(ECX, 2);
+ OR32RtoR (EAX, ECX);
+ MOV32RtoM((u32)&psxRegs.CP0.n.Status, EAX);
+}
+//#endif
+
+#define CP2_FUNC(f) \
+void gte##f(); \
+static void rec##f() { \
+ MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \
+ MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \
+ CALLFunc ((u32)gte##f); \
+/* branch = 2; */\
+}
+
+CP2_FUNC(MFC2);
+CP2_FUNC(MTC2);
+CP2_FUNC(CFC2);
+CP2_FUNC(CTC2);
+CP2_FUNC(LWC2);
+CP2_FUNC(SWC2);
+
+CP2_FUNC(RTPS);
+CP2_FUNC(OP);
+CP2_FUNC(NCLIP);
+CP2_FUNC(DPCS);
+CP2_FUNC(INTPL);
+CP2_FUNC(MVMVA);
+CP2_FUNC(NCDS);
+CP2_FUNC(NCDT);
+CP2_FUNC(CDP);
+CP2_FUNC(NCCS);
+CP2_FUNC(CC);
+CP2_FUNC(NCS);
+CP2_FUNC(NCT);
+CP2_FUNC(SQR);
+CP2_FUNC(DCPL);
+CP2_FUNC(DPCT);
+CP2_FUNC(AVSZ3);
+CP2_FUNC(AVSZ4);
+CP2_FUNC(RTPT);
+CP2_FUNC(GPF);
+CP2_FUNC(GPL);
+CP2_FUNC(NCCT);
+
+static void recHLE() {
+ MOV32ItoR(EAX, (u32)psxHLEt[psxRegs.code & 0xff]);
+ CALL32R(EAX);
+ branch = 2;
+}
+
+//
+
+static void (*recBSC[64])() = {
+ recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ,
+ recADDI , recADDIU , recSLTI, recSLTIU, recANDI, recORI , recXORI, recLUI ,
+ recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL,
+ recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL,
+ recLB , recLH , recLWL , recLW , recLBU , recLHU , recLWR , recNULL,
+ recSB , recSH , recSWL , recSW , recNULL, recNULL, recSWR , recNULL,
+ recNULL , recNULL , recLWC2, recNULL , recNULL, recNULL, recNULL, recNULL,
+ recNULL , recNULL , recSWC2, recHLE , recNULL, recNULL, recNULL, recNULL
+};
+
+static void (*recSPC[64])() = {
+ recSLL , recNULL, recSRL , recSRA , recSLLV , recNULL , recSRLV, recSRAV,
+ recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL,
+ recMFHI, recMTHI, recMFLO, recMTLO, recNULL , recNULL , recNULL, recNULL,
+ recMULT, recMULTU, recDIV, recDIVU, recNULL , recNULL , recNULL, recNULL,
+ recADD , recADDU, recSUB , recSUBU, recAND , recOR , recXOR , recNOR ,
+ recNULL, recNULL, recSLT , recSLTU, recNULL , recNULL , recNULL, recNULL,
+ recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL,
+ recNULL, recNULL, recNULL, recNULL, recNULL , recNULL , recNULL, recNULL
+};
+
+static void (*recREG[32])() = {
+ recBLTZ , recBGEZ , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
+ recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
+ recBLTZAL, recBGEZAL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
+ recNULL , recNULL , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
+};
+
+static void (*recCP0[32])() = {
+ recMFC0, recNULL, recCFC0, recNULL, recMTC0, recNULL, recCTC0, recNULL,
+ recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
+ recRFE , recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
+ recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
+};
+
+static void (*recCP2[64])() = {
+ recBASIC, recRTPS , recNULL , recNULL, recNULL, recNULL , recNCLIP, recNULL, // 00
+ recNULL , recNULL , recNULL , recNULL, recOP , recNULL , recNULL , recNULL, // 08
+ recDPCS , recINTPL, recMVMVA, recNCDS, recCDP , recNULL , recNCDT , recNULL, // 10
+ recNULL , recNULL , recNULL , recNCCS, recCC , recNULL , recNCS , recNULL, // 18
+ recNCT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 20
+ recSQR , recDCPL , recDPCT , recNULL, recNULL, recAVSZ3, recAVSZ4, recNULL, // 28
+ recRTPT , recNULL , recNULL , recNULL, recNULL, recNULL , recNULL , recNULL, // 30
+ recNULL , recNULL , recNULL , recNULL, recNULL, recGPF , recGPL , recNCCT // 38
+};
+
+static void (*recCP2BSC[32])() = {
+ recMFC2, recNULL, recCFC2, recNULL, recMTC2, recNULL, recCTC2, recNULL,
+ recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
+ recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL,
+ recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL, recNULL
+};
+
+static void recRecompile() {
+ /* if x86Ptr reached the mem limit reset whole mem */
+ if (((u32)x86Ptr - (u32)recMem) >= (RECMEM_SIZE - 0x10000))
+ recReset();
+
+ PC_REC32(psxRegs.pc) = (u32)x86Ptr;
+ pc = psxRegs.pc;
+
+ for (count=0; count<500;) {
+ char *p;
+
+ p = (char *)PSXM(pc);
+ if (p == NULL) recError();
+ psxRegs.code = *(u32 *)p;
+
+ pc+=4; count++;
+ recBSC[psxRegs.code>>26]();
+
+ if (branch) {
+ break;
+ }
+ }
+
+ if (!branch) {
+ MOV32ItoM((u32)&psxRegs.pc, pc);
+ }
+
+ /* store cycle */
+ ADD32ItoM((u32)&psxRegs.cycle, count);
+
+ branch = 0;
+
+ RET();
+}
+
+
+R3000Acpu psxRec = {
+ recInit,
+ recReset,
+ recExecute,
+ recExecuteBlock,
+ recClear,
+ recShutdown
+};