/* 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 #include #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= (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.pcvaddr+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 };