blob: e2ee986751b62665772393d671eba5cd00dcbdda [file] [log] [blame]
#include "dbg.h"
#include "cpu.h"
#include <readline/readline.h>
#include <readline/history.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
bool debug_stmt(cpu_t *cpu, char *input, bool *running)
{
char *tok = strtok(input, " \t\r\n\v");
if (!tok || !*tok)
return false;
if (!strcmp(tok, "step") || !strcmp(tok, "s"))
{
step(cpu);
}
else if (!strcmp(tok, "show") || !strcmp(tok, "print"))
{
if ((tok = strtok(NULL, " ")))
{
char *ok = 0;
if (tok[0] == '$')
{
uint16_t addr = strtol(tok + 1, &ok, 16);
printf("Memory:\n");
printf("\t$%x %x\n", addr, cpu->mem[addr]);
if (addr < 0xFFFF)
printf("\t$%x %x\n", addr + 1, cpu->mem[addr + 1]);
}
else
{
printf("Expected an address as an argument in the form "
"$1234, not %s\n", tok);
}
}
else
{
printf("Registers:\n");
printf("\tPC:\t$%x\n", cpu->pc);
#define R(r) printf("\t" #r ":\t$%x\n", cpu->regs[r]);
REGISTERS
#undef R
}
}
else if (!strcmp(tok, "set"))
{
char reg_name[32];
uint16_t addr;
uint8_t val;
tok = strtok(NULL, "\0");
printf("%s\n", tok);
if (sscanf(tok, "$%hx #$%hhx", &addr, &val))
{
cpu->mem[addr] = val;
}
else if (sscanf(tok, "%s #$%hhx", reg_name, &val))
{
int reg = -1;
if (!strcasecmp(reg_name, "A"))
reg = A;
else if (!strcasecmp(reg_name, "X"))
reg = X;
else if (!strcasecmp(reg_name, "Y"))
reg = Y;
else if (!strcasecmp(reg_name, "SP"))
reg = SP;
else if (!strcasecmp(reg_name, "PC"))
cpu->pc = val;
else if (!strcasecmp(reg_name, "SR"))
*(uint8_t *)&cpu->status = val;
else
printf("set command expected a register as the first argument, got %s\n",
reg_name);
if (reg != -1)
{
cpu->regs[reg] = val;
}
}
else
{
printf("set command expects either a memory address and a constant, "
"or a register and a constant as arguments.\n");
}
}
else if (!strcmp(tok, "run"))
{
*running = true;
}
else if (!strcmp(tok, "pause"))
{
*running = false;
}
else if (!strcmp(tok, "quit") || !strcmp(tok, "exit"))
{
printf("Bye\n");
return true;
}
else
{
printf("Unknown command %s\n", tok);
}
return false;
}
typedef struct
{
mqd_t mq;
cpu_t *cpu;
} debug_prompt_arg_t;
void debug_prompt(debug_prompt_arg_t *arg)
{
mqd_t mq = arg->mq;
cpu_t *cpu = arg->cpu;
free(arg);
bool running = true;
while (running)
{
char *input = readline("\033[33m> \033[0m");
if (!input || !*input)
continue;
if (!strcmp(input, "quit") || !strcmp(input, "exit"))
running = false;
mq_send(mq, input, strlen(input) + 1, 2);
add_history(input);
free(input);
}
}
pthread_t start_debug_prompt(mqd_t mq, cpu_t *cpu)
{
debug_prompt_arg_t *arg = malloc(sizeof(debug_prompt_arg_t));
arg->mq = mq;
arg->cpu = cpu;
pthread_t thread;
pthread_create(&thread, NULL, (void *(*)(void *))&debug_prompt, arg);
return thread;
}