CPU testing

This commit is contained in:
Samuel Walker 2025-01-31 17:07:09 -07:00
parent 9a6dc67c3e
commit 5206c3871e
Signed by: piwalker
GPG Key ID: BE1F84BF85111255
11 changed files with 212 additions and 14 deletions

View File

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

View File

@ -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);
void cpu_set_int_flags(u8 value);
void inst_to_str(cpu_context *ctx, char *str);

6
include/dbg.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <common.h>
void dbg_update();
void dbg_print();

6
include/io.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <common.h>
u8 io_read(u16 address);
void io_write(u16 address, u8 value);

View File

@ -3,6 +3,7 @@
#include <cart.h>
#include <cpu.h>
#include <ram.h>
#include <io.h>
// 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) {

View File

@ -3,6 +3,7 @@
#include <common.h>
#include <emu.h>
#include <interrupts.h>
#include <dbg.h>
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

View File

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

View File

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

21
lib/dbg.c Normal file
View File

@ -0,0 +1,21 @@
#include <dbg.h>
#include <bus.h>
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);
}
}

View File

@ -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[] = {
"<NONE>",
"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
}
}

32
lib/io.c Normal file
View File

@ -0,0 +1,32 @@
#include <io.h>
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);
}