From da5765a3c71fe357c877a31262186df41c2a736c Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 25 Apr 2016 02:35:35 -0500 Subject: [PATCH] PUSH/POP IX/Y; DJNZ; LD (HL), r --- src/z80.c | 13 ++++++++++- src/z80_ops.inc.c | 61 +++++++++++++++++++++++++++++++++++++++++++--------- src/z80_tables.inc.c | 20 ++++++++--------- 3 files changed, 73 insertions(+), 21 deletions(-) diff --git a/src/z80.c b/src/z80.c index c86afe6..fb995b5 100644 --- a/src/z80.c +++ b/src/z80.c @@ -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) diff --git a/src/z80_ops.inc.c b/src/z80_ops.inc.c index 40b394c..c495c52 100644 --- a/src/z80_ops.inc.c +++ b/src/z80_ops.inc.c @@ -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): diff --git a/src/z80_tables.inc.c b/src/z80_tables.inc.c index ee45802..760b6f7 100644 --- a/src/z80_tables.inc.c +++ b/src/z80_tables.inc.c @@ -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,