cleanup to move debugger to separate file

This commit is contained in:
Kelvin Sherlock 2013-07-03 23:50:30 -04:00
parent 98b5455549
commit ba2fba246b
4 changed files with 338 additions and 103 deletions

View File

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

View File

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