cpu: fix up register accesses

The HL dereference operations cause problems indexing into the
registers array, because it causes a hole in the array that only
exists in the 8-bit register space.

Instead of accessing the registers directly by the same indices used
in in the assembly instructions, create a lookup table to map between
them.

Signed-off-by: Max Regan <mgregan2@gmail.com>
This commit is contained in:
2017-04-07 16:19:42 -07:00
parent 0268f13080
commit 5bbc6097b5
2 changed files with 37 additions and 13 deletions

View File

@@ -382,30 +382,52 @@ static lr35902_instr lr35902_cb_instrs[] = {
/*0xF?*/ set, set, /*0xF?*/ set, set,
}; };
static int cpu_reg16_to_idx[NUM_LR35902_REGS_16] = {
[LR35902_REG_BC] = 0,
[LR35902_REG_DE] = 1,
[LR35902_REG_HL] = 2,
[LR35902_REG_AF] = 3,
[LR35902_REG_PC] = 4,
[LR35902_REG_SP] = 5,
};
uint16_t lr35902_get_reg_16(struct lr35902_state *cpu, lr35902_regs_16 reg) uint16_t lr35902_get_reg_16(struct lr35902_state *cpu, lr35902_regs_16 reg)
{ {
ASSERT(reg >= 0); ASSERT_MSG(reg >= 0 && reg < NUM_LR35902_REGS_16, "reg=%d\n", reg);
ASSERT_MSG(reg < NUM_LR35902_REGS_16, "reg=%d\n", reg); return cpu->regs_16[cpu_reg16_to_idx[reg]];
return cpu->regs_16[reg];
} }
static int cpu_reg8_to_idx[NUM_LR35902_REGS_8] = {
[LR35902_REG_A] = 6,
[LR35902_REG_B] = 0,
[LR35902_REG_C] = 1,
[LR35902_REG_D] = 2,
[LR35902_REG_E] = 3,
[LR35902_REG_H] = 4,
[LR35902_REG_L] = 5,
[LR35902_REG_F] = 7,
[LR35902_REG_HL_DEREF] = -1,
};
uint8_t lr35902_get_reg_8(struct lr35902_state *cpu, lr35902_regs_8 reg) uint8_t lr35902_get_reg_8(struct lr35902_state *cpu, lr35902_regs_8 reg)
{ {
ASSERT(reg < NUM_LR35902_REGS_8);
ASSERT(reg != LR35902_REG_HL_DEREF); ASSERT(reg != LR35902_REG_HL_DEREF);
return cpu->regs_8[reg]; return cpu->regs_8[cpu_reg8_to_idx[reg]];
} }
void lr35902_set_reg_16(struct lr35902_state *cpu, lr35902_regs_16 reg, void lr35902_set_reg_16(struct lr35902_state *cpu, lr35902_regs_16 reg,
uint16_t val) uint16_t val)
{ {
cpu->regs_16[reg] = val; ASSERT(reg < NUM_LR35902_REGS_16 && reg >= 0);
cpu->regs_16[cpu_reg16_to_idx[reg]] = val;
} }
void lr35902_set_reg_8(struct lr35902_state *cpu, lr35902_regs_8 reg, void lr35902_set_reg_8(struct lr35902_state *cpu, lr35902_regs_8 reg,
uint8_t val) uint8_t val)
{ {
ASSERT(reg < NUM_LR35902_REGS_8); ASSERT(reg < NUM_LR35902_REGS_8 && reg >= 0);
cpu->regs_8[reg] = val; cpu->regs_8[cpu_reg8_to_idx[reg]] = val;
} }
@@ -534,15 +556,17 @@ static uint8_t _get_reg_8(struct lr35902_state *cpu, uint8_t reg){
if (reg == LR35902_REG_HL_DEREF){ if (reg == LR35902_REG_HL_DEREF){
return cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_HL)); return cpu->mem_read(cpu, lr35902_get_reg_16(cpu, LR35902_REG_HL));
} else { } else {
return cpu->regs_8[reg]; return cpu->regs_8[cpu_reg8_to_idx[reg]];
} }
} }
static void _set_reg_8(struct lr35902_state *cpu, uint8_t reg, uint8_t val){ static void _set_reg_8(struct lr35902_state *cpu, uint8_t reg, uint8_t val){
ASSERT(reg < NUM_LR35902_REGS_8 && reg >= 0);
if (reg == LR35902_REG_HL_DEREF){ if (reg == LR35902_REG_HL_DEREF){
cpu->mem_write(cpu, lr35902_get_reg_16(cpu, LR35902_REG_HL), val); cpu->mem_write(cpu, lr35902_get_reg_16(cpu, LR35902_REG_HL), val);
} else { } else {
cpu->regs_8[reg] = val; cpu->regs_8[cpu_reg8_to_idx[reg]] = val;
} }
} }

View File

@@ -15,10 +15,10 @@
#define LR35902_MAX_EVENTS 16 #define LR35902_MAX_EVENTS 16
typedef enum { typedef enum {
LR35902_REG_AF= 0, LR35902_REG_BC = 0,
LR35902_REG_BC, LR35902_REG_DE = 1,
LR35902_REG_DE, LR35902_REG_HL = 2,
LR35902_REG_HL, LR35902_REG_AF = 3,
LR35902_REG_SP, LR35902_REG_SP,
LR35902_REG_PC, LR35902_REG_PC,
NUM_LR35902_REGS_16 NUM_LR35902_REGS_16