From 5206c3871e204fd9d2eebdcc9134f3f69a554393 Mon Sep 17 00:00:00 2001 From: Samuel Walker Date: Fri, 31 Jan 2025 17:07:09 -0700 Subject: [PATCH] CPU testing --- include/common.h | 2 +- include/cpu.h | 4 +- include/dbg.h | 6 +++ include/io.h | 6 +++ lib/bus.c | 8 +-- lib/cpu.c | 11 +++- lib/cpu_fetch.c | 2 +- lib/cpu_proc.c | 4 +- lib/dbg.c | 21 ++++++++ lib/instructions.c | 130 +++++++++++++++++++++++++++++++++++++++++++-- lib/io.c | 32 +++++++++++ 11 files changed, 212 insertions(+), 14 deletions(-) create mode 100644 include/dbg.h create mode 100644 include/io.h create mode 100644 lib/dbg.c create mode 100644 lib/io.c diff --git a/include/common.h b/include/common.h index 48d90ae..61356e1 100644 --- a/include/common.h +++ b/include/common.h @@ -11,7 +11,7 @@ typedef uint32_t u32; typedef uint64_t u64; #define BIT(a, n) ((a & (1 << n)) ? 1 : 0) -#define BIT_SET(a, n, on) {if(on) a |= (1 << n); else a &= !(1 << n);} +#define BIT_SET(a, n, on) {if(on) a |= (1 << n); else a &= ~(1 << n);} #define BETWEEN(a, b, c) ((a >= b) && (a <= c)) void delay(u32 ms); diff --git a/include/cpu.h b/include/cpu.h index 99d5997..f086e2b 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -63,4 +63,6 @@ void cpu_set_ie_register(u8 ie); cpu_registers *cpu_get_regs(); u8 cpu_get_int_flags(); -void cpu_set_int_flags(u8 value); \ No newline at end of file +void cpu_set_int_flags(u8 value); + +void inst_to_str(cpu_context *ctx, char *str); \ No newline at end of file diff --git a/include/dbg.h b/include/dbg.h new file mode 100644 index 0000000..dcc81c9 --- /dev/null +++ b/include/dbg.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +void dbg_update(); +void dbg_print(); \ No newline at end of file diff --git a/include/io.h b/include/io.h new file mode 100644 index 0000000..a917303 --- /dev/null +++ b/include/io.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +u8 io_read(u16 address); +void io_write(u16 address, u8 value); \ No newline at end of file diff --git a/lib/bus.c b/lib/bus.c index e569e71..1075dd1 100644 --- a/lib/bus.c +++ b/lib/bus.c @@ -3,6 +3,7 @@ #include #include #include +#include // 0x0000 - 0x3FFF : ROM Bank 0 // 0x4000 - 0x7FFF : ROM Bank 1 - Switchable @@ -48,9 +49,8 @@ u8 bus_read(u16 address) { } else if (address < 0xFF80) { //IO registers //TODO - printf("UNSUPPORTED bus_read(%04X)\n", address); //NO_IMPL - return 0; + return io_read(address); } else if (address == 0xFFFF) { //CPU ENABLE REGISTER //TODO @@ -68,6 +68,7 @@ void bus_write(u16 address, u8 value) { //Char/Map Data //TODO printf("UNSUPPORTED bus_write(%04X)\n", address); + return; //NO_IMPL } else if (address < 0xC000) { //Cartridge RAM @@ -84,6 +85,7 @@ void bus_write(u16 address, u8 value) { //OAM //TODO printf("UNSUPPORTED bus_write(%04X)\n", address); + return; //NO_IMPL } else if (address < 0xFF00) { //reserved unusable @@ -91,7 +93,7 @@ void bus_write(u16 address, u8 value) { } else if (address < 0xFF80) { //IO registers //TODO - printf("UNSUPPORTED bus_write(%04X)\n", address); + io_write(address, value); //NO_IMPL return; } else if (address == 0xFFFF) { diff --git a/lib/cpu.c b/lib/cpu.c index 09472f2..98aed72 100644 --- a/lib/cpu.c +++ b/lib/cpu.c @@ -3,6 +3,7 @@ #include #include #include +#include cpu_context ctx = {0}; @@ -39,11 +40,19 @@ bool cpu_step() { ctx.regs.f & (1 << 5) ? 'H' : '-', ctx.regs.f & (1 << 4) ? 'C' : '-' ); - printf("%08lX - %04X: %-7s (%02X %02X %02X) A: %02X F: %s BC: %02X%02X DE: %02X%02X HL: %02X%02X SP: %04X PC: %04X\n", emu_get_context()->ticks, pc, inst_name(ctx.cur_inst->type), ctx.cur_opcode, bus_read(pc+1), bus_read(pc+2), ctx.regs.a, flags, ctx.regs.b, ctx.regs.c, ctx.regs.d, ctx.regs.e, ctx.regs.h, ctx.regs.l, ctx.regs.sp, ctx.regs.pc); + + char inst[16]; + inst_to_str(&ctx, inst); + + printf("%08lX - %04X: %-12s (%02X %02X %02X) A: %02X F: %s BC: %02X%02X DE: %02X%02X HL: %02X%02X SP: %04X PC: %04X\n", emu_get_context()->ticks, pc, inst, ctx.cur_opcode, bus_read(pc+1), bus_read(pc+2), ctx.regs.a, flags, ctx.regs.b, ctx.regs.c, ctx.regs.d, ctx.regs.e, ctx.regs.h, ctx.regs.l, ctx.regs.sp, ctx.regs.pc); if(ctx.cur_inst == NULL){ printf("Unknown Instruction! %02X\n", ctx.cur_opcode); exit(-7); } + + dbg_update(); + dbg_print(); + execute(); } else { //is halted diff --git a/lib/cpu_fetch.c b/lib/cpu_fetch.c index e1eaa51..6f2466c 100644 --- a/lib/cpu_fetch.c +++ b/lib/cpu_fetch.c @@ -63,7 +63,7 @@ void fetch_data() { return; case AM_HLI_R: ctx.fetched_data = cpu_read_reg(ctx.cur_inst->reg_2); - ctx.mem_dest = bus_read(cpu_read_reg(ctx.cur_inst->reg_1)); + ctx.mem_dest = cpu_read_reg(ctx.cur_inst->reg_1); ctx.dest_is_mem = true; cpu_set_reg(RT_HL, cpu_read_reg(RT_HL)+1); return; diff --git a/lib/cpu_proc.c b/lib/cpu_proc.c index 558044b..f207dfa 100644 --- a/lib/cpu_proc.c +++ b/lib/cpu_proc.c @@ -37,7 +37,7 @@ static void proc_daa(cpu_context *ctx) { u8 u = 0; int fc = 0; - if(CPU_FLAG_H || (!CPU_FLAG_N && (ctx->regs.a & 0xF) >9)) { + if(CPU_FLAG_H || (!CPU_FLAG_N && (ctx->regs.a & 0xF) > 9)) { u = 6; } @@ -402,7 +402,7 @@ static void proc_ldh(cpu_context *ctx) { if (!ctx->dest_is_mem) { cpu_set_reg(ctx->cur_inst->reg_1, bus_read(0XFF00 | ctx->fetched_data)); } else { - bus_write(0xFF00 | ctx->mem_dest, ctx->cur_inst->reg_2); + bus_write(0xFF00 | ctx->mem_dest, cpu_read_reg(ctx->cur_inst->reg_2)); } emu_cycles(1); } diff --git a/lib/dbg.c b/lib/dbg.c new file mode 100644 index 0000000..69d0a92 --- /dev/null +++ b/lib/dbg.c @@ -0,0 +1,21 @@ +#include +#include + +static char dbg_msg[1024] = {0}; +static int msg_size = 0; + +void dbg_update(){ + if (bus_read(0xFF02) == 0x81) { + char c = bus_read(0xFF01); + + dbg_msg[msg_size++] = c; + + bus_write(0xFF02, 0); + } +} + +void dbg_print(){ + if(dbg_msg[0]) { + printf("DBG: %s\n", dbg_msg); + } +} \ No newline at end of file diff --git a/lib/instructions.c b/lib/instructions.c index af10498..019eba0 100644 --- a/lib/instructions.c +++ b/lib/instructions.c @@ -242,12 +242,12 @@ instruction instructions[0x100] = { [0xE1] = {IN_POP, AM_IMP, RT_HL}, [0xE2] = {IN_LD, AM_MR_R, RT_C, RT_A}, [0xE5] = {IN_PUSH, AM_IMP, RT_HL}, - [0xE6] = {IN_AND, AM_D8}, + [0xE6] = {IN_AND, AM_R_D8, RT_A}, [0xE7] = {IN_RST, AM_IMP, RT_NONE, RT_NONE, CT_NONE, 0x20}, [0xE8] = {IN_ADD, AM_R_D8, RT_SP}, - [0xE9] = {IN_JP, AM_MR, RT_HL}, + [0xE9] = {IN_JP, AM_R, RT_HL}, [0xEA] = {IN_LD, AM_A16_R, RT_NONE, RT_A}, - [0xEE] = {IN_XOR, AM_D8}, + [0xEE] = {IN_XOR, AM_R_D8, RT_A}, [0xEF] = {IN_RST, AM_IMP, RT_NONE, RT_NONE, CT_NONE, 0x28}, //0xFX [0xF0] = {IN_LDH, AM_R_A8, RT_A}, @@ -255,13 +255,13 @@ instruction instructions[0x100] = { [0xF2] = {IN_LD, AM_R_MR, RT_A, RT_C}, [0xF3] = {IN_DI}, [0xF5] = {IN_PUSH, AM_IMP, RT_AF}, - [0xF6] = {IN_OR, AM_D8}, + [0xF6] = {IN_OR, AM_R_D8, RT_A}, [0xF7] = {IN_RST, AM_IMP, RT_NONE, RT_NONE, CT_NONE, 0x30}, [0xF8] = {IN_LD, AM_HL_SPR, RT_HL, RT_SP}, [0xF9] = {IN_LD, AM_R_R, RT_HL, RT_SP}, [0xFA] = {IN_LD, AM_R_A16, RT_A}, [0xFB] = {IN_EI}, - [0xFE] = {IN_CP, AM_D8}, + [0xFE] = {IN_CP, AM_R_D8, RT_A}, [0xFF] = {IN_RST, AM_IMP, RT_NONE, RT_NONE, CT_NONE, 0x38} }; @@ -322,4 +322,124 @@ char *inst_lookup[] = { char *inst_name(in_type t) { return inst_lookup[t]; +} + +static char *rt_lookup[] = { + "", + "A", + "F", + "B", + "C", + "D", + "E", + "H", + "L", + "AF", + "BC", + "DE", + "HL", + "SP", + "PC" +}; + +void inst_to_str(cpu_context *ctx, char *str) { + instruction *inst = ctx->cur_inst; + sprintf(str, "%s ", inst_name(inst->type)); + + switch(inst->mode) { + case AM_IMP: + return; + + case AM_R_D16: + case AM_R_A16: + sprintf(str, "%s %s,$%04X", inst_name(inst->type), + rt_lookup[inst->reg_1], ctx->fetched_data); + return; + + case AM_R: + sprintf(str, "%s %s", inst_name(inst->type), + rt_lookup[inst->reg_1]); + return; + + case AM_R_R: + sprintf(str, "%s %s,%s", inst_name(inst->type), + rt_lookup[inst->reg_1], rt_lookup[inst->reg_2]); + return; + + case AM_MR_R: + sprintf(str, "%s (%s),%s", inst_name(inst->type), + rt_lookup[inst->reg_1], rt_lookup[inst->reg_2]); + return; + + case AM_MR: + sprintf(str, "%s (%s)", inst_name(inst->type), + rt_lookup[inst->reg_1]); + return; + + case AM_R_MR: + sprintf(str, "%s %s,(%s)", inst_name(inst->type), + rt_lookup[inst->reg_1], rt_lookup[inst->reg_2]); + return; + + case AM_R_D8: + case AM_R_A8: + sprintf(str, "%s %s,$%02X", inst_name(inst->type), + rt_lookup[inst->reg_1], ctx->fetched_data & 0xFF); + return; + + case AM_R_HLI: + sprintf(str, "%s %s,(%s+)", inst_name(inst->type), + rt_lookup[inst->reg_1], rt_lookup[inst->reg_2]); + return; + + case AM_R_HLD: + sprintf(str, "%s %s,(%s-)", inst_name(inst->type), + rt_lookup[inst->reg_1], rt_lookup[inst->reg_2]); + return; + + case AM_HLI_R: + sprintf(str, "%s (%s+),%s", inst_name(inst->type), + rt_lookup[inst->reg_1], rt_lookup[inst->reg_2]); + return; + + case AM_HLD_R: + sprintf(str, "%s (%s-),%s", inst_name(inst->type), + rt_lookup[inst->reg_1], rt_lookup[inst->reg_2]); + return; + + case AM_A8_R: + sprintf(str, "%s $%02X,%s", inst_name(inst->type), + bus_read(ctx->regs.pc - 1), rt_lookup[inst->reg_2]); + + return; + + case AM_HL_SPR: + sprintf(str, "%s (%s),SP+%d", inst_name(inst->type), + rt_lookup[inst->reg_1], ctx->fetched_data & 0xFF); + return; + + case AM_D8: + sprintf(str, "%s $%02X", inst_name(inst->type), + ctx->fetched_data & 0xFF); + return; + + case AM_D16: + sprintf(str, "%s $%04X", inst_name(inst->type), + ctx->fetched_data); + return; + + case AM_MR_D8: + sprintf(str, "%s (%s),$%02X", inst_name(inst->type), + rt_lookup[inst->reg_1], ctx->fetched_data & 0xFF); + return; + + case AM_A16_R: + sprintf(str, "%s ($%04X),%s", inst_name(inst->type), + ctx->fetched_data, rt_lookup[inst->reg_2]); + return; + + default: + fprintf(stderr, "INVALID AM: %d\n", inst->mode); + NO_IMPL + } } \ No newline at end of file diff --git a/lib/io.c b/lib/io.c new file mode 100644 index 0000000..e8615af --- /dev/null +++ b/lib/io.c @@ -0,0 +1,32 @@ +#include + +static char serial_data[2]; + +u8 io_read(u16 address){ + if(address == 0xFF01) { + return serial_data[0]; + } + + if(address == 0xFF02) { + return serial_data[1]; + } + + printf("UNSUPPORTED io_read(%04X)\n", address); + return 0; +} + + +void io_write(u16 address, u8 value){ + if(address == 0xFF01) { + serial_data[0] = value; + return; + } + + if(address == 0xFF02) { + serial_data[1] = value; + return; + } + + printf("UNSUPPORTED io_write(%04X)\n", address); +} +