mirror of
https://github.com/rkujawa/rk65c02.git
synced 2024-12-04 19:50:19 +00:00
More refactoring and improvements to logging!
This commit is contained in:
parent
0c77eeb505
commit
5fddf2c5dc
11
src/bus.c
11
src/bus.c
@ -33,6 +33,9 @@ bus_device_add(bus_t *b, device_t *d, uint16_t addr)
|
|||||||
dm->addr = addr;
|
dm->addr = addr;
|
||||||
|
|
||||||
LL_APPEND((b->dm_head), dm);
|
LL_APPEND((b->dm_head), dm);
|
||||||
|
|
||||||
|
rk65c02_log(LOG_INFO, "Bus mapping added: %x device %s size %x.",
|
||||||
|
addr, d->name, d->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -71,7 +74,7 @@ bus_access_device(bus_t *t, uint16_t addr, device_t **d, uint16_t *off)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (*d == NULL) {
|
if (*d == NULL) {
|
||||||
rk6502_log(LOG_WARN, "Hitting unmapped bus space @ %x!", addr);
|
rk65c02_log(LOG_WARN, "Hitting unmapped bus space @ %x!", addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +96,7 @@ bus_read_1(bus_t *t, uint16_t addr)
|
|||||||
val = d->read_1(d, off);
|
val = d->read_1(d, off);
|
||||||
|
|
||||||
if (t->access_debug)
|
if (t->access_debug)
|
||||||
rk6502_log(LOG_DEBUG, "bus READ @ %x (off %x) value %x\n",
|
rk65c02_log(LOG_DEBUG, "bus READ @ %x (off %x) value %x\n",
|
||||||
addr, off, val);
|
addr, off, val);
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
@ -108,7 +111,7 @@ bus_write_1(bus_t *t, uint16_t addr, uint8_t val)
|
|||||||
bus_access_device(t, addr, &d, &off);
|
bus_access_device(t, addr, &d, &off);
|
||||||
|
|
||||||
if (t->access_debug)
|
if (t->access_debug)
|
||||||
rk6502_log(LOG_DEBUG, "bus WRITE @ %x (off %x) value %x\n",
|
rk65c02_log(LOG_DEBUG, "bus WRITE @ %x (off %x) value %x\n",
|
||||||
addr, off, val);
|
addr, off, val);
|
||||||
|
|
||||||
d->write_1(d, off, val);
|
d->write_1(d, off, val);
|
||||||
@ -163,7 +166,7 @@ bus_load_file(bus_t *t, uint16_t addr, const char *filename)
|
|||||||
|
|
||||||
fd = open(filename, O_RDONLY);
|
fd = open(filename, O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
rk6502_log(LOG_ERROR, "Problem while trying to open file: %s",
|
rk65c02_log(LOG_ERROR, "Problem while trying to open file: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
13
src/debug.c
13
src/debug.c
@ -18,6 +18,8 @@ debug_trace_print_all(rk65c02emu_t *e)
|
|||||||
{
|
{
|
||||||
trace_t *tr;
|
trace_t *tr;
|
||||||
instruction_t i;
|
instruction_t i;
|
||||||
|
char *instrstr;
|
||||||
|
char *regsstr;
|
||||||
|
|
||||||
if (e->trace_head == NULL)
|
if (e->trace_head == NULL)
|
||||||
return;
|
return;
|
||||||
@ -26,11 +28,14 @@ debug_trace_print_all(rk65c02emu_t *e)
|
|||||||
i.opcode = tr->opcode;
|
i.opcode = tr->opcode;
|
||||||
i.op1 = tr->op1;
|
i.op1 = tr->op1;
|
||||||
i.op2 = tr->op2;
|
i.op2 = tr->op2;
|
||||||
|
instrstr = instruction_string_get(&i);
|
||||||
|
regsstr = rk65c02_regs_string_get(tr->regs);
|
||||||
|
|
||||||
rk6502_log(LOG_TRACE, " %X:\t", tr->address);
|
rk65c02_log(LOG_TRACE, "%X: %s\t%s", tr->address, instrstr,
|
||||||
instruction_print(&i);
|
regsstr);
|
||||||
printf("\t");
|
|
||||||
rk65c02_dump_regs(tr->regs);
|
free(instrstr);
|
||||||
|
free(regsstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -55,59 +56,83 @@ instruction_fetch(bus_t *b, uint16_t addr)
|
|||||||
void
|
void
|
||||||
instruction_print(instruction_t *i)
|
instruction_print(instruction_t *i)
|
||||||
{
|
{
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
str = instruction_string_get(i);
|
||||||
|
|
||||||
|
printf("%s", str);
|
||||||
|
|
||||||
|
free(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
instruction_string_get(instruction_t *i)
|
||||||
|
{
|
||||||
|
#define INSTR_STR_LEN 16
|
||||||
instrdef_t id;
|
instrdef_t id;
|
||||||
|
char *str;
|
||||||
|
|
||||||
|
str = malloc(INSTR_STR_LEN);
|
||||||
|
if (str == NULL) {
|
||||||
|
rk65c02_log(LOG_CRIT, "Error allocating memory for buffer: %s.",
|
||||||
|
strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(str, 0, INSTR_STR_LEN);
|
||||||
|
|
||||||
id = instruction_decode(i->opcode);
|
id = instruction_decode(i->opcode);
|
||||||
switch (id.mode) {
|
switch (id.mode) {
|
||||||
case IMPLIED:
|
case IMPLIED:
|
||||||
printf("%s", id.mnemonic);
|
snprintf(str, INSTR_STR_LEN, "%s", id.mnemonic);
|
||||||
break;
|
break;
|
||||||
case ACCUMULATOR:
|
case ACCUMULATOR:
|
||||||
printf("%s A", id.mnemonic);
|
snprintf(str, INSTR_STR_LEN, "%s A", id.mnemonic);
|
||||||
break;
|
break;
|
||||||
case IMMEDIATE:
|
case IMMEDIATE:
|
||||||
printf("%s #%#02x", id.mnemonic, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s #%#02x", id.mnemonic, i->op1);
|
||||||
break;
|
break;
|
||||||
case ZP:
|
case ZP:
|
||||||
printf("%s %#02x", id.mnemonic, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s %#02x", id.mnemonic, i->op1);
|
||||||
break;
|
break;
|
||||||
case ZPX:
|
case ZPX:
|
||||||
printf("%s %#02x,X", id.mnemonic, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s %#02x,X", id.mnemonic, i->op1);
|
||||||
break;
|
break;
|
||||||
case ZPY:
|
case ZPY:
|
||||||
printf("%s %#02x,Y", id.mnemonic, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s %#02x,Y", id.mnemonic, i->op1);
|
||||||
break;
|
break;
|
||||||
case IZP:
|
case IZP:
|
||||||
printf("%s (%#02x)", id.mnemonic, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s (%#02x)", id.mnemonic, i->op1);
|
||||||
break;
|
break;
|
||||||
case IZPX:
|
case IZPX:
|
||||||
printf("%s (%#02x,X)", id.mnemonic, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s (%#02x,X)", id.mnemonic, i->op1);
|
||||||
break;
|
break;
|
||||||
case IZPY:
|
case IZPY:
|
||||||
printf("%s (%#02x),Y", id.mnemonic, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s (%#02x),Y", id.mnemonic, i->op1);
|
||||||
break;
|
break;
|
||||||
case ZPR:
|
case ZPR:
|
||||||
printf("%s %#02x,%#02x", id.mnemonic, i->op1, i->op2);
|
snprintf(str, INSTR_STR_LEN, "%s %#02x,%#02x", id.mnemonic, i->op1, i->op2);
|
||||||
break;
|
break;
|
||||||
case ABSOLUTE:
|
case ABSOLUTE:
|
||||||
printf("%s %#02x%02x", id.mnemonic, i->op2, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s %#02x%02x", id.mnemonic, i->op2, i->op1);
|
||||||
break;
|
break;
|
||||||
case ABSOLUTEX:
|
case ABSOLUTEX:
|
||||||
printf("%s %#02x%02x,X", id.mnemonic, i->op2, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s %#02x%02x,X", id.mnemonic, i->op2, i->op1);
|
||||||
break;
|
break;
|
||||||
case ABSOLUTEY:
|
case ABSOLUTEY:
|
||||||
printf("%s %#02x%02x,Y", id.mnemonic, i->op2, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s %#02x%02x,Y", id.mnemonic, i->op2, i->op1);
|
||||||
break;
|
break;
|
||||||
case IABSOLUTE:
|
case IABSOLUTE:
|
||||||
printf("%s (%#02x%02x)", id.mnemonic, i->op2, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s (%#02x%02x)", id.mnemonic, i->op2, i->op1);
|
||||||
break;
|
break;
|
||||||
case IABSOLUTEX:
|
case IABSOLUTEX:
|
||||||
printf("%s (%#02x%02x,X)", id.mnemonic, i->op2, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s (%#02x%02x,X)", id.mnemonic, i->op2, i->op1);
|
||||||
break;
|
break;
|
||||||
case RELATIVE:
|
case RELATIVE:
|
||||||
printf("%s %#02x", id.mnemonic, i->op1);
|
snprintf(str, INSTR_STR_LEN, "%s %#02x", id.mnemonic, i->op1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
assembler_t
|
assembler_t
|
||||||
@ -173,7 +198,7 @@ assemble_single_buf(uint8_t **buf, uint8_t *bsize, const char *mnemonic, address
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
rk6502_log(LOG_ERROR,
|
rk65c02_log(LOG_ERROR,
|
||||||
"Couldn't find opcode for mnemonic %s mode %x.",
|
"Couldn't find opcode for mnemonic %s mode %x.",
|
||||||
mnemonic, mode);
|
mnemonic, mode);
|
||||||
return false;
|
return false;
|
||||||
@ -182,7 +207,7 @@ assemble_single_buf(uint8_t **buf, uint8_t *bsize, const char *mnemonic, address
|
|||||||
*bsize = id.size;
|
*bsize = id.size;
|
||||||
*buf = malloc(id.size);
|
*buf = malloc(id.size);
|
||||||
if(*buf == NULL) {
|
if(*buf == NULL) {
|
||||||
rk6502_log(LOG_ERROR, "Error allocating assembly buffer.");
|
rk65c02_log(LOG_ERROR, "Error allocating assembly buffer.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +329,7 @@ instruction_data_write_1(rk65c02emu_t *e, instrdef_t *id, instruction_t *i, uint
|
|||||||
* PC which is handled within emulation of a given opcode.
|
* PC which is handled within emulation of a given opcode.
|
||||||
*/
|
*/
|
||||||
default:
|
default:
|
||||||
rk6502_log(LOG_ERROR,
|
rk65c02_log(LOG_ERROR,
|
||||||
"unhandled addressing mode for opcode %x\n", i->opcode);
|
"unhandled addressing mode for opcode %x\n", i->opcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -371,7 +396,7 @@ instruction_data_read_1(rk65c02emu_t *e, instrdef_t *id, instruction_t *i)
|
|||||||
* PC which is handled within emulation of a given opcode.
|
* PC which is handled within emulation of a given opcode.
|
||||||
*/
|
*/
|
||||||
default:
|
default:
|
||||||
rk6502_log(LOG_ERROR,
|
rk65c02_log(LOG_ERROR,
|
||||||
"unhandled addressing mode for opcode %x\n", i->opcode);
|
"unhandled addressing mode for opcode %x\n", i->opcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,7 @@ typedef struct assembler assembler_t;
|
|||||||
instruction_t instruction_fetch(bus_t *, uint16_t);
|
instruction_t instruction_fetch(bus_t *, uint16_t);
|
||||||
instrdef_t instruction_decode(uint8_t);
|
instrdef_t instruction_decode(uint8_t);
|
||||||
void instruction_print(instruction_t *);
|
void instruction_print(instruction_t *);
|
||||||
|
char * instruction_string_get(instruction_t *);
|
||||||
void disassemble(bus_t *, uint16_t);
|
void disassemble(bus_t *, uint16_t);
|
||||||
uint8_t instruction_data_read_1(rk65c02emu_t *, instrdef_t *, instruction_t *);
|
uint8_t instruction_data_read_1(rk65c02emu_t *, instrdef_t *, instruction_t *);
|
||||||
void instruction_data_write_1(rk65c02emu_t *, instrdef_t *, instruction_t *, uint8_t);
|
void instruction_data_write_1(rk65c02emu_t *, instrdef_t *, instruction_t *, uint8_t);
|
||||||
|
@ -16,12 +16,12 @@ static const char *level_str[] = {
|
|||||||
|
|
||||||
static uint8_t level = LOG_INFO;
|
static uint8_t level = LOG_INFO;
|
||||||
|
|
||||||
void rk6502_loglevel_set(uint8_t l)
|
void rk65c02_loglevel_set(uint8_t l)
|
||||||
{
|
{
|
||||||
level = l;
|
level = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rk6502_log(uint8_t l, const char* fmt, ...)
|
void rk65c02_log(uint8_t l, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
struct timeval t;
|
struct timeval t;
|
||||||
|
@ -10,6 +10,6 @@
|
|||||||
current level, but not when creating new log
|
current level, but not when creating new log
|
||||||
messages. */
|
messages. */
|
||||||
|
|
||||||
void rk6502_loglevel_set(uint8_t);
|
void rk65c02_loglevel_set(uint8_t);
|
||||||
void rk6502_log(uint8_t, const char *, ...);
|
void rk65c02_log(uint8_t, const char *, ...);
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ rk65c02_init(bus_t *b)
|
|||||||
e.trace_head = NULL;
|
e.trace_head = NULL;
|
||||||
e.runtime_disassembly = false;
|
e.runtime_disassembly = false;
|
||||||
|
|
||||||
rk6502_log(LOG_DEBUG, "Initialized new emulator.");
|
rk65c02_log(LOG_DEBUG, "Initialized new emulator.");
|
||||||
|
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
@ -119,7 +120,7 @@ rk65c02_exec(rk65c02emu_t *e)
|
|||||||
if (!instruction_modify_pc(&id))
|
if (!instruction_modify_pc(&id))
|
||||||
program_counter_increment(e, &id);
|
program_counter_increment(e, &id);
|
||||||
} else {
|
} else {
|
||||||
rk6502_log(LOG_ERROR, "unimplemented opcode %X @ %X\n",
|
rk65c02_log(LOG_ERROR, "unimplemented opcode %X @ %X\n",
|
||||||
i.opcode, e->regs.PC);
|
i.opcode, e->regs.PC);
|
||||||
e->state = STOPPED;
|
e->state = STOPPED;
|
||||||
e->stopreason = EMUERROR;
|
e->stopreason = EMUERROR;
|
||||||
@ -188,50 +189,42 @@ rk65c02_dump_stack(rk65c02emu_t *e, uint8_t n)
|
|||||||
void
|
void
|
||||||
rk65c02_dump_regs(reg_state_t regs)
|
rk65c02_dump_regs(reg_state_t regs)
|
||||||
{
|
{
|
||||||
printf("A: %X X: %X Y: %X PC: %X SP: %X P: ",
|
char *str;
|
||||||
regs.A, regs.X, regs.Y, regs.PC, regs.SP);
|
|
||||||
|
|
||||||
if (regs.P & P_NEGATIVE)
|
str = rk65c02_regs_string_get(regs);
|
||||||
printf("N");
|
|
||||||
else
|
|
||||||
printf("-");
|
|
||||||
|
|
||||||
if (regs.P & P_SIGN_OVERFLOW)
|
printf ("%s", str);
|
||||||
printf("V");
|
|
||||||
else
|
|
||||||
printf("-");
|
|
||||||
|
|
||||||
if (regs.P & P_UNDEFINED)
|
free(str);
|
||||||
printf("1");
|
}
|
||||||
else
|
|
||||||
printf("-");
|
|
||||||
|
|
||||||
if (regs.P & P_BREAK)
|
char *
|
||||||
printf("B");
|
rk65c02_regs_string_get(reg_state_t regs)
|
||||||
else
|
{
|
||||||
printf("-");
|
#define REGS_STR_LEN 50
|
||||||
|
char *str;
|
||||||
|
|
||||||
if (regs.P & P_DECIMAL)
|
/* XXX: string allocation to a separate utility function? */
|
||||||
printf("D");
|
str = malloc(REGS_STR_LEN);
|
||||||
else
|
if (str == NULL) {
|
||||||
printf("-");
|
rk65c02_log(LOG_CRIT, "Error allocating memory for buffer: %s.",
|
||||||
|
strerror(errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(str, 0, REGS_STR_LEN);
|
||||||
|
|
||||||
if (regs.P & P_IRQ_DISABLE)
|
snprintf(str, REGS_STR_LEN, "A: %X X: %X Y: %X PC: %X SP: %X P: %c%c%c%c%c%c%c%c",
|
||||||
printf("I");
|
regs.A, regs.X, regs.Y, regs.PC, regs.SP,
|
||||||
else
|
(regs.P & P_NEGATIVE) ? 'N' : '-',
|
||||||
printf("-");
|
(regs.P & P_SIGN_OVERFLOW) ? 'V' : '-',
|
||||||
|
(regs.P & P_UNDEFINED) ? '1' : '-',
|
||||||
|
(regs.P & P_BREAK) ? 'B' : '-',
|
||||||
|
(regs.P & P_DECIMAL) ? 'D' : '-',
|
||||||
|
(regs.P & P_IRQ_DISABLE) ? 'I' : '-',
|
||||||
|
(regs.P & P_ZERO) ? 'Z' : '-',
|
||||||
|
(regs.P & P_CARRY) ? 'C' : '-');
|
||||||
|
|
||||||
if (regs.P & P_ZERO)
|
return str;
|
||||||
printf("Z");
|
|
||||||
else
|
|
||||||
printf("-");
|
|
||||||
|
|
||||||
if (regs.P & P_CARRY)
|
|
||||||
printf("C");
|
|
||||||
else
|
|
||||||
printf("-");
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
int
|
int
|
||||||
@ -252,7 +245,7 @@ main(void)
|
|||||||
bus_write_1(&b, 8, 0x0);
|
bus_write_1(&b, 8, 0x0);
|
||||||
bus_write_1(&b, 9, OP_STP);
|
bus_write_1(&b, 9, OP_STP);
|
||||||
|
|
||||||
rk6502_start(&b, 0);
|
rk65c02_start(&b, 0);
|
||||||
|
|
||||||
bus_finish(&b);
|
bus_finish(&b);
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,8 @@ typedef struct rk65c02emu rk65c02emu_t;
|
|||||||
rk65c02emu_t rk65c02_init(bus_t *);
|
rk65c02emu_t rk65c02_init(bus_t *);
|
||||||
void rk65c02_start(rk65c02emu_t *);
|
void rk65c02_start(rk65c02emu_t *);
|
||||||
void rk65c02_step(rk65c02emu_t *, uint16_t);
|
void rk65c02_step(rk65c02emu_t *, uint16_t);
|
||||||
void rk65c02_dump_regs(reg_state_t regs);
|
char *rk65c02_regs_string_get(reg_state_t);
|
||||||
|
void rk65c02_dump_regs(reg_state_t);
|
||||||
void rk65c02_dump_stack(rk65c02emu_t *, uint8_t);
|
void rk65c02_dump_stack(rk65c02emu_t *, uint8_t);
|
||||||
void rk65c02_irq(rk65c02emu_t *e);
|
void rk65c02_irq(rk65c02emu_t *e);
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ ATF_TC_BODY(trace, tc)
|
|||||||
trace_t *tr;
|
trace_t *tr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
rk6502_loglevel_set(LOG_TRACE);
|
rk65c02_loglevel_set(LOG_TRACE);
|
||||||
|
|
||||||
b = bus_init_with_default_devs();
|
b = bus_init_with_default_devs();
|
||||||
a = assemble_init(&b, ROM_LOAD_ADDR);
|
a = assemble_init(&b, ROM_LOAD_ADDR);
|
||||||
|
Loading…
Reference in New Issue
Block a user