@@ -72,7 +72,7 @@ void z80_power(Z80 *z80) | |||
regfile->ix = 0xFFFF; | |||
regfile->iy = 0xFFFF; | |||
regfile->sp = 0xFFFF; | |||
regfile->sp = 0xFFF0; | |||
regfile->pc = 0x0000; | |||
regfile->i = 0xFF; | |||
@@ -261,6 +261,17 @@ static inline bool extract_cond(const Z80 *z80, uint8_t opcode) | |||
} | |||
/* | |||
Extract the current index register. | |||
*/ | |||
static inline uint16_t* extract_index(Z80 *z80) | |||
{ | |||
uint8_t prefix = mmu_read_byte(z80->mmu, z80->regfile.pc - 1); | |||
if (prefix != 0xDD && prefix != 0xFD) | |||
FATAL("invalid call: extract_index(z80, 0x%02X)", prefix) | |||
return prefix == 0xDD ? &z80->regfile.ix : &z80->regfile.iy; | |||
} | |||
/* | |||
Return the CPU's current interrupt mode. | |||
*/ | |||
static inline uint8_t get_interrupt_mode(const Z80 *z80) | |||
@@ -63,7 +63,7 @@ static uint8_t z80_inst_ld_r_n(Z80 *z80, uint8_t opcode) | |||
/* | |||
LD r, (HL) (0x46, 0x4E, 0x56, 0x5E, 0x66, 0x6E, 0x7E): | |||
Load the contents of HL into r (8-bit register). | |||
Load the memory pointed to by HL into r (8-bit register). | |||
*/ | |||
static uint8_t z80_inst_ld_r_hl(Z80 *z80, uint8_t opcode) | |||
{ | |||
@@ -84,9 +84,17 @@ static uint8_t z80_inst_ld_r_hl(Z80 *z80, uint8_t opcode) | |||
// static uint8_t z80_inst_ld_r_iy(Z80 *z80, uint8_t opcode) | |||
/* | |||
LD (HL), r | |||
LD (HL), r (0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x77): | |||
Load r (8-bit register) into the memory pointed to by HL. | |||
*/ | |||
// static uint8_t z80_inst_ld_hl_r(Z80 *z80, uint8_t opcode) | |||
static uint8_t z80_inst_ld_hl_r(Z80 *z80, uint8_t opcode) | |||
{ | |||
uint8_t *reg = extract_reg(z80, opcode << 3); | |||
uint16_t addr = get_pair(z80, REG_HL); | |||
mmu_write_byte(z80->mmu, addr, *reg); | |||
z80->regfile.pc++; | |||
return 7; | |||
} | |||
/* | |||
LD (IX+d), r | |||
@@ -230,9 +238,17 @@ static uint8_t z80_inst_push_qq(Z80 *z80, uint8_t opcode) | |||
return 11; | |||
} | |||
// PUSH IX | |||
// PUSH IY | |||
/* | |||
PUSH IXY (0xDDE5, 0xFDE5): | |||
Push IX or IY onto the stack, and decrement SP by two. | |||
*/ | |||
static uint8_t z80_inst_push_ixy(Z80 *z80, uint8_t opcode) | |||
{ | |||
(void) opcode; | |||
stack_push(z80, *extract_index(z80)); | |||
z80->regfile.pc++; | |||
return 15; | |||
} | |||
/* | |||
POP qq (0xC1, 0xD1, 0xE1, 0xF1): | |||
@@ -246,9 +262,17 @@ static uint8_t z80_inst_pop_qq(Z80 *z80, uint8_t opcode) | |||
return 10; | |||
} | |||
// POP IX | |||
// POP IY | |||
/* | |||
POP IXY (0xDDE1, 0xFDE1): | |||
Pop IX or IY from the stack, and increment SP by two. | |||
*/ | |||
static uint8_t z80_inst_pop_ixy(Z80 *z80, uint8_t opcode) | |||
{ | |||
(void) opcode; | |||
*extract_index(z80) = stack_pop(z80); | |||
z80->regfile.pc++; | |||
return 14; | |||
} | |||
// EX DE, HL | |||
@@ -632,7 +656,24 @@ static uint8_t z80_inst_jr_cc_e(Z80 *z80, uint8_t opcode) | |||
// JP (IY) | |||
// DJNZ, e | |||
/* | |||
DJNZ, e (0x10): | |||
Decrement b and relative jump e (signed 8-bit immediate) if non-zero. | |||
*/ | |||
static uint8_t z80_inst_djnz_e(Z80 *z80, uint8_t opcode) | |||
{ | |||
(void) opcode; | |||
z80->regfile.b--; | |||
if (z80->regfile.b != 0) { | |||
int8_t jump = mmu_read_byte(z80->mmu, z80->regfile.pc + 1); | |||
z80->regfile.pc += jump + 2; | |||
return 13; | |||
} else { | |||
z80->regfile.pc += 2; | |||
return 8; | |||
} | |||
} | |||
/* | |||
CALL nn (0xCD): | |||
@@ -18,7 +18,7 @@ static DispatchTable instruction_table = { | |||
[0x0D] = z80_inst_unimplemented, // TODO | |||
[0x0E] = z80_inst_ld_r_n, | |||
[0x0F] = z80_inst_unimplemented, // TODO | |||
[0x10] = z80_inst_unimplemented, // TODO | |||
[0x10] = z80_inst_djnz_e, | |||
[0x11] = z80_inst_ld_dd_nn, | |||
[0x12] = z80_inst_unimplemented, // TODO | |||
[0x13] = z80_inst_inc_ss, | |||
@@ -114,14 +114,14 @@ static DispatchTable instruction_table = { | |||
[0x6D] = z80_inst_ld_r_r, | |||
[0x6E] = z80_inst_ld_r_hl, | |||
[0x6F] = z80_inst_ld_r_r, | |||
[0x70] = z80_inst_unimplemented, // TODO | |||
[0x71] = z80_inst_unimplemented, // TODO | |||
[0x72] = z80_inst_unimplemented, // TODO | |||
[0x73] = z80_inst_unimplemented, // TODO | |||
[0x74] = z80_inst_unimplemented, // TODO | |||
[0x75] = z80_inst_unimplemented, // TODO | |||
[0x70] = z80_inst_ld_hl_r, | |||
[0x71] = z80_inst_ld_hl_r, | |||
[0x72] = z80_inst_ld_hl_r, | |||
[0x73] = z80_inst_ld_hl_r, | |||
[0x74] = z80_inst_ld_hl_r, | |||
[0x75] = z80_inst_ld_hl_r, | |||
[0x76] = z80_inst_halt, | |||
[0x77] = z80_inst_unimplemented, // TODO | |||
[0x77] = z80_inst_ld_hl_r, | |||
[0x78] = z80_inst_ld_r_r, | |||
[0x79] = z80_inst_ld_r_r, | |||
[0x7A] = z80_inst_ld_r_r, | |||
@@ -1004,11 +1004,11 @@ static DispatchTable instruction_table_index = { | |||
[0xDE] = z80_inst_nop2, | |||
[0xDF] = z80_inst_nop2, | |||
[0xE0] = z80_inst_nop2, | |||
[0xE1] = z80_inst_unimplemented, // TODO | |||
[0xE1] = z80_inst_pop_ixy, | |||
[0xE2] = z80_inst_nop2, | |||
[0xE3] = z80_inst_unimplemented, // TODO | |||
[0xE4] = z80_inst_nop2, | |||
[0xE5] = z80_inst_unimplemented, // TODO | |||
[0xE5] = z80_inst_push_ixy, | |||
[0xE6] = z80_inst_nop2, | |||
[0xE7] = z80_inst_nop2, | |||
[0xE8] = z80_inst_nop2, | |||