pcsxr/libpcsxcore/ix86/iR3000A.c
Stelios Tsampas a93c5c5420 * Fix CMake to include PGXP sources. Import updated translations.
Includes some small fixes on CMake, such as prettier status messages,
    host and target arch detection (taken from PCSX2), and various other
    small errors.
2017-07-31 17:09:40 +03:00

3167 lines
69 KiB
C
Executable file

/***************************************************************************
* 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 02110-1301 USA. *
***************************************************************************/
/*
* i386 assembly functions for R3000A core.
*/
#ifdef __i386__
#include "ix86.h"
#include <sys/mman.h>
#include "../pgxp_cpu.h"
#include "../pgxp_gte.h"
#include "../pgxp_debug.h"
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
u32 *psxRecLUT;
#undef PC_REC
#undef PC_REC8
#undef PC_REC16
#undef PC_REC32
#define PC_REC(x) (psxRecLUT[(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 u32 pcold; /* recompiler oldpc */
static int count; /* recompiler intruction count */
static int branch; /* set for branch */
static u32 target; /* branch target */
static u32 resp;
typedef struct {
int state;
u32 k;
int reg;
} iRegisters;
static iRegisters iRegs[32];
static iRegisters iRegsS[32];
#define ST_UNK 0
#define ST_CONST 1
#define ST_MAPPED 2
#define IsConst(reg) (iRegs[reg].state == ST_CONST)
#define IsMapped(reg) (iRegs[reg].state == ST_MAPPED)
static void (*recBSC[64])();
static void (*recSPC[64])();
static void (*recREG[32])();
static void (*recCP0[32])();
static void (*recCP2[64])();
static void (*recCP2BSC[32])();
/// PGXP function tables
static void (*pgxpRecBSC[64])();
static void (*pgxpRecSPC[64])();
static void (*pgxpRecCP0[32])();
static void (*pgxpRecCP2BSC[32])();
static void(*pgxpRecBSCMem[64])();
///
static void(**pRecBSC)() = recBSC;
static void(**pRecSPC)() = recSPC;
static void(**pRecREG)() = recREG;
static void(**pRecCP0)() = recCP0;
static void(**pRecCP2)() = recCP2;
static void(**pRecCP2BSC)() = recCP2BSC;
static void recReset();
static void recSetPGXPMode(u32 pgxpMode)
{
switch(pgxpMode)
{
case 0: //PGXP_MODE_DISABLED:
pRecBSC = recBSC;
pRecSPC = recSPC;
pRecREG = recREG;
pRecCP0 = recCP0;
pRecCP2 = recCP2;
pRecCP2BSC = recCP2BSC;
break;
case 1: //PGXP_MODE_MEM:
pRecBSC = pgxpRecBSCMem;
pRecSPC = recSPC;
pRecREG = recREG;
pRecCP0 = pgxpRecCP0;
pRecCP2 = recCP2;
pRecCP2BSC = pgxpRecCP2BSC;
break;
case 2: //PGXP_MODE_FULL:
pRecBSC = pgxpRecBSC;
pRecSPC = pgxpRecSPC;
pRecREG = recREG;
pRecCP0 = pgxpRecCP0;
pRecCP2 = recCP2;
pRecCP2BSC = pgxpRecCP2BSC;
break;
}
// set interpreter mode too
psxInt.SetPGXPMode(pgxpMode);
// reset to ensure new func tables are used
recReset();
}
#define DYNAREC_BLOCK 50
static void MapConst(int reg, u32 _const) {
iRegs[reg].k = _const;
iRegs[reg].state = ST_CONST;
}
static void iFlushReg(int reg) {
if (IsConst(reg)) {
MOV32ItoM((u32)&psxRegs.GPR.r[reg], iRegs[reg].k);
}
iRegs[reg].state = ST_UNK;
}
static void iFlushRegs() {
int i;
for (i=1; i<32; i++) {
iFlushReg(i);
}
}
static void iPushReg(int reg) {
if (IsConst(reg)) {
PUSH32I(iRegs[reg].k);
} else {
PUSH32M((u32)&psxRegs.GPR.r[reg]);
}
}
static void iStoreCycle() {
count = ((pc - pcold) / 4) * BIAS;
ADD32ItoM((u32)&psxRegs.cycle, count);
}
static void iRet() {
iStoreCycle();
if (resp) ADD32ItoR(ESP, resp);
RET();
}
static int iLoadTest() {
u32 tmp;
// check for load delay
tmp = psxRegs.code >> 26;
switch (tmp) {
case 0x10: // COP0
switch (_Rs_) {
case 0x00: // MFC0
case 0x02: // CFC0
return 1;
}
break;
case 0x12: // COP2
switch (_Funct_) {
case 0x00:
switch (_Rs_) {
case 0x00: // MFC2
case 0x02: // CFC2
return 1;
}
break;
}
break;
case 0x32: // LWC2
return 1;
default:
if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
return 1;
}
break;
}
return 0;
}
/* set a pending branch */
static void SetBranch() {
branch = 1;
psxRegs.code = PSXMu32(pc);
pc += 4;
if (iLoadTest() == 1) {
iFlushRegs();
MOV32ItoM((u32)&psxRegs.code, psxRegs.code);
/* store cycle */
count = ((pc - pcold) / 4) * BIAS;
ADD32ItoM((u32)&psxRegs.cycle, count);
if (resp) ADD32ItoR(ESP, resp);
PUSH32M((u32)&target);
PUSH32I(_Rt_);
CALLFunc((u32)psxDelayTest);
ADD32ItoR(ESP, 2*4);
RET();
return;
}
switch( psxRegs.code >> 26 ) {
// Lode Runner (jr - beq)
// bltz - bgez - bltzal - bgezal / beq - bne - blez - bgtz
case 0x01:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
break;
default:
pRecBSC[psxRegs.code>>26]();
break;
}
iFlushRegs();
iStoreCycle();
MOV32MtoR(EAX, (u32)&target);
MOV32RtoM((u32)&psxRegs.pc, EAX);
CALLFunc((u32)psxBranchTest);
if (resp) ADD32ItoR(ESP, resp);
RET();
}
static void iJump(u32 branchPC) {
branch = 1;
psxRegs.code = PSXMu32(pc);
pc+=4;
if (iLoadTest() == 1) {
iFlushRegs();
MOV32ItoM((u32)&psxRegs.code, psxRegs.code);
/* store cycle */
count = ((pc - pcold) / 4) * BIAS;
ADD32ItoM((u32)&psxRegs.cycle, count);
if (resp) ADD32ItoR(ESP, resp);
PUSH32I(branchPC);
PUSH32I(_Rt_);
CALLFunc((u32)psxDelayTest);
ADD32ItoR(ESP, 2*4);
RET();
return;
}
pRecBSC[psxRegs.code>>26]();
iFlushRegs();
iStoreCycle();
MOV32ItoM((u32)&psxRegs.pc, branchPC);
CALLFunc((u32)psxBranchTest);
if (resp) ADD32ItoR(ESP, resp);
// maybe just happened an interruption, check so
CMP32ItoM((u32)&psxRegs.pc, branchPC);
j8Ptr[0] = JE8(0);
RET();
x86SetJ8(j8Ptr[0]);
MOV32MtoR(EAX, PC_REC(branchPC));
TEST32RtoR(EAX, EAX);
j8Ptr[1] = JNE8(0);
RET();
x86SetJ8(j8Ptr[1]);
RET();
JMP32R(EAX);
}
static void iBranch(u32 branchPC, int savectx) {
u32 respold=0;
if (savectx) {
respold = resp;
memcpy(iRegsS, iRegs, sizeof(iRegs));
}
branch = 1;
psxRegs.code = PSXMu32(pc);
// the delay test is only made when the branch is taken
// savectx == 0 will mean that :)
if (savectx == 0 && iLoadTest() == 1) {
iFlushRegs();
MOV32ItoM((u32)&psxRegs.code, psxRegs.code);
/* store cycle */
count = (((pc+4) - pcold) / 4) * BIAS;
ADD32ItoM((u32)&psxRegs.cycle, count);
if (resp) ADD32ItoR(ESP, resp);
PUSH32I(branchPC);
PUSH32I(_Rt_);
CALLFunc((u32)psxDelayTest);
ADD32ItoR(ESP, 2*4);
RET();
return;
}
pc+= 4;
pRecBSC[psxRegs.code>>26]();
iFlushRegs();
iStoreCycle();
MOV32ItoM((u32)&psxRegs.pc, branchPC);
CALLFunc((u32)psxBranchTest);
if (resp) ADD32ItoR(ESP, resp);
// maybe just happened an interruption, check so
CMP32ItoM((u32)&psxRegs.pc, branchPC);
j8Ptr[1] = JE8(0);
RET();
x86SetJ8(j8Ptr[1]);
MOV32MtoR(EAX, PC_REC(branchPC));
TEST32RtoR(EAX, EAX);
j8Ptr[2] = JNE8(0);
RET();
x86SetJ8(j8Ptr[2]);
JMP32R(EAX);
pc-= 4;
if (savectx) {
resp = respold;
memcpy(iRegs, iRegsS, sizeof(iRegs));
}
}
char *txt0 = "EAX = %x : ECX = %x : EDX = %x\n";
char *txt1 = "EAX = %x\n";
char *txt2 = "M32 = %x\n";
void iLogX86() {
PUSHA32();
PUSH32R (EDX);
PUSH32R (ECX);
PUSH32R (EAX);
PUSH32M ((u32)&txt0);
CALLFunc ((u32)SysPrintf);
ADD32ItoR(ESP, 4*4);
POPA32();
}
void iLogEAX() {
PUSH32R (EAX);
PUSH32M ((u32)&txt1);
CALLFunc ((u32)SysPrintf);
ADD32ItoR(ESP, 4*2);
}
void iLogM32(u32 mem) {
PUSH32M (mem);
PUSH32M ((u32)&txt2);
CALLFunc ((u32)SysPrintf);
ADD32ItoR(ESP, 4*2);
}
#if 0
static void iDumpRegs() {
int i, j;
printf("%x %x\n", psxRegs.pc, psxRegs.cycle);
for (i = 0; i < 4; i++) {
for (j = 0; j < 8; j++)
printf("%x ", psxRegs.GPR.r[j * i]);
printf("\n");
}
}
#endif
void iDumpBlock(char *ptr) {
FILE *f;
u32 i;
SysPrintf("dump1 %x:%x, %x\n", psxRegs.pc, pc, psxRegs.cycle);
for (i = psxRegs.pc; i < pc; i += 4)
SysPrintf("%s\n", disR3000AF(PSXMu32(i), i));
fflush(stdout);
f = fopen("dump1", "w");
fwrite(ptr, 1, (u32)x86Ptr - (u32)ptr, f);
fclose(f);
system("ndisasmw -u dump1");
fflush(stdout);
}
#define REC_FUNC(f) \
void psx##f(); \
static void rec##f() { \
iFlushRegs(); \
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() { \
iFlushRegs(); \
MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \
MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \
CALLFunc((u32)psx##f); \
branch = 2; \
iRet(); \
}
#define REC_BRANCH(f) \
void psx##f(); \
static void rec##f() { \
iFlushRegs(); \
MOV32ItoM((u32)&psxRegs.code, (u32)psxRegs.code); \
MOV32ItoM((u32)&psxRegs.pc, (u32)pc); \
CALLFunc((u32)psx##f); \
branch = 2; \
iRet(); \
}
static void recRecompile();
static int recInit() {
int i;
psxRecLUT = (u32 *)malloc(0x010000 * 4);
recMem = mmap(0, RECMEM_SIZE + 0x1000,
PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
recRAM = (char *)malloc(0x200000);
recROM = (char *)malloc(0x080000);
if (recRAM == NULL || recROM == NULL || recMem == NULL || psxRecLUT == NULL) {
SysMessage("Error allocating memory"); return -1;
}
for (i = 0; i < 0x80; i++) psxRecLUT[i + 0x0000] = (u32)&recRAM[(i & 0x1f) << 16];
memcpy(psxRecLUT + 0x8000, psxRecLUT, 0x80 * 4);
memcpy(psxRecLUT + 0xa000, psxRecLUT, 0x80 * 4);
for (i = 0; i < 0x08; i++) psxRecLUT[i + 0xbfc0] = (u32)&recROM[i << 16];
x86Init();
return 0;
}
static void recReset() {
memset(recRAM, 0, 0x200000);
memset(recROM, 0, 0x080000);
x86SetPtr(recMem);
branch = 0;
memset(iRegs, 0, sizeof(iRegs));
iRegs[0].state = ST_CONST;
iRegs[0].k = 0;
}
static void recShutdown() {
if (recMem == NULL) return;
free(psxRecLUT);
munmap(recMem, RECMEM_SIZE + 0x1000);
free(recRAM);
free(recROM);
x86Shutdown();
}
static void recError() {
SysReset();
ClosePlugins();
SysMessage("Unrecoverable error while running recompiler\n");
SysRunGui();
}
__inline static void execute() {
void (**recFunc)() = NULL;
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 recExecute() {
for (;;) execute();
}
static void recExecuteBlock() {
execute();
}
static void recClear(u32 Addr, u32 Size) {
u32 bank,offset;
bank = Addr >> 24;
offset = Addr & 0xffffff;
// Pitfall 3D - clear dynarec slots that contain 'stale' ram data
// - fixes stage 1 loading crash
if( bank == 0x80 || bank == 0xa0 || bank == 0x00 ) {
offset &= 0x1fffff;
if( offset >= DYNAREC_BLOCK * 4 )
memset((void*)PC_REC(Addr - DYNAREC_BLOCK * 4), 0, DYNAREC_BLOCK * 4);
else
memset((void*)PC_REC(Addr - offset), 0, offset);
}
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() {
pRecSPC[_Funct_]();
}
static void recREGIMM() {
pRecREG[_Rt_]();
}
static void recCOP0() {
pRecCP0[_Rs_]();
}
//REC_SYS(COP2);
static void recCOP2() {
MOV32MtoR(EAX, (u32)&psxRegs.CP0.n.Status);
AND32ItoR(EAX, 0x40000000);
j8Ptr[31] = JZ8(0);
pRecCP2[_Funct_]();
x86SetJ8(j8Ptr[31]);
}
static void recBASIC() {
pRecCP2BSC[_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;
// iFlushRegs();
if (_Rs_ == _Rt_) {
if (IsConst(_Rt_)) {
iRegs[_Rt_].k+= _Imm_;
} else {
if (_Imm_ == 1) {
INC32M((u32)&psxRegs.GPR.r[_Rt_]);
} else if (_Imm_ == -1) {
DEC32M((u32)&psxRegs.GPR.r[_Rt_]);
} else if (_Imm_) {
ADD32ItoM((u32)&psxRegs.GPR.r[_Rt_], _Imm_);
}
}
} else {
if (IsConst(_Rs_)) {
MapConst(_Rt_, iRegs[_Rs_].k + _Imm_);
} else {
iRegs[_Rt_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
if (_Imm_ == 1) {
INC32R(EAX);
} else if (_Imm_ == -1) {
DEC32R(EAX);
} else if (_Imm_) {
ADD32ItoR(EAX, _Imm_);
}
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
}
}
}
static void recADDI() {
// Rt = Rs + Im
if (!_Rt_) return;
// iFlushRegs();
if (_Rs_ == _Rt_) {
if (IsConst(_Rt_)) {
iRegs[_Rt_].k += _Imm_;
} else {
if (_Imm_ == 1) {
INC32M((u32)&psxRegs.GPR.r[_Rt_]);
} else if (_Imm_ == -1) {
DEC32M((u32)&psxRegs.GPR.r[_Rt_]);
} else if (_Imm_) {
ADD32ItoM((u32)&psxRegs.GPR.r[_Rt_], _Imm_);
}
}
} else {
if (IsConst(_Rs_)) {
MapConst(_Rt_, iRegs[_Rs_].k + _Imm_);
} else {
iRegs[_Rt_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
if (_Imm_ == 1) {
INC32R(EAX);
} else if (_Imm_ == -1) {
DEC32R(EAX);
} else if (_Imm_) {
ADD32ItoR(EAX, _Imm_);
}
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
}
}
}
static void recSLTI() {
// Rt = Rs < Im (signed)
if (!_Rt_) return;
// iFlushRegs();
if (IsConst(_Rs_)) {
MapConst(_Rt_, (s32)iRegs[_Rs_].k < _Imm_);
} else {
iRegs[_Rt_].state = ST_UNK;
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;
// iFlushRegs();
if (IsConst(_Rs_)) {
MapConst(_Rt_, iRegs[_Rs_].k < _ImmU_);
} else {
iRegs[_Rt_].state = ST_UNK;
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;
// iFlushRegs();
if (_Rs_ == _Rt_) {
if (IsConst(_Rt_)) {
iRegs[_Rt_].k&= _ImmU_;
} else {
AND32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_);
}
} else {
if (IsConst(_Rs_)) {
MapConst(_Rt_, iRegs[_Rs_].k & _ImmU_);
} else {
iRegs[_Rt_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
AND32ItoR(EAX, _ImmU_);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
}
}
}
static void recORI() {
// Rt = Rs Or Im
if (!_Rt_) return;
// iFlushRegs();
if (_Rs_ == _Rt_) {
if (IsConst(_Rt_)) {
iRegs[_Rt_].k|= _ImmU_;
} else {
OR32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_);
}
} else {
if (IsConst(_Rs_)) {
MapConst(_Rt_, iRegs[_Rs_].k | _ImmU_);
} else {
iRegs[_Rt_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
if (_ImmU_) OR32ItoR (EAX, _ImmU_);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
}
}
}
static void recXORI() {
// Rt = Rs Xor Im
if (!_Rt_) return;
// iFlushRegs();
if (_Rs_ == _Rt_) {
if (IsConst(_Rt_)) {
iRegs[_Rt_].k^= _ImmU_;
} else {
XOR32ItoM((u32)&psxRegs.GPR.r[_Rt_], _ImmU_);
}
} else {
if (IsConst(_Rs_)) {
MapConst(_Rt_, iRegs[_Rs_].k ^ _ImmU_);
} else {
iRegs[_Rt_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
XOR32ItoR(EAX, _ImmU_);
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;
MapConst(_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;
// iFlushRegs();
if (IsConst(_Rs_) && IsConst(_Rt_)) {
MapConst(_Rd_, iRegs[_Rs_].k + iRegs[_Rt_].k);
} else if (IsConst(_Rs_)) {
iRegs[_Rd_].state = ST_UNK;
if (_Rt_ == _Rd_) {
if (iRegs[_Rs_].k == 1) {
INC32M((u32)&psxRegs.GPR.r[_Rd_]);
} else if (iRegs[_Rs_].k == -1) {
DEC32M((u32)&psxRegs.GPR.r[_Rd_]);
} else if (iRegs[_Rs_].k) {
ADD32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k);
}
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
if (iRegs[_Rs_].k == 1) {
INC32R(EAX);
} else if (iRegs[_Rs_].k == 0xffffffff) {
DEC32R(EAX);
} else if (iRegs[_Rs_].k) {
ADD32ItoR(EAX, iRegs[_Rs_].k);
}
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
} else if (IsConst(_Rt_)) {
iRegs[_Rd_].state = ST_UNK;
if (_Rs_ == _Rd_) {
if (iRegs[_Rt_].k == 1) {
INC32M((u32)&psxRegs.GPR.r[_Rd_]);
} else if (iRegs[_Rt_].k == -1) {
DEC32M((u32)&psxRegs.GPR.r[_Rd_]);
} else if (iRegs[_Rt_].k) {
ADD32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k);
}
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
if (iRegs[_Rt_].k == 1) {
INC32R(EAX);
} else if (iRegs[_Rt_].k == 0xffffffff) {
DEC32R(EAX);
} else if (iRegs[_Rt_].k) {
ADD32ItoR(EAX, iRegs[_Rt_].k);
}
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
} else {
iRegs[_Rd_].state = ST_UNK;
if (_Rs_ == _Rd_) { // Rd+= Rt
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
ADD32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else if (_Rt_ == _Rd_) { // Rd+= Rs
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
ADD32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else { // Rd = Rs + Rt
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
ADD32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
}
}
static void recADD() {
// Rd = Rs + Rt
recADDU();
}
static void recSUBU() {
// Rd = Rs - Rt
if (!_Rd_) return;
// iFlushRegs();
if (IsConst(_Rs_) && IsConst(_Rt_)) {
MapConst(_Rd_, iRegs[_Rs_].k - iRegs[_Rt_].k);
} else if (IsConst(_Rs_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32ItoR(EAX, iRegs[_Rs_].k);
SUB32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else if (IsConst(_Rt_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
SUB32ItoR(EAX, iRegs[_Rt_].k);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
SUB32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
}
static void recSUB() {
// Rd = Rs - Rt
recSUBU();
}
static void recAND() {
// Rd = Rs And Rt
if (!_Rd_) return;
// iFlushRegs();
if (IsConst(_Rs_) && IsConst(_Rt_)) {
MapConst(_Rd_, iRegs[_Rs_].k & iRegs[_Rt_].k);
} else if (IsConst(_Rs_)) {
iRegs[_Rd_].state = ST_UNK;
if (_Rd_ == _Rt_) { // Rd&= Rs
AND32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rs_].k);
} else {
MOV32ItoR(EAX, iRegs[_Rs_].k);
AND32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
} else if (IsConst(_Rt_)) {
iRegs[_Rd_].state = ST_UNK;
if (_Rd_ == _Rs_) { // Rd&= kRt
AND32ItoM((u32)&psxRegs.GPR.r[_Rd_], iRegs[_Rt_].k);
} else { // Rd = Rs & kRt
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
AND32ItoR(EAX, iRegs[_Rt_].k);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
} else {
iRegs[_Rd_].state = ST_UNK;
if (_Rs_ == _Rd_) { // Rd&= Rt
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
AND32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else if (_Rt_ == _Rd_) { // Rd&= Rs
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
AND32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else { // Rd = Rs & Rt
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
AND32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
}
}
static void recOR() {
// Rd = Rs Or Rt
if (!_Rd_) return;
// iFlushRegs();
if (IsConst(_Rs_) && IsConst(_Rt_)) {
MapConst(_Rd_, iRegs[_Rs_].k | iRegs[_Rt_].k);
} else if (IsConst(_Rs_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32ItoR(EAX, iRegs[_Rs_].k);
OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else if (IsConst(_Rt_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
OR32ItoR (EAX, iRegs[_Rt_].k);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
}
static void recXOR() {
// Rd = Rs Xor Rt
if (!_Rd_) return;
// iFlushRegs();
if (IsConst(_Rs_) && IsConst(_Rt_)) {
MapConst(_Rd_, iRegs[_Rs_].k ^ iRegs[_Rt_].k);
} else if (IsConst(_Rs_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32ItoR(EAX, iRegs[_Rs_].k);
XOR32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else if (IsConst(_Rt_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
XOR32ItoR(EAX, iRegs[_Rt_].k);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
XOR32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
}
static void recNOR() {
// Rd = Rs Nor Rt
if (!_Rd_) return;
// iFlushRegs();
if (IsConst(_Rs_) && IsConst(_Rt_)) {
MapConst(_Rd_, ~(iRegs[_Rs_].k | iRegs[_Rt_].k));
} else if (IsConst(_Rs_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32ItoR(EAX, iRegs[_Rs_].k);
OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]);
NOT32R (EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else if (IsConst(_Rt_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
OR32ItoR (EAX, iRegs[_Rt_].k);
NOT32R (EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
OR32MtoR (EAX, (u32)&psxRegs.GPR.r[_Rt_]);
NOT32R (EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
}
static void recSLT() {
// Rd = Rs < Rt (signed)
if (!_Rd_) return;
// iFlushRegs();
if (IsConst(_Rs_) && IsConst(_Rt_)) {
MapConst(_Rd_, (s32)iRegs[_Rs_].k < (s32)iRegs[_Rt_].k);
} else if (IsConst(_Rs_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32ItoR(EAX, iRegs[_Rs_].k);
CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
SETL8R (EAX);
AND32ItoR(EAX, 0xff);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else if (IsConst(_Rt_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
CMP32ItoR(EAX, iRegs[_Rt_].k);
SETL8R (EAX);
AND32ItoR(EAX, 0xff);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else {
iRegs[_Rd_].state = ST_UNK;
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;
// iFlushRegs();
if (IsConst(_Rs_) && IsConst(_Rt_)) {
MapConst(_Rd_, iRegs[_Rs_].k < iRegs[_Rt_].k);
} else if (IsConst(_Rs_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32ItoR(EAX, iRegs[_Rs_].k);
CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
SBB32RtoR(EAX, EAX);
NEG32R (EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else if (IsConst(_Rt_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
CMP32ItoR(EAX, iRegs[_Rt_].k);
SBB32RtoR(EAX, EAX);
NEG32R (EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else {
iRegs[_Rd_].state = ST_UNK;
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)
// iFlushRegs();
if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
(IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
XOR32RtoR(EAX, EAX);
MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
return;
}
if (IsConst(_Rs_)) {
MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multrsk %x\n", iRegs[_Rs_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
}
if (IsConst(_Rt_)) {
MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multrtk %x\n", iRegs[_Rt_].k);
IMUL32R (EDX);
} else {
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)
// iFlushRegs();
if ((IsConst(_Rs_) && iRegs[_Rs_].k == 0) ||
(IsConst(_Rt_) && iRegs[_Rt_].k == 0)) {
XOR32RtoR(EAX, EAX);
MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
return;
}
if (IsConst(_Rs_)) {
MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("multursk %x\n", iRegs[_Rs_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
}
if (IsConst(_Rt_)) {
MOV32ItoR(EDX, iRegs[_Rt_].k);// printf("multurtk %x\n", iRegs[_Rt_].k);
MUL32R (EDX);
} else {
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)
// iFlushRegs();
if (IsConst(_Rt_)) {
if (iRegs[_Rt_].k == 0) {
MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff);
if (IsConst(_Rs_)) {
MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
}
return;
}
MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divrtk %x\n", iRegs[_Rt_].k);
} else {
MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
CMP32ItoR(ECX, 0);
j8Ptr[0] = JE8(0);
}
if (IsConst(_Rs_)) {
MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divrsk %x\n", iRegs[_Rs_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
}
CDQ();
IDIV32R (ECX);
MOV32RtoM((u32)&psxRegs.GPR.n.lo, EAX);
MOV32RtoM((u32)&psxRegs.GPR.n.hi, EDX);
if (!IsConst(_Rt_)) {
j8Ptr[1] = JMP8(1);
x86SetJ8(j8Ptr[0]);
MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff);
if (IsConst(_Rs_)) {
MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
}
x86SetJ8(j8Ptr[1]);
}
}
static void recDIVU() {
// Lo/Hi = Rs / Rt (unsigned)
// iFlushRegs();
if (IsConst(_Rt_)) {
if (iRegs[_Rt_].k == 0) {
MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff);
if (IsConst(_Rs_)) {
MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
}
return;
}
MOV32ItoR(ECX, iRegs[_Rt_].k);// printf("divurtk %x\n", iRegs[_Rt_].k);
} else {
MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
CMP32ItoR(ECX, 0);
j8Ptr[0] = JE8(0);
}
if (IsConst(_Rs_)) {
MOV32ItoR(EAX, iRegs[_Rs_].k);// printf("divursk %x\n", iRegs[_Rs_].k);
} else {
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);
if (!IsConst(_Rt_)) {
j8Ptr[1] = JMP8(1);
x86SetJ8(j8Ptr[0]);
MOV32ItoM((u32)&psxRegs.GPR.n.lo, 0xffffffff);
if (IsConst(_Rs_)) {
MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
}
x86SetJ8(j8Ptr[1]);
}
}
//#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);
/* Push OfB for Stores/Loads */
static void iPushOfB() {
if (IsConst(_Rs_)) {
PUSH32I (iRegs[_Rs_].k + _Imm_);
} else {
if (_Imm_) {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
ADD32ItoR(EAX, _Imm_);
PUSH32R (EAX);
} else {
PUSH32M ((u32)&psxRegs.GPR.r[_Rs_]);
}
}
}
//#if 0
static void recLB() {
// Rt = mem[Rs + Im] (signed)
// iFlushRegs();
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
if ((t & 0xfff0) == 0xbfc0) {
if (!_Rt_) return;
// since bios is readonly it won't change
MapConst(_Rt_, psxRs8(addr));
return;
}
if ((t & 0x1fe0) == 0) {
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOVSX32M8toR(EAX, (u32)&psxM[addr & 0x1fffff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOVSX32M8toR(EAX, (u32)&psxH[addr & 0xfff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
// SysPrintf("unhandled r8 %x\n", addr);
}
iPushOfB();
CALLFunc((u32)psxMemRead8);
if (_Rt_) {
iRegs[_Rt_].state = ST_UNK;
MOVSX32R8toR(EAX, EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
}
// ADD32ItoR(ESP, 4);
resp+= 4;
}
static void recLBU() {
// Rt = mem[Rs + Im] (unsigned)
// iFlushRegs();
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
if ((t & 0xfff0) == 0xbfc0) {
if (!_Rt_) return;
// since bios is readonly it won't change
MapConst(_Rt_, psxRu8(addr));
return;
}
if ((t & 0x1fe0) == 0) {
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOVZX32M8toR(EAX, (u32)&psxM[addr & 0x1fffff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOVZX32M8toR(EAX, (u32)&psxH[addr & 0xfff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
// SysPrintf("unhandled r8u %x\n", addr);
}
iPushOfB();
CALLFunc((u32)psxMemRead8);
if (_Rt_) {
iRegs[_Rt_].state = ST_UNK;
MOVZX32R8toR(EAX, EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
}
// ADD32ItoR(ESP, 4);
resp+= 4;
}
static void recLH() {
// Rt = mem[Rs + Im] (signed)
// iFlushRegs();
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
if ((t & 0xfff0) == 0xbfc0) {
if (!_Rt_) return;
// since bios is readonly it won't change
MapConst(_Rt_, psxRs16(addr));
return;
}
if ((t & 0x1fe0) == 0) {
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOVSX32M16toR(EAX, (u32)&psxM[addr & 0x1fffff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOVSX32M16toR(EAX, (u32)&psxH[addr & 0xfff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
// SysPrintf("unhandled r16 %x\n", addr);
}
iPushOfB();
CALLFunc((u32)psxMemRead16);
if (_Rt_) {
iRegs[_Rt_].state = ST_UNK;
MOVSX32R16toR(EAX, EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
}
// ADD32ItoR(ESP, 4);
resp+= 4;
}
static void recLHU() {
// Rt = mem[Rs + Im] (unsigned)
// iFlushRegs();
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
if ((t & 0xfff0) == 0xbfc0) {
if (!_Rt_) return;
// since bios is readonly it won't change
MapConst(_Rt_, psxRu16(addr));
return;
}
if ((t & 0x1fe0) == 0) {
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOVZX32M16toR(EAX, (u32)&psxM[addr & 0x1fffff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOVZX32M16toR(EAX, (u32)&psxH[addr & 0xfff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
if (t == 0x1f80) {
if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
PUSH32I (addr);
CALL32M ((u32)&SPU_readRegister);
MOVZX32R16toR(EAX, EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
#ifndef __WIN32__
resp+= 4;
#endif
return;
}
switch (addr) {
case 0x1f801100: case 0x1f801110: case 0x1f801120:
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
PUSH32I((addr >> 4) & 0x3);
CALLFunc((u32)psxRcntRcount);
MOVZX32R16toR(EAX, EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
resp+= 4;
return;
case 0x1f801104: case 0x1f801114: case 0x1f801124:
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
PUSH32I((addr >> 4) & 0x3);
CALLFunc((u32)psxRcntRmode);
MOVZX32R16toR(EAX, EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
resp+= 4;
return;
case 0x1f801108: case 0x1f801118: case 0x1f801128:
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
PUSH32I((addr >> 4) & 0x3);
CALLFunc((u32)psxRcntRtarget);
MOVZX32R16toR(EAX, EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
resp+= 4;
return;
}
}
// SysPrintf("unhandled r16u %x\n", addr);
}
iPushOfB();
CALLFunc((u32)psxMemRead16);
if (_Rt_) {
iRegs[_Rt_].state = ST_UNK;
MOVZX32R16toR(EAX, EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
}
// ADD32ItoR(ESP, 4);
resp+= 4;
}
static void recLW() {
// Rt = mem[Rs + Im] (unsigned)
// iFlushRegs();
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
if ((t & 0xfff0) == 0xbfc0) {
if (!_Rt_) return;
// since bios is readonly it won't change
MapConst(_Rt_, psxRu32(addr));
return;
}
if ((t & 0x1fe0) == 0) {
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxM[addr & 0x1fffff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
if (t == 0x1f80) {
switch (addr) {
case 0x1f801080: case 0x1f801084: case 0x1f801088:
case 0x1f801090: case 0x1f801094: case 0x1f801098:
case 0x1f8010a0: case 0x1f8010a4: case 0x1f8010a8:
case 0x1f8010b0: case 0x1f8010b4: case 0x1f8010b8:
case 0x1f8010c0: case 0x1f8010c4: case 0x1f8010c8:
case 0x1f8010d0: case 0x1f8010d4: case 0x1f8010d8:
case 0x1f8010e0: case 0x1f8010e4: case 0x1f8010e8:
case 0x1f801070: case 0x1f801074:
case 0x1f8010f0: case 0x1f8010f4:
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxH[addr & 0xffff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
case 0x1f801810:
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
CALL32M((u32)&GPU_readData);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
case 0x1f801814:
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
CALL32M((u32)&GPU_readStatus);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
}
// SysPrintf("unhandled r32 %x\n", addr);
}
iPushOfB();
CALLFunc((u32)psxMemRead32);
if (_Rt_) {
iRegs[_Rt_].state = ST_UNK;
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
}
// ADD32ItoR(ESP, 4);
resp+= 4;
}
extern u32 LWL_MASK[4];
extern u32 LWL_SHIFT[4];
void iLWLk(u32 shift) {
if (IsConst(_Rt_)) {
MOV32ItoR(ECX, iRegs[_Rt_].k);
} else {
MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
}
AND32ItoR(ECX, LWL_MASK[shift]);
SHL32ItoR(EAX, LWL_SHIFT[shift]);
OR32RtoR (EAX, ECX);
}
void recLWL() {
// Rt = Rt Merge mem[Rs + Im]
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
if ((t & 0x1fe0) == 0) {
MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
iLWLk(addr & 3);
iRegs[_Rt_].state = ST_UNK;
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
iLWLk(addr & 3);
iRegs[_Rt_].state = ST_UNK;
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
}
if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
if (_Imm_) ADD32ItoR(EAX, _Imm_);
}
PUSH32R (EAX);
AND32ItoR(EAX, ~3);
PUSH32R (EAX);
CALLFunc((u32)psxMemRead32);
if (_Rt_) {
ADD32ItoR(ESP, 4);
POP32R (EDX);
AND32ItoR(EDX, 0x3); // shift = addr & 3;
MOV32ItoR(ECX, (u32)LWL_SHIFT);
MOV32RmStoR(ECX, ECX, EDX, 2);
SHL32CLtoR(EAX); // mem(EAX) << LWL_SHIFT[shift]
MOV32ItoR(ECX, (u32)LWL_MASK);
MOV32RmStoR(ECX, ECX, EDX, 2);
if (IsConst(_Rt_)) {
MOV32ItoR(EDX, iRegs[_Rt_].k);
} else {
MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
}
AND32RtoR(EDX, ECX); // _rRt_ & LWL_MASK[shift]
OR32RtoR(EAX, EDX);
iRegs[_Rt_].state = ST_UNK;
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
} else {
// ADD32ItoR(ESP, 8);
resp+= 8;
}
}
#if 0
static void recLWBlock(int count) {
u32 *code = (u32 *)PSXM(pc);
int i, respsave;
// Rt = mem[Rs + Im] (unsigned)
// iFlushRegs();
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
if ((t & 0xfff0) == 0xbfc0) {
// since bios is readonly it won't change
for (i = 0; i < count; i++, code++, addr += 4) {
if (_fRt_(*code)) {
MapConst(_fRt_(*code), psxRu32(addr));
}
}
return;
}
if ((t & 0x1fe0) == 0) {
for (i = 0; i < count; i++, code++, addr += 4) {
if (!_fRt_(*code))
return;
iRegs[_fRt_(*code)].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxM[addr & 0x1fffff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
}
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
for (i = 0; i < count; i++, code++, addr += 4) {
if (!_fRt_(*code))
return;
iRegs[_fRt_(*code)].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
}
return;
}
}
SysPrintf("recLWBlock %d: %d\n", count, IsConst(_Rs_));
iPushOfB();
CALLFunc((u32)psxMemPointer);
// ADD32ItoR(ESP, 4);
resp += 4;
respsave = resp; resp = 0;
TEST32RtoR(EAX, EAX);
j32Ptr[4] = JZ32(0);
XOR32RtoR(ECX, ECX);
for (i = 0; i < count; i++, code++) {
if (_fRt_(*code)) {
iRegs[_fRt_(*code)].state = ST_UNK;
MOV32RmStoR(EDX, EAX, ECX, 2);
MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EDX);
}
if (i != (count - 1))
INC32R(ECX);
}
j32Ptr[5] = JMP32(0);
x86SetJ32(j32Ptr[4]);
for (i = 0, code = (u32 *)PSXM(pc); i < count; i++, code++) {
psxRegs.code = *code;
recLW();
}
ADD32ItoR(ESP, resp);
x86SetJ32(j32Ptr[5]);
resp = respsave;
}
#endif
extern u32 LWR_MASK[4];
extern u32 LWR_SHIFT[4];
void iLWRk(u32 shift) {
if (IsConst(_Rt_)) {
MOV32ItoR(ECX, iRegs[_Rt_].k);
} else {
MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
}
AND32ItoR(ECX, LWR_MASK[shift]);
SHR32ItoR(EAX, LWR_SHIFT[shift]);
OR32RtoR(EAX, ECX);
}
void recLWR() {
// Rt = Rt Merge mem[Rs + Im]
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
if ((t & 0x1fe0) == 0) {
MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
iLWRk(addr & 3);
iRegs[_Rt_].state = ST_UNK;
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
iLWRk(addr & 3);
iRegs[_Rt_].state = ST_UNK;
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
return;
}
}
if (IsConst(_Rs_))
MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
if (_Imm_) ADD32ItoR(EAX, _Imm_);
}
PUSH32R (EAX);
AND32ItoR(EAX, ~3);
PUSH32R (EAX);
CALLFunc((u32)psxMemRead32);
if (_Rt_) {
ADD32ItoR(ESP, 4);
POP32R (EDX);
AND32ItoR(EDX, 0x3); // shift = addr & 3;
MOV32ItoR(ECX, (u32)LWR_SHIFT);
MOV32RmStoR(ECX, ECX, EDX, 2);
SHR32CLtoR(EAX); // mem(EAX) >> LWR_SHIFT[shift]
MOV32ItoR(ECX, (u32)LWR_MASK);
MOV32RmStoR(ECX, ECX, EDX, 2);
if (IsConst(_Rt_)) {
MOV32ItoR(EDX, iRegs[_Rt_].k);
} else {
MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
}
AND32RtoR(EDX, ECX); // _rRt_ & LWR_MASK[shift]
OR32RtoR(EAX, EDX);
iRegs[_Rt_].state = ST_UNK;
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
} else {
// ADD32ItoR(ESP, 8);
resp+= 8;
}
}
static void recSB() {
// mem[Rs + Im] = Rt
// iFlushRegs();
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
if (IsConst(_Rt_)) {
MOV8ItoM((u32)&psxM[addr & 0x1fffff], (u8)iRegs[_Rt_].k);
} else {
MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV8RtoM((u32)&psxM[addr & 0x1fffff], EAX);
}
PUSH32I(1);
PUSH32I(addr & ~3);
CALLFunc((u32)&recClear);
resp += 8;
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
if (IsConst(_Rt_)) {
MOV8ItoM((u32)&psxH[addr & 0xfff], (u8)iRegs[_Rt_].k);
} else {
MOV8MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV8RtoM((u32)&psxH[addr & 0xfff], EAX);
}
return;
}
// SysPrintf("unhandled w8 %x\n", addr);
}
if (IsConst(_Rt_)) {
PUSH32I (iRegs[_Rt_].k);
} else {
PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]);
}
iPushOfB();
CALLFunc((u32)psxMemWrite8);
// ADD32ItoR(ESP, 8);
resp+= 8;
}
static void recSH() {
// mem[Rs + Im] = Rt
// iFlushRegs();
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
if (IsConst(_Rt_)) {
MOV16ItoM((u32)&psxM[addr & 0x1fffff], (u16)iRegs[_Rt_].k);
} else {
MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV16RtoM((u32)&psxM[addr & 0x1fffff], EAX);
}
PUSH32I(1);
PUSH32I(addr & ~3);
CALLFunc((u32)&recClear);
resp += 8;
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
if (IsConst(_Rt_)) {
MOV16ItoM((u32)&psxH[addr & 0xfff], (u16)iRegs[_Rt_].k);
} else {
MOV16MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV16RtoM((u32)&psxH[addr & 0xfff], EAX);
}
return;
}
if (t == 0x1f80) {
if (addr >= 0x1f801c00 && addr < 0x1f801e00) {
if (IsConst(_Rt_)) {
PUSH32I(iRegs[_Rt_].k);
} else {
PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
}
PUSH32I (addr);
CALL32M ((u32)&SPU_writeRegister);
#ifndef __WIN32__
resp+= 8;
#endif
return;
}
}
// SysPrintf("unhandled w16 %x\n", addr);
}
if (IsConst(_Rt_)) {
PUSH32I (iRegs[_Rt_].k);
} else {
PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]);
}
iPushOfB();
CALLFunc((u32)psxMemWrite16);
// ADD32ItoR(ESP, 8);
resp+= 8;
}
static void recSW() {
// mem[Rs + Im] = Rt
// iFlushRegs();
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
if (IsConst(_Rt_)) {
MOV32ItoM((u32)&psxM[addr & 0x1fffff], iRegs[_Rt_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX);
}
PUSH32I(1);
PUSH32I(addr);
CALLFunc((u32)&recClear);
resp += 8;
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
if (IsConst(_Rt_)) {
MOV32ItoM((u32)&psxH[addr & 0xfff], iRegs[_Rt_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxH[addr & 0xfff], EAX);
}
return;
}
if (t == 0x1f80) {
switch (addr) {
case 0x1f801080: case 0x1f801084:
case 0x1f801090: case 0x1f801094:
case 0x1f8010a0: case 0x1f8010a4:
case 0x1f8010b0: case 0x1f8010b4:
case 0x1f8010c0: case 0x1f8010c4:
case 0x1f8010d0: case 0x1f8010d4:
case 0x1f8010e0: case 0x1f8010e4:
case 0x1f801074:
case 0x1f8010f0:
if (IsConst(_Rt_)) {
MOV32ItoM((u32)&psxH[addr & 0xffff], iRegs[_Rt_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32RtoM((u32)&psxH[addr & 0xffff], EAX);
}
return;
case 0x1f801810:
if (IsConst(_Rt_)) {
PUSH32I(iRegs[_Rt_].k);
} else {
PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
}
CALL32M((u32)&GPU_writeData);
#ifndef __WIN32__
resp+= 4;
#endif
return;
case 0x1f801814:
if (IsConst(_Rt_)) {
PUSH32I(iRegs[_Rt_].k);
} else {
PUSH32M((u32)&psxRegs.GPR.r[_Rt_]);
}
CALL32M((u32)&GPU_writeStatus);
#ifndef __WIN32__
resp+= 4;
#endif
return;
}
}
// SysPrintf("unhandled w32 %x\n", addr);
}
if (IsConst(_Rt_)) {
PUSH32I (iRegs[_Rt_].k);
} else {
PUSH32M ((u32)&psxRegs.GPR.r[_Rt_]);
}
iPushOfB();
CALLFunc((u32)psxMemWrite32);
// ADD32ItoR(ESP, 8);
resp+= 8;
}
//#endif
#if 0
static void recSWBlock(int count) {
u32 *code;
int i, respsave;
// mem[Rs + Im] = Rt
// iFlushRegs();
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
code = (u32 *)PSXM(pc);
if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
for (i = 0; i < count; i++, code++, addr += 4) {
if (IsConst(_fRt_(*code))) {
MOV32ItoM((u32)&psxM[addr & 0x1fffff], iRegs[_fRt_(*code)].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_fRt_(*code)]);
MOV32RtoM((u32)&psxM[addr & 0x1fffff], EAX);
}
}
return;
}
if (t == 0x1f80 && addr < 0x1f801000) {
for (i = 0; i < count; i++, code++, addr += 4) {
if (!_fRt_(*code))
return;
iRegs[_fRt_(*code)].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxH[addr & 0xfff]);
MOV32RtoM((u32)&psxRegs.GPR.r[_fRt_(*code)], EAX);
}
return;
}
}
SysPrintf("recSWBlock %d: %d\n", count, IsConst(_Rs_));
iPushOfB();
CALLFunc((u32)psxMemPointer);
// ADD32ItoR(ESP, 4);
resp += 4;
respsave = resp;
resp = 0;
TEST32RtoR(EAX, EAX);
j32Ptr[4] = JZ32(0);
XOR32RtoR(ECX, ECX);
for (i = 0, code = (u32 *)PSXM(pc); i < count; i++, code++) {
if (IsConst(_fRt_(*code))) {
MOV32ItoR(EDX, iRegs[_fRt_(*code)].k);
} else {
MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_fRt_(*code)]);
}
MOV32RtoRmS(EAX, ECX, 2, EDX);
if (i != (count - 1))
INC32R(ECX);
}
j32Ptr[5] = JMP32(0);
x86SetJ32(j32Ptr[4]);
for (i = 0, code = (u32 *)PSXM(pc); i < count; i++, code++) {
psxRegs.code = *code;
recSW();
}
ADD32ItoR(ESP, resp);
x86SetJ32(j32Ptr[5]);
resp = respsave;
}
#endif
extern u32 SWL_MASK[4];
extern u32 SWL_SHIFT[4];
void iSWLk(u32 shift) {
if (IsConst(_Rt_)) {
MOV32ItoR(ECX, iRegs[_Rt_].k);
} else {
MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
}
SHR32ItoR(ECX, SWL_SHIFT[shift]);
AND32ItoR(EAX, SWL_MASK[shift]);
OR32RtoR (EAX, ECX);
}
void recSWL() {
// mem[Rs + Im] = Rt Merge mem[Rs + Im]
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
#if 0
if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
iSWLk(addr & 3);
MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX);
return;
}
#endif
if (t == 0x1f80 && addr < 0x1f801000) {
MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
iSWLk(addr & 3);
MOV32RtoM((u32)&psxH[addr & 0xffc], EAX);
return;
}
}
if (IsConst(_Rs_)) {
MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
if (_Imm_) ADD32ItoR(EAX, _Imm_);
}
PUSH32R (EAX);
AND32ItoR(EAX, ~3);
PUSH32R (EAX);
CALLFunc((u32)psxMemRead32);
ADD32ItoR(ESP, 4);
POP32R (EDX);
AND32ItoR(EDX, 0x3); // shift = addr & 3;
MOV32ItoR(ECX, (u32)SWL_MASK);
MOV32RmStoR(ECX, ECX, EDX, 2);
AND32RtoR(EAX, ECX); // mem & SWL_MASK[shift]
MOV32ItoR(ECX, (u32)SWL_SHIFT);
MOV32RmStoR(ECX, ECX, EDX, 2);
if (IsConst(_Rt_)) {
MOV32ItoR(EDX, iRegs[_Rt_].k);
} else {
MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
}
SHR32CLtoR(EDX); // _rRt_ >> SWL_SHIFT[shift]
OR32RtoR (EAX, EDX);
PUSH32R (EAX);
if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
if (_Imm_) ADD32ItoR(EAX, _Imm_);
}
AND32ItoR(EAX, ~3);
PUSH32R (EAX);
CALLFunc((u32)psxMemWrite32);
// ADD32ItoR(ESP, 8);
resp+= 8;
}
extern u32 SWR_MASK[4];
extern u32 SWR_SHIFT[4];
void iSWRk(u32 shift) {
if (IsConst(_Rt_)) {
MOV32ItoR(ECX, iRegs[_Rt_].k);
} else {
MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rt_]);
}
SHL32ItoR(ECX, SWR_SHIFT[shift]);
AND32ItoR(EAX, SWR_MASK[shift]);
OR32RtoR (EAX, ECX);
}
void recSWR() {
// mem[Rs + Im] = Rt Merge mem[Rs + Im]
if (IsConst(_Rs_)) {
u32 addr = iRegs[_Rs_].k + _Imm_;
int t = addr >> 16;
#if 0
if ((t & 0x1fe0) == 0 && (t & 0x1fff) != 0) {
MOV32MtoR(EAX, (u32)&psxM[addr & 0x1ffffc]);
iSWRk(addr & 3);
MOV32RtoM((u32)&psxM[addr & 0x1ffffc], EAX);
return;
}
#endif
if (t == 0x1f80 && addr < 0x1f801000) {
MOV32MtoR(EAX, (u32)&psxH[addr & 0xffc]);
iSWRk(addr & 3);
MOV32RtoM((u32)&psxH[addr & 0xffc], EAX);
return;
}
}
if (IsConst(_Rs_)) {
MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
if (_Imm_) ADD32ItoR(EAX, _Imm_);
}
PUSH32R (EAX);
AND32ItoR(EAX, ~3);
PUSH32R (EAX);
CALLFunc((u32)psxMemRead32);
ADD32ItoR(ESP, 4);
POP32R (EDX);
AND32ItoR(EDX, 0x3); // shift = addr & 3;
MOV32ItoR(ECX, (u32)SWR_MASK);
MOV32RmStoR(ECX, ECX, EDX, 2);
AND32RtoR(EAX, ECX); // mem & SWR_MASK[shift]
MOV32ItoR(ECX, (u32)SWR_SHIFT);
MOV32RmStoR(ECX, ECX, EDX, 2);
if (IsConst(_Rt_)) {
MOV32ItoR(EDX, iRegs[_Rt_].k);
} else {
MOV32MtoR(EDX, (u32)&psxRegs.GPR.r[_Rt_]);
}
SHL32CLtoR(EDX); // _rRt_ << SWR_SHIFT[shift]
OR32RtoR (EAX, EDX);
PUSH32R (EAX);
if (IsConst(_Rs_)) MOV32ItoR(EAX, iRegs[_Rs_].k + _Imm_);
else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
if (_Imm_) ADD32ItoR(EAX, _Imm_);
}
AND32ItoR(EAX, ~3);
PUSH32R (EAX);
CALLFunc((u32)psxMemWrite32);
// ADD32ItoR(ESP, 8);
resp += 8;
}
/*REC_FUNC(SLL);
REC_FUNC(SRL);
REC_FUNC(SRA);
#if 0*/
static void recSLL() {
// Rd = Rt << Sa
if (!_Rd_)
return;
// iFlushRegs();
if (IsConst(_Rt_)) {
MapConst(_Rd_, iRegs[_Rt_].k << _Sa_);
} else {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
if (_Sa_) SHL32ItoR(EAX, _Sa_);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
}
static void recSRL() {
// Rd = Rt >> Sa
if (!_Rd_)
return;
// iFlushRegs();
if (IsConst(_Rt_)) {
MapConst(_Rd_, iRegs[_Rt_].k >> _Sa_);
} else {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
if (_Sa_) SHR32ItoR(EAX, _Sa_);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
}
static void recSRA() {
// Rd = Rt >> Sa
if (!_Rd_)
return;
// iFlushRegs();
if (IsConst(_Rt_)) {
MapConst(_Rd_, (s32)iRegs[_Rt_].k >> _Sa_);
} else {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
if (_Sa_) SAR32ItoR(EAX, _Sa_);
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;
// iFlushRegs();
if (IsConst(_Rt_) && IsConst(_Rs_)) {
MapConst(_Rd_, iRegs[_Rt_].k << iRegs[_Rs_].k);
} else if (IsConst(_Rs_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32ItoR(ECX, iRegs[_Rs_].k);
SHL32CLtoR(EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else if (IsConst(_Rt_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32ItoR(EAX, iRegs[_Rt_].k);
MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
SHL32CLtoR(EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
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;
// iFlushRegs();
if (IsConst(_Rt_) && IsConst(_Rs_)) {
MapConst(_Rd_, iRegs[_Rt_].k >> iRegs[_Rs_].k);
} else if (IsConst(_Rs_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32ItoR(ECX, iRegs[_Rs_].k);
SHR32CLtoR(EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else if (IsConst(_Rt_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32ItoR(EAX, iRegs[_Rt_].k);
MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
SHR32CLtoR(EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
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;
// iFlushRegs();
if (IsConst(_Rt_) && IsConst(_Rs_)) {
MapConst(_Rd_, (s32)iRegs[_Rt_].k >> iRegs[_Rs_].k);
} else if (IsConst(_Rs_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
MOV32ItoR(ECX, iRegs[_Rs_].k);
SAR32CLtoR(EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else if (IsConst(_Rt_)) {
iRegs[_Rd_].state = ST_UNK;
MOV32ItoR(EAX, iRegs[_Rt_].k);
MOV32MtoR(ECX, (u32)&psxRegs.GPR.r[_Rs_]);
SAR32CLtoR(EAX);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
} else {
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
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*/
int dump;
static void recSYSCALL() {
// dump = 1;
iFlushRegs();
MOV32ItoR(EAX, pc - 4);
MOV32RtoM((u32)&psxRegs.pc, EAX);
PUSH32I (branch == 1 ? 1 : 0);
PUSH32I (0x20);
CALLFunc ((u32)psxException);
ADD32ItoR(ESP, 8);
branch = 2;
iRet();
}
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;
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.n.hi);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
static void recMTHI() {
// Hi = Rs
if (IsConst(_Rs_)) {
MOV32ItoM((u32)&psxRegs.GPR.n.hi, iRegs[_Rs_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
MOV32RtoM((u32)&psxRegs.GPR.n.hi, EAX);
}
}
static void recMFLO() {
// Rd = Lo
if (!_Rd_)
return;
iRegs[_Rd_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.GPR.n.lo);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rd_], EAX);
}
static void recMTLO() {
// Lo = Rs
if (IsConst(_Rs_)) {
MOV32ItoM((u32)&psxRegs.GPR.n.lo, iRegs[_Rs_].k);
} else {
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
u32 bpc = _Imm_ * 4 + pc;
// iFlushRegs();
if (bpc == pc+4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
return;
}
if (IsConst(_Rs_)) {
if ((s32)iRegs[_Rs_].k < 0) {
iJump(bpc);
return;
} else {
iJump(pc + 4);
return;
}
}
CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
j32Ptr[4] = JL32(0);
iBranch(pc+4, 1);
x86SetJ32(j32Ptr[4]);
iBranch(bpc, 0);
pc += 4;
}
static void recBGTZ() {
// Branch if Rs > 0
u32 bpc = _Imm_ * 4 + pc;
// iFlushRegs();
if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
return;
}
if (IsConst(_Rs_)) {
if ((s32)iRegs[_Rs_].k > 0) {
iJump(bpc);
return;
} else {
iJump(pc + 4);
return;
}
}
CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
j32Ptr[4] = JG32(0);
iBranch(pc + 4, 1);
x86SetJ32(j32Ptr[4]);
iBranch(bpc, 0);
pc+=4;
}
static void recBLTZAL() {
// Branch if Rs < 0
u32 bpc = _Imm_ * 4 + pc;
// iFlushRegs();
if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
return;
}
if (IsConst(_Rs_)) {
if ((s32)iRegs[_Rs_].k < 0) {
MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4);
iJump(bpc); return;
} else {
iJump(pc + 4); return;
}
}
CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
j32Ptr[4] = JL32(0);
iBranch(pc + 4, 1);
x86SetJ32(j32Ptr[4]);
MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4);
iBranch(bpc, 0);
pc += 4;
}
static void recBGEZAL() {
// Branch if Rs >= 0
u32 bpc = _Imm_ * 4 + pc;
// iFlushRegs();
if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
return;
}
if (IsConst(_Rs_)) {
if ((s32)iRegs[_Rs_].k >= 0) {
MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4);
iJump(bpc); return;
} else {
iJump(pc+4); return;
}
}
CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
j32Ptr[4] = JGE32(0);
iBranch(pc+4, 1);
x86SetJ32(j32Ptr[4]);
MOV32ItoM((u32)&psxRegs.GPR.r[31], pc + 4);
iBranch(bpc, 0);
pc+=4;
}
static void recJ() {
// j target
iJump(_Target_ * 4 + (pc & 0xf0000000));
}
static void recJAL() {
// jal target
MapConst(31, pc + 4);
iJump(_Target_ * 4 + (pc & 0xf0000000));
}
static void recJR() {
// jr Rs
if (IsConst(_Rs_)) {
MOV32ItoM((u32)&target, iRegs[_Rs_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
MOV32RtoM((u32)&target, EAX);
}
SetBranch();
}
static void recJALR() {
// jalr Rs
if (IsConst(_Rs_)) {
MOV32ItoM((u32)&target, iRegs[_Rs_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
MOV32RtoM((u32)&target, EAX);
}
if (_Rd_) {
MapConst(_Rd_, pc + 4);
}
SetBranch();
}
static void recBEQ() {
// Branch if Rs == Rt
u32 bpc = _Imm_ * 4 + pc;
// iFlushRegs();
if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
return;
}
if (_Rs_ == _Rt_) {
iJump(bpc);
} else {
if (IsConst(_Rs_) && IsConst(_Rt_)) {
if (iRegs[_Rs_].k == iRegs[_Rt_].k) {
iJump(bpc);
return;
} else {
iJump(pc + 4);
return;
}
} else if (IsConst(_Rs_)) {
CMP32ItoM((u32)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k);
} else if (IsConst(_Rt_)) {
CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
}
j32Ptr[4] = JE32(0);
iBranch(pc + 4, 1);
x86SetJ32(j32Ptr[4]);
iBranch(bpc, 0);
pc += 4;
}
}
static void recBNE() {
// Branch if Rs != Rt
u32 bpc = _Imm_ * 4 + pc;
// iFlushRegs();
if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
return;
}
if (IsConst(_Rs_) && IsConst(_Rt_)) {
if (iRegs[_Rs_].k != iRegs[_Rt_].k) {
iJump(bpc);
return;
} else {
iJump(pc + 4);
return;
}
} else if (IsConst(_Rs_)) {
CMP32ItoM((u32)&psxRegs.GPR.r[_Rt_], iRegs[_Rs_].k);
} else if (IsConst(_Rt_)) {
CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], iRegs[_Rt_].k);
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rs_]);
CMP32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
}
j32Ptr[4] = JNE32(0);
iBranch(pc + 4, 1);
x86SetJ32(j32Ptr[4]);
iBranch(bpc, 0);
pc += 4;
}
static void recBLEZ() {
// Branch if Rs <= 0
u32 bpc = _Imm_ * 4 + pc;
// iFlushRegs();
if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
return;
}
if (IsConst(_Rs_)) {
if ((s32)iRegs[_Rs_].k <= 0) {
iJump(bpc);
return;
} else {
iJump(pc + 4);
return;
}
}
CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
j32Ptr[4] = JLE32(0);
iBranch(pc + 4, 1);
x86SetJ32(j32Ptr[4]);
iBranch(bpc, 0);
pc += 4;
}
static void recBGEZ() {
// Branch if Rs >= 0
u32 bpc = _Imm_ * 4 + pc;
// iFlushRegs();
if (bpc == pc + 4 && psxTestLoadDelay(_Rs_, PSXMu32(bpc)) == 0) {
return;
}
if (IsConst(_Rs_)) {
if ((s32)iRegs[_Rs_].k >= 0) {
iJump(bpc);
return;
} else {
iJump(pc + 4);
return;
}
}
CMP32ItoM((u32)&psxRegs.GPR.r[_Rs_], 0);
j32Ptr[4] = JGE32(0);
iBranch(pc + 4, 1);
x86SetJ32(j32Ptr[4]);
iBranch(bpc, 0);
pc += 4;
}
//#endif
/*REC_FUNC(MFC0);
REC_SYS(MTC0);
REC_FUNC(CFC0);
REC_SYS(CTC0);
REC_FUNC(RFE);
#if 0*/
static void recMFC0() {
// Rt = Cop0->Rd
if (!_Rt_) return;
iRegs[_Rt_].state = ST_UNK;
MOV32MtoR(EAX, (u32)&psxRegs.CP0.r[_Rd_]);
MOV32RtoM((u32)&psxRegs.GPR.r[_Rt_], EAX);
}
static void recCFC0() {
// Rt = Cop0->Rd
recMFC0();
}
void psxMTC0();
static void recMTC0() {
// Cop0->Rd = Rt
if (IsConst(_Rt_)) {
switch (_Rd_) {
case 12:
MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
break;
case 13:
MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k & ~(0xfc00));
break;
default:
MOV32ItoM((u32)&psxRegs.CP0.r[_Rd_], iRegs[_Rt_].k);
break;
}
} else {
MOV32MtoR(EAX, (u32)&psxRegs.GPR.r[_Rt_]);
switch (_Rd_) {
case 13:
AND32ItoR(EAX, ~(0xfc00));
break;
}
MOV32RtoM((u32)&psxRegs.CP0.r[_Rd_], EAX);
}
if (_Rd_ == 12 || _Rd_ == 13) {
iFlushRegs();
MOV32ItoM((u32)&psxRegs.pc, (u32)pc);
CALLFunc((u32)psxTestSWInts);
if (branch == 0) {
branch = 2;
iRet();
}
}
}
static void recCTC0() {
// Cop0->Rd = Rt
recMTC0();
}
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);
iFlushRegs();
MOV32ItoM((u32)&psxRegs.pc, (u32)pc);
CALLFunc((u32)psxTestSWInts);
if (branch == 0) {
branch = 2;
iRet();
}
}
//#endif
#include "iGte.h"
//
static void recHLE() {
iFlushRegs();
MOV32ItoR(EAX, (u32)psxHLEt[psxRegs.code & 0xffff]);
CALL32R(EAX);
branch = 2;
iRet();
}
//
#include "iPGXP.h"
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
};
// Trace all functions using PGXP
static void(*pgxpRecBSC[64])() = {
recSPECIAL, recREGIMM, recJ , recJAL , recBEQ , recBNE , recBLEZ, recBGTZ,
pgxpRecADDI , pgxpRecADDIU , pgxpRecSLTI, pgxpRecSLTIU, pgxpRecANDI, pgxpRecORI , pgxpRecXORI, pgxpRecLUI ,
recCOP0 , recNULL , recCOP2, recNULL , recNULL, recNULL, recNULL, recNULL,
recNULL , recNULL , recNULL, recNULL , recNULL, recNULL, recNULL, recNULL,
pgxpRecLB , pgxpRecLH , pgxpRecLWL , pgxpRecLW , pgxpRecLBU , pgxpRecLHU , pgxpRecLWR , pgxpRecNULL,
pgxpRecSB , pgxpRecSH , pgxpRecSWL , pgxpRecSW , pgxpRecNULL, pgxpRecNULL, pgxpRecSWR , pgxpRecNULL,
recNULL , recNULL , pgxpRecLWC2, recNULL , recNULL, recNULL, recNULL, recNULL,
recNULL , recNULL , pgxpRecSWC2, recHLE , recNULL, recNULL, recNULL, recNULL
};
static void(*pgxpRecSPC[64])() = {
pgxpRecSLL , pgxpRecNULL, pgxpRecSRL , pgxpRecSRA , pgxpRecSLLV , pgxpRecNULL , pgxpRecSRLV, pgxpRecSRAV,
recJR , recJALR, recNULL, recNULL, recSYSCALL, recBREAK, recNULL, recNULL,
pgxpRecMFHI, pgxpRecMTHI, pgxpRecMFLO, pgxpRecMTLO, pgxpRecNULL , pgxpRecNULL , pgxpRecNULL, pgxpRecNULL,
pgxpRecMULT, pgxpRecMULTU, pgxpRecDIV, pgxpRecDIVU, pgxpRecNULL , pgxpRecNULL , pgxpRecNULL, pgxpRecNULL,
pgxpRecADD , pgxpRecADDU, pgxpRecSUB , pgxpRecSUBU, pgxpRecAND , pgxpRecOR , pgxpRecXOR , pgxpRecNOR ,
pgxpRecNULL, pgxpRecNULL, pgxpRecSLT , pgxpRecSLTU, pgxpRecNULL , pgxpRecNULL , pgxpRecNULL, pgxpRecNULL,
pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL , pgxpRecNULL , pgxpRecNULL, pgxpRecNULL,
pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL , pgxpRecNULL , pgxpRecNULL, pgxpRecNULL
};
static void(*pgxpRecCP0[32])() = {
pgxpRecMFC0, pgxpRecNULL, pgxpRecCFC0, pgxpRecNULL, pgxpRecMTC0, pgxpRecNULL, pgxpRecCTC0, pgxpRecNULL,
pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL,
pgxpRecRFE , pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL,
pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL
};
static void(*pgxpRecCP2BSC[32])() = {
pgxpRecMFC2, pgxpRecNULL, pgxpRecCFC2, pgxpRecNULL, pgxpRecMTC2, pgxpRecNULL, pgxpRecCTC2, pgxpRecNULL,
pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL,
pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL,
pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL, pgxpRecNULL
};
// Trace memory functions only
static void(*pgxpRecBSCMem[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,
pgxpRecLB , pgxpRecLH , pgxpRecLWL , pgxpRecLW , pgxpRecLBU , pgxpRecLHU , pgxpRecLWR , pgxpRecNULL,
pgxpRecSB , pgxpRecSH , pgxpRecSWL , pgxpRecSW , pgxpRecNULL, pgxpRecNULL, pgxpRecSWR , pgxpRecNULL,
recNULL , recNULL , pgxpRecLWC2, recNULL , recNULL, recNULL, recNULL, recNULL,
recNULL , recNULL , pgxpRecSWC2, recHLE , recNULL, recNULL, recNULL, recNULL
};
static void recRecompile() {
char *p;
char *ptr;
dump = 0;
resp = 0;
/* if x86Ptr reached the mem limit reset whole mem */
if (((u32)x86Ptr - (u32)recMem) >= (RECMEM_SIZE - 0x10000))
recReset();
x86Align(32);
ptr = x86Ptr;
PC_REC32(psxRegs.pc) = (u32)x86Ptr;
pc = psxRegs.pc;
pcold = pc;
for (count = 0; count < DYNAREC_BLOCK;) {
p = (char *)PSXM(pc);
if (p == NULL) recError();
psxRegs.code = *(u32 *)p;
/*
if ((psxRegs.code >> 26) == 0x23) { // LW
int i;
u32 code;
for (i=1;; i++) {
p = (char *)PSXM(pc+i*4);
if (p == NULL) recError();
code = *(u32 *)p;
if ((code >> 26) != 0x23 ||
_fRs_(code) != _Rs_ ||
_fImm_(code) != (_Imm_+i*4))
break;
}
if (i > 1) {
recLWBlock(i);
pc = pc + i*4; continue;
}
}
if ((psxRegs.code >> 26) == 0x2b) { // SW
int i;
u32 code;
for (i=1;; i++) {
p = (char *)PSXM(pc+i*4);
if (p == NULL) recError();
code = *(u32 *)p;
if ((code >> 26) != 0x2b ||
_fRs_(code) != _Rs_ ||
_fImm_(code) != (_Imm_+i*4))
break;
}
if (i > 1) {
recSWBlock(i);
pc = pc + i*4; continue;
}
}*/
pc += 4;
count++;
pRecBSC[psxRegs.code >> 26]();
if (branch) {
branch = 0;
if (dump) iDumpBlock(ptr);
return;
}
}
iFlushRegs();
MOV32ItoM((u32)&psxRegs.pc, pc);
iRet();
}
R3000Acpu psxRec = {
recInit,
recReset,
recExecute,
recExecuteBlock,
recClear,
recShutdown,
recSetPGXPMode
};
#endif