mirror of
https://github.com/ksherlock/mpw.git
synced 2024-11-28 08:49:20 +00:00
move debugger code into bin, clean up dispatch
This commit is contained in:
parent
62a374ee16
commit
6fbde7e1bf
@ -12,4 +12,3 @@ add_subdirectory(toolbox)
|
|||||||
add_subdirectory(mplite)
|
add_subdirectory(mplite)
|
||||||
add_subdirectory(mpw)
|
add_subdirectory(mpw)
|
||||||
add_subdirectory(macos)
|
add_subdirectory(macos)
|
||||||
add_subdirectory(debugger)
|
|
@ -2,13 +2,32 @@
|
|||||||
#set(CMAKE_CXX_COMPILER "clang++")
|
#set(CMAKE_CXX_COMPILER "clang++")
|
||||||
set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -Wall -Wno-deprecated-declarations -g")
|
set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -Wall -Wno-deprecated-declarations -g")
|
||||||
SET(CMAKE_EXE_LINKER_FLAGS "-framework Carbon")
|
SET(CMAKE_EXE_LINKER_FLAGS "-framework Carbon")
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
add_definitions(-I ${CMAKE_SOURCE_DIR}/)
|
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 CPU_LIB)
|
||||||
target_link_libraries(mpw DEBUGGER_LIB)
|
|
||||||
target_link_libraries(mpw TOOLBOX_LIB)
|
target_link_libraries(mpw TOOLBOX_LIB)
|
||||||
target_link_libraries(mpw MPW_LIB)
|
target_link_libraries(mpw MPW_LIB)
|
||||||
target_link_libraries(mpw MPLITE_LIB)
|
target_link_libraries(mpw MPLITE_LIB)
|
||||||
|
307
bin/debugger.cpp
307
bin/debugger.cpp
@ -20,7 +20,7 @@
|
|||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
#include "address_map.h"
|
#include "address_map.h"
|
||||||
|
|
||||||
#include <debugger/commands.h>
|
#include "debugger.h"
|
||||||
|
|
||||||
#include <cpu/defs.h>
|
#include <cpu/defs.h>
|
||||||
#include <cpu/CpuModule.h>
|
#include <cpu/CpuModule.h>
|
||||||
@ -28,45 +28,6 @@
|
|||||||
#include <macos/traps.h>
|
#include <macos/traps.h>
|
||||||
#include <macos/sysequ.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 {
|
namespace {
|
||||||
|
|
||||||
bool sigInt = false;
|
bool sigInt = false;
|
||||||
@ -148,7 +109,7 @@ namespace {
|
|||||||
pc += mboffset;
|
pc += mboffset;
|
||||||
// check for MacsBug name after rts.
|
// check for MacsBug name after rts.
|
||||||
std::string s;
|
std::string s;
|
||||||
unsigned b = debuggerReadByte(pc);
|
unsigned b = Debug::ReadByte(pc);
|
||||||
if (b > 0x80 && b < 0xa0)
|
if (b > 0x80 && b < 0xa0)
|
||||||
{
|
{
|
||||||
b -= 0x80;
|
b -= 0x80;
|
||||||
@ -156,7 +117,7 @@ namespace {
|
|||||||
s.reserve(b);
|
s.reserve(b);
|
||||||
for (unsigned i = 0; i < b; ++i)
|
for (unsigned i = 0; i < b; ++i)
|
||||||
{
|
{
|
||||||
s.push_back(debuggerReadByte(pc++));
|
s.push_back(Debug::ReadByte(pc++));
|
||||||
}
|
}
|
||||||
printf("%s\n", s.c_str());
|
printf("%s\n", s.c_str());
|
||||||
}
|
}
|
||||||
@ -175,7 +136,7 @@ namespace {
|
|||||||
return pc;
|
return pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t opcode = debuggerReadWord(pc);
|
uint16_t opcode = Debug::ReadWord(pc);
|
||||||
if (op) *op = opcode;
|
if (op) *op = opcode;
|
||||||
|
|
||||||
if ((opcode & 0xf000) == 0xa000)
|
if ((opcode & 0xf000) == 0xa000)
|
||||||
@ -220,7 +181,7 @@ namespace {
|
|||||||
|
|
||||||
uint32_t pc = cpuGetPC();
|
uint32_t pc = cpuGetPC();
|
||||||
if (trace) disasm(pc, &op);
|
if (trace) disasm(pc, &op);
|
||||||
else op = debuggerReadWord(pc);
|
else op = Debug::ReadWord(pc);
|
||||||
|
|
||||||
if (Flags.traceMacsbug && !trace)
|
if (Flags.traceMacsbug && !trace)
|
||||||
printMacsbug(pc, op);
|
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("help\n");
|
||||||
printf("break expression\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)
|
printf("$%08x %12u", data, data);
|
||||||
{
|
if (data & 0x80000000)
|
||||||
uint32_t data = cmd.argv[i];
|
printf(" %12d", (int32_t)data);
|
||||||
printf("$%08x %12u", data, data);
|
if ((data & 0xffff8000) == 0x8000)
|
||||||
if (data & 0x80000000)
|
printf(" %6d", (int16_t)data);
|
||||||
printf(" %12d", (int32_t)data);
|
|
||||||
if ((data & 0xffff8000) == 0x8000)
|
printf("\n");
|
||||||
printf(" %6d", (int16_t)data);
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DebugDump(const Command &cmd)
|
void Dump(uint32_t start, int size)
|
||||||
{
|
{
|
||||||
// TODO -- if no address, use previous address.
|
// TODO -- if no address, use previous address.
|
||||||
// TODO -- support range?
|
// TODO -- support range?
|
||||||
|
|
||||||
|
|
||||||
uint32_t start = cmd.argv[0];
|
if (size <= 0) return;
|
||||||
uint32_t end = cmd.argc == 2 ? cmd.argv[1] : start + 256;
|
|
||||||
|
uint32_t end = start + size;
|
||||||
|
|
||||||
if (start >= Flags.memorySize) return;
|
if (start >= Flags.memorySize) return;
|
||||||
|
|
||||||
end = std::min(end, Flags.memorySize);
|
end = std::min(end, Flags.memorySize);
|
||||||
ssize_t size = end - start;
|
size = end - start;
|
||||||
|
|
||||||
hexdump(Flags.memory + start, size, 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 -- if no address, use previous address.
|
||||||
// TODO -- support range?
|
if (pc & 0x01)
|
||||||
if (cmd.argc == 1)
|
|
||||||
{
|
{
|
||||||
uint32_t pc = cmd.argv[0];
|
printf("address is not aligned: $%08x\n", pc);
|
||||||
if (pc & 0x01)
|
return;
|
||||||
{
|
}
|
||||||
printf("address is not aligned: $%08x\n", pc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < 32; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
if (pc >= Flags.memorySize) break;
|
if (pc >= Flags.memorySize) break;
|
||||||
pc = disasm(pc);
|
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];
|
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];
|
tool = -tool;
|
||||||
bool remove = false;
|
remove = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (tool < 0)
|
if (tool >= 0xa000 && tool <= 0xafff)
|
||||||
{
|
{
|
||||||
tool = -tool;
|
if (remove) tbrkMap.remove(tool);
|
||||||
remove = true;
|
else tbrkMap.add(tool);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (tool >= 0xa000 && tool <= 0xafff)
|
{
|
||||||
{
|
fprintf(stderr, "Invalid tool: $%04x\n", tool);
|
||||||
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.
|
// 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];
|
address = -address;
|
||||||
bool remove = false;
|
remove = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (address < 0)
|
if ((address & 0xff000000) == 0)
|
||||||
{
|
{
|
||||||
address = -address;
|
if (remove) brkMap.remove(address);
|
||||||
remove = true;
|
else brkMap.add(address);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if ((address & 0xff000000) == 0)
|
{
|
||||||
{
|
fprintf(stderr, "Invalid address: $%08x\n", address);
|
||||||
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 n to step specified # of instructions.
|
||||||
// TODO -- step @address to step until address?
|
// 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)) ;
|
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) return;
|
||||||
if (reg == 7)
|
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;
|
if (reg > 7) return;
|
||||||
unsigned reg = cmd.argv[0];
|
|
||||||
uint32_t value = cmd.argv[1];
|
|
||||||
|
|
||||||
cpuSetDReg(reg, value);
|
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)
|
if (reg == 0)
|
||||||
{
|
{
|
||||||
@ -541,7 +537,7 @@ void DebugSetXRegister(Command &cmd)
|
|||||||
|
|
||||||
if (reg == 1)
|
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 -- RUN command - reload, re-initialize, re-execute
|
||||||
// TODO -- parser calls commands directly (except trace/step/run/etc)
|
// TODO -- parser calls commands directly (except trace/step/run/etc)
|
||||||
void DebugShell()
|
void Shell()
|
||||||
{
|
{
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
@ -582,55 +578,19 @@ void DebugShell()
|
|||||||
{
|
{
|
||||||
switch(cmd.action)
|
switch(cmd.action)
|
||||||
{
|
{
|
||||||
case NullCommand:
|
case cmdNull:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Print:
|
case cmdStep:
|
||||||
DebugPrint(cmd);
|
Step(cmd);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Dump:
|
case cmdContinue:
|
||||||
DebugDump(cmd);
|
Continue(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);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
DebugHelp(cmd);
|
Help();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -643,3 +603,6 @@ void DebugShell()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace Debugger
|
||||||
|
|
||||||
|
|
||||||
|
51
bin/debugger.h
Normal file
51
bin/debugger.h
Normal 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
|
@ -6,7 +6,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "commands.h"
|
#include "debugger.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
|
||||||
// re2c -b -i
|
// re2c -b -i
|
||||||
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
void *ParseAlloc(void *(*mallocProc)(size_t));
|
void *ParseAlloc(void *(*mallocProc)(size_t));
|
||||||
void ParseFree(void *p, void (*freeProc)(void*));
|
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);
|
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)
|
bool ParseLine(const char *iter, Command *command)
|
||||||
{
|
{
|
||||||
void *parser;
|
void *parser;
|
||||||
@ -110,7 +61,7 @@ bool ParseLine(const char *iter, Command *command)
|
|||||||
parser = ParseAlloc(malloc);
|
parser = ParseAlloc(malloc);
|
||||||
|
|
||||||
//ParseTrace(stdout, "--> ");
|
//ParseTrace(stdout, "--> ");
|
||||||
|
command->action = cmdNull;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
const char *begin = iter;
|
const char *begin = iter;
|
||||||
@ -351,4 +302,6 @@ bool ParseLine(const char *iter, Command *command)
|
|||||||
fprintf(stderr,"I don't understand.\n");
|
fprintf(stderr,"I don't understand.\n");
|
||||||
|
|
||||||
return command->valid;
|
return command->valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace Debugger
|
@ -29,6 +29,7 @@
|
|||||||
#include <macos/traps.h>
|
#include <macos/traps.h>
|
||||||
|
|
||||||
#include "loader.h"
|
#include "loader.h"
|
||||||
|
#include "debugger.h"
|
||||||
|
|
||||||
Settings Flags;
|
Settings Flags;
|
||||||
|
|
||||||
@ -767,7 +768,7 @@ int main(int argc, char **argv)
|
|||||||
cpuInitializeFromNewPC(address);
|
cpuInitializeFromNewPC(address);
|
||||||
|
|
||||||
|
|
||||||
if (Flags.debugger) DebugShell();
|
if (Flags.debugger) Debug::Shell();
|
||||||
else MainLoop();
|
else MainLoop();
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
%extra_argument { struct Command *command }
|
%extra_argument { Debug::Command *command }
|
||||||
%token_prefix tk
|
%token_prefix tk
|
||||||
|
|
||||||
%token_type {uint32_t}
|
%token_type {uint32_t}
|
||||||
@ -7,7 +7,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "commands.h"
|
#include "debugger.h"
|
||||||
|
|
||||||
#include <toolbox/MM.h>
|
#include <toolbox/MM.h>
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -18,7 +18,6 @@ uint32_t cpuGetSR();
|
|||||||
uint32_t cpuGetPC();
|
uint32_t cpuGetPC();
|
||||||
uint32_t cpuGetAReg(unsigned);
|
uint32_t cpuGetAReg(unsigned);
|
||||||
uint32_t cpuGetDReg(unsigned);
|
uint32_t cpuGetDReg(unsigned);
|
||||||
uint32_t debuggerReadLong(uint32_t);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
@ -55,103 +54,87 @@ uint32_t debuggerReadLong(uint32_t);
|
|||||||
|
|
||||||
stmt ::= expr(a) EOL.
|
stmt ::= expr(a) EOL.
|
||||||
{
|
{
|
||||||
command->action = Print;
|
Debug::Print(a);
|
||||||
command->argc = 1;
|
|
||||||
command->argv[0] = a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= STAR EOL.
|
stmt ::= STAR EOL.
|
||||||
{
|
{
|
||||||
command->action = PrintRegisters;
|
Debug::PrintRegisters();
|
||||||
command->argc = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= PRINT expr(a) EOL.
|
stmt ::= PRINT expr(a) EOL.
|
||||||
{
|
{
|
||||||
command->action = Print;
|
Debug::Print(a);
|
||||||
command->argc = 1;
|
|
||||||
command->argv[0] = a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= BREAK expr(a) EOL.
|
stmt ::= BREAK expr(a) EOL.
|
||||||
{
|
{
|
||||||
command->action = Break;
|
Debug::Break(a);
|
||||||
command->argc = 1;
|
|
||||||
command->argv[0] = a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= CONTINUE EOL.
|
stmt ::= CONTINUE EOL.
|
||||||
{
|
{
|
||||||
command->action = Continue;
|
command->action = Debug::cmdContinue;
|
||||||
command->argc = 0;
|
command->argc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= TBREAK expr(a) EOL.
|
stmt ::= TBREAK expr(a) EOL.
|
||||||
{
|
{
|
||||||
// negative number = remove it.
|
Debug::ToolBreak(a);
|
||||||
command->action = TBreak;
|
|
||||||
command->argc = 1;
|
|
||||||
command->argv[0] = a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= NEXT EOL.
|
stmt ::= NEXT EOL.
|
||||||
{
|
{
|
||||||
command->action = Step;
|
command->action = Debug::cmdStep;
|
||||||
command->argc = 0;
|
command->argc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= NEXT expr(a) EOL.
|
stmt ::= NEXT expr(a) EOL.
|
||||||
{
|
{
|
||||||
command->action = Step;
|
command->action = Debug::cmdStep;
|
||||||
command->argc = 1;
|
command->argc = 1;
|
||||||
command->argv[0] = a;
|
command->argv[0] = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= DUMP expr(a) EOL.
|
stmt ::= DUMP expr(a) EOL.
|
||||||
{
|
{
|
||||||
command->action = Dump;
|
Debug::Dump(a);
|
||||||
command->argc = 1;
|
|
||||||
command->argv[0] = a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= DUMP expr(a) COLON expr(b) EOL.
|
stmt ::= DUMP expr(a) COLON expr(b) EOL.
|
||||||
{
|
{
|
||||||
// range dump
|
Debug::Dump(a, b - a);
|
||||||
command->action = Dump;
|
|
||||||
command->argc = 2;
|
|
||||||
command->argv[0] = a;
|
|
||||||
command->argv[1] = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= DUMP expr(a) AT expr(b) EOL.
|
stmt ::= DUMP expr(a) AT expr(b) EOL.
|
||||||
{
|
{
|
||||||
// count dump
|
Debug::Dump(a, b);
|
||||||
command->action = Dump;
|
|
||||||
command->argc = 2;
|
|
||||||
command->argv[0] = a;
|
|
||||||
command->argv[1] = a+b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= LIST expr(a) EOL.
|
stmt ::= LIST expr(a) EOL.
|
||||||
{
|
{
|
||||||
command->action = List;
|
Debug::List(a);
|
||||||
command->argc = 1;
|
|
||||||
command->argv[0] = a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
stmt ::= expr(a) SEMIH EOL.
|
stmt ::= expr(a) SEMIH EOL.
|
||||||
{
|
{
|
||||||
command->action = Dump;
|
Debug::Dump(a);
|
||||||
command->argc = 1;
|
|
||||||
command->argv[0] = 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.
|
stmt ::= expr(a) SEMII EOL.
|
||||||
{
|
{
|
||||||
command->action = NullCommand;
|
|
||||||
command->argc = 0;
|
|
||||||
|
|
||||||
MM::Native::MemoryInfo(a);
|
MM::Native::MemoryInfo(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,40 +142,28 @@ stmt ::= expr(a) SEMII EOL.
|
|||||||
|
|
||||||
stmt ::= expr(a) SEMIL EOL.
|
stmt ::= expr(a) SEMIL EOL.
|
||||||
{
|
{
|
||||||
command->action = List;
|
Debug::List(a);
|
||||||
command->argc = 1;
|
|
||||||
command->argv[0] = a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
stmt ::= DREGISTER(a) EQ expr(b) EOL.
|
stmt ::= DREGISTER(a) EQ expr(b) EOL.
|
||||||
{
|
{
|
||||||
command->action = SetDRegister;
|
Debug::SetDRegister(a, b);
|
||||||
command->argc = 2;
|
|
||||||
command->argv[0] = a;
|
|
||||||
command->argv[1] = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= AREGISTER(a) EQ expr(b) EOL.
|
stmt ::= AREGISTER(a) EQ expr(b) EOL.
|
||||||
{
|
{
|
||||||
command->action = SetARegister;
|
Debug::SetARegister(a, b);
|
||||||
command->argc = 2;
|
|
||||||
command->argv[0] = a;
|
|
||||||
command->argv[1] = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= XREGISTER(a) EQ expr(b) EOL.
|
stmt ::= XREGISTER(a) EQ expr(b) EOL.
|
||||||
{
|
{
|
||||||
command->action = SetXRegister;
|
Debug::SetXRegister(a, b);
|
||||||
command->argc = 2;
|
|
||||||
command->argv[0] = a;
|
|
||||||
command->argv[1] = b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt ::= HELP EOL.
|
stmt ::= HELP EOL.
|
||||||
{
|
{
|
||||||
command->action = Help;
|
Debug::Help();
|
||||||
command->argc = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expr(rhs) ::= unary(a). { rhs = a; }
|
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) ::= MINUS unary(a). [BANG] { rhs = -a; }
|
||||||
unary(rhs) ::= TILDE unary(a). { rhs = ~a; }
|
unary(rhs) ::= TILDE unary(a). { rhs = ~a; }
|
||||||
unary(rhs) ::= BANG 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; }
|
term(rhs) ::= LPAREN expr(a) RPAREN. { rhs = a; }
|
@ -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})
|
|
@ -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
|
|
Loading…
Reference in New Issue
Block a user