@@ -72,7 +72,7 @@ void z80_power(Z80 *z80) | |||||
regfile->ix = 0xFFFF; | regfile->ix = 0xFFFF; | ||||
regfile->iy = 0xFFFF; | regfile->iy = 0xFFFF; | ||||
regfile->sp = 0xFFFF; | |||||
regfile->sp = 0xFFF0; | |||||
regfile->pc = 0x0000; | regfile->pc = 0x0000; | ||||
regfile->i = 0xFF; | 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. | Return the CPU's current interrupt mode. | ||||
*/ | */ | ||||
static inline uint8_t get_interrupt_mode(const Z80 *z80) | 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): | 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) | 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) | // 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 | LD (IX+d), r | ||||
@@ -230,9 +238,17 @@ static uint8_t z80_inst_push_qq(Z80 *z80, uint8_t opcode) | |||||
return 11; | 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): | POP qq (0xC1, 0xD1, 0xE1, 0xF1): | ||||
@@ -246,9 +262,17 @@ static uint8_t z80_inst_pop_qq(Z80 *z80, uint8_t opcode) | |||||
return 10; | 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 | // EX DE, HL | ||||
@@ -632,7 +656,24 @@ static uint8_t z80_inst_jr_cc_e(Z80 *z80, uint8_t opcode) | |||||
// JP (IY) | // 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): | CALL nn (0xCD): | ||||
@@ -18,7 +18,7 @@ static DispatchTable instruction_table = { | |||||
[0x0D] = z80_inst_unimplemented, // TODO | [0x0D] = z80_inst_unimplemented, // TODO | ||||
[0x0E] = z80_inst_ld_r_n, | [0x0E] = z80_inst_ld_r_n, | ||||
[0x0F] = z80_inst_unimplemented, // TODO | [0x0F] = z80_inst_unimplemented, // TODO | ||||
[0x10] = z80_inst_unimplemented, // TODO | |||||
[0x10] = z80_inst_djnz_e, | |||||
[0x11] = z80_inst_ld_dd_nn, | [0x11] = z80_inst_ld_dd_nn, | ||||
[0x12] = z80_inst_unimplemented, // TODO | [0x12] = z80_inst_unimplemented, // TODO | ||||
[0x13] = z80_inst_inc_ss, | [0x13] = z80_inst_inc_ss, | ||||
@@ -114,14 +114,14 @@ static DispatchTable instruction_table = { | |||||
[0x6D] = z80_inst_ld_r_r, | [0x6D] = z80_inst_ld_r_r, | ||||
[0x6E] = z80_inst_ld_r_hl, | [0x6E] = z80_inst_ld_r_hl, | ||||
[0x6F] = z80_inst_ld_r_r, | [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, | [0x76] = z80_inst_halt, | ||||
[0x77] = z80_inst_unimplemented, // TODO | |||||
[0x77] = z80_inst_ld_hl_r, | |||||
[0x78] = z80_inst_ld_r_r, | [0x78] = z80_inst_ld_r_r, | ||||
[0x79] = z80_inst_ld_r_r, | [0x79] = z80_inst_ld_r_r, | ||||
[0x7A] = z80_inst_ld_r_r, | [0x7A] = z80_inst_ld_r_r, | ||||
@@ -1004,11 +1004,11 @@ static DispatchTable instruction_table_index = { | |||||
[0xDE] = z80_inst_nop2, | [0xDE] = z80_inst_nop2, | ||||
[0xDF] = z80_inst_nop2, | [0xDF] = z80_inst_nop2, | ||||
[0xE0] = z80_inst_nop2, | [0xE0] = z80_inst_nop2, | ||||
[0xE1] = z80_inst_unimplemented, // TODO | |||||
[0xE1] = z80_inst_pop_ixy, | |||||
[0xE2] = z80_inst_nop2, | [0xE2] = z80_inst_nop2, | ||||
[0xE3] = z80_inst_unimplemented, // TODO | [0xE3] = z80_inst_unimplemented, // TODO | ||||
[0xE4] = z80_inst_nop2, | [0xE4] = z80_inst_nop2, | ||||
[0xE5] = z80_inst_unimplemented, // TODO | |||||
[0xE5] = z80_inst_push_ixy, | |||||
[0xE6] = z80_inst_nop2, | [0xE6] = z80_inst_nop2, | ||||
[0xE7] = z80_inst_nop2, | [0xE7] = z80_inst_nop2, | ||||
[0xE8] = z80_inst_nop2, | [0xE8] = z80_inst_nop2, | ||||