CPU testing
This commit is contained in:
parent
9a6dc67c3e
commit
5206c3871e
@ -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);
|
||||
|
@ -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
6
include/dbg.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <common.h>
|
||||
|
||||
void dbg_update();
|
||||
void dbg_print();
|
6
include/io.h
Normal file
6
include/io.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <common.h>
|
||||
|
||||
u8 io_read(u16 address);
|
||||
void io_write(u16 address, u8 value);
|
@ -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) {
|
||||
|
11
lib/cpu.c
11
lib/cpu.c
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
21
lib/dbg.c
Normal 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);
|
||||
}
|
||||
}
|
@ -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
32
lib/io.c
Normal 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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user