mirror of
https://github.com/ksherlock/mpw.git
synced 2024-12-26 11:30:25 +00:00
cleanup to move debugger to separate file
This commit is contained in:
parent
98b5455549
commit
ba2fba246b
@ -6,12 +6,14 @@ SET(CMAKE_EXE_LINKER_FLAGS "-framework Carbon")
|
||||
add_definitions(-I ${CMAKE_SOURCE_DIR}/)
|
||||
|
||||
|
||||
add_executable(mpw loader.cpp)
|
||||
add_executable(mpw loader.cpp debugger.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)
|
||||
target_link_libraries(mpw MACOS_LIB)
|
||||
set_target_properties(mpw PROPERTIES LINK_FLAGS "-ledit")
|
||||
|
||||
|
||||
add_executable(disasm disasm.cpp)
|
||||
|
172
bin/debugger.cpp
Normal file
172
bin/debugger.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <readline/readline.h>
|
||||
|
||||
|
||||
#include "loader.h"
|
||||
|
||||
#include <debugger/commands.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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DebugHelp(const Command &cmd)
|
||||
{
|
||||
printf("help\n");
|
||||
printf("break expression\n");
|
||||
printf("step");
|
||||
printf("continue");
|
||||
printf("\n");
|
||||
printf("print expression\n");
|
||||
printf("list expression\n");
|
||||
printf("dump expression\n");
|
||||
printf("register=expression\n");
|
||||
printf("\n");
|
||||
printf("registers: a0-7, d0-7, pc, sp, fp, csr\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
void DebugPrint(const Command &cmd)
|
||||
{
|
||||
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("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void hexdump(const uint8_t *data, ssize_t size, uint32_t address = 0)
|
||||
{
|
||||
const char *HexMap = "0123456789abcdef";
|
||||
|
||||
char buffer1[16 * 3 + 1 + 1];
|
||||
char buffer2[16 + 1];
|
||||
ssize_t offset = 0;
|
||||
unsigned i, j;
|
||||
|
||||
|
||||
while(size > 0)
|
||||
{
|
||||
std::memset(buffer1, ' ', sizeof(buffer1));
|
||||
std::memset(buffer2, ' ', sizeof(buffer2));
|
||||
|
||||
unsigned linelen = (unsigned)std::min(size, (ssize_t)16);
|
||||
|
||||
|
||||
for (i = 0, j = 0; i < linelen; i++)
|
||||
{
|
||||
unsigned x = data[i];
|
||||
buffer1[j++] = HexMap[x >> 4];
|
||||
buffer1[j++] = HexMap[x & 0x0f];
|
||||
j++;
|
||||
if (i == 7) j++;
|
||||
|
||||
// isascii not part of std:: and may be a macro.
|
||||
buffer2[i] = isascii(x) && std::isprint(x) ? x : '.';
|
||||
|
||||
}
|
||||
|
||||
buffer1[sizeof(buffer1)-1] = 0;
|
||||
buffer2[sizeof(buffer2)-1] = 0;
|
||||
|
||||
|
||||
std::printf("%08x:\t%s\t%s\n", address + (unsigned)offset, buffer1, buffer2);
|
||||
offset += 16;
|
||||
data += 16;
|
||||
size -= 16;
|
||||
}
|
||||
std::printf("\n");
|
||||
}
|
||||
|
||||
void DebugDump(const Command &cmd)
|
||||
{
|
||||
// TODO -- if no address, use previous address.
|
||||
if (cmd.argc == 1)
|
||||
{
|
||||
uint32_t start = cmd.argv[0];
|
||||
if (start > Flags.memorySize) return;
|
||||
|
||||
uint32_t end = std::min(start + 512, Flags.memorySize);
|
||||
ssize_t size = end - start;
|
||||
|
||||
hexdump(Flags.memory + start, size, start);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void DebugShell()
|
||||
{
|
||||
char *cp;
|
||||
|
||||
add_history("!Andy, it still has history!");
|
||||
for(;;)
|
||||
{
|
||||
cp = readline("] ");
|
||||
if (!cp)
|
||||
{
|
||||
printf("\n");
|
||||
break; // prompt for exit?
|
||||
}
|
||||
// parse the command...
|
||||
const char *iter = cp;
|
||||
while (*iter && isspace(*iter)) ++iter;
|
||||
|
||||
if (*iter)
|
||||
{
|
||||
Command cmd;
|
||||
std::memset(&cmd, 0, sizeof(cmd));
|
||||
if (ParseLine(iter, &cmd))
|
||||
{
|
||||
switch(cmd.action)
|
||||
{
|
||||
case Print:
|
||||
DebugPrint(cmd);
|
||||
break;
|
||||
|
||||
case Dump:
|
||||
DebugDump(cmd);
|
||||
break;
|
||||
|
||||
default:
|
||||
DebugHelp(cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// todo -- don't add if same as previous command.
|
||||
add_history(cp);
|
||||
}
|
||||
free(cp);
|
||||
}
|
||||
|
||||
}
|
||||
|
224
bin/loader.cpp
224
bin/loader.cpp
@ -1,6 +1,7 @@
|
||||
// clang++ -c -std=c++11 -stdlib=libc++ -Wno-deprecated-declarations loader.cpp
|
||||
|
||||
#include <cstdint>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -27,21 +28,9 @@
|
||||
#include <macos/sysequ.h>
|
||||
#include <macos/traps.h>
|
||||
|
||||
struct {
|
||||
uint32_t ram;
|
||||
uint32_t stack;
|
||||
uint32_t machine;
|
||||
|
||||
bool traceCPU;
|
||||
bool traceMacsbug;
|
||||
bool traceGlobals;
|
||||
bool traceToolBox;
|
||||
bool traceMPW;
|
||||
|
||||
bool memoryStats;
|
||||
|
||||
} Flags = { 16 * 1024 * 1024, 8 * 1024, 68030, false, false, false, false, false, false};
|
||||
#include "loader.h"
|
||||
|
||||
Settings Flags;
|
||||
|
||||
const uint32_t kGlobalSize = 0x10000;
|
||||
// retained to make debugging easier.
|
||||
@ -113,6 +102,8 @@ void WriteLong(void *data, uint32_t offset, uint32_t value)
|
||||
((uint8_t *)data)[offset++] = value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32_t load(const char *file)
|
||||
{
|
||||
|
||||
@ -280,10 +271,41 @@ void GlobalInit()
|
||||
// so put stack at top of memory?
|
||||
|
||||
// 0x0130 -- ApplLimit
|
||||
memoryWriteLong(Flags.ram - 1, MacOS::ApplLimit);
|
||||
memoryWriteLong(Flags.memorySize - 1, MacOS::ApplLimit);
|
||||
}
|
||||
|
||||
|
||||
void CreateStack()
|
||||
{
|
||||
// allocate stack, set A7...
|
||||
|
||||
uint32_t address;
|
||||
uint16_t error;
|
||||
|
||||
Flags.stackSize = (Flags.stackSize + 3) & ~0x03;
|
||||
|
||||
error = MM::Native::NewPtr(Flags.stackSize, true, address);
|
||||
if (error)
|
||||
{
|
||||
fprintf(stderr, "Unable to allocate stack (%08x bytes)\n", Flags.stackSize);
|
||||
exit(EX_CONFIG);
|
||||
}
|
||||
|
||||
|
||||
Flags.stackRange.first = address;
|
||||
Flags.stackRange.second = address + Flags.stackSize;
|
||||
|
||||
// TODO -- is there a global for the max (min) stack pointer?
|
||||
|
||||
// address grows down
|
||||
// -4 is for the return address.
|
||||
cpuSetAReg(7, Flags.stackRange.second - 4);
|
||||
// return address.
|
||||
memoryWriteLong(MacOS::MinusOne, Flags.stackRange.second - 4); // MinusOne Global -- 0xffff ffff
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LogToolBox(uint32_t pc, uint16_t trap)
|
||||
{
|
||||
const char *name;
|
||||
@ -509,6 +531,62 @@ std::string find_exe(const std::string &name)
|
||||
}
|
||||
|
||||
|
||||
void MainLoop()
|
||||
{
|
||||
#if 0
|
||||
auto begin_emu_time = std::chrono::high_resolution_clock::now();
|
||||
fprintf(stderr, "Begin Emulation Time: %20lld\n", (begin_emu_time - start_time).count());
|
||||
#endif
|
||||
|
||||
|
||||
uint64_t cycles = 0;
|
||||
for (;;)
|
||||
{
|
||||
uint32_t pc = cpuGetPC();
|
||||
uint32_t sp = cpuGetAReg(7);
|
||||
|
||||
if (pc == 0x00000000)
|
||||
{
|
||||
fprintf(stderr, "Exiting - PC = 0\n");
|
||||
exit(EX_SOFTWARE);
|
||||
}
|
||||
|
||||
if (sp < Flags.stackRange.first)
|
||||
{
|
||||
fprintf(stderr, "Stack overflow error - please increase the stack size (--stack=size)\n");
|
||||
fprintf(stderr, "Current stack size is 0x%06x\n", Flags.stackSize);
|
||||
exit(EX_SOFTWARE);
|
||||
}
|
||||
|
||||
if (sp > Flags.stackRange.second)
|
||||
{
|
||||
fprintf(stderr, "Stack underflow error\n");
|
||||
exit(EX_SOFTWARE);
|
||||
}
|
||||
|
||||
|
||||
if (cpuGetStop()) break; // will this also be set by an interrupt?
|
||||
|
||||
|
||||
#ifndef CPU_INSTRUCTION_LOGGING
|
||||
if (Flags.traceCPU || Flags.traceMacsbug)
|
||||
{
|
||||
InstructionLogger();
|
||||
}
|
||||
#endif
|
||||
|
||||
cycles += cpuExecuteInstruction();
|
||||
}
|
||||
|
||||
#if 0
|
||||
auto end_emu_time = std::chrono::high_resolution_clock::now();
|
||||
fprintf(stderr, " End Emulation Time: %20lld\n", (end_emu_time - start_time).count());
|
||||
fprintf(stderr, " Cycles: %20lld\n", cycles);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
// getopt...
|
||||
@ -520,6 +598,7 @@ int main(int argc, char **argv)
|
||||
kTraceGlobals,
|
||||
kTraceToolBox,
|
||||
kTraceMPW,
|
||||
kDebugger,
|
||||
kMemoryStats,
|
||||
};
|
||||
static struct option LongOpts[] =
|
||||
@ -534,6 +613,9 @@ int main(int argc, char **argv)
|
||||
{ "trace-tools", no_argument, NULL, kTraceToolBox },
|
||||
{ "trace-mpw", no_argument, NULL, kTraceMPW },
|
||||
|
||||
{ "debug", no_argument, NULL, kDebugger },
|
||||
{ "debugger", no_argument, NULL, kDebugger },
|
||||
|
||||
{ "memory-stats", no_argument, NULL, kMemoryStats },
|
||||
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
@ -572,18 +654,22 @@ int main(int argc, char **argv)
|
||||
Flags.memoryStats = true;
|
||||
break;
|
||||
|
||||
case kDebugger:
|
||||
Flags.debugger = true;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (!parse_number(optarg, &Flags.machine))
|
||||
exit(EX_CONFIG);
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
if (!parse_number(optarg, &Flags.ram))
|
||||
if (!parse_number(optarg, &Flags.memorySize))
|
||||
exit(EX_CONFIG);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (!parse_number(optarg, &Flags.stack))
|
||||
if (!parse_number(optarg, &Flags.stackSize))
|
||||
exit(EX_CONFIG);
|
||||
break;
|
||||
|
||||
@ -615,6 +701,19 @@ int main(int argc, char **argv)
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
|
||||
if (Flags.stackSize < 0x100)
|
||||
{
|
||||
fprintf(stderr, "Invalid stack size\n");
|
||||
exit(EX_CONFIG);
|
||||
}
|
||||
|
||||
if (Flags.memorySize < 0x200)
|
||||
{
|
||||
fprintf(stderr, "Invalid ram size\n");
|
||||
exit(EX_CONFIG);
|
||||
}
|
||||
|
||||
|
||||
std::string command(argv[0]); // InitMPW updates argv...
|
||||
|
||||
command = find_exe(command);
|
||||
@ -628,9 +727,9 @@ int main(int argc, char **argv)
|
||||
argv[0] = ::strdup(command.c_str()); // hmm.. could setenv(mpw_command) instead.
|
||||
|
||||
|
||||
|
||||
Memory = new uint8_t[Flags.ram];
|
||||
MemorySize = Flags.ram;
|
||||
// move to CreateRam()
|
||||
Memory = Flags.memory = new uint8_t[Flags.memorySize];
|
||||
MemorySize = Flags.memorySize;
|
||||
|
||||
|
||||
/// ahhh... need to set PC after memory.
|
||||
@ -649,39 +748,7 @@ int main(int argc, char **argv)
|
||||
cpuSetModel(3,0);
|
||||
|
||||
|
||||
|
||||
if (!Flags.stack)
|
||||
{
|
||||
fprintf(stderr, "Invalid stack size\n");
|
||||
exit(EX_CONFIG);
|
||||
}
|
||||
|
||||
std::pair<uint32_t, uint32_t> StackRange;
|
||||
// allocate stack, set A7...
|
||||
{
|
||||
uint32_t address;
|
||||
uint16_t error;
|
||||
|
||||
Flags.stack = (Flags.stack + 3) & ~0x03;
|
||||
|
||||
error = MM::Native::NewPtr(Flags.stack, true, address);
|
||||
if (error)
|
||||
{
|
||||
fprintf(stderr, "Unable to allocate stack (%08x bytes)\n", Flags.stack);
|
||||
exit(EX_CONFIG);
|
||||
}
|
||||
|
||||
StackRange.first = address;
|
||||
StackRange.second = address + Flags.stack;
|
||||
|
||||
// TODO -- is there a global for the max (min) stack pointer?
|
||||
|
||||
// address grows down
|
||||
// -4 is for the return address.
|
||||
cpuSetAReg(7, address + Flags.stack - 4);
|
||||
// return address.
|
||||
memoryWriteLong(MacOS::MinusOne, StackRange.second - 4); // MinusOne Global -- 0xffff ffff
|
||||
}
|
||||
CreateStack();
|
||||
|
||||
|
||||
uint32_t address = load(command.c_str());
|
||||
@ -712,58 +779,11 @@ int main(int argc, char **argv)
|
||||
|
||||
cpuInitializeFromNewPC(address);
|
||||
|
||||
#if 0
|
||||
auto begin_emu_time = std::chrono::high_resolution_clock::now();
|
||||
fprintf(stderr, "Begin Emulation Time: %20lld\n", (begin_emu_time - start_time).count());
|
||||
#endif
|
||||
|
||||
uint64_t cycles = 0;
|
||||
for (;;)
|
||||
{
|
||||
uint32_t pc = cpuGetPC();
|
||||
uint32_t sp = cpuGetAReg(7);
|
||||
|
||||
if (pc == 0x00000000)
|
||||
{
|
||||
fprintf(stderr, "Exiting - PC = 0\n");
|
||||
exit(EX_SOFTWARE);
|
||||
}
|
||||
|
||||
if (sp < StackRange.first)
|
||||
{
|
||||
fprintf(stderr, "Stack overflow error - please increase the stack size (--stack=size)\n");
|
||||
fprintf(stderr, "Current stack size is 0x%06x\n", Flags.stack);
|
||||
exit(EX_SOFTWARE);
|
||||
}
|
||||
|
||||
if (sp > StackRange.second)
|
||||
{
|
||||
fprintf(stderr, "Stack underflow error\n");
|
||||
exit(EX_SOFTWARE);
|
||||
}
|
||||
if (Flags.debugger) DebugShell();
|
||||
else MainLoop();
|
||||
|
||||
|
||||
if (cpuGetStop()) break; // will this also be set by an interrupt?
|
||||
|
||||
|
||||
|
||||
#ifndef CPU_INSTRUCTION_LOGGING
|
||||
if (Flags.traceCPU || Flags.traceMacsbug)
|
||||
{
|
||||
InstructionLogger();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
cycles += cpuExecuteInstruction();
|
||||
}
|
||||
|
||||
#if 0
|
||||
auto end_emu_time = std::chrono::high_resolution_clock::now();
|
||||
fprintf(stderr, " End Emulation Time: %20lld\n", (end_emu_time - start_time).count());
|
||||
fprintf(stderr, " Cycles: %20lld\n", cycles);
|
||||
#endif
|
||||
|
||||
if (Flags.memoryStats)
|
||||
{
|
||||
|
41
bin/loader.h
Normal file
41
bin/loader.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef __mpw_loader__
|
||||
#define __mpw_loader__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
struct Settings {
|
||||
Settings() {}
|
||||
|
||||
// command-line settings.
|
||||
|
||||
uint32_t memorySize = 16 * 1024 * 1024;
|
||||
uint32_t stackSize = 16 * 1024;
|
||||
uint32_t machine = 68030;
|
||||
|
||||
bool traceCPU = false;
|
||||
bool traceMacsbug = false;
|
||||
bool traceGlobals = false;
|
||||
bool traceToolBox = false;
|
||||
bool traceMPW = false;
|
||||
|
||||
bool debugger = false;
|
||||
|
||||
bool memoryStats = false;
|
||||
|
||||
|
||||
// updated later.
|
||||
std::pair<uint32_t, uint32_t> stackRange = {0, 0};
|
||||
uint8_t *memory = nullptr;
|
||||
|
||||
uint64_t cycles = 0;
|
||||
|
||||
const uint32_t kGlobalSize = 0x10000;
|
||||
};
|
||||
|
||||
|
||||
extern Settings Flags;
|
||||
|
||||
void DebugShell();
|
||||
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user