From 8de5117a49f852567214de0bae34d8e2ee04bdc4 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Fri, 22 Apr 2016 14:47:20 -0500 Subject: [PATCH] mmu_write_double, stack_push; LD (HL), n; JR; CALL --- src/mmu.c | 10 +++++++ src/mmu.h | 1 + src/z80.c | 9 +++++++ src/z80_ops.inc.c | 76 +++++++++++++++++++++++++++++++++++++++++++--------- src/z80_tables.inc.c | 30 ++++++++++----------- 5 files changed, 99 insertions(+), 27 deletions(-) diff --git a/src/mmu.c b/src/mmu.c index 2213af4..cca507a 100644 --- a/src/mmu.c +++ b/src/mmu.c @@ -181,3 +181,13 @@ bool mmu_write_byte(MMU *mmu, uint16_t addr, uint8_t value) return true; } } + +/* + Write two bytes of memory to the given address. +*/ +bool mmu_write_double(MMU *mmu, uint16_t addr, uint16_t value) +{ + bool b1 = mmu_write_byte(mmu, addr, value & 0xFF); + bool b2 = mmu_write_byte(mmu, addr + 1, value >> 8); + return b1 && b2; +} diff --git a/src/mmu.h b/src/mmu.h index 8a5dd0c..1b987bf 100644 --- a/src/mmu.h +++ b/src/mmu.h @@ -30,3 +30,4 @@ uint8_t mmu_read_byte(const MMU*, uint16_t); uint16_t mmu_read_double(const MMU*, uint16_t); uint32_t mmu_read_quad(const MMU*, uint16_t); bool mmu_write_byte(MMU*, uint16_t, uint8_t); +bool mmu_write_double(MMU*, uint16_t, uint16_t); diff --git a/src/z80.c b/src/z80.c index 9a8d1f2..88e159f 100644 --- a/src/z80.c +++ b/src/z80.c @@ -161,6 +161,15 @@ static inline void update_flags(Z80 *z80, bool c, bool n, bool pv, bool f3, } /* + Push a two-byte value onto the stack. +*/ +static inline void stack_push(Z80 *z80, uint16_t value) +{ + z80->regfile.sp -= 2; + mmu_write_double(z80->mmu, z80->regfile.sp, value); +} + +/* Read and return a byte from the given port. */ static uint8_t read_port(Z80 *z80, uint8_t port) diff --git a/src/z80_ops.inc.c b/src/z80_ops.inc.c index dd22905..90623ab 100644 --- a/src/z80_ops.inc.c +++ b/src/z80_ops.inc.c @@ -99,9 +99,18 @@ static uint8_t z80_inst_ld_r_hl(Z80 *z80, uint8_t opcode) // static uint8_t z80_inst_ld_iy_r(Z80 *z80, uint8_t opcode) /* - LD (HL), n + LD (HL), n (0x36): + Load n (8-bit immediate) into the memory address pointed to by HL. */ -// static uint8_t z80_inst_ld_hl_n(Z80 *z80, uint8_t opcode) +static uint8_t z80_inst_ld_hl_n(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t addr = get_pair(z80, REG_HL); + uint8_t byte = mmu_read_byte(z80->mmu, ++z80->regfile.pc); + mmu_write_byte(z80->mmu, addr, byte); + z80->regfile.pc++; + return 10; +} /* LD (IX+d), n @@ -564,19 +573,38 @@ static uint8_t z80_inst_jp_cc_nn(Z80 *z80, uint8_t opcode) if (extract_cond(z80, opcode)) z80->regfile.pc = mmu_read_double(z80->mmu, ++z80->regfile.pc); else - z80->regfile.pc += 2; + z80->regfile.pc += 3; return 10; } -// JR e - -// JR C, e - -// JR NC, e +/* + JR e (0x18): + Relative jump e (signed 8-bit immediate) bytes. +*/ +static uint8_t z80_inst_jr_e(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + int8_t jump = mmu_read_byte(z80->mmu, ++z80->regfile.pc); + z80->regfile.pc += jump + 2; + return 12; +} -// JR Z, e -// JR NZ, e +/* + JR cc, e (0x20, 0x28, 0x30, 0x38): + Relative jump e (signed 8-bit immediate) bytes if cc (condition) is true. +*/ +static uint8_t z80_inst_jr_cc_e(Z80 *z80, uint8_t opcode) +{ + if (extract_cond(z80, opcode - 0x20)) { + int8_t jump = mmu_read_byte(z80->mmu, ++z80->regfile.pc); + z80->regfile.pc += jump + 2; + return 12; + } else { + z80->regfile.pc += 2; + return 7; + } +} // JP (HL) @@ -586,9 +614,33 @@ static uint8_t z80_inst_jp_cc_nn(Z80 *z80, uint8_t opcode) // DJNZ, e -// CALL nn +/* + CALL nn (0xCD): + Push PC+3 onto the stack and jump to nn (16-bit immediate). +*/ +static uint8_t z80_inst_call_nn(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + stack_push(z80, z80->regfile.pc + 3); + z80->regfile.pc = mmu_read_double(z80->mmu, ++z80->regfile.pc); + return 17; +} -// CALL cc, nn +/* + CALL cc, nn (0xC4, 0xCC, 0xD4, 0xDC, 0xE4, 0xEC, 0xF4, 0xFC): + Push PC+3 onto the stack and jump to nn (16-bit immediate) if cc is true. +*/ +static uint8_t z80_inst_call_cc_nn(Z80 *z80, uint8_t opcode) +{ + if (extract_cond(z80, opcode)) { + stack_push(z80, z80->regfile.pc + 3); + z80->regfile.pc = mmu_read_double(z80->mmu, ++z80->regfile.pc); + return 17; + } else { + z80->regfile.pc += 3; + return 10; + } +} // RET diff --git a/src/z80_tables.inc.c b/src/z80_tables.inc.c index 3a2275f..8fad0bf 100644 --- a/src/z80_tables.inc.c +++ b/src/z80_tables.inc.c @@ -26,7 +26,7 @@ static DispatchTable instruction_table = { [0x15] = z80_inst_unimplemented, // TODO [0x16] = z80_inst_ld_r_n, [0x17] = z80_inst_unimplemented, // TODO - [0x18] = z80_inst_unimplemented, // TODO + [0x18] = z80_inst_jr_e, [0x19] = z80_inst_unimplemented, // TODO [0x1A] = z80_inst_unimplemented, // TODO [0x1B] = z80_inst_unimplemented, // TODO @@ -34,7 +34,7 @@ static DispatchTable instruction_table = { [0x1D] = z80_inst_unimplemented, // TODO [0x1E] = z80_inst_ld_r_n, [0x1F] = z80_inst_unimplemented, // TODO - [0x20] = z80_inst_unimplemented, // TODO + [0x20] = z80_inst_jr_cc_e, [0x21] = z80_inst_ld_dd_nn, [0x22] = z80_inst_unimplemented, // TODO [0x23] = z80_inst_inc_ss, @@ -42,7 +42,7 @@ static DispatchTable instruction_table = { [0x25] = z80_inst_unimplemented, // TODO [0x26] = z80_inst_ld_r_n, [0x27] = z80_inst_unimplemented, // TODO - [0x28] = z80_inst_unimplemented, // TODO + [0x28] = z80_inst_jr_cc_e, [0x29] = z80_inst_unimplemented, // TODO [0x2A] = z80_inst_unimplemented, // TODO [0x2B] = z80_inst_unimplemented, // TODO @@ -50,15 +50,15 @@ static DispatchTable instruction_table = { [0x2D] = z80_inst_unimplemented, // TODO [0x2E] = z80_inst_ld_r_n, [0x2F] = z80_inst_unimplemented, // TODO - [0x30] = z80_inst_unimplemented, // TODO + [0x30] = z80_inst_jr_cc_e, [0x31] = z80_inst_ld_dd_nn, [0x32] = z80_inst_ld_nn_a, [0x33] = z80_inst_inc_ss, [0x34] = z80_inst_unimplemented, // TODO [0x35] = z80_inst_unimplemented, // TODO - [0x36] = z80_inst_unimplemented, // TODO + [0x36] = z80_inst_ld_hl_n, [0x37] = z80_inst_unimplemented, // TODO - [0x38] = z80_inst_unimplemented, // TODO + [0x38] = z80_inst_jr_cc_e, [0x39] = z80_inst_unimplemented, // TODO [0x3A] = z80_inst_unimplemented, // TODO [0x3B] = z80_inst_unimplemented, // TODO @@ -198,7 +198,7 @@ static DispatchTable instruction_table = { [0xC1] = z80_inst_unimplemented, // TODO [0xC2] = z80_inst_jp_cc_nn, [0xC3] = z80_inst_jp_nn, - [0xC4] = z80_inst_unimplemented, // TODO + [0xC4] = z80_inst_call_cc_nn, [0xC5] = z80_inst_unimplemented, // TODO [0xC6] = z80_inst_unimplemented, // TODO [0xC7] = z80_inst_unimplemented, // TODO @@ -206,15 +206,15 @@ static DispatchTable instruction_table = { [0xC9] = z80_inst_unimplemented, // TODO [0xCA] = z80_inst_jp_cc_nn, [0xCB] = z80_prefix_bits, - [0xCC] = z80_inst_unimplemented, // TODO - [0xCD] = z80_inst_unimplemented, // TODO + [0xCC] = z80_inst_call_cc_nn, + [0xCD] = z80_inst_call_nn, [0xCE] = z80_inst_unimplemented, // TODO [0xCF] = z80_inst_unimplemented, // TODO [0xD0] = z80_inst_unimplemented, // TODO [0xD1] = z80_inst_unimplemented, // TODO [0xD2] = z80_inst_jp_cc_nn, [0xD3] = z80_inst_out_n_a, - [0xD4] = z80_inst_unimplemented, // TODO + [0xD4] = z80_inst_call_cc_nn, [0xD5] = z80_inst_unimplemented, // TODO [0xD6] = z80_inst_unimplemented, // TODO [0xD7] = z80_inst_unimplemented, // TODO @@ -222,7 +222,7 @@ static DispatchTable instruction_table = { [0xD9] = z80_inst_exx, [0xDA] = z80_inst_jp_cc_nn, [0xDB] = z80_inst_in_a_n, - [0xDC] = z80_inst_unimplemented, // TODO + [0xDC] = z80_inst_call_cc_nn, [0xDD] = z80_prefix_index, [0xDE] = z80_inst_unimplemented, // TODO [0xDF] = z80_inst_unimplemented, // TODO @@ -230,7 +230,7 @@ static DispatchTable instruction_table = { [0xE1] = z80_inst_unimplemented, // TODO [0xE2] = z80_inst_jp_cc_nn, [0xE3] = z80_inst_unimplemented, // TODO - [0xE4] = z80_inst_unimplemented, // TODO + [0xE4] = z80_inst_call_cc_nn, [0xE5] = z80_inst_unimplemented, // TODO [0xE6] = z80_inst_unimplemented, // TODO [0xE7] = z80_inst_unimplemented, // TODO @@ -238,7 +238,7 @@ static DispatchTable instruction_table = { [0xE9] = z80_inst_unimplemented, // TODO [0xEA] = z80_inst_jp_cc_nn, [0xEB] = z80_inst_unimplemented, // TODO - [0xEC] = z80_inst_unimplemented, // TODO + [0xEC] = z80_inst_call_cc_nn, [0xED] = z80_prefix_extended, [0xEE] = z80_inst_unimplemented, // TODO [0xEF] = z80_inst_unimplemented, // TODO @@ -246,7 +246,7 @@ static DispatchTable instruction_table = { [0xF1] = z80_inst_unimplemented, // TODO [0xF2] = z80_inst_jp_cc_nn, [0xF3] = z80_inst_di, - [0xF4] = z80_inst_unimplemented, // TODO + [0xF4] = z80_inst_call_cc_nn, [0xF5] = z80_inst_unimplemented, // TODO [0xF6] = z80_inst_unimplemented, // TODO [0xF7] = z80_inst_unimplemented, // TODO @@ -254,7 +254,7 @@ static DispatchTable instruction_table = { [0xF9] = z80_inst_unimplemented, // TODO [0xFA] = z80_inst_jp_cc_nn, [0xFB] = z80_inst_ei, - [0xFC] = z80_inst_unimplemented, // TODO + [0xFC] = z80_inst_call_cc_nn, [0xFD] = z80_prefix_index, [0xFE] = z80_inst_cp_n, [0xFF] = z80_inst_unimplemented // TODO