mirror of https://github.com/PCSX2/pcsx2.git
783 lines
28 KiB
C
783 lines
28 KiB
C
/* Pcsx2 - Pc Ps2 Emulator
|
|
* Copyright (C) 2002-2003 Pcsx2 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
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "PsxCommon.h"
|
|
//#include "PsxBios2.h"
|
|
|
|
static int branch = 0;
|
|
static int branch2 = 0;
|
|
static u32 branchPC;
|
|
|
|
// These macros are used to assemble the repassembler functions
|
|
|
|
#ifdef PSXCPU_LOG
|
|
#define debugI() \
|
|
if (Log) { \
|
|
PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc)); \
|
|
}
|
|
#else
|
|
#define debugI()
|
|
#endif
|
|
|
|
#define execI() { \
|
|
psxRegs.code = PSXMu32(psxRegs.pc); \
|
|
\
|
|
debugI(); \
|
|
psxRegs.pc+= 4; \
|
|
psxRegs.cycle++; \
|
|
\
|
|
psxBSC[psxRegs.code >> 26](); \
|
|
EEsCycle-= (psxRegs.cycle - IOPoCycle) << 3; \
|
|
IOPoCycle = psxRegs.cycle; \
|
|
}
|
|
|
|
#define doBranch(tar) { \
|
|
branch2 = branch = 1; \
|
|
branchPC = tar; \
|
|
execI(); \
|
|
branch = 0; \
|
|
psxRegs.pc = branchPC; \
|
|
\
|
|
psxBranchTest(); \
|
|
}
|
|
|
|
// Subsets
|
|
void (*psxBSC[64])();
|
|
void (*psxSPC[64])();
|
|
void (*psxREG[32])();
|
|
void (*psxCP0[32])();
|
|
void (*psxCP2[64])();
|
|
void (*psxCP2BSC[32])();
|
|
|
|
extern void bios_write();
|
|
extern void bios_printf();
|
|
|
|
typedef struct {
|
|
char name[8];
|
|
char names[64][32];
|
|
int maxn;
|
|
} irxlib;
|
|
|
|
#define IRXLIBS 14
|
|
irxlib irxlibs[32] = {
|
|
/*00*/ { { "sysmem" } ,
|
|
{ "start", "init_memory", "retonly", "return_addr_of_memsize",
|
|
"AllocSysMemory", "FreeSysMemory", "QueryMemSize", "QueryMaxFreeMemSize",
|
|
"QueryTotalFreeMemSize", "QueryBlockTopAddress", "QueryBlockSize", "retonly",
|
|
"retonly", "retonly", "Kprintf", "set_Kprintf" } ,
|
|
16 },
|
|
/*01*/ { { "loadcore" } ,
|
|
{ "start", "retonly", "retonly_", "return_LibraryEntryTable",
|
|
"FlushIcache", "FlushDcache", "RegisterLibraryEntries", "ReleaseLibraryEntries",
|
|
"findFixImports", "restoreImports", "RegisterNonAutoLinkEntries", "QueryLibraryEntryTable",
|
|
"QueryBootMode", "RegisterBootMode", "setFlag", "resetFlag",
|
|
"linkModule", "unlinkModule", "retonly_", "retonly_",
|
|
"registerFunc", "jumpA0001B34", "read_header", "load_module",
|
|
"findImageInfo" },
|
|
25 },
|
|
/*02*/ { { "excepman" } ,
|
|
{ "start", "reinit", "deinit", "getcommon",
|
|
"RegisterExceptionHandler", "RegisterPriorityExceptionHandler",
|
|
"RegisterDefaultExceptionHandler", "ReleaseExceptionHandler",
|
|
"ReleaseDefaultExceptionHandler" } ,
|
|
9 },
|
|
/*03_4*/{ { "intrman" } ,
|
|
{ "start", "return_0", "deinit", "call3",
|
|
"RegisterIntrHandler", "ReleaseIntrHandler", "EnableIntr", "DisableIntr",
|
|
"CpuDisableIntr", "CpuEnableIntr", "syscall04", "syscall08",
|
|
"resetICTRL", "setICTRL", "syscall0C", "call15",
|
|
"call16", "CpuSuspendIntr", "CpuResumeIntr", "CpuSuspendIntr",
|
|
"CpuResumeIntr", "syscall10", "syscall14", "QueryIntrContext",
|
|
"QueryIntrStack", "iCatchMultiIntr", "retonly", "call27",
|
|
"set_h1", "reset_h1", "set_h2", "reset_h2" } ,
|
|
0x20 },
|
|
/*05*/ { { "ssbusc" } ,
|
|
{ "start", "retonly", "return_0", "retonly",
|
|
"setTable1", "getTable1", "setTable2", "getTable2",
|
|
"setCOM_DELAY_1st", "getCOM_DELAY_1st", "setCOM_DELAY_2nd", "getCOM_DELAY_2nd",
|
|
"setCOM_DELAY_3rd", "getCOM_DELAY_3rd", "setCOM_DELAY_4th", "getCOM_DELAY_4th",
|
|
"setCOM_DELAY", "getCOM_DELAY" } ,
|
|
18 },
|
|
/*06*/ { { "dmacman" } ,
|
|
{ "start", "retonly", "deinit", "retonly",
|
|
"SetD_MADR", "GetD_MADR", "SetD_BCR", "GetD_BCR",
|
|
"SetD_CHCR", "GetD_CHCR", "SetD_TADR", "GetD_TADR",
|
|
"Set_4_9_A", "Get_4_9_A", "SetDPCR", "GetDPCR",
|
|
"SetDPCR2", "GetDPCR2", "SetDPCR3", "GetDPCR3",
|
|
"SetDICR", "GetDICR", "SetDICR2", "GetDICR2",
|
|
"SetBF80157C", "GetBF80157C", "SetBF801578", "GetBF801578",
|
|
"SetDMA", "SetDMA_chainedSPU_SIF0", "SetDMA_SIF0", "SetDMA_SIF1",
|
|
"StartTransfer", "SetVal", "EnableDMAch", "DisableDMAch" } ,
|
|
36 },
|
|
/*07_8*/{ { "timrman" } ,
|
|
{ "start", "retonly", "retonly", "call3",
|
|
"AllocHardTimer", "ReferHardTimer", "FreeHardTimer", "SetTimerMode",
|
|
"GetTimerStatus", "SetTimerCounter", "GetTimerCounter", "SetTimerCompare",
|
|
"GetTimerCompare", "SetHoldMode", "GetHoldMode", "GetHoldReg",
|
|
"GetHardTimerIntrCode" } ,
|
|
17 },
|
|
/*09*/ { { "sysclib" } ,
|
|
{ "start", "reinit", "retonly", "retonly",
|
|
"setjmp", "longjmp", "toupper", "tolower",
|
|
"look_ctype_table", "get_ctype_table", "memchr", "memcmp",
|
|
"memcpy", "memmove", "memset", "bcmp",
|
|
"bcopy", "bzero", "prnt", "sprintf",
|
|
"strcat", "strchr", "strcmp", "strcpy",
|
|
"strcspn", "index", "rindex", "strlen",
|
|
"strncat", "strncmp", "strncpy", "strpbrk",
|
|
"strrchr", "strspn", "strstr", "strtok",
|
|
"strtol", "atob", "strtoul", "wmemcopy",
|
|
"wmemset", "vsprintf" } ,
|
|
0x2b },
|
|
/*0A*/ { { "heaplib" } ,
|
|
{ "start", "retonly", "retonly", "retonly",
|
|
"CreateHeap", "DestroyHeap", "HeapMalloc", "HeapFree",
|
|
"HeapSize", "retonly", "retonly", "call11",
|
|
"call12", "call13", "call14", "call15",
|
|
"retonly", "retonly" } ,
|
|
18 },
|
|
/*13*/ { { "stdio" } ,
|
|
{ "start", "unknown", "unknown", "unknown",
|
|
"printf" } ,
|
|
5 },
|
|
/*14*/ { { "sifman" } ,
|
|
{ "start", "retonly", "deinit", "retonly",
|
|
"sceSif2Init", "sceSifInit", "sceSifSetDChain", "sceSifSetDma",
|
|
"sceSifDmaStat", "sceSifSend", "sceSifSendSync", "sceSifIsSending",
|
|
"sceSifSetSIF0DMA", "sceSifSendSync0", "sceSifIsSending0", "sceSifSetSIF1DMA",
|
|
"sceSifSendSync1", "sceSifIsSending1", "sceSifSetSIF2DMA", "sceSifSendSync2",
|
|
"sceSifIsSending2", "getEEIOPflags", "setEEIOPflags", "getIOPEEflags",
|
|
"setIOPEEflags", "getEErcvaddr", "getIOPrcvaddr", "setIOPrcvaddr",
|
|
"call28", "sceSifCheckInit", "setSif0CB", "resetSif0CB",
|
|
"retonly", "retonly", "retonly", "retonly" } ,
|
|
36 },
|
|
/*16*/ { { "sifcmd" } ,
|
|
{ "start", "retonly", "deinit", "retonly",
|
|
"sceSifInitCmd", "sceSifExitCmd", "sceSifGetSreg", "sceSifSetSreg",
|
|
"sceSifSetCmdBuffer", "sceSifSetSysCmdBuffer",
|
|
"sceSifAddCmdHandler", "sceSifRemoveCmdHandler",
|
|
"sceSifSendCmd", "isceSifSendCmd", "sceSifInitRpc", "sceSifBindRpc",
|
|
"sceSifCallRpc", "sceSifRegisterRpc",
|
|
"sceSifCheckStatRpc", "sceSifSetRpcQueue",
|
|
"sceSifGetNextRequest", "sceSifExecRequest",
|
|
"sceSifRpcLoop", "sceSifGetOtherData",
|
|
"sceSifRemoveRpc", "sceSifRemoveRpcQueue",
|
|
"setSif1CB", "resetSif1CB",
|
|
"retonly", "retonly", "retonly", "retonly" } ,
|
|
32 },
|
|
/*19*/ { { "cdvdman" } ,
|
|
{ "start", "retonly", "retonly", "retonly",
|
|
"sceCdInit", "sceCdStandby", "sceCdRead", "sceCdSeek",
|
|
"sceCdGetError", "sceCdGetToc", "sceCdSearchFile", "sceCdSync",
|
|
"sceCdGetDiskType", "sceCdDiskReady", "sceCdTrayReq", "sceCdStop",
|
|
"sceCdPosToInt", "sceCdIntToPos", "retonly", "call19",
|
|
"sceDvdRead", "sceCdCheckCmd", "_sceCdRI", "sceCdWriteILinkID",
|
|
"sceCdReadClock", "sceCdWriteRTC", "sceCdReadNVM", "sceCdWriteNVM",
|
|
"sceCdStatus", "sceCdApplySCmd", "setHDmode", "sceCdOpenConfig",
|
|
"sceCdCloseConfig", "sceCdReadConfig", "sceCdWriteConfig", "sceCdReadKey",
|
|
"sceCdDecSet", "sceCdCallback", "sceCdPause", "sceCdBreak",
|
|
"call40", "sceCdReadConsoleID", "sceCdWriteConsoleID", "sceCdGetMecaconVersion",
|
|
"sceCdGetReadPos", "AudioDigitalOut", "sceCdNop", "_sceGetFsvRbuf",
|
|
"_sceCdstm0Cb", "_sceCdstm1Cb", "_sceCdSC", "_sceCdRC",
|
|
"sceCdForbidDVDP", "sceCdReadSubQ", "sceCdApplyNCmd", "AutoAdjustCtrl",
|
|
"sceCdStInit", "sceCdStRead", "sceCdStSeek", "sceCdStStart",
|
|
"sceCdStStat", "sceCdStStop" } ,
|
|
62 },
|
|
/*??*/ { { "sio2man" } ,
|
|
{ "start", "retonly", "deinit", "retonly",
|
|
"set8268_ctrl", "get8268_ctrl", "get826C_recv1", "call7_send1",
|
|
"call8_send1", "call9_send2", "call10_send2", "get8270_recv2",
|
|
"call12_set_params", "call13_get_params", "get8274_recv3", "set8278",
|
|
"get8278", "set827C", "get827C", "set8260_datain",
|
|
"get8264_dataout", "set8280_intr", "get8280_intr", "signalExchange1",
|
|
"signalExchange2", "packetExchange" } ,
|
|
26 }
|
|
};
|
|
|
|
#define Ra0 ((char*)PSXM(psxRegs.GPR.n.a0))
|
|
#define Ra1 ((char*)PSXM(psxRegs.GPR.n.a1))
|
|
#define Ra2 ((char*)PSXM(psxRegs.GPR.n.a2))
|
|
#define Ra3 ((char*)PSXM(psxRegs.GPR.n.a3))
|
|
|
|
char* intrname[]={
|
|
"INT_VBLANK", "INT_GM", "INT_CDROM", "INT_DMA", //00
|
|
"INT_RTC0", "INT_RTC1", "INT_RTC2", "INT_SIO0", //04
|
|
"INT_SIO1", "INT_SPU", "INT_PIO", "INT_EVBLANK", //08
|
|
"INT_DVD", "INT_PCMCIA", "INT_RTC3", "INT_RTC4", //0C
|
|
"INT_RTC5", "INT_SIO2", "INT_HTR0", "INT_HTR1", //10
|
|
"INT_HTR2", "INT_HTR3", "INT_USB", "INT_EXTR", //14
|
|
"INT_FWRE", "INT_FDMA", "INT_1A", "INT_1B", //18
|
|
"INT_1C", "INT_1D", "INT_1E", "INT_1F", //1C
|
|
"INT_dmaMDECi", "INT_dmaMDECo", "INT_dmaGPU", "INT_dmaCD", //20
|
|
"INT_dmaSPU", "INT_dmaPIO", "INT_dmaOTC", "INT_dmaBERR", //24
|
|
"INT_dmaSPU2", "INT_dma8", "INT_dmaSIF0", "INT_dmaSIF1", //28
|
|
"INT_dmaSIO2i", "INT_dmaSIO2o", "INT_2E", "INT_2F", //2C
|
|
"INT_30", "INT_31", "INT_32", "INT_33", //30
|
|
"INT_34", "INT_35", "INT_36", "INT_37", //34
|
|
"INT_38", "INT_39", "INT_3A", "INT_3B", //38
|
|
"INT_3C", "INT_3D", "INT_3E", "INT_3F", //3C
|
|
"INT_MAX" //40
|
|
};
|
|
|
|
void zeroEx() {
|
|
u32 pc;
|
|
u32 code;
|
|
char *lib;
|
|
char *fname = NULL;
|
|
int i;
|
|
|
|
if (!Config.PsxOut) return;
|
|
|
|
pc = psxRegs.pc;
|
|
while (PSXMu32(pc) != 0x41e00000) pc-=4;
|
|
|
|
lib = (char*)PSXM(pc+12);
|
|
code = PSXMu32(psxRegs.pc - 4) & 0xffff;
|
|
|
|
for (i=0; i<IRXLIBS; i++) {
|
|
if (!strncmp(lib, irxlibs[i].name, 8)) {
|
|
if (code >= (u32)irxlibs[i].maxn) break;
|
|
|
|
fname = irxlibs[i].names[code]; break;
|
|
}
|
|
}
|
|
|
|
#ifdef PSXBIOS_LOG
|
|
{char libz[9]; memcpy(libz, lib, 8); libz[8]=0;
|
|
PSXBIOS_LOG("%s: %s (%x)"
|
|
" (%x, %x, %x, %x)" //comment this line to disable param showing
|
|
, libz, fname == NULL ? "unknown" : fname, code,
|
|
psxRegs.GPR.n.a0, psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3);
|
|
}
|
|
#endif
|
|
|
|
// Log=0;
|
|
// if (!strcmp(lib, "intrman") && code == 0x11) Log=1;
|
|
// if (!strcmp(lib, "sifman") && code == 0x5) Log=1;
|
|
// if (!strcmp(lib, "sifcmd") && code == 0x4) Log=1;
|
|
// if (!strcmp(lib, "thbase") && code == 0x6) Log=1;
|
|
/*
|
|
if (!strcmp(lib, "sifcmd") && code == 0xe) {
|
|
branchPC = psxRegs.GPR.n.ra;
|
|
psxRegs.GPR.n.v0 = 0;
|
|
return;
|
|
}
|
|
*/
|
|
if (!strncmp(lib, "ioman", 5) && code == 7) {
|
|
if (psxRegs.GPR.n.a0 == 1) {
|
|
pc = psxRegs.pc;
|
|
bios_write();
|
|
psxRegs.pc = pc;
|
|
}
|
|
}
|
|
|
|
if (!strncmp(lib, "sysmem", 6) && code == 0xe) {
|
|
bios_printf();
|
|
psxRegs.pc = psxRegs.GPR.n.ra;
|
|
}
|
|
|
|
if (!strncmp(lib, "loadcore", 8) && code == 6) {
|
|
SysPrintf("loadcore RegisterLibraryEntries (%x): %8.8s\n", psxRegs.pc, PSXM(psxRegs.GPR.n.a0+12));
|
|
}
|
|
|
|
if (!strncmp(lib, "intrman", 7) && code == 4) {
|
|
SysPrintf("intrman RegisterIntrHandler (%x): intr %s, handler %x\n", psxRegs.pc, intrname[psxRegs.GPR.n.a0], psxRegs.GPR.n.a2);
|
|
}
|
|
|
|
if (!strncmp(lib, "sifcmd", 6) && code == 17) {
|
|
SysPrintf("sifcmd sceSifRegisterRpc (%x): rpc_id %x\n", psxRegs.pc, psxRegs.GPR.n.a1);
|
|
}
|
|
|
|
#ifdef PSXBIOS_LOG
|
|
if (!strncmp(lib, "sysclib", 8)) {
|
|
switch (code) {
|
|
case 0x16: // strcmp
|
|
if (varLog & 0x00800000) EMU_LOG(" \"%s\": \"%s\"", Ra0, Ra1);
|
|
break;
|
|
|
|
case 0x1e: // strncpy
|
|
if (varLog & 0x00800000) EMU_LOG(" \"%s\"", Ra1);
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef PSXBIOS_LOG
|
|
if (varLog & 0x00800000) EMU_LOG("\n");
|
|
#endif
|
|
|
|
/* psxRegs.pc = branchPC;
|
|
pc = psxRegs.GPR.n.ra;
|
|
while (psxRegs.pc != pc) psxCpu->ExecuteBlock();
|
|
|
|
#ifdef PSXBIOS_LOG
|
|
PSXBIOS_LOG("%s: %s (%x) END\n", lib, fname == NULL ? "unknown" : fname, code);
|
|
#endif*/
|
|
}
|
|
/*/==========================================CALL LOG
|
|
char* getName(char *file, u32 addr){
|
|
FILE *f; u32 a;
|
|
static char name[100];
|
|
|
|
f=fopen(file, "r");
|
|
if (!f)
|
|
name[0]=0;
|
|
else{
|
|
while (!feof(f)){
|
|
fscanf(f, "%08X %s\r\n", &a, name);
|
|
if (a==addr)break;
|
|
}
|
|
fclose(f);
|
|
}
|
|
return name;
|
|
}
|
|
|
|
void spyFunctions(){
|
|
register irxImageInfo *iii;
|
|
if (psxRegs.pc >= 0x200000) return;
|
|
for (iii=(irxImageInfo*)PSXM(0x800); iii && iii->text_size;
|
|
iii=iii->next ? (irxImageInfo*)PSXM(iii->next) : NULL)
|
|
if (iii->vaddr<=psxRegs.pc && psxRegs.pc<iii->vaddr+iii->text_size+iii->data_size+iii->bss_size){
|
|
if (strcmp("secrman_for_cex", PSXM(iii->name))==0){
|
|
char *name=getName("secrman.fun", psxRegs.pc-iii->vaddr);
|
|
if (strncmp("__push_params", name, 13)==0){
|
|
PAD_LOG(PSXM(psxRegs.GPR.n.a0), psxRegs.GPR.n.a1, psxRegs.GPR.n.a2, psxRegs.GPR.n.a3);
|
|
}else{
|
|
PAD_LOG("secrman: %s (ra=%06X cycle=%d)\n", name, psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}}else
|
|
if (strcmp("mcman", PSXM(iii->name))==0){
|
|
PAD_LOG("mcman: %s (ra=%06X cycle=%d)\n", getName("mcman.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}else
|
|
if (strcmp("padman", PSXM(iii->name))==0){
|
|
PAD_LOG("padman: %s (ra=%06X cycle=%d)\n", getName("padman.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}else
|
|
if (strcmp("sio2man", PSXM(iii->name))==0){
|
|
PAD_LOG("sio2man: %s (ra=%06X cycle=%d)\n", getName("sio2man.fun", psxRegs.pc-iii->vaddr), psxRegs.GPR.n.ra-iii->vaddr, psxRegs.cycle);}
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
/*********************************************************
|
|
* Arithmetic with immediate operand *
|
|
* Format: OP rt, rs, immediate *
|
|
*********************************************************/
|
|
void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
|
|
void psxADDIU() { if (!_Rt_) { zeroEx(); return; } _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
|
|
void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
|
|
void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
|
|
void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
|
|
void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
|
|
void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < _ImmU_; } // Rt = Rs < Im (Unsigned)
|
|
|
|
/*********************************************************
|
|
* Register arithmetic *
|
|
* Format: OP rd, rs, rt *
|
|
*********************************************************/
|
|
void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
|
|
void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
|
|
void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
|
|
void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
|
|
void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
|
|
void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
|
|
void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
|
|
void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
|
|
void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
|
|
void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
|
|
|
|
/*********************************************************
|
|
* Register mult/div & Register trap logic *
|
|
* Format: OP rs, rt *
|
|
*********************************************************/
|
|
void psxDIV() {
|
|
if (_rRt_ != 0) {
|
|
_rLo_ = _i32(_rRs_) / _i32(_rRt_);
|
|
_rHi_ = _i32(_rRs_) % _i32(_rRt_);
|
|
}
|
|
}
|
|
|
|
void psxDIVU() {
|
|
if (_rRt_ != 0) {
|
|
_rLo_ = _rRs_ / _rRt_;
|
|
_rHi_ = _rRs_ % _rRt_;
|
|
}
|
|
}
|
|
|
|
void psxMULT() {
|
|
u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
|
|
|
|
psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
|
|
psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
|
|
}
|
|
|
|
void psxMULTU() {
|
|
u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
|
|
|
|
psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
|
|
psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
|
|
}
|
|
|
|
/*********************************************************
|
|
* Register branch logic *
|
|
* Format: OP rs, offset *
|
|
*********************************************************/
|
|
#define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
|
|
#define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
|
|
|
|
void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
|
|
void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
|
|
void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
|
|
void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
|
|
void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
|
|
void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
|
|
|
|
/*********************************************************
|
|
* Shift arithmetic with constant shift *
|
|
* Format: OP rd, rt, sa *
|
|
*********************************************************/
|
|
void psxSLL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
|
|
void psxSRA() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
|
|
void psxSRL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
|
|
|
|
/*********************************************************
|
|
* Shift arithmetic with variant register shift *
|
|
* Format: OP rd, rt, rs *
|
|
*********************************************************/
|
|
void psxSLLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
|
|
void psxSRAV() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
|
|
void psxSRLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
|
|
|
|
/*********************************************************
|
|
* Load higher 16 bits of the first word in GPR with imm *
|
|
* Format: OP rt, immediate *
|
|
*********************************************************/
|
|
void psxLUI() { if (!_Rt_) return; _rRt_ = psxRegs.code << 16; } // Upper halfword of Rt = Im
|
|
|
|
/*********************************************************
|
|
* Move from HI/LO to GPR *
|
|
* Format: OP rd *
|
|
*********************************************************/
|
|
void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
|
|
void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
|
|
|
|
/*********************************************************
|
|
* Move to GPR to HI/LO & Register jump *
|
|
* Format: OP rs *
|
|
*********************************************************/
|
|
void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
|
|
void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
|
|
|
|
/*********************************************************
|
|
* Special purpose instructions *
|
|
* Format: OP *
|
|
*********************************************************/
|
|
void psxBREAK() {
|
|
// Break exception - psx rom doens't handles this
|
|
psxRegs.pc -= 4;
|
|
psxException(0x24, branch);
|
|
}
|
|
|
|
void psxSYSCALL() {
|
|
psxRegs.pc -= 4;
|
|
psxException(0x20, branch);
|
|
|
|
}
|
|
|
|
void psxRFE() {
|
|
// SysPrintf("RFE\n");
|
|
psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
|
|
((psxRegs.CP0.n.Status & 0x3c) >> 2);
|
|
// Log=0;
|
|
}
|
|
|
|
/*********************************************************
|
|
* Register branch logic *
|
|
* Format: OP rs, rt, offset *
|
|
*********************************************************/
|
|
#define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
|
|
|
|
void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
|
|
void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
|
|
|
|
/*********************************************************
|
|
* Jump to target *
|
|
* Format: OP target *
|
|
*********************************************************/
|
|
void psxJ() { doBranch(_JumpTarget_); }
|
|
void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); /*spyFunctions();*/ }
|
|
|
|
/*********************************************************
|
|
* Register jump *
|
|
* Format: OP rs, rd *
|
|
*********************************************************/
|
|
void psxJR() { doBranch(_u32(_rRs_)); }
|
|
void psxJALR() { if (_Rd_) { _SetLink(_Rd_); } doBranch(_u32(_rRs_)); }
|
|
|
|
/*********************************************************
|
|
* Load and store for GPR *
|
|
* Format: OP rt, offset(base) *
|
|
*********************************************************/
|
|
|
|
#define _oB_ (_u32(_rRs_) + _Imm_)
|
|
|
|
void psxLB() {
|
|
if (_Rt_) {
|
|
_rRt_ = (s8 )psxMemRead8(_oB_);
|
|
} else {
|
|
psxMemRead8(_oB_);
|
|
}
|
|
}
|
|
|
|
void psxLBU() {
|
|
if (_Rt_) {
|
|
_rRt_ = psxMemRead8(_oB_);
|
|
} else {
|
|
psxMemRead8(_oB_);
|
|
}
|
|
}
|
|
|
|
void psxLH() {
|
|
if (_Rt_) {
|
|
_rRt_ = (s16)psxMemRead16(_oB_);
|
|
} else {
|
|
psxMemRead16(_oB_);
|
|
}
|
|
}
|
|
|
|
void psxLHU() {
|
|
if (_Rt_) {
|
|
_rRt_ = psxMemRead16(_oB_);
|
|
} else {
|
|
psxMemRead16(_oB_);
|
|
}
|
|
}
|
|
|
|
void psxLW() {
|
|
if (_Rt_) {
|
|
_rRt_ = psxMemRead32(_oB_);
|
|
} else {
|
|
psxMemRead32(_oB_);
|
|
}
|
|
}
|
|
|
|
void psxLWL() {
|
|
u32 shift = (_oB_ & 3) << 3;
|
|
u32 mem = psxMemRead32(_oB_ & 0xfffffffc);
|
|
|
|
if (!_Rt_) return;
|
|
_rRt_ = ( _u32(_rRt_) & (0x00ffffff >> shift) ) |
|
|
( mem << (24 - shift) );
|
|
|
|
/*
|
|
Mem = 1234. Reg = abcd
|
|
|
|
0 4bcd (mem << 24) | (reg & 0x00ffffff)
|
|
1 34cd (mem << 16) | (reg & 0x0000ffff)
|
|
2 234d (mem << 8) | (reg & 0x000000ff)
|
|
3 1234 (mem ) | (reg & 0x00000000)
|
|
|
|
*/
|
|
}
|
|
|
|
void psxLWR() {
|
|
u32 shift = (_oB_ & 3) << 3;
|
|
u32 mem = psxMemRead32(_oB_ & 0xfffffffc);
|
|
|
|
if (!_Rt_) return;
|
|
_rRt_ = ( _u32(_rRt_) & (0xffffff00 << (24 - shift)) ) |
|
|
( mem >> shift );
|
|
|
|
/*
|
|
Mem = 1234. Reg = abcd
|
|
|
|
0 1234 (mem ) | (reg & 0x00000000)
|
|
1 a123 (mem >> 8) | (reg & 0xff000000)
|
|
2 ab12 (mem >> 16) | (reg & 0xffff0000)
|
|
3 abc1 (mem >> 24) | (reg & 0xffffff00)
|
|
|
|
*/
|
|
}
|
|
|
|
void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); }
|
|
void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); }
|
|
void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); }
|
|
|
|
void psxSWL() {
|
|
u32 shift = (_oB_ & 3) << 3;
|
|
u32 mem = psxMemRead32(_oB_ & 0xfffffffc);
|
|
|
|
psxMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) >> (24 - shift) ) ) |
|
|
( mem & (0xffffff00 << shift) ));
|
|
/*
|
|
Mem = 1234. Reg = abcd
|
|
|
|
0 123a (reg >> 24) | (mem & 0xffffff00)
|
|
1 12ab (reg >> 16) | (mem & 0xffff0000)
|
|
2 1abc (reg >> 8) | (mem & 0xff000000)
|
|
3 abcd (reg ) | (mem & 0x00000000)
|
|
|
|
*/
|
|
}
|
|
|
|
void psxSWR() {
|
|
u32 shift = (_oB_ & 3) << 3;
|
|
u32 mem = psxMemRead32(_oB_ & 0xfffffffc);
|
|
|
|
psxMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) << shift ) |
|
|
(mem & (0x00ffffff >> (24 - shift)) ) ) );
|
|
/*
|
|
Mem = 1234. Reg = abcd
|
|
|
|
0 abcd (reg ) | (mem & 0x00000000)
|
|
1 bcd4 (reg << 8) | (mem & 0x000000ff)
|
|
2 cd34 (reg << 16) | (mem & 0x0000ffff)
|
|
3 d234 (reg << 24) | (mem & 0x00ffffff)
|
|
|
|
*/
|
|
}
|
|
|
|
/*********************************************************
|
|
* Moves between GPR and COPx *
|
|
* Format: OP rt, fs *
|
|
*********************************************************/
|
|
void psxMFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; }
|
|
void psxCFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; }
|
|
|
|
void psxMTC0() { _rFs_ = _u32(_rRt_); }
|
|
void psxCTC0() { _rFs_ = _u32(_rRt_); }
|
|
|
|
/*********************************************************
|
|
* Unknow instruction (would generate an exception) *
|
|
* Format: ? *
|
|
*********************************************************/
|
|
void psxNULL() {
|
|
SysPrintf("psx: Unimplemented op %x\n", psxRegs.code);
|
|
}
|
|
|
|
void psxSPECIAL() {
|
|
psxSPC[_Funct_]();
|
|
}
|
|
|
|
void psxREGIMM() {
|
|
psxREG[_Rt_]();
|
|
}
|
|
|
|
void psxCOP0() {
|
|
psxCP0[_Rs_]();
|
|
}
|
|
|
|
void psxCOP2() {
|
|
psxCP2[_Funct_]();
|
|
}
|
|
|
|
void psxBASIC() {
|
|
psxCP2BSC[_Rs_]();
|
|
}
|
|
|
|
|
|
void (*psxBSC[64])() = {
|
|
psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
|
|
psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
|
|
psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
|
|
psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
|
|
psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
|
|
psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
|
|
psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
|
|
psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL
|
|
};
|
|
|
|
|
|
void (*psxSPC[64])() = {
|
|
psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
|
|
psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
|
|
psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
|
|
psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
|
|
psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
|
|
psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
|
|
psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
|
|
psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
|
|
};
|
|
|
|
void (*psxREG[32])() = {
|
|
psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
|
|
psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
|
|
psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
|
|
psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
|
|
};
|
|
|
|
void (*psxCP0[32])() = {
|
|
psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
|
|
psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
|
|
psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
|
|
psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
|
|
};
|
|
|
|
void (*psxCP2[64])() = {
|
|
psxBASIC, psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL, psxNULL, // 00
|
|
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 08
|
|
psxNULL , psxNULL, psxNULL, psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 10
|
|
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 18
|
|
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
|
|
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, // 28
|
|
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
|
|
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL // 38
|
|
};
|
|
|
|
void (*psxCP2BSC[32])() = {
|
|
psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
|
|
psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
|
|
psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
|
|
psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
|
|
};
|
|
|
|
|
|
///////////////////////////////////////////
|
|
|
|
static int intInit() {
|
|
return 0;
|
|
}
|
|
|
|
static void intReset() {
|
|
}
|
|
|
|
static void intExecute() {
|
|
for (;;) execI();
|
|
}
|
|
|
|
static void intExecuteBlock() {
|
|
while (EEsCycle > 0){
|
|
branch2 = 0;
|
|
while (!branch2)
|
|
execI();
|
|
}
|
|
}
|
|
|
|
static void intClear(u32 Addr, u32 Size) {
|
|
}
|
|
|
|
static void intShutdown() {
|
|
}
|
|
|
|
R3000Acpu psxInt = {
|
|
intInit,
|
|
intReset,
|
|
intExecute,
|
|
intExecuteBlock,
|
|
intClear,
|
|
intShutdown
|
|
};
|