diff --git a/CMakeLists.txt b/CMakeLists.txt index 796b644..f7e308a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,4 +12,3 @@ add_subdirectory(toolbox) add_subdirectory(mplite) add_subdirectory(mpw) add_subdirectory(macos) -add_subdirectory(debugger) \ No newline at end of file diff --git a/bin/CMakeLists.txt b/bin/CMakeLists.txt index 23b2f78..4071dfa 100644 --- a/bin/CMakeLists.txt +++ b/bin/CMakeLists.txt @@ -2,13 +2,32 @@ #set(CMAKE_CXX_COMPILER "clang++") set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -Wall -Wno-deprecated-declarations -g") SET(CMAKE_EXE_LINKER_FLAGS "-framework Carbon") +set(CMAKE_INCLUDE_CURRENT_DIR ON) add_definitions(-I ${CMAKE_SOURCE_DIR}/) -add_executable(mpw loader.cpp debugger.cpp address_map.cpp) +add_custom_command( + OUTPUT lexer.cpp + COMMAND re2c -b -i -o lexer.cpp "${CMAKE_CURRENT_SOURCE_DIR}/lexer.re.cpp" + MAIN_DEPENDENCY lexer.re.cpp + DEPENDS debugger.h parser.h +) + +add_custom_command( + OUTPUT parser.cpp parser.h + COMMAND cp -f "${CMAKE_CURRENT_SOURCE_DIR}/parser.lemon" "parser.lemon" + COMMAND lemon parser.lemon + COMMAND cp -f parser.h "${CMAKE_CURRENT_SOURCE_DIR}/" + COMMAND cp -f parser.out "${CMAKE_CURRENT_SOURCE_DIR}/" + COMMAND mv -f parser.c parser.cpp + MAIN_DEPENDENCY parser.lemon + DEPENDS debugger.h +) + + +add_executable(mpw loader.cpp debugger.cpp address_map.cpp lexer.cpp parser.cpp) target_link_libraries(mpw CPU_LIB) -target_link_libraries(mpw DEBUGGER_LIB) target_link_libraries(mpw TOOLBOX_LIB) target_link_libraries(mpw MPW_LIB) target_link_libraries(mpw MPLITE_LIB) diff --git a/bin/debugger.cpp b/bin/debugger.cpp index ea35566..f6e61a6 100644 --- a/bin/debugger.cpp +++ b/bin/debugger.cpp @@ -20,7 +20,7 @@ #include "loader.h" #include "address_map.h" -#include +#include "debugger.h" #include #include @@ -28,45 +28,6 @@ #include #include -bool ParseLine(const char *iter, Command *command); - -extern "C" { - - uint32_t debuggerReadLong(uint32_t address) - { - uint32_t tmp = 0; - for (unsigned i = 0; i < 4; ++i) - { - if (address < Flags.memorySize) - tmp = (tmp << 8) + Flags.memory[address++]; - } - - return tmp; - } - - - uint16_t debuggerReadWord(uint32_t address) - { - uint16_t tmp = 0; - for (unsigned i = 0; i < 2; ++i) - { - if (address < Flags.memorySize) - tmp = (tmp << 8) + Flags.memory[address++]; - } - - return tmp; - } - - uint8_t debuggerReadByte(uint32_t address) - { - if (address < Flags.memorySize) - return Flags.memory[address]; - - return 0; - } - -} - namespace { bool sigInt = false; @@ -148,7 +109,7 @@ namespace { pc += mboffset; // check for MacsBug name after rts. std::string s; - unsigned b = debuggerReadByte(pc); + unsigned b = Debug::ReadByte(pc); if (b > 0x80 && b < 0xa0) { b -= 0x80; @@ -156,7 +117,7 @@ namespace { s.reserve(b); for (unsigned i = 0; i < b; ++i) { - s.push_back(debuggerReadByte(pc++)); + s.push_back(Debug::ReadByte(pc++)); } printf("%s\n", s.c_str()); } @@ -175,7 +136,7 @@ namespace { return pc; } - uint16_t opcode = debuggerReadWord(pc); + uint16_t opcode = Debug::ReadWord(pc); if (op) *op = opcode; if ((opcode & 0xf000) == 0xa000) @@ -220,7 +181,7 @@ namespace { uint32_t pc = cpuGetPC(); if (trace) disasm(pc, &op); - else op = debuggerReadWord(pc); + else op = Debug::ReadWord(pc); if (Flags.traceMacsbug && !trace) printMacsbug(pc, op); @@ -289,8 +250,46 @@ namespace { } +#pragma mark - Debugger -void DebugHelp(const Command &cmd) +namespace Debug { + +uint32_t ReadLong(uint32_t address) +{ + uint32_t tmp = 0; + for (unsigned i = 0; i < 4; ++i) + { + if (address < Flags.memorySize) + tmp = (tmp << 8) + Flags.memory[address++]; + } + + return tmp; +} + + +uint16_t ReadWord(uint32_t address) +{ + uint16_t tmp = 0; + for (unsigned i = 0; i < 2; ++i) + { + if (address < Flags.memorySize) + tmp = (tmp << 8) + Flags.memory[address++]; + } + + return tmp; +} + +uint8_t ReadByte(uint32_t address) +{ + if (address < Flags.memorySize) + return Flags.memory[address]; + + return 0; +} + + + +void Help() { printf("help\n"); printf("break expression\n"); @@ -307,64 +306,76 @@ void DebugHelp(const Command &cmd) } -void DebugPrint(const Command &cmd) +void Print(uint32_t data) { - for (unsigned i = 0; i < cmd.argc; ++i) - { - uint32_t data = cmd.argv[i]; - printf("$%08x %12u", data, data); - if (data & 0x80000000) - printf(" %12d", (int32_t)data); - if ((data & 0xffff8000) == 0x8000) - printf(" %6d", (int16_t)data); + printf("$%08x %12u", data, data); + if (data & 0x80000000) + printf(" %12d", (int32_t)data); + if ((data & 0xffff8000) == 0x8000) + printf(" %6d", (int16_t)data); + + printf("\n"); - printf("\n"); - } } -void DebugDump(const Command &cmd) +void Dump(uint32_t start, int size) { // TODO -- if no address, use previous address. // TODO -- support range? - uint32_t start = cmd.argv[0]; - uint32_t end = cmd.argc == 2 ? cmd.argv[1] : start + 256; + if (size <= 0) return; + + uint32_t end = start + size; if (start >= Flags.memorySize) return; end = std::min(end, Flags.memorySize); - ssize_t size = end - start; + size = end - start; hexdump(Flags.memory + start, size, start); } -void DebugList(const Command &cmd) +// grr... need separate count/range options. +void List(uint32_t pc, int count) { // TODO -- if no address, use previous address. - // TODO -- support range? - if (cmd.argc == 1) + if (pc & 0x01) { - uint32_t pc = cmd.argv[0]; - if (pc & 0x01) - { - printf("address is not aligned: $%08x\n", pc); - return; - } + printf("address is not aligned: $%08x\n", pc); + return; + } - for (unsigned i = 0; i < 32; ++i) - { - if (pc >= Flags.memorySize) break; - pc = disasm(pc); - } + for (int i = 0; i < count; ++i) + { + if (pc >= Flags.memorySize) break; + pc = disasm(pc); } } +void List(uint32_t pc, uint32_t endpc) +{ + if (endpc < pc) return; -void DebugPrintRegisters(const Command &cmd) + if (pc & 0x01) + { + printf("address is not aligned: $%08x\n", pc); + return; + } + + while (pc <= endpc) + { + if (pc >= Flags.memorySize) break; + pc = disasm(pc); + } + +} + + +void PrintRegisters() { char srbits[20]; @@ -406,60 +417,54 @@ void DebugPrintRegisters(const Command &cmd) } -void DebugToolBreak(Command &cmd) +void ToolBreak(int32_t tool) { - for (unsigned i = 0; i < cmd.argc; ++i) + + bool remove = false; + + if (tool < 0) { - int32_t tool = (int32_t)cmd.argv[i]; - bool remove = false; + tool = -tool; + remove = true; + } - if (tool < 0) - { - tool = -tool; - remove = true; - } - - if (tool >= 0xa000 && tool <= 0xafff) - { - if (remove) tbrkMap.remove(tool); - else tbrkMap.add(tool); - } - else - { - fprintf(stderr, "Invalid tool: $%04x\n", tool); - } + if (tool >= 0xa000 && tool <= 0xafff) + { + if (remove) tbrkMap.remove(tool); + else tbrkMap.add(tool); + } + else + { + fprintf(stderr, "Invalid tool: $%04x\n", tool); } } -void DebugBreak(Command &cmd) +void Break(int32_t address) { // 24-bit only, - address to remove. - for (unsigned i = 0; i < cmd.argc; ++i) + + bool remove = false; + + if (address < 0) { - int32_t address = (int32_t)cmd.argv[i]; - bool remove = false; + address = -address; + remove = true; + } - if (address < 0) - { - address = -address; - remove = true; - } - - if ((address & 0xff000000) == 0) - { - if (remove) brkMap.remove(address); - else brkMap.add(address); - } - else - { - fprintf(stderr, "Invalid address: $%08x\n", address); - } + if ((address & 0xff000000) == 0) + { + if (remove) brkMap.remove(address); + else brkMap.add(address); + } + else + { + fprintf(stderr, "Invalid address: $%08x\n", address); } } -void DebugStep(const Command &cmd) +void Step(const Command &cmd) { // TODO - step n to step specified # of instructions. // TODO -- step @address to step until address? @@ -478,17 +483,13 @@ void DebugStep(const Command &cmd) } -void DebugContinue(const Command &cmd) +void Continue(const Command &cmd) { while (step(false)) ; } -void DebugSetARegister(Command &cmd) +void SetARegister(unsigned reg, uint32_t value) { - if (cmd.argc != 2) return; - unsigned reg = cmd.argv[0]; - uint32_t value = cmd.argv[1]; - if (reg > 7) return; if (reg == 7) { @@ -509,20 +510,15 @@ void DebugSetARegister(Command &cmd) } -void DebugSetDRegister(Command &cmd) +void SetDRegister(unsigned reg, uint32_t value) { - if (cmd.argc != 2) return; - unsigned reg = cmd.argv[0]; - uint32_t value = cmd.argv[1]; + if (reg > 7) return; cpuSetDReg(reg, value); } -void DebugSetXRegister(Command &cmd) +void SetXRegister(unsigned reg, uint32_t value) { - if (cmd.argc != 2) return; - unsigned reg = cmd.argv[0]; - uint32_t value = cmd.argv[1]; if (reg == 0) { @@ -541,7 +537,7 @@ void DebugSetXRegister(Command &cmd) if (reg == 1) { - cpuSetSR(value); + cpuSetSR(value & 0xffff); } } @@ -550,7 +546,7 @@ void DebugSetXRegister(Command &cmd) // TODO -- RUN command - reload, re-initialize, re-execute // TODO -- parser calls commands directly (except trace/step/run/etc) -void DebugShell() +void Shell() { char *cp; @@ -582,55 +578,19 @@ void DebugShell() { switch(cmd.action) { - case NullCommand: + case cmdNull: break; - case Print: - DebugPrint(cmd); + case cmdStep: + Step(cmd); break; - case Dump: - DebugDump(cmd); - break; - - case List: - DebugList(cmd); - break; - - case PrintRegisters: - DebugPrintRegisters(cmd); - break; - - case Step: - DebugStep(cmd); - break; - - case Continue: - DebugContinue(cmd); - break; - - case TBreak: - DebugToolBreak(cmd); - break; - - case Break: - DebugBreak(cmd); - break; - - case SetARegister: - DebugSetARegister(cmd); - break; - - case SetDRegister: - DebugSetDRegister(cmd); - break; - - case SetXRegister: - DebugSetXRegister(cmd); + case cmdContinue: + Continue(cmd); break; default: - DebugHelp(cmd); + Help(); break; } } @@ -643,3 +603,6 @@ void DebugShell() } +} // namespace Debugger + + diff --git a/bin/debugger.h b/bin/debugger.h new file mode 100644 index 0000000..a25c98c --- /dev/null +++ b/bin/debugger.h @@ -0,0 +1,51 @@ +#ifndef __debugger_h__ +#define __debugger_h__ + + +#include + +// Debugger is a function in MacTypes.h +namespace Debug { + + +enum { + cmdNull, + cmdContinue, + cmdStep, + cmdRun, +}; + +struct Command { + bool valid; + int action; + uint32_t argc; + uint32_t argv[10]; +}; + + +bool ParseLine(const char *iter, Command *command); + +void Shell(); +void Help(); + +uint32_t ReadLong(uint32_t); +uint16_t ReadWord(uint32_t); +uint8_t ReadByte(uint32_t); + +void Print(uint32_t value); +void PrintRegisters(); + +void Dump(uint32_t address, int count = 256); +void List(uint32_t address, int count = 20); +void List(uint32_t pc, uint32_t endpc); + +void SetARegister(unsigned reg, uint32_t value); +void SetDRegister(unsigned reg, uint32_t value); +void SetXRegister(unsigned reg, uint32_t value); + +void ToolBreak(int32_t tool); +void Break(int32_t address); + +} + +#endif \ No newline at end of file diff --git a/debugger/lexer.re.cpp b/bin/lexer.re.cpp similarity index 85% rename from debugger/lexer.re.cpp rename to bin/lexer.re.cpp index fd5f1bd..a8dffdd 100644 --- a/debugger/lexer.re.cpp +++ b/bin/lexer.re.cpp @@ -6,7 +6,7 @@ #include #include -#include "commands.h" +#include "debugger.h" #include "parser.h" // re2c -b -i @@ -16,7 +16,7 @@ void *ParseAlloc(void *(*mallocProc)(size_t)); void ParseFree(void *p, void (*freeProc)(void*)); - void Parse(void *yyp, int yymajor, uint32_t yyminor, Command *command); + void Parse(void *yyp, int yymajor, uint32_t yyminor, Debug::Command *command); void ParseTrace(FILE *TraceFILE, char *zTracePrompt); //} @@ -51,58 +51,9 @@ namespace { } } -#if 0 -/* - * unordered_set of breakpoints? - * bloom filter via std::bitset<16 * 1024> ? - */ - class AddressFilter { - std::bitset<4096> pageSet; - std::unordered_set addSet; - - bool test(uint32_t address) const - { - if (address > 0xffffff) return false; - if (!pageSet[address >> 12]) return false; - - return addSet.find(address) != addSet.end(); - } - - void add(uint32_t address) - { - if (address > 0xffffff) return; - - pageSet[address >> 12] = true; - addSet.insert(address); - } - - void remove(uint32_t address) - { - if (address > 0xffffff) return; - - auto iter = addSet.find(address); - if (iter != addSet.end()) - { - addSet.remove(); - // need to re-scan all addresses to update the pageSet... - uint32_t page = address >> 12; - pageSet[page] = false; - for (auto x : addSet) - { - if ((x >> 12) == page) - { - addSet[page] = true; - break; - } - } - } - } - - }; - -#endif +namespace Debug { bool ParseLine(const char *iter, Command *command) { void *parser; @@ -110,7 +61,7 @@ bool ParseLine(const char *iter, Command *command) parser = ParseAlloc(malloc); //ParseTrace(stdout, "--> "); - + command->action = cmdNull; for (;;) { const char *begin = iter; @@ -351,4 +302,6 @@ bool ParseLine(const char *iter, Command *command) fprintf(stderr,"I don't understand.\n"); return command->valid; -} \ No newline at end of file +} + +} // namespace Debugger \ No newline at end of file diff --git a/bin/loader.cpp b/bin/loader.cpp index bdbf750..0067f03 100644 --- a/bin/loader.cpp +++ b/bin/loader.cpp @@ -29,6 +29,7 @@ #include #include "loader.h" +#include "debugger.h" Settings Flags; @@ -767,7 +768,7 @@ int main(int argc, char **argv) cpuInitializeFromNewPC(address); - if (Flags.debugger) DebugShell(); + if (Flags.debugger) Debug::Shell(); else MainLoop(); diff --git a/debugger/parser.lemon b/bin/parser.lemon similarity index 66% rename from debugger/parser.lemon rename to bin/parser.lemon index 52ae596..37a647c 100644 --- a/debugger/parser.lemon +++ b/bin/parser.lemon @@ -1,5 +1,5 @@ -%extra_argument { struct Command *command } +%extra_argument { Debug::Command *command } %token_prefix tk %token_type {uint32_t} @@ -7,7 +7,7 @@ #include #include #include -#include "commands.h" +#include "debugger.h" #include #ifdef __cplusplus @@ -18,7 +18,6 @@ uint32_t cpuGetSR(); uint32_t cpuGetPC(); uint32_t cpuGetAReg(unsigned); uint32_t cpuGetDReg(unsigned); -uint32_t debuggerReadLong(uint32_t); #ifdef __cplusplus } @@ -55,103 +54,87 @@ uint32_t debuggerReadLong(uint32_t); stmt ::= expr(a) EOL. { - command->action = Print; - command->argc = 1; - command->argv[0] = a; + Debug::Print(a); } stmt ::= STAR EOL. { - command->action = PrintRegisters; - command->argc = 0; + Debug::PrintRegisters(); } stmt ::= PRINT expr(a) EOL. { - command->action = Print; - command->argc = 1; - command->argv[0] = a; + Debug::Print(a); } stmt ::= BREAK expr(a) EOL. { - command->action = Break; - command->argc = 1; - command->argv[0] = a; + Debug::Break(a); } stmt ::= CONTINUE EOL. { - command->action = Continue; + command->action = Debug::cmdContinue; command->argc = 0; } stmt ::= TBREAK expr(a) EOL. { - // negative number = remove it. - command->action = TBreak; - command->argc = 1; - command->argv[0] = a; + Debug::ToolBreak(a); } stmt ::= NEXT EOL. { - command->action = Step; + command->action = Debug::cmdStep; command->argc = 0; } stmt ::= NEXT expr(a) EOL. { - command->action = Step; + command->action = Debug::cmdStep; command->argc = 1; command->argv[0] = a; } stmt ::= DUMP expr(a) EOL. { - command->action = Dump; - command->argc = 1; - command->argv[0] = a; + Debug::Dump(a); } stmt ::= DUMP expr(a) COLON expr(b) EOL. { - // range dump - command->action = Dump; - command->argc = 2; - command->argv[0] = a; - command->argv[1] = b; + Debug::Dump(a, b - a); } stmt ::= DUMP expr(a) AT expr(b) EOL. { - // count dump - command->action = Dump; - command->argc = 2; - command->argv[0] = a; - command->argv[1] = a+b; + Debug::Dump(a, b); } stmt ::= LIST expr(a) EOL. { - command->action = List; - command->argc = 1; - command->argv[0] = a; + Debug::List(a); } stmt ::= expr(a) SEMIH EOL. { - command->action = Dump; - command->argc = 1; - command->argv[0] = a; + Debug::Dump(a); } +stmt ::= expr(a) COLON expr(b) SEMIH EOL. +{ + Debug::Dump(a, b - a); +} + +stmt ::= expr(a) AT expr(b) SEMIH EOL. +{ + Debug::Dump(a, b); +} + + stmt ::= expr(a) SEMII EOL. { - command->action = NullCommand; - command->argc = 0; - MM::Native::MemoryInfo(a); } @@ -159,40 +142,28 @@ stmt ::= expr(a) SEMII EOL. stmt ::= expr(a) SEMIL EOL. { - command->action = List; - command->argc = 1; - command->argv[0] = a; + Debug::List(a); } stmt ::= DREGISTER(a) EQ expr(b) EOL. { - command->action = SetDRegister; - command->argc = 2; - command->argv[0] = a; - command->argv[1] = b; + Debug::SetDRegister(a, b); } stmt ::= AREGISTER(a) EQ expr(b) EOL. { - command->action = SetARegister; - command->argc = 2; - command->argv[0] = a; - command->argv[1] = b; + Debug::SetARegister(a, b); } stmt ::= XREGISTER(a) EQ expr(b) EOL. { - command->action = SetXRegister; - command->argc = 2; - command->argv[0] = a; - command->argv[1] = b; + Debug::SetXRegister(a, b); } stmt ::= HELP EOL. { - command->action = Help; - command->argc = 0; + Debug::Help(); } expr(rhs) ::= unary(a). { rhs = a; } @@ -221,7 +192,7 @@ unary(rhs) ::= PLUS unary(a). [BANG] { rhs = a; } unary(rhs) ::= MINUS unary(a). [BANG] { rhs = -a; } unary(rhs) ::= TILDE unary(a). { rhs = ~a; } unary(rhs) ::= BANG unary(a). { rhs = !a; } -unary(rhs) ::= STAR unary(a). [BANG] { rhs = debuggerReadLong(a); } +unary(rhs) ::= STAR unary(a). [BANG] { rhs = Debug::ReadLong(a); } term(rhs) ::= LPAREN expr(a) RPAREN. { rhs = a; } diff --git a/debugger/CMakeLists.txt b/debugger/CMakeLists.txt deleted file mode 100644 index 782d29c..0000000 --- a/debugger/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -set(CMAKE_INCLUDE_CURRENT_DIR ON) -add_definitions(-I ${CMAKE_SOURCE_DIR}/) - - -set(DEBUGGER_SRC lexer.cpp parser.cpp) - -add_custom_command( - OUTPUT lexer.cpp - COMMAND re2c -b -i -o lexer.cpp "${CMAKE_CURRENT_SOURCE_DIR}/lexer.re.cpp" - MAIN_DEPENDENCY lexer.re.cpp - DEPENDS commands.h parser.h -) - -add_custom_command( - OUTPUT parser.cpp parser.h - COMMAND cp -f "${CMAKE_CURRENT_SOURCE_DIR}/parser.lemon" "parser.lemon" - COMMAND lemon parser.lemon - COMMAND cp -f parser.h "${CMAKE_CURRENT_SOURCE_DIR}/" - COMMAND cp -f parser.out "${CMAKE_CURRENT_SOURCE_DIR}/" - COMMAND mv -f parser.c parser.cpp - MAIN_DEPENDENCY parser.lemon - DEPENDS commands.h -) - -add_library(DEBUGGER_LIB ${DEBUGGER_SRC}) \ No newline at end of file diff --git a/debugger/commands.h b/debugger/commands.h deleted file mode 100644 index b8f110f..0000000 --- a/debugger/commands.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __debugger_commands__ -#define __debugger_commands__ - - -enum { - NullCommand, - Help, - Print, - PrintRegisters, - Dump, - List, - Info, - Break, - TBreak, - Continue, - Step, - SetARegister, - SetDRegister, - SetXRegister, -}; - -struct Command { - bool valid; - int action; - uint32_t argc; - uint32_t argv[10]; -}; - - -#endif \ No newline at end of file