From 42690f93804708e57c887d5ce64fcb8807ef5075 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Wed, 27 Apr 2016 04:05:48 -0500 Subject: [PATCH] Implement more instructions. --- src/z80.c | 4 +- src/z80_ops.inc.c | 67 ++++++++++++++++++++-- src/z80_tables.inc.c | 154 +++++++++++++++++++++++++-------------------------- 3 files changed, 142 insertions(+), 83 deletions(-) diff --git a/src/z80.c b/src/z80.c index 22a3506..32dfa5e 100644 --- a/src/z80.c +++ b/src/z80.c @@ -254,9 +254,9 @@ static inline bool extract_cond(const Z80 *z80, uint8_t opcode) /* Return the address signified by a indirect index instruction. */ -static inline uint16_t get_index_addr(Z80 *z80, int8_t offset) +static inline uint16_t get_index_addr(Z80 *z80, uint16_t offset_addr) { - return *z80->last_index + offset; + return *z80->last_index + ((int8_t) mmu_read_byte(z80->mmu, offset_addr)); } /* diff --git a/src/z80_ops.inc.c b/src/z80_ops.inc.c index 21a2ef8..d1292c2 100644 --- a/src/z80_ops.inc.c +++ b/src/z80_ops.inc.c @@ -273,7 +273,18 @@ static uint8_t z80_inst_ld_nn_hl(Z80 *z80, uint8_t opcode) return 16; } -// LD (nn), dd +/* + LD (nn), dd (0xED43, 0xED53, 0xED63, 0xED73); + Load dd (16-bit register) into memory address nn. +*/ +static uint8_t z80_inst_ld_nn_dd(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint16_t addr = mmu_read_double(z80->mmu, ++z80->regfile.pc); + mmu_write_double(z80->mmu, addr, extract_pair(opcode)); + z80->regfile.pc += 2; + return 16; +} // LD (nn), IXY @@ -756,7 +767,22 @@ static uint8_t z80_inst_dec_r(Z80 *z80, uint8_t opcode) return 4; } -// DEC (HL) +/* + DEC (HL) (0x35): + Decrement the memory address pointed to by HL. +*/ +static uint8_t z80_inst_dec_hl(Z80 *z80, uint8_t opcode) +{ + (void) opcode; + uint8_t byte = mmu_read_byte(z80->mmu, get_pair(z80, REG_HL)); + bool halfcarry = !!(((byte & 0x0F) + 1) & 0x10); + mmu_write_byte(z80->mmu, get_pair(z80, REG_HL), --byte); + update_flags(z80, 0, 1, byte == 0x7F, !!(byte & 0x08), halfcarry, + !!(byte & 0x20), byte == 0, !!(byte & 0x80), 0xFE); + + z80->regfile.pc++; + return 11; +} // DEC (IXY+d) @@ -1017,7 +1043,23 @@ static uint8_t z80_inst_bit_b_hl(Z80 *z80, uint8_t opcode) return 8; } -// BIT b, (IXY+d) +/* + BIT b, (IXY+d) (0xDDCB40-0xDDCB7F, 0xFDCB40-0xFDCB7F): + Test bit b of (IX+d) or (IY+d). +*/ +static uint8_t z80_inst_bit_b_ixy(Z80 *z80, uint8_t opcode) +{ + uint16_t addr = get_index_addr(z80, z80->regfile.pc - 1); + uint8_t val = mmu_read_byte(z80->mmu, addr); + uint8_t bit = (opcode >> 3) & 0x07; + bool z = ((val >> bit) & 1) == 0; + if (z) + update_flags(z80, 0, 0, 1, 0, 1, 0, 1, 0, 0xFE); + else + update_flags(z80, 0, 0, 0, bit == 3, 1, bit == 5, 0, bit == 7, 0xFE); + z80->regfile.pc++; + return 8; +} // SET b, r @@ -1025,7 +1067,24 @@ static uint8_t z80_inst_bit_b_hl(Z80 *z80, uint8_t opcode) // SET b, (IXY+d) -// RES b, m +// RES b, r + +/* + RES b, (HL) (0xCB86, 0xCB8E, 0xCB96, 0xCB9E, 0xCBA6, 0xCBAE, 0xCBB6, + 0xCBBE): + Reset bit b of (HL). +*/ +static uint8_t z80_inst_res_b_hl(Z80 *z80, uint8_t opcode) +{ + uint8_t val = mmu_read_byte(z80->mmu, get_pair(z80, REG_HL)); + uint8_t bit = (opcode >> 3) & 0x07; + val &= ~(1 << bit); + mmu_write_byte(z80->mmu, get_pair(z80, REG_HL), val); + z80->regfile.pc++; + return 8; +} + +// RES b, (IXY+d) /* JP nn (0xC3): diff --git a/src/z80_tables.inc.c b/src/z80_tables.inc.c index 9bc7515..7d28d43 100644 --- a/src/z80_tables.inc.c +++ b/src/z80_tables.inc.c @@ -55,7 +55,7 @@ static DispatchTable instruction_table = { [0x32] = z80_inst_ld_nn_a, [0x33] = z80_inst_inc_ss, [0x34] = z80_inst_inc_hl, - [0x35] = z80_inst_unimplemented, // TODO + [0x35] = z80_inst_dec_hl, [0x36] = z80_inst_ld_hl_n, [0x37] = z80_inst_unimplemented, // TODO [0x38] = z80_inst_jr_cc_e, @@ -328,7 +328,7 @@ static DispatchTable instruction_table_extended = { [0x40] = z80_inst_in_r_c, [0x41] = z80_inst_out_c_r, [0x42] = z80_inst_sbc_hl_ss, - [0x43] = z80_inst_unimplemented, // TODO + [0x43] = z80_inst_ld_nn_dd, [0x44] = z80_inst_unimplemented, // TODO [0x45] = z80_inst_retn, [0x46] = z80_inst_im, @@ -344,7 +344,7 @@ static DispatchTable instruction_table_extended = { [0x50] = z80_inst_in_r_c, [0x51] = z80_inst_out_c_r, [0x52] = z80_inst_sbc_hl_ss, - [0x53] = z80_inst_unimplemented, // TODO + [0x53] = z80_inst_ld_nn_dd, [0x54] = z80_inst_unimplemented, // TODO [0x55] = z80_inst_retn, [0x56] = z80_inst_im, @@ -360,7 +360,7 @@ static DispatchTable instruction_table_extended = { [0x60] = z80_inst_in_r_c, [0x61] = z80_inst_out_c_r, [0x62] = z80_inst_sbc_hl_ss, - [0x63] = z80_inst_unimplemented, // TODO + [0x63] = z80_inst_ld_nn_dd, [0x64] = z80_inst_unimplemented, // TODO [0x65] = z80_inst_retn, [0x66] = z80_inst_im, @@ -376,7 +376,7 @@ static DispatchTable instruction_table_extended = { [0x70] = z80_inst_in_r_c, [0x71] = z80_inst_out_c_r, [0x72] = z80_inst_sbc_hl_ss, - [0x73] = z80_inst_unimplemented, // TODO + [0x73] = z80_inst_ld_nn_dd, [0x74] = z80_inst_unimplemented, // TODO [0x75] = z80_inst_retn, [0x76] = z80_inst_im, @@ -654,7 +654,7 @@ static DispatchTable instruction_table_bits = { [0x83] = z80_inst_unimplemented, // TODO [0x84] = z80_inst_unimplemented, // TODO [0x85] = z80_inst_unimplemented, // TODO - [0x86] = z80_inst_unimplemented, // TODO + [0x86] = z80_inst_res_b_hl, [0x87] = z80_inst_unimplemented, // TODO [0x88] = z80_inst_unimplemented, // TODO [0x89] = z80_inst_unimplemented, // TODO @@ -662,7 +662,7 @@ static DispatchTable instruction_table_bits = { [0x8B] = z80_inst_unimplemented, // TODO [0x8C] = z80_inst_unimplemented, // TODO [0x8D] = z80_inst_unimplemented, // TODO - [0x8E] = z80_inst_unimplemented, // TODO + [0x8E] = z80_inst_res_b_hl, [0x8F] = z80_inst_unimplemented, // TODO [0x90] = z80_inst_unimplemented, // TODO [0x91] = z80_inst_unimplemented, // TODO @@ -670,7 +670,7 @@ static DispatchTable instruction_table_bits = { [0x93] = z80_inst_unimplemented, // TODO [0x94] = z80_inst_unimplemented, // TODO [0x95] = z80_inst_unimplemented, // TODO - [0x96] = z80_inst_unimplemented, // TODO + [0x96] = z80_inst_res_b_hl, [0x97] = z80_inst_unimplemented, // TODO [0x98] = z80_inst_unimplemented, // TODO [0x99] = z80_inst_unimplemented, // TODO @@ -678,7 +678,7 @@ static DispatchTable instruction_table_bits = { [0x9B] = z80_inst_unimplemented, // TODO [0x9C] = z80_inst_unimplemented, // TODO [0x9D] = z80_inst_unimplemented, // TODO - [0x9E] = z80_inst_unimplemented, // TODO + [0x9E] = z80_inst_res_b_hl, [0x9F] = z80_inst_unimplemented, // TODO [0xA0] = z80_inst_unimplemented, // TODO [0xA1] = z80_inst_unimplemented, // TODO @@ -686,7 +686,7 @@ static DispatchTable instruction_table_bits = { [0xA3] = z80_inst_unimplemented, // TODO [0xA4] = z80_inst_unimplemented, // TODO [0xA5] = z80_inst_unimplemented, // TODO - [0xA6] = z80_inst_unimplemented, // TODO + [0xA6] = z80_inst_res_b_hl, [0xA7] = z80_inst_unimplemented, // TODO [0xA8] = z80_inst_unimplemented, // TODO [0xA9] = z80_inst_unimplemented, // TODO @@ -694,7 +694,7 @@ static DispatchTable instruction_table_bits = { [0xAB] = z80_inst_unimplemented, // TODO [0xAC] = z80_inst_unimplemented, // TODO [0xAD] = z80_inst_unimplemented, // TODO - [0xAE] = z80_inst_unimplemented, // TODO + [0xAE] = z80_inst_res_b_hl, [0xAF] = z80_inst_unimplemented, // TODO [0xB0] = z80_inst_unimplemented, // TODO [0xB1] = z80_inst_unimplemented, // TODO @@ -702,7 +702,7 @@ static DispatchTable instruction_table_bits = { [0xB3] = z80_inst_unimplemented, // TODO [0xB4] = z80_inst_unimplemented, // TODO [0xB5] = z80_inst_unimplemented, // TODO - [0xB6] = z80_inst_unimplemented, // TODO + [0xB6] = z80_inst_res_b_hl, [0xB7] = z80_inst_unimplemented, // TODO [0xB8] = z80_inst_unimplemented, // TODO [0xB9] = z80_inst_unimplemented, // TODO @@ -710,7 +710,7 @@ static DispatchTable instruction_table_bits = { [0xBB] = z80_inst_unimplemented, // TODO [0xBC] = z80_inst_unimplemented, // TODO [0xBD] = z80_inst_unimplemented, // TODO - [0xBE] = z80_inst_unimplemented, // TODO + [0xBE] = z80_inst_res_b_hl, [0xBF] = z80_inst_unimplemented, // TODO [0xC0] = z80_inst_unimplemented, // TODO [0xC1] = z80_inst_unimplemented, // TODO @@ -1102,70 +1102,70 @@ static DispatchTable instruction_table_index_bits = { [0x3D] = z80_inst_unimplemented, // TODO [0x3E] = z80_inst_unimplemented, // TODO [0x3F] = z80_inst_unimplemented, // TODO - [0x40] = z80_inst_unimplemented, // TODO - [0x41] = z80_inst_unimplemented, // TODO - [0x42] = z80_inst_unimplemented, // TODO - [0x43] = z80_inst_unimplemented, // TODO - [0x44] = z80_inst_unimplemented, // TODO - [0x45] = z80_inst_unimplemented, // TODO - [0x46] = z80_inst_unimplemented, // TODO - [0x47] = z80_inst_unimplemented, // TODO - [0x48] = z80_inst_unimplemented, // TODO - [0x49] = z80_inst_unimplemented, // TODO - [0x4A] = z80_inst_unimplemented, // TODO - [0x4B] = z80_inst_unimplemented, // TODO - [0x4C] = z80_inst_unimplemented, // TODO - [0x4D] = z80_inst_unimplemented, // TODO - [0x4E] = z80_inst_unimplemented, // TODO - [0x4F] = z80_inst_unimplemented, // TODO - [0x50] = z80_inst_unimplemented, // TODO - [0x51] = z80_inst_unimplemented, // TODO - [0x52] = z80_inst_unimplemented, // TODO - [0x53] = z80_inst_unimplemented, // TODO - [0x54] = z80_inst_unimplemented, // TODO - [0x55] = z80_inst_unimplemented, // TODO - [0x56] = z80_inst_unimplemented, // TODO - [0x57] = z80_inst_unimplemented, // TODO - [0x58] = z80_inst_unimplemented, // TODO - [0x59] = z80_inst_unimplemented, // TODO - [0x5A] = z80_inst_unimplemented, // TODO - [0x5B] = z80_inst_unimplemented, // TODO - [0x5C] = z80_inst_unimplemented, // TODO - [0x5D] = z80_inst_unimplemented, // TODO - [0x5E] = z80_inst_unimplemented, // TODO - [0x5F] = z80_inst_unimplemented, // TODO - [0x60] = z80_inst_unimplemented, // TODO - [0x61] = z80_inst_unimplemented, // TODO - [0x62] = z80_inst_unimplemented, // TODO - [0x63] = z80_inst_unimplemented, // TODO - [0x64] = z80_inst_unimplemented, // TODO - [0x65] = z80_inst_unimplemented, // TODO - [0x66] = z80_inst_unimplemented, // TODO - [0x67] = z80_inst_unimplemented, // TODO - [0x68] = z80_inst_unimplemented, // TODO - [0x69] = z80_inst_unimplemented, // TODO - [0x6A] = z80_inst_unimplemented, // TODO - [0x6B] = z80_inst_unimplemented, // TODO - [0x6C] = z80_inst_unimplemented, // TODO - [0x6D] = z80_inst_unimplemented, // TODO - [0x6E] = z80_inst_unimplemented, // TODO - [0x6F] = z80_inst_unimplemented, // TODO - [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 - [0x76] = z80_inst_unimplemented, // TODO - [0x77] = z80_inst_unimplemented, // TODO - [0x78] = z80_inst_unimplemented, // TODO - [0x79] = z80_inst_unimplemented, // TODO - [0x7A] = z80_inst_unimplemented, // TODO - [0x7B] = z80_inst_unimplemented, // TODO - [0x7C] = z80_inst_unimplemented, // TODO - [0x7D] = z80_inst_unimplemented, // TODO - [0x7E] = z80_inst_unimplemented, // TODO - [0x7F] = z80_inst_unimplemented, // TODO + [0x40] = z80_inst_bit_b_ixy, + [0x41] = z80_inst_bit_b_ixy, + [0x42] = z80_inst_bit_b_ixy, + [0x43] = z80_inst_bit_b_ixy, + [0x44] = z80_inst_bit_b_ixy, + [0x45] = z80_inst_bit_b_ixy, + [0x46] = z80_inst_bit_b_ixy, + [0x47] = z80_inst_bit_b_ixy, + [0x48] = z80_inst_bit_b_ixy, + [0x49] = z80_inst_bit_b_ixy, + [0x4A] = z80_inst_bit_b_ixy, + [0x4B] = z80_inst_bit_b_ixy, + [0x4C] = z80_inst_bit_b_ixy, + [0x4D] = z80_inst_bit_b_ixy, + [0x4E] = z80_inst_bit_b_ixy, + [0x4F] = z80_inst_bit_b_ixy, + [0x50] = z80_inst_bit_b_ixy, + [0x51] = z80_inst_bit_b_ixy, + [0x52] = z80_inst_bit_b_ixy, + [0x53] = z80_inst_bit_b_ixy, + [0x54] = z80_inst_bit_b_ixy, + [0x55] = z80_inst_bit_b_ixy, + [0x56] = z80_inst_bit_b_ixy, + [0x57] = z80_inst_bit_b_ixy, + [0x58] = z80_inst_bit_b_ixy, + [0x59] = z80_inst_bit_b_ixy, + [0x5A] = z80_inst_bit_b_ixy, + [0x5B] = z80_inst_bit_b_ixy, + [0x5C] = z80_inst_bit_b_ixy, + [0x5D] = z80_inst_bit_b_ixy, + [0x5E] = z80_inst_bit_b_ixy, + [0x5F] = z80_inst_bit_b_ixy, + [0x60] = z80_inst_bit_b_ixy, + [0x61] = z80_inst_bit_b_ixy, + [0x62] = z80_inst_bit_b_ixy, + [0x63] = z80_inst_bit_b_ixy, + [0x64] = z80_inst_bit_b_ixy, + [0x65] = z80_inst_bit_b_ixy, + [0x66] = z80_inst_bit_b_ixy, + [0x67] = z80_inst_bit_b_ixy, + [0x68] = z80_inst_bit_b_ixy, + [0x69] = z80_inst_bit_b_ixy, + [0x6A] = z80_inst_bit_b_ixy, + [0x6B] = z80_inst_bit_b_ixy, + [0x6C] = z80_inst_bit_b_ixy, + [0x6D] = z80_inst_bit_b_ixy, + [0x6E] = z80_inst_bit_b_ixy, + [0x6F] = z80_inst_bit_b_ixy, + [0x70] = z80_inst_bit_b_ixy, + [0x71] = z80_inst_bit_b_ixy, + [0x72] = z80_inst_bit_b_ixy, + [0x73] = z80_inst_bit_b_ixy, + [0x74] = z80_inst_bit_b_ixy, + [0x75] = z80_inst_bit_b_ixy, + [0x76] = z80_inst_bit_b_ixy, + [0x77] = z80_inst_bit_b_ixy, + [0x78] = z80_inst_bit_b_ixy, + [0x79] = z80_inst_bit_b_ixy, + [0x7A] = z80_inst_bit_b_ixy, + [0x7B] = z80_inst_bit_b_ixy, + [0x7C] = z80_inst_bit_b_ixy, + [0x7D] = z80_inst_bit_b_ixy, + [0x7E] = z80_inst_bit_b_ixy, + [0x7F] = z80_inst_bit_b_ixy, [0x80] = z80_inst_unimplemented, // TODO [0x81] = z80_inst_unimplemented, // TODO [0x82] = z80_inst_unimplemented, // TODO