From f0a806e6b168b1c9cab5c9d7a27435dc4a76476a Mon Sep 17 00:00:00 2001 From: Shamus Hammons Date: Fri, 6 Dec 2013 11:31:01 -0600 Subject: [PATCH] Added breakpoint on memory access to Alpine mode. --- src/gui/debug/cpubrowser.cpp | 30 ++++++++++++++- src/gui/debug/cpubrowser.h | 6 ++- src/jaguar.cpp | 74 ++++++++++++++++++++++++++++++++++++ src/jaguar.h | 2 + src/m68000/m68kinterface.c | 29 +++++++++++++- src/m68000/m68kinterface.h | 4 ++ 6 files changed, 140 insertions(+), 5 deletions(-) diff --git a/src/gui/debug/cpubrowser.cpp b/src/gui/debug/cpubrowser.cpp index daabbf3..2f478ce 100644 --- a/src/gui/debug/cpubrowser.cpp +++ b/src/gui/debug/cpubrowser.cpp @@ -19,19 +19,25 @@ #include "m68000/m68kinterface.h" #include "dsp.h" #include "gpu.h" +#include "jaguar.h" CPUBrowserWindow::CPUBrowserWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt::Dialog), -// layout(new QVBoxLayout), text(new QTextBrowser), layout(new QVBoxLayout), text(new QLabel), refresh(new QPushButton(tr("Refresh"))), - memBase(0) + bpm(new QCheckBox(tr("BPM"))), bpmAddress(new QLineEdit) { setWindowTitle(tr("CPU Browser")); // Need to set the size as well... // resize(560, 480); + // Limit input to 6 hex digits + bpmAddress->setInputMask("hhhhhh"); + QHBoxLayout * hbox1 = new QHBoxLayout; + hbox1->addWidget(bpm); + hbox1->addWidget(bpmAddress); + // QFont fixedFont("Lucida Console", 8, QFont::Normal); QFont fixedFont("", 8, QFont::Normal); fixedFont.setStyleHint(QFont::TypeWriter); @@ -40,9 +46,12 @@ CPUBrowserWindow::CPUBrowserWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt: setLayout(layout); layout->addWidget(text); + layout->addLayout(hbox1); layout->addWidget(refresh); connect(refresh, SIGNAL(clicked()), this, SLOT(RefreshContents())); + connect(bpm, SIGNAL(clicked(bool)), this, SLOT(HandleBPM(bool))); + connect(bpmAddress, SIGNAL(textChanged(const QString &)), this, SLOT(HandleBPMAddress(const QString &))); } @@ -236,10 +245,26 @@ DSP Control: } +void CPUBrowserWindow::HandleBPM(bool state) +{ + bpmActive = state; +if (bpmActive) + printf("BPM Set: $%06X\n", bpmAddress1); +} + + +void CPUBrowserWindow::HandleBPMAddress(const QString & newText) +{ + bool ok; + bpmAddress1 = newText.toUInt(&ok, 16); +} + + void CPUBrowserWindow::keyPressEvent(QKeyEvent * e) { if (e->key() == Qt::Key_Escape) hide(); +#if 0 else if (e->key() == Qt::Key_PageUp) { memBase -= 480; @@ -276,4 +301,5 @@ void CPUBrowserWindow::keyPressEvent(QKeyEvent * e) RefreshContents(); } +#endif } diff --git a/src/gui/debug/cpubrowser.h b/src/gui/debug/cpubrowser.h index 0ea0cda..e651872 100644 --- a/src/gui/debug/cpubrowser.h +++ b/src/gui/debug/cpubrowser.h @@ -22,6 +22,8 @@ class CPUBrowserWindow: public QWidget public slots: // void DefineAllKeys(void); void RefreshContents(void); + void HandleBPM(bool); + void HandleBPMAddress(const QString &); protected: void keyPressEvent(QKeyEvent *); @@ -31,8 +33,10 @@ class CPUBrowserWindow: public QWidget // QTextBrowser * text; QLabel * text; QPushButton * refresh; + QCheckBox * bpm; + QLineEdit * bpmAddress; - int32_t memBase; +// int32_t memBase; }; #endif // __CPUBROWSER_H__ diff --git a/src/jaguar.cpp b/src/jaguar.cpp index b92b221..cfbf3ef 100644 --- a/src/jaguar.cpp +++ b/src/jaguar.cpp @@ -45,6 +45,7 @@ #define CPU_DEBUG_MEMORY //#define LOG_CD_BIOS_CALLS #define CPU_DEBUG_TRACING +#define ALPINE_FUNCTIONS // Private function prototypes @@ -99,6 +100,11 @@ uint32_t d7Queue[0x400]; uint32_t pcQPtr = 0; bool startM68KTracing = false; +// Breakpoint on memory access vars (exported) +bool bpmActive = false; +uint32_t bpmAddress1; + + // // Callback function to detect illegal instructions // @@ -860,27 +866,33 @@ WriteLog("JERRY: (68K int en/lat - Unhandled!) Tried to write $%02X to $%08X!\n" ; // Do nothing } + void WriteWord(uint32_t adddress, uint16_t word) { } + void WriteDWord(uint32_t adddress, uint32_t dword) { } + uint8_t ReadByte(uint32_t adddress) { } + uint16_t ReadWord(uint32_t adddress) { } + uint32_t ReadDWord(uint32_t adddress) { } #endif + void ShowM68KContext(void) { printf("\t68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC)); @@ -914,6 +926,7 @@ void ShowM68KContext(void) while (disPC < (currpc + 10)); } + // // Custom UAE 68000 read/write/IRQ functions // @@ -1005,10 +1018,17 @@ int irq_ack_handler(int level) return M68K_INT_ACK_AUTOVECTOR; } + //#define USE_NEW_MMU unsigned int m68k_read_memory_8(unsigned int address) { +#ifdef ALPINE_FUNCTIONS + // Check if breakpoint on memory is active, and deal with it + if (bpmActive && address == bpmAddress1) + M68KSetHalt(); +#endif + // Musashi does this automagically for you, UAE core does not :-P address &= 0x00FFFFFF; #ifdef CPU_DEBUG_MEMORY @@ -1056,11 +1076,18 @@ unsigned int m68k_read_memory_8(unsigned int address) #endif } + void gpu_dump_disassembly(void); void gpu_dump_registers(void); unsigned int m68k_read_memory_16(unsigned int address) { +#ifdef ALPINE_FUNCTIONS + // Check if breakpoint on memory is active, and deal with it + if (bpmActive && address == bpmAddress1) + M68KSetHalt(); +#endif + // Musashi does this automagically for you, UAE core does not :-P address &= 0x00FFFFFF; #ifdef CPU_DEBUG_MEMORY @@ -1160,8 +1187,15 @@ unsigned int m68k_read_memory_16(unsigned int address) #endif } + unsigned int m68k_read_memory_32(unsigned int address) { +#ifdef ALPINE_FUNCTIONS + // Check if breakpoint on memory is active, and deal with it + if (bpmActive && address == bpmAddress1) + M68KSetHalt(); +#endif + // Musashi does this automagically for you, UAE core does not :-P address &= 0x00FFFFFF; //; So, it seems that it stores the returned DWORD at $51136 and $FB074. @@ -1176,8 +1210,15 @@ unsigned int m68k_read_memory_32(unsigned int address) #endif } + void m68k_write_memory_8(unsigned int address, unsigned int value) { +#ifdef ALPINE_FUNCTIONS + // Check if breakpoint on memory is active, and deal with it + if (bpmActive && address == bpmAddress1) + M68KSetHalt(); +#endif + // Musashi does this automagically for you, UAE core does not :-P address &= 0x00FFFFFF; #ifdef CPU_DEBUG_MEMORY @@ -1226,8 +1267,15 @@ void m68k_write_memory_8(unsigned int address, unsigned int value) #endif } + void m68k_write_memory_16(unsigned int address, unsigned int value) { +#ifdef ALPINE_FUNCTIONS + // Check if breakpoint on memory is active, and deal with it + if (bpmActive && address == bpmAddress1) + M68KSetHalt(); +#endif + // Musashi does this automagically for you, UAE core does not :-P address &= 0x00FFFFFF; #ifdef CPU_DEBUG_MEMORY @@ -1314,8 +1362,15 @@ if (address == 0xF02110) #endif } + void m68k_write_memory_32(unsigned int address, unsigned int value) { +#ifdef ALPINE_FUNCTIONS + // Check if breakpoint on memory is active, and deal with it + if (bpmActive && address == bpmAddress1) + M68KSetHalt(); +#endif + // Musashi does this automagically for you, UAE core does not :-P address &= 0x00FFFFFF; /*if (address == 0x4E00) @@ -1354,12 +1409,14 @@ uint32_t JaguarGetHandler(uint32_t i) return JaguarReadLong(i * 4); } + bool JaguarInterruptHandlerIsValid(uint32_t i) // Debug use only... { uint32_t handler = JaguarGetHandler(i); return (handler && (handler != 0xFFFFFFFF) ? true : false); } + void M68K_show_context(void) { WriteLog("68K PC=%06X\n", m68k_get_reg(NULL, M68K_REG_PC)); @@ -1412,6 +1469,7 @@ void M68K_show_context(void) } } + // // Unknown read/write byte/word routines // @@ -1446,6 +1504,7 @@ void jaguar_unknown_writebyte(unsigned address, unsigned data, uint32_t who/*=UN #endif } + void jaguar_unknown_writeword(unsigned address, unsigned data, uint32_t who/*=UNKNOWN*/) { #ifdef LOG_UNMAPPED_MEMORY_ACCESSES @@ -1460,6 +1519,7 @@ void jaguar_unknown_writeword(unsigned address, unsigned data, uint32_t who/*=UN #endif } + unsigned jaguar_unknown_readbyte(unsigned address, uint32_t who/*=UNKNOWN*/) { #ifdef LOG_UNMAPPED_MEMORY_ACCESSES @@ -1475,6 +1535,7 @@ unsigned jaguar_unknown_readbyte(unsigned address, uint32_t who/*=UNKNOWN*/) return 0xFF; } + unsigned jaguar_unknown_readword(unsigned address, uint32_t who/*=UNKNOWN*/) { #ifdef LOG_UNMAPPED_MEMORY_ACCESSES @@ -1490,6 +1551,7 @@ unsigned jaguar_unknown_readword(unsigned address, uint32_t who/*=UNKNOWN*/) return 0xFFFF; } + // // Disassemble M68K instructions at the given offset // @@ -1499,16 +1561,19 @@ unsigned int m68k_read_disassembler_8(unsigned int address) return m68k_read_memory_8(address); } + unsigned int m68k_read_disassembler_16(unsigned int address) { return m68k_read_memory_16(address); } + unsigned int m68k_read_disassembler_32(unsigned int address) { return m68k_read_memory_32(address); } + void JaguarDasm(uint32_t offset, uint32_t qt) { #ifdef CPU_DEBUG @@ -1530,6 +1595,7 @@ void JaguarDasm(uint32_t offset, uint32_t qt) #endif } + uint8_t JaguarReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/) { uint8_t data = 0x00; @@ -1556,6 +1622,7 @@ uint8_t JaguarReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/) return data; } + uint16_t JaguarReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/) { offset &= 0xFFFFFF; @@ -1585,6 +1652,7 @@ uint16_t JaguarReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/) return jaguar_unknown_readword(offset, who); } + void JaguarWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/) { /* if (offset >= 0x4E00 && offset < 0x4E04) @@ -1621,6 +1689,7 @@ void JaguarWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/) jaguar_unknown_writebyte(offset, data, who); } + uint32_t starCount; void JaguarWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/) { @@ -1756,12 +1825,14 @@ if (offset == 0x11D31A + 0x48000 || offset == 0x11D31A) jaguar_unknown_writeword(offset, data, who); } + // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!! uint32_t JaguarReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/) { return (JaguarReadWord(offset, who) << 16) | JaguarReadWord(offset+2, who); } + // We really should re-do this so that it does *real* 32-bit access... !!! FIX !!! void JaguarWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/) { @@ -1778,18 +1849,21 @@ void JaguarWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/) JaguarWriteWord(offset+2, data & 0xFFFF, who); } + void JaguarSetScreenBuffer(uint32_t * buffer) { // This is in TOM, but we set it here... screenBuffer = buffer; } + void JaguarSetScreenPitch(uint32_t pitch) { // This is in TOM, but we set it here... screenPitch = pitch; } + // // Jaguar console initialization // diff --git a/src/jaguar.h b/src/jaguar.h index 54e25ae..63e6de6 100644 --- a/src/jaguar.h +++ b/src/jaguar.h @@ -28,6 +28,8 @@ extern int32_t jaguarCPUInExec; extern uint32_t jaguarMainROMCRC32, jaguarROMSize, jaguarRunAddress; extern char * jaguarEepromsPath; extern bool jaguarCartInserted; +extern bool bpmActive; +extern uint32_t bpmAddress1; // Various clock rates diff --git a/src/m68000/m68kinterface.c b/src/m68000/m68kinterface.c index dd5dfc1..13015d0 100644 --- a/src/m68000/m68kinterface.c +++ b/src/m68000/m68kinterface.c @@ -127,6 +127,18 @@ void DumpRegisters(void) #endif +void M68KSetHalt(void) +{ + regs.stopped = 1; +} + + +void M68KClearHalt(void) +{ + regs.stopped = 0; +} + + void m68k_set_cpu_type(unsigned int type) { } @@ -327,6 +339,16 @@ if (inRoutine) //printf("Executed opcode $%04X (%i cycles)...\n", opcode, cycles); #endif + // This is so our debugging code can break in on a dime. + // Otherwise, this is just extra slow down :-P + if (regs.stopped) + { + num_cycles = initialCycles - regs.remainingCycles; + regs.remainingCycles = 0; // int32_t + regs.interruptCycles = 0; // uint32_t + + return num_cycles; + } } while (regs.remainingCycles > 0); @@ -466,11 +488,14 @@ void m68ki_exception_interrupt(uint32_t intLevel) #endif /* M68K_EMULATE_INT_ACK */ #else // Turn off the stopped state - regs.stopped = 0; +// Needed? +// regs.stopped = 0; //JLH: need to add halt state? +// prolly, for debugging/alpine mode... :-/ +// but then again, this should be handled already by the main execution loop :-P // If we are halted, don't do anything -// if (CPU_STOPPED) +// if (regs.stopped) // return; // Acknowledge the interrupt (NOTE: This is a user supplied function!) diff --git a/src/m68000/m68kinterface.h b/src/m68000/m68kinterface.h index 613bb11..a3c6e3c 100644 --- a/src/m68000/m68kinterface.h +++ b/src/m68000/m68kinterface.h @@ -97,6 +97,10 @@ int irq_ack_handler(int); void M68KInstructionHook(void); #endif +// Functions to allow debugging +void M68KSetHalt(void); +void M68KClearHalt(void); + /* Peek at the internals of a CPU context. This can either be a context * retrieved using m68k_get_context() or the currently running context. * If context is NULL, the currently running CPU context will be used. -- 2.37.2