void r4300i_LL (void) { uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset; uintptr_t ll = 0; if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } if (Opcode.rt == 0) { return; } if (!r4300i_LW_VAddr(Address,&GPR[Opcode.rt].UW[0])) { //if (ShowTLBMisses) { DisplayError("LW TLB: %X",Address); //} TLB_READ_EXCEPTION(Address); } else { GPR[Opcode.rt].DW = GPR[Opcode.rt].W[0]; } LLBit = 1; LLAddr = Address; ll = LLAddr; TranslateVaddr(&ll); LLAddr = ll; }
void ExecuteInterpreterOpCode (usf_state_t * state) { if (*state->WaitMode) state->Timers->Timer = -1; if (!r4300i_LW_VAddr(state, state->PROGRAM_COUNTER, &state->Opcode.u.Hex)) { DoTLBMiss(state, state->NextInstruction == JUMP,state->PROGRAM_COUNTER); state->NextInstruction = NORMAL; return; } #ifdef DEBUG_INFO { char opcode[256]; char arguments[256]; r4300_decode_op(state->Opcode.u.Hex, opcode, arguments, state->PROGRAM_COUNTER); fprintf(state->debug_log, "%08x: %-16s %s\n", state->PROGRAM_COUNTER, opcode, arguments); } #endif COUNT_REGISTER += 2; state->Timers->Timer -= 2; RANDOM_REGISTER -= 1; if ((int32_t)RANDOM_REGISTER < (int32_t)WIRED_REGISTER) { RANDOM_REGISTER = 31; } R4300i_Opcode[ state->Opcode.u.b.op ](state); if (state->GPR[0].DW != 0) { state->GPR[0].DW = 0; } switch (state->NextInstruction) { case NORMAL: state->PROGRAM_COUNTER += 4; break; case DELAY_SLOT: state->NextInstruction = JUMP; state->PROGRAM_COUNTER += 4; break; case JUMP: if ( #ifdef DEBUG_INFO 0 && #endif state->cpu_hle_entry_count && DoCPUHLE(state, state->JumpToLocation)) { state->PROGRAM_COUNTER = state->GPR[31].UW[0]; state->NextInstruction = NORMAL; } else { state->PROGRAM_COUNTER = state->JumpToLocation; state->NextInstruction = NORMAL; } if ((int32_t)state->Timers->Timer < 0) { TimerDone(state); } if (state->CPU_Action->DoSomething) { DoSomething(state); } } }
void _fastcall r4300i_LWC1 (void) { DWORD Address = GPR[Opcode.base].UW[0] + (DWORD)((short)Opcode.offset); TEST_COP1_USABLE_EXCEPTION if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,TRUE); } if (!r4300i_LW_VAddr(Address,&*(DWORD *)FPRFloatLocation[Opcode.ft])) { if (ShowTLBMisses) { DisplayError("LWC1 TLB: %X",Address); } TLB_READ_EXCEPTION(Address); } }
void _fastcall r4300i_LWU (void) { DWORD Address = GPR[Opcode.base].UW[0] + (short)Opcode.offset; if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,TRUE); } if (Opcode.rt == 0) { return; } if (!r4300i_LW_VAddr(Address,&GPR[Opcode.rt].UW[0])) { if (ShowTLBMisses) { DisplayError("LWU TLB: %X",Address); } TLB_READ_EXCEPTION(Address); } else { GPR[Opcode.rt].UDW = GPR[Opcode.rt].UW[0]; } }
void _fastcall r4300i_LWR (void) { DWORD Offset, Address, Value; Address = GPR[Opcode.base].UW[0] + (short)Opcode.offset; Offset = Address & 3; if (!r4300i_LW_VAddr((Address & ~3),&Value)) { DisplayError("LDL TLB: %X",Address); return; } GPR[Opcode.rt].DW = (int)(GPR[Opcode.rt].W[0] & LWR_MASK[Offset]); GPR[Opcode.rt].DW += (int)(Value >> LWR_SHIFT[Offset]); }
void r4300i_LWL (void) { u32 Offset, Address, Value; Address = GPR[Opcode.base].UW[0] + (short)Opcode.offset; Offset = Address & 3; if (!r4300i_LW_VAddr((Address & ~3),&Value)) { //DisplayError("LDL TLB: %X",Address); return; } GPR[Opcode.rt].DW = (int)(GPR[Opcode.rt].W[0] & LWL_MASK[Offset]); GPR[Opcode.rt].DW += (int)(Value << LWL_SHIFT[Offset]); }
void r4300i_LWR (void) { uint32_t Offset, Address, Value; Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset; Offset = Address & 3; if (!r4300i_LW_VAddr((Address & ~3),&Value)) { return; } GPR[Opcode.rt].DW = (int32_t)(GPR[Opcode.rt].W[0] & LWR_MASK[Offset]); GPR[Opcode.rt].DW += (int32_t)(Value >> LWR_SHIFT[Offset]); }
void _fastcall r4300i_LWL (void) { DWORD Offset, Address, Value; Address = GPR[Opcode.base].UW[0] + (short)Opcode.offset; Offset = Address & 3; if (!r4300i_LW_VAddr((Address & ~3),&Value)) { #ifndef EXTERNAL_RELEASE DisplayError("LDL TLB: %X",Address); #endif return; } GPR[Opcode.rt].DW = (int)(GPR[Opcode.rt].W[0] & LWL_MASK[Offset]); GPR[Opcode.rt].DW += (int)(Value << LWL_SHIFT[Offset]); }
void r4300i_LWC1 (void) { uint32_t Address = GPR[Opcode.base].UW[0] + (uint32_t)((int16_t)Opcode.offset); TEST_COP1_USABLE_EXCEPTION if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } if (!r4300i_LW_VAddr(Address,&*(uint32_t *)FPRFloatLocation[Opcode.ft])) { //if (ShowTLBMisses) { DisplayError("LWC1 TLB: %X",Address); //} TLB_READ_EXCEPTION(Address); } }
void _fastcall r4300i_SWR (void) { DWORD Offset, Address, Value; Address = GPR[Opcode.base].UW[0] + (short)Opcode.offset; Offset = Address & 3; if (!r4300i_LW_VAddr((Address & ~3),&Value)) { DisplayError("SWL TLB: %X",Address); return; } Value &= SWR_MASK[Offset]; Value += GPR[Opcode.rt].UW[0] << SWR_SHIFT[Offset]; if (!r4300i_SW_VAddr((Address & ~0x03),Value)) { DisplayError("SWL TLB: %X",Address); } }
void r4300i_LL (void) { u32 Address = GPR[Opcode.base].UW[0] + (short)Opcode.offset; if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,TRUE); } if (Opcode.rt == 0) { return; } if (!r4300i_LW_VAddr(Address,&GPR[Opcode.rt].UW[0])) { if (ShowTLBMisses) { //DisplayError("LW TLB: %X",Address); } TLB_READ_EXCEPTION(Address); } else { GPR[Opcode.rt].DW = GPR[Opcode.rt].W[0]; } LLBit = 1; LLAddr = Address; TranslateVaddr(&LLAddr); }
void r4300i_SWL (void) { s32 Offset; u32 Address, Value; Address = GPR[Opcode.base].UW[0] + (short)Opcode.offset; Offset = Address & 3; if (!r4300i_LW_VAddr((Address & ~3),&Value)) { //DisplayError("SWL TLB: %X",Address); return; } Value &= SWL_MASK[Offset]; Value += GPR[Opcode.rt].UW[0] >> SWL_SHIFT[Offset]; if (!r4300i_SW_VAddr((Address & ~0x03),Value)) { //DisplayError("SWL TLB: %X",Address); } }
void r4300i_SWR (void) { uint32_t Offset, Address, Value; Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset; Offset = Address & 3; if (!r4300i_LW_VAddr((Address & ~3),&Value)) { return; } Value &= SWR_MASK[Offset]; Value += GPR[Opcode.rt].UW[0] << SWR_SHIFT[Offset]; if (!r4300i_SW_VAddr((Address & ~0x03),Value)) { } }
void ExecuteInterpreterOpCode (usf_state_t * state) { if (*state->WaitMode) state->Timers->Timer = -1; if (!r4300i_LW_VAddr(state, state->PROGRAM_COUNTER, &state->Opcode.u.Hex)) { DoTLBMiss(state, state->NextInstruction == JUMP,state->PROGRAM_COUNTER); state->NextInstruction = NORMAL; return; } COUNT_REGISTER += 2; state->Timers->Timer -= 2; RANDOM_REGISTER -= 1; if ((int32_t)RANDOM_REGISTER < (int32_t)WIRED_REGISTER) { RANDOM_REGISTER = 31; } R4300i_Opcode[ state->Opcode.u.b.op ](state); if (state->GPR[0].DW != 0) { state->GPR[0].DW = 0; } switch (state->NextInstruction) { case NORMAL: state->PROGRAM_COUNTER += 4; break; case DELAY_SLOT: state->NextInstruction = JUMP; state->PROGRAM_COUNTER += 4; break; case JUMP: state->PROGRAM_COUNTER = state->JumpToLocation; state->NextInstruction = NORMAL; if ((int32_t)state->Timers->Timer < 0) { TimerDone(state); } if (state->CPU_Action->DoSomething) { DoSomething(state); } } }
void _fastcall r4300i_LW (void) { DWORD Address = GPR[Opcode.base].UW[0] + (short)Opcode.offset; if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,TRUE); } #if (!defined(EXTERNAL_RELEASE)) Log_LW(PROGRAM_COUNTER,Address); #endif if (Opcode.rt == 0) { return; } if (!r4300i_LW_VAddr(Address,&GPR[Opcode.rt].UW[0])) { if (ShowTLBMisses) { DisplayError("LW TLB: %X",Address); } TLB_READ_EXCEPTION(Address); } else { GPR[Opcode.rt].DW = GPR[Opcode.rt].W[0]; //TranslateVaddr(&Address); //if (Address == 0x00090AA0) { // LogMessage("%X: Read %X from %X",PROGRAM_COUNTER,GPR[Opcode.rt].UW[0],GPR[Opcode.base].UW[0] + (short)Opcode.offset); //} } }
void _fastcall r4300i_SWL (void) { DWORD Offset, Address, Value; Address = GPR[Opcode.base].UW[0] + (short)Opcode.offset; Offset = Address & 3; if (!r4300i_LW_VAddr((Address & ~3),&Value)) { #ifndef EXTERNAL_RELEASE DisplayError("SWL TLB: %X",Address); #endif return; } Value &= SWL_MASK[Offset]; Value += GPR[Opcode.rt].UW[0] >> SWL_SHIFT[Offset]; if (!r4300i_SW_VAddr((Address & ~0x03),Value)) { #ifndef EXTERNAL_RELEASE DisplayError("SWL TLB: %X",Address); #endif } }
void r4300i_LW (void) { uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset; if (Opcode.rt == 0) { return; } if (!r4300i_LW_VAddr(Address,&GPR[Opcode.rt].UW[0])) { //if (ShowTLBMisses) { printf("LW TLB: %X",Address); //} TLB_READ_EXCEPTION(Address); } else { GPR[Opcode.rt].DW = GPR[Opcode.rt].W[0]; } }
void r4300i_LWU (void) { uint32_t Address = GPR[Opcode.base].UW[0] + (int16_t)Opcode.offset; if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } if (Opcode.rt == 0) { return; } if (!r4300i_LW_VAddr(Address,&GPR[Opcode.rt].UW[0])) { //if (ShowTLBMisses) { DisplayError("LWU TLB: %X",Address); //} TLB_READ_EXCEPTION(Address); } else { GPR[Opcode.rt].UDW = GPR[Opcode.rt].UW[0]; } }
int32_t DelaySlotEffectsJump (usf_state_t * state, uint32_t JumpPC) { OPCODE Command; if (!r4300i_LW_VAddr(state, JumpPC, &Command.u.Hex)) { return 1; } switch (Command.u.b.op) { case R4300i_SPECIAL: switch (Command.u.e.funct) { case R4300i_SPECIAL_JR: return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,0); case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,31); } break; case R4300i_REGIMM: switch (Command.u.b.rt) { case R4300i_REGIMM_BLTZ: case R4300i_REGIMM_BGEZ: case R4300i_REGIMM_BLTZL: case R4300i_REGIMM_BGEZL: case R4300i_REGIMM_BLTZAL: case R4300i_REGIMM_BGEZAL: return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,0); } break; case R4300i_JAL: case R4300i_SPECIAL_JALR: return DelaySlotEffectsCompare(state,JumpPC,31,0); break; case R4300i_J: return 0; case R4300i_BEQ: case R4300i_BNE: case R4300i_BLEZ: case R4300i_BGTZ: return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,Command.u.b.rt); case R4300i_CP1: switch (Command.u.f.fmt) { case R4300i_COP1_BC: switch (Command.u.f.ft) { case R4300i_COP1_BC_BCF: case R4300i_COP1_BC_BCT: case R4300i_COP1_BC_BCFL: case R4300i_COP1_BC_BCTL: { int32_t EffectDelaySlot; OPCODE NewCommand; if (!r4300i_LW_VAddr(state, JumpPC + 4, &NewCommand.u.Hex)) { return 1; } EffectDelaySlot = 0; if (NewCommand.u.b.op == R4300i_CP1) { if (NewCommand.u.f.fmt == R4300i_COP1_S && (NewCommand.u.e.funct & 0x30) == 0x30 ) { EffectDelaySlot = 1; } if (NewCommand.u.f.fmt == R4300i_COP1_D && (NewCommand.u.e.funct & 0x30) == 0x30 ) { EffectDelaySlot = 1; } } return EffectDelaySlot; } break; } break; } break; case R4300i_BEQL: case R4300i_BNEL: case R4300i_BLEZL: case R4300i_BGTZL: return DelaySlotEffectsCompare(state,JumpPC,Command.u.b.rs,Command.u.b.rt); } return 1; }
int32_t DelaySlotEffectsCompare (usf_state_t * state, uint32_t PC, uint32_t Reg1, uint32_t Reg2) { OPCODE Command; if (!r4300i_LW_VAddr(state, PC + 4, (uint32_t*)&Command.u.Hex)) { return 1; } switch (Command.u.b.op) { case R4300i_SPECIAL: switch (Command.u.e.funct) { case R4300i_SPECIAL_SLL: case R4300i_SPECIAL_SRL: case R4300i_SPECIAL_SRA: case R4300i_SPECIAL_SLLV: case R4300i_SPECIAL_SRLV: case R4300i_SPECIAL_SRAV: case R4300i_SPECIAL_MFHI: case R4300i_SPECIAL_MTHI: case R4300i_SPECIAL_MFLO: case R4300i_SPECIAL_MTLO: case R4300i_SPECIAL_DSLLV: case R4300i_SPECIAL_DSRLV: case R4300i_SPECIAL_DSRAV: case R4300i_SPECIAL_ADD: case R4300i_SPECIAL_ADDU: case R4300i_SPECIAL_SUB: case R4300i_SPECIAL_SUBU: case R4300i_SPECIAL_AND: case R4300i_SPECIAL_OR: case R4300i_SPECIAL_XOR: case R4300i_SPECIAL_NOR: case R4300i_SPECIAL_SLT: case R4300i_SPECIAL_SLTU: case R4300i_SPECIAL_DADD: case R4300i_SPECIAL_DADDU: case R4300i_SPECIAL_DSUB: case R4300i_SPECIAL_DSUBU: case R4300i_SPECIAL_DSLL: case R4300i_SPECIAL_DSRL: case R4300i_SPECIAL_DSRA: case R4300i_SPECIAL_DSLL32: case R4300i_SPECIAL_DSRL32: case R4300i_SPECIAL_DSRA32: if (Command.u.e.rd == 0) { return 0; } if (Command.u.e.rd == Reg1) { return 1; } if (Command.u.e.rd == Reg2) { return 1; } break; case R4300i_SPECIAL_MULT: case R4300i_SPECIAL_MULTU: case R4300i_SPECIAL_DIV: case R4300i_SPECIAL_DIVU: case R4300i_SPECIAL_DMULT: case R4300i_SPECIAL_DMULTU: case R4300i_SPECIAL_DDIV: case R4300i_SPECIAL_DDIVU: break; default: return 1; } break; case R4300i_CP0: switch (Command.u.b.rs) { case R4300i_COP0_MT: break; case R4300i_COP0_MF: if (Command.u.b.rt == 0) { return 0; } if (Command.u.b.rt == Reg1) { return 1; } if (Command.u.b.rt == Reg2) { return 1; } break; default: if ( (Command.u.b.rs & 0x10 ) != 0 ) { switch( state->Opcode.u.e.funct ) { case R4300i_COP0_CO_TLBR: break; case R4300i_COP0_CO_TLBWI: break; case R4300i_COP0_CO_TLBWR: break; case R4300i_COP0_CO_TLBP: break; default: return 1; } return 1; } } break; case R4300i_CP1: switch (Command.u.f.fmt) { case R4300i_COP1_MF: if (Command.u.b.rt == 0) { return 0; } if (Command.u.b.rt == Reg1) { return 1; } if (Command.u.b.rt == Reg2) { return 1; } break; case R4300i_COP1_CF: break; case R4300i_COP1_MT: break; case R4300i_COP1_CT: break; case R4300i_COP1_S: break; case R4300i_COP1_D: break; case R4300i_COP1_W: break; case R4300i_COP1_L: break; return 1; } break; case R4300i_ANDI: case R4300i_ORI: case R4300i_XORI: case R4300i_LUI: case R4300i_ADDI: case R4300i_ADDIU: case R4300i_SLTI: case R4300i_SLTIU: case R4300i_DADDI: case R4300i_DADDIU: case R4300i_LB: case R4300i_LH: case R4300i_LW: case R4300i_LWL: case R4300i_LWR: case R4300i_LDL: case R4300i_LDR: case R4300i_LBU: case R4300i_LHU: case R4300i_LD: case R4300i_LWC1: case R4300i_LDC1: if (Command.u.b.rt == 0) { return 0; } if (Command.u.b.rt == Reg1) { return 1; } if (Command.u.b.rt == Reg2) { return 1; } break; case R4300i_CACHE: break; case R4300i_SB: break; case R4300i_SH: break; case R4300i_SW: break; case R4300i_SWR: break; case R4300i_SWL: break; case R4300i_SWC1: break; case R4300i_SDC1: break; case R4300i_SD: break; default: return 1; } return 0; }