move debugger code into bin, clean up dispatch

This commit is contained in:
Kelvin Sherlock 2013-07-06 16:38:11 -04:00
parent 62a374ee16
commit 6fbde7e1bf
9 changed files with 248 additions and 346 deletions

View File

@ -12,4 +12,3 @@ add_subdirectory(toolbox)
add_subdirectory(mplite)
add_subdirectory(mpw)
add_subdirectory(macos)
add_subdirectory(debugger)

View File

@ -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)

View File

@ -20,7 +20,7 @@
#include "loader.h"
#include "address_map.h"
#include <debugger/commands.h>
#include "debugger.h"
#include <cpu/defs.h>
#include <cpu/CpuModule.h>
@ -28,45 +28,6 @@
#include <macos/traps.h>
#include <macos/sysequ.h>
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

51
bin/debugger.h Normal file
View File

@ -0,0 +1,51 @@
#ifndef __debugger_h__
#define __debugger_h__
#include <cstdint>
// 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

View File

@ -6,7 +6,7 @@
#include <cstdint>
#include <stdlib.h>
#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<uint32_t> 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;
}
}
} // namespace Debugger

View File

@ -29,6 +29,7 @@
#include <macos/traps.h>
#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();

View File

@ -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 <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "commands.h"
#include "debugger.h"
#include <toolbox/MM.h>
#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; }

View File

@ -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})

View File

@ -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