diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..756b5d9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/src/cpu/cop0.h b/src/cpu/cop0.h index 4dc4737..791768e 100644 --- a/src/cpu/cop0.h +++ b/src/cpu/cop0.h @@ -32,6 +32,8 @@ struct COP0 { uint32_t superMasterEnable2 : 1; // bits 24..29 }; + inline bool codeBreakpointEnabled() { return masterEnableBreakpoints && superMasterEnable1 && superMasterEnable2 && breakOnCode; } + uint32_t _reg; DCIC() : _reg(0) {} }; diff --git a/src/cpu/cpu.cpp b/src/cpu/cpu.cpp index 14db06d..4271cc6 100644 --- a/src/cpu/cpu.cpp +++ b/src/cpu/cpu.cpp @@ -54,7 +54,17 @@ void CPU::saveStateForException() { branchTaken = false; } -bool CPU::handleBreakpoints() { +void CPU::handleHardwareBreakpoints() { + if (cop0.dcic.codeBreakpointEnabled()) { + if (((PC ^ cop0.bpcm) & cop0.bpc) == 0) { + cop0.dcic.codeBreakpointHit = 1; + cop0.dcic.breakpointHit = 1; + instructions::exception(this, COP0::CAUSE::Exception::breakpoint); + } + } +} + +bool CPU::handleSoftwareBreakpoints() { if (!breakpoints.empty()) { auto bp = breakpoints.find(PC); if (bp != breakpoints.end() && bp->second.enabled) { @@ -83,10 +93,10 @@ bool CPU::executeInstructions(int count) { if (maskedPc == 0xa0 || maskedPc == 0xb0 || maskedPc == 0xc0) sys->handleBiosFunction(); saveStateForException(); - checkForInterrupts(); + handleHardwareBreakpoints(); - if (handleBreakpoints()) return false; + if (handleSoftwareBreakpoints()) return false; _opcode = Opcode(sys->readMemory32(PC)); const auto& op = instructions::OpcodeTable[_opcode.op]; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 2a92b89..444e7af 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -96,7 +96,8 @@ struct CPU { } void saveStateForException(); - bool handleBreakpoints(); + void handleHardwareBreakpoints(); + bool handleSoftwareBreakpoints(); bool executeInstructions(int count); struct Breakpoint { diff --git a/src/cpu/instructions.cpp b/src/cpu/instructions.cpp index 44eefe1..b6d6ba2 100644 --- a/src/cpu/instructions.cpp +++ b/src/cpu/instructions.cpp @@ -201,7 +201,12 @@ void exception(CPU *cpu, COP0::CAUSE::Exception cause) { cpu->cop0.tar = cpu->PC; } - cpu->setPC(cpu->cop0.status.getHandlerAddress()); + uint32_t handlerAddress = cpu->cop0.status.getHandlerAddress(); + if (cause == Exception::breakpoint) { + handlerAddress -= 0x40; + } + + cpu->setPC(handlerAddress); } void dummy(CPU *cpu, Opcode i) {