2013-07-03 23:50:30 -04:00
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
#include <cctype>
|
|
|
|
#include <cstring>
|
2013-07-04 00:29:09 -04:00
|
|
|
#include <cstdlib>
|
|
|
|
|
2013-07-04 12:52:35 -04:00
|
|
|
#include <signal.h>
|
|
|
|
|
2013-07-03 23:50:30 -04:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2013-07-04 12:12:44 -04:00
|
|
|
#include <array>
|
2013-07-04 00:29:09 -04:00
|
|
|
#include <unordered_set>
|
2013-07-04 12:12:44 -04:00
|
|
|
#include <unordered_map>
|
|
|
|
|
2013-07-04 00:29:09 -04:00
|
|
|
#include <bitset>
|
2013-07-03 23:50:30 -04:00
|
|
|
|
|
|
|
#include <readline/readline.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include "loader.h"
|
2013-07-05 13:54:15 -04:00
|
|
|
#include "address_map.h"
|
2013-07-03 23:50:30 -04:00
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
#include "debugger.h"
|
2013-07-03 23:50:30 -04:00
|
|
|
|
2013-07-04 00:29:09 -04:00
|
|
|
#include <cpu/defs.h>
|
|
|
|
#include <cpu/CpuModule.h>
|
2013-07-03 23:50:30 -04:00
|
|
|
|
2013-07-04 00:29:09 -04:00
|
|
|
#include <macos/traps.h>
|
|
|
|
#include <macos/sysequ.h>
|
|
|
|
|
2013-07-04 12:52:35 -04:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
bool sigInt = false;
|
|
|
|
void sigIntHandler(int)
|
|
|
|
{
|
|
|
|
sigInt = true;
|
|
|
|
}
|
|
|
|
|
2013-07-05 13:54:15 -04:00
|
|
|
AddressMap brkMap; // address breaks
|
|
|
|
AddressMap rbrkMap; // read breaks.
|
|
|
|
AddressMap wbrkMap; // write breaks.
|
|
|
|
ToolMap tbrkMap; // tool breaks.
|
2013-07-04 12:12:44 -04:00
|
|
|
|
|
|
|
|
2013-07-04 00:29:09 -04:00
|
|
|
|
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2013-07-05 13:54:44 -04:00
|
|
|
|
|
|
|
void printMacsbug(uint32_t pc, uint32_t opcode)
|
|
|
|
{
|
|
|
|
|
|
|
|
unsigned mboffset;
|
|
|
|
switch(opcode)
|
|
|
|
{
|
|
|
|
case 0x4E75: // rts
|
|
|
|
case 0x4ED0: // jmp (a0)
|
|
|
|
mboffset = 2;
|
|
|
|
break;
|
|
|
|
case 0x4E74: // rtd #
|
|
|
|
mboffset = 4;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pc += mboffset;
|
|
|
|
// check for MacsBug name after rts.
|
|
|
|
std::string s;
|
2013-07-06 16:38:11 -04:00
|
|
|
unsigned b = Debug::ReadByte(pc);
|
2013-07-05 13:54:44 -04:00
|
|
|
if (b > 0x80 && b < 0xa0)
|
|
|
|
{
|
|
|
|
b -= 0x80;
|
|
|
|
pc++;
|
|
|
|
s.reserve(b);
|
|
|
|
for (unsigned i = 0; i < b; ++i)
|
|
|
|
{
|
2013-07-06 16:38:11 -04:00
|
|
|
s.push_back(Debug::ReadByte(pc++));
|
2013-07-05 13:54:44 -04:00
|
|
|
}
|
|
|
|
printf("%s\n", s.c_str());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-04 12:13:31 -04:00
|
|
|
uint32_t disasm(uint32_t pc, uint16_t *op = nullptr)
|
|
|
|
{
|
2013-07-04 00:29:09 -04:00
|
|
|
|
2013-07-04 12:13:31 -04:00
|
|
|
static char strings[4][256];
|
2013-07-03 23:50:30 -04:00
|
|
|
|
2013-07-04 12:13:31 -04:00
|
|
|
if (pc >= Flags.memorySize)
|
2013-07-03 23:50:30 -04:00
|
|
|
{
|
2013-07-04 12:13:31 -04:00
|
|
|
if (op) *op = 0;
|
|
|
|
return pc;
|
2013-07-03 23:50:30 -04:00
|
|
|
}
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
uint16_t opcode = Debug::ReadWord(pc);
|
2013-07-04 12:13:31 -04:00
|
|
|
if (op) *op = opcode;
|
2013-07-03 23:50:30 -04:00
|
|
|
|
2013-07-04 12:13:31 -04:00
|
|
|
if ((opcode & 0xf000) == 0xa000)
|
2013-07-04 00:29:09 -04:00
|
|
|
{
|
2013-07-04 12:13:31 -04:00
|
|
|
|
|
|
|
const char *name;
|
|
|
|
|
|
|
|
name = TrapName(opcode);
|
|
|
|
|
|
|
|
if (name)
|
|
|
|
{
|
|
|
|
printf("$%08X %-51s ; %04X\n", pc, name, opcode);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
printf("$%08X Tool #$%04X ; %04X\n",
|
|
|
|
pc, opcode, opcode);
|
|
|
|
}
|
|
|
|
|
|
|
|
pc += 2;
|
|
|
|
return pc;
|
2013-07-04 00:29:09 -04:00
|
|
|
}
|
|
|
|
|
2013-07-04 12:13:31 -04:00
|
|
|
for (unsigned j = 0; j < 4; ++j) strings[j][0] = 0;
|
2013-07-04 00:29:09 -04:00
|
|
|
|
2013-07-05 13:54:44 -04:00
|
|
|
uint32_t newpc = cpuDisOpcode(pc, strings[0], strings[1], strings[2], strings[3]);
|
2013-07-04 12:13:31 -04:00
|
|
|
printf("%s %-10s %-40s ; %s\n", strings[0], strings[2], strings[3], strings[1]);
|
2013-07-04 00:29:09 -04:00
|
|
|
|
2013-07-05 13:54:44 -04:00
|
|
|
printMacsbug(pc, opcode);
|
|
|
|
|
|
|
|
return newpc;
|
2013-07-04 00:29:09 -04:00
|
|
|
}
|
|
|
|
|
2013-07-04 12:52:35 -04:00
|
|
|
|
|
|
|
|
|
|
|
bool step(bool trace)
|
|
|
|
{
|
|
|
|
// return false to break (toolbreak, address break, etc.)
|
|
|
|
|
|
|
|
uint16_t op;
|
|
|
|
cpuExecuteInstruction();
|
|
|
|
|
|
|
|
uint32_t pc = cpuGetPC();
|
|
|
|
if (trace) disasm(pc, &op);
|
2013-07-06 16:38:11 -04:00
|
|
|
else op = Debug::ReadWord(pc);
|
2013-07-04 12:52:35 -04:00
|
|
|
|
2013-07-05 13:54:44 -04:00
|
|
|
if (Flags.traceMacsbug && !trace)
|
|
|
|
printMacsbug(pc, op);
|
2013-07-04 12:52:35 -04:00
|
|
|
|
|
|
|
// will this also be set by an interrupt?
|
|
|
|
if (cpuGetStop())
|
|
|
|
{
|
|
|
|
if (!trace) disasm(pc);
|
|
|
|
printf("CPU stopped\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sigInt)
|
|
|
|
{
|
|
|
|
if (!trace) disasm(pc);
|
|
|
|
printf("^C break\n");
|
|
|
|
sigInt = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// check for pc breaks
|
2013-07-05 13:54:15 -04:00
|
|
|
if (brkMap.lookup(pc))
|
2013-07-04 12:52:35 -04:00
|
|
|
{
|
|
|
|
if (!trace) disasm(pc);
|
|
|
|
printf("Address break: $%08x\n", pc);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// todo -- instruction break for rts /rtn
|
|
|
|
|
|
|
|
// check for toolbreaks.
|
|
|
|
if ((op & 0xf000) == 0xa000)
|
|
|
|
{
|
2013-07-05 13:54:15 -04:00
|
|
|
if (tbrkMap.lookup(op))
|
2013-07-04 12:52:35 -04:00
|
|
|
{
|
|
|
|
if (!trace) disasm(pc);
|
|
|
|
printf("Tool break: $%04x\n", op);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pc > Flags.memorySize)
|
|
|
|
{
|
|
|
|
printf("PC out of range\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t sp = cpuGetAReg(7);
|
|
|
|
if (sp < Flags.stackRange.first)
|
|
|
|
{
|
|
|
|
printf("Stack overflow error\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sp > Flags.stackRange.second)
|
|
|
|
{
|
|
|
|
printf("Stack underflow error\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-07-03 23:50:30 -04:00
|
|
|
}
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
#pragma mark - Debugger
|
|
|
|
|
|
|
|
namespace Debug {
|
2013-07-04 12:13:31 -04:00
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
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()
|
2013-07-03 23:50:30 -04:00
|
|
|
{
|
|
|
|
printf("help\n");
|
|
|
|
printf("break expression\n");
|
2013-07-04 00:29:09 -04:00
|
|
|
printf("step\n");
|
|
|
|
printf("continue\n");
|
2013-07-03 23:50:30 -04:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
void Print(uint32_t data)
|
2013-07-03 23:50:30 -04:00
|
|
|
{
|
2013-07-06 16:38:11 -04:00
|
|
|
printf("$%08x %12u", data, data);
|
|
|
|
if (data & 0x80000000)
|
|
|
|
printf(" %12d", (int32_t)data);
|
|
|
|
if ((data & 0xffff8000) == 0x8000)
|
|
|
|
printf(" %6d", (int16_t)data);
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
2013-07-03 23:50:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
void Dump(uint32_t start, int size)
|
2013-07-03 23:50:30 -04:00
|
|
|
{
|
|
|
|
// TODO -- if no address, use previous address.
|
2013-07-04 00:29:09 -04:00
|
|
|
// TODO -- support range?
|
2013-07-03 23:50:30 -04:00
|
|
|
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
if (size <= 0) return;
|
|
|
|
|
|
|
|
uint32_t end = start + size;
|
2013-07-03 23:50:30 -04:00
|
|
|
|
2013-07-05 13:54:44 -04:00
|
|
|
if (start >= Flags.memorySize) return;
|
|
|
|
|
|
|
|
end = std::min(end, Flags.memorySize);
|
2013-07-06 16:38:11 -04:00
|
|
|
size = end - start;
|
2013-07-05 13:54:44 -04:00
|
|
|
|
|
|
|
hexdump(Flags.memory + start, size, start);
|
2013-07-03 23:50:30 -04:00
|
|
|
}
|
|
|
|
|
2013-07-04 12:13:31 -04:00
|
|
|
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
// grr... need separate count/range options.
|
|
|
|
void List(uint32_t pc, int count)
|
2013-07-04 00:29:09 -04:00
|
|
|
{
|
|
|
|
// TODO -- if no address, use previous address.
|
2013-07-06 16:38:11 -04:00
|
|
|
if (pc & 0x01)
|
2013-07-04 00:29:09 -04:00
|
|
|
{
|
2013-07-06 16:38:11 -04:00
|
|
|
printf("address is not aligned: $%08x\n", pc);
|
|
|
|
return;
|
|
|
|
}
|
2013-07-04 00:29:09 -04:00
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
|
{
|
|
|
|
if (pc >= Flags.memorySize) break;
|
|
|
|
pc = disasm(pc);
|
2013-07-04 00:29:09 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
void List(uint32_t pc, uint32_t endpc)
|
|
|
|
{
|
|
|
|
if (endpc < pc) return;
|
|
|
|
|
|
|
|
if (pc & 0x01)
|
|
|
|
{
|
|
|
|
printf("address is not aligned: $%08x\n", pc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (pc <= endpc)
|
|
|
|
{
|
|
|
|
if (pc >= Flags.memorySize) break;
|
|
|
|
pc = disasm(pc);
|
|
|
|
}
|
2013-07-04 00:29:09 -04:00
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrintRegisters()
|
2013-07-04 00:29:09 -04:00
|
|
|
{
|
2013-07-04 12:13:31 -04:00
|
|
|
char srbits[20];
|
|
|
|
|
|
|
|
uint16_t sr = cpuGetSR();
|
|
|
|
|
|
|
|
srbits[0] = sr & (1 << 15) ? 'T' : ' ';
|
|
|
|
srbits[1] = sr & (1 << 14) ? 'T' : ' ';
|
|
|
|
srbits[2] = sr & (1 << 13) ? 'S' : ' ';
|
|
|
|
srbits[3] = sr & (1 << 12) ? 'M' : ' ';
|
|
|
|
srbits[4] = ' ';
|
|
|
|
srbits[5] = sr & (1 << 10) ? 'I' : ' ';
|
|
|
|
srbits[6] = sr & (1 << 9) ? 'I' : ' ';
|
|
|
|
srbits[7] = sr & (1 << 8) ? 'I' : ' ';
|
|
|
|
srbits[8] = ' ';
|
|
|
|
srbits[9] = ' ';
|
|
|
|
srbits[10] = ' ';
|
|
|
|
srbits[11] = sr & (1 << 4) ? 'X' : ' ';
|
|
|
|
srbits[12] = sr & (1 << 3) ? 'N' : ' ';
|
|
|
|
srbits[13] = sr & (1 << 2) ? 'Z' : ' ';
|
|
|
|
srbits[14] = sr & (1 << 1) ? 'V' : ' ';
|
|
|
|
srbits[15] = sr & (1 << 0) ? 'C' : ' ';
|
|
|
|
srbits[16] = 0;
|
|
|
|
|
|
|
|
|
|
|
|
printf(" 0 1 2 3 4 5 6 7\n");
|
2013-07-04 00:29:09 -04:00
|
|
|
printf("D: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
|
|
|
cpuGetDReg(0), cpuGetDReg(1), cpuGetDReg(2), cpuGetDReg(3),
|
|
|
|
cpuGetDReg(4), cpuGetDReg(5), cpuGetDReg(6), cpuGetDReg(7)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
printf("A: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
|
|
|
cpuGetAReg(0), cpuGetAReg(1), cpuGetAReg(2), cpuGetAReg(3),
|
|
|
|
cpuGetAReg(4), cpuGetAReg(5), cpuGetAReg(6), cpuGetAReg(7)
|
|
|
|
);
|
|
|
|
|
2013-07-04 12:13:31 -04:00
|
|
|
printf("PC: %08X CSR: %04x %s\n", cpuGetPC(), sr, srbits);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
void ToolBreak(int32_t tool)
|
2013-07-04 12:13:31 -04:00
|
|
|
{
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
bool remove = false;
|
2013-07-04 12:13:31 -04:00
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
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);
|
2013-07-04 12:13:31 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
void Break(int32_t address)
|
2013-07-04 12:13:31 -04:00
|
|
|
{
|
|
|
|
// 24-bit only, - address to remove.
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
bool remove = false;
|
2013-07-04 12:13:31 -04:00
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
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);
|
2013-07-04 12:13:31 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-04 12:52:35 -04:00
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
void Step(const Command &cmd)
|
2013-07-04 12:13:31 -04:00
|
|
|
{
|
|
|
|
// TODO - step n to step specified # of instructions.
|
|
|
|
// TODO -- step @address to step until address?
|
|
|
|
|
|
|
|
// disasm 1 line, execute it.
|
|
|
|
|
|
|
|
int count = 0;
|
|
|
|
if (cmd.argc == 1) count = (int)cmd.argv[0];
|
|
|
|
if (count < 1) count = 1;
|
|
|
|
|
|
|
|
// TODO -- move to common function...
|
|
|
|
for (int i = 0; i < count; ++i)
|
|
|
|
{
|
2013-07-04 12:52:35 -04:00
|
|
|
if (!step(true)) break;
|
|
|
|
}
|
|
|
|
}
|
2013-07-04 12:13:31 -04:00
|
|
|
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
void Continue(const Command &cmd)
|
2013-07-04 12:52:35 -04:00
|
|
|
{
|
|
|
|
while (step(false)) ;
|
2013-07-04 12:13:31 -04:00
|
|
|
}
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
void SetARegister(unsigned reg, uint32_t value)
|
2013-07-04 12:13:31 -04:00
|
|
|
{
|
|
|
|
if (reg > 7) return;
|
|
|
|
if (reg == 7)
|
|
|
|
{
|
|
|
|
// sp/7 must be aligned.
|
|
|
|
if (value & 0x01)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Address is not aligned: $%08x\n", value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value > Flags.memorySize)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Warning: address exceeeds memory size: $%08x\n", value);
|
|
|
|
}
|
|
|
|
|
|
|
|
cpuSetAReg(reg, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
void SetDRegister(unsigned reg, uint32_t value)
|
2013-07-04 12:13:31 -04:00
|
|
|
{
|
2013-07-06 16:38:11 -04:00
|
|
|
if (reg > 7) return;
|
2013-07-04 12:13:31 -04:00
|
|
|
|
|
|
|
cpuSetDReg(reg, value);
|
2013-07-04 00:29:09 -04:00
|
|
|
}
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
void SetXRegister(unsigned reg, uint32_t value)
|
2013-07-04 12:13:31 -04:00
|
|
|
{
|
|
|
|
|
|
|
|
if (reg == 0)
|
|
|
|
{
|
|
|
|
if (value & 0x01)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Address is not aligned: $%08x\n", value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (value > Flags.memorySize)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Warning: address exceeeds memory size: $%08x\n", value);
|
|
|
|
}
|
|
|
|
cpuSetPC(value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (reg == 1)
|
|
|
|
{
|
2013-07-06 16:38:11 -04:00
|
|
|
cpuSetSR(value & 0xffff);
|
2013-07-04 12:13:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-07-04 00:29:09 -04:00
|
|
|
|
2013-07-05 13:54:44 -04:00
|
|
|
// TODO -- RUN command - reload, re-initialize, re-execute
|
|
|
|
// TODO -- parser calls commands directly (except trace/step/run/etc)
|
2013-07-06 16:38:11 -04:00
|
|
|
void Shell()
|
2013-07-03 23:50:30 -04:00
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
add_history("!Andy, it still has history!");
|
2013-07-04 12:13:31 -04:00
|
|
|
|
|
|
|
// start it up
|
|
|
|
printf("MPW Debugger shell\n\n");
|
|
|
|
disasm(cpuGetPC());
|
|
|
|
|
2013-07-04 12:52:35 -04:00
|
|
|
signal(SIGINT, sigIntHandler);
|
|
|
|
|
2013-07-03 23:50:30 -04:00
|
|
|
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)
|
|
|
|
{
|
2013-07-06 16:38:11 -04:00
|
|
|
case cmdNull:
|
2013-07-04 00:29:09 -04:00
|
|
|
break;
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
case cmdStep:
|
|
|
|
Step(cmd);
|
2013-07-04 00:29:09 -04:00
|
|
|
break;
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
case cmdContinue:
|
|
|
|
Continue(cmd);
|
2013-07-04 12:13:31 -04:00
|
|
|
break;
|
|
|
|
|
2013-07-03 23:50:30 -04:00
|
|
|
default:
|
2013-07-06 16:38:11 -04:00
|
|
|
Help();
|
2013-07-03 23:50:30 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// todo -- don't add if same as previous command.
|
|
|
|
add_history(cp);
|
|
|
|
}
|
|
|
|
free(cp);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-07-06 16:38:11 -04:00
|
|
|
} // namespace Debugger
|
|
|
|
|
|
|
|
|