Browse Source

Implement an assorted bunch of instructions.

master
Ben Kurtovic 8 years ago
parent
commit
53c0757362
2 changed files with 241 additions and 114 deletions
  1. +135
    -8
      src/z80_ops.inc.c
  2. +106
    -106
      src/z80_tables.inc.c

+ 135
- 8
src/z80_ops.inc.c View File

@@ -192,9 +192,33 @@ static uint8_t z80_inst_ld_dd_nn(Z80 *z80, uint8_t opcode)

// LD IXY, nn

// LD HL, (nn)
/*
LD HL, (nn) (0x2A):
Load memory at address nn into HL.
*/
static uint8_t z80_inst_ld_hl_nn(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint16_t addr = mmu_read_double(z80->mmu, ++z80->regfile.pc);
uint16_t value = mmu_read_double(z80->mmu, addr);
set_pair(z80, REG_HL, value);
z80->regfile.pc += 2;
return 16;
}

// LD dd, (nn)
/*
LD dd, (nn) (0xED4B, 0xED5B, 0xED6B, 0xED7B):
Load memory at address nn into dd (16-bit register).
*/
static uint8_t z80_inst_ld_dd_inn(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint16_t addr = mmu_read_double(z80->mmu, ++z80->regfile.pc);
uint16_t value = mmu_read_double(z80->mmu, addr);
set_pair(z80, extract_pair(opcode), value);
z80->regfile.pc += 2;
return 20;
}

// LD IXY, (nn)

@@ -281,7 +305,19 @@ static uint8_t z80_inst_ex_de_hl(Z80 *z80, uint8_t opcode)
return 4;
}

// EX AF, AF′
/*
EX AF, AF' (0x08):
Exchange AF with AF'.
*/
static uint8_t z80_inst_ex_af_af(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint16_t af = get_pair(z80, REG_AF);
set_pair(z80, REG_AF, get_pair(z80, REG_AF_));
set_pair(z80, REG_AF_, af);
z80->regfile.pc++;
return 4;
}

/*
EXX (0xD9):
@@ -306,7 +342,19 @@ static uint8_t z80_inst_exx(Z80 *z80, uint8_t opcode)
return 4;
}

// EX (SP), HL
/*
EX (SP), HL (0xE3):
Exchange the memory pointed to by SP with HL.
*/
static uint8_t z80_inst_ex_sp_hl(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint16_t hl = get_pair(z80, REG_HL), sp = get_pair(z80, REG_SP);
set_pair(z80, REG_HL, mmu_read_double(z80->mmu, sp));
mmu_write_double(z80->mmu, sp, hl);
z80->regfile.pc++;
return 19;
}

// EX (SP), IXY

@@ -425,6 +473,24 @@ static uint8_t z80_inst_sub_n(Z80 *z80, uint8_t opcode)

// AND s

/*
AND n (0xE6):
Bitwise AND A with n (8-bit immediate).
*/
static uint8_t z80_inst_and_n(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint8_t imm = mmu_read_byte(z80->mmu, ++z80->regfile.pc);
uint8_t a = (z80->regfile.a &= imm);

bool parity = !(__builtin_popcount(a) % 2);
update_flags(z80, 0, 0, parity, !!(a & 0x08), 1, !!(a & 0x20), a == 0,
!!(a & 0x80), 0xFF);

z80->regfile.pc++;
return 7;
}

// OR s

/*
@@ -538,7 +604,22 @@ static uint8_t z80_inst_inc_r(Z80 *z80, uint8_t opcode)
return 4;
}

// INC (HL)
/*
INC (HL) (0x34):
Increment the memory address pointed to by HL.
*/
static uint8_t z80_inst_inc_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, 0, byte == 0x80, !!(byte & 0x08), halfcarry,
!!(byte & 0x20), byte == 0, !!(byte & 0x80), 0xFE);

z80->regfile.pc++;
return 11;
}

// INC (IXY+d)

@@ -754,9 +835,46 @@ static uint8_t z80_inst_dec_ss(Z80 *z80, uint8_t opcode)

// RRD

// BIT b, r
/*
BIT b, r (0xCB40, 0xCB41, 0xCB42, 0xCB43, 0xCB44, 0xCB45, 0xCB47, 0xCB48,
0xCB49, 0xCB4A, 0xCB4B, 0xCB4C, 0xCB4D, 0xCB4F, 0xCB50, 0xCB51, 0xCB52,
0xCB53, 0xCB54, 0xCB55, 0xCB57, 0xCB58, 0xCB59, 0xCB5A, 0xCB5B, 0xCB5C,
0xCB5D, 0xCB5F, 0xCB60, 0xCB61, 0xCB62, 0xCB63, 0xCB64, 0xCB65, 0xCB67,
0xCB68, 0xCB69, 0xCB6A, 0xCB6B, 0xCB6C, 0xCB6D, 0xCB6F, 0xCB70, 0xCB71,
0xCB72, 0xCB73, 0xCB74, 0xCB75, 0xCB77, 0xCB78, 0xCB79, 0xCB7A, 0xCB7B,
0xCB7C, 0xCB7D, 0xCB7F):
Test bit b of r (8-bit register).
*/
static uint8_t z80_inst_bit_b_r(Z80 *z80, uint8_t opcode)
{
uint8_t *reg = extract_reg(z80, opcode << 3);
uint8_t bit = opcode >> 3;
bool z = (((*reg) >> 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;
}

// BIT b, (HL)
/*
BIT b, (HL) (0xCB46, 0xCB4E, 0xCB56, 0xCB5E, 0xCB66, 0xCB6E, 0xCB76,
0xCB7E):
Test bit b of (HL).
*/
static uint8_t z80_inst_bit_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;
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;
}

// BIT b, (IXY+d)

@@ -898,7 +1016,16 @@ static uint8_t z80_inst_ret_cc(Z80 *z80, uint8_t opcode)
}
}

// RETI
/*
RETI (0xED4D):
Pop PC from the stack.
*/
static uint8_t z80_inst_reti(Z80 *z80, uint8_t opcode)
{
(void) opcode;
z80->regfile.pc = stack_pop(z80);
return 14;
}

/*
RETN (0xED45, 0xED55, 0xED5D, 0xED65, 0xED6D, 0xED75, 0xED7D):


+ 106
- 106
src/z80_tables.inc.c View File

@@ -10,7 +10,7 @@ static DispatchTable instruction_table = {
[0x05] = z80_inst_dec_r,
[0x06] = z80_inst_ld_r_n,
[0x07] = z80_inst_unimplemented, // TODO
[0x08] = z80_inst_unimplemented, // TODO
[0x08] = z80_inst_ex_af_af,
[0x09] = z80_inst_add_hl_ss,
[0x0A] = z80_inst_unimplemented, // TODO
[0x0B] = z80_inst_dec_ss,
@@ -44,7 +44,7 @@ static DispatchTable instruction_table = {
[0x27] = z80_inst_unimplemented, // TODO
[0x28] = z80_inst_jr_cc_e,
[0x29] = z80_inst_add_hl_ss,
[0x2A] = z80_inst_unimplemented, // TODO
[0x2A] = z80_inst_ld_hl_nn,
[0x2B] = z80_inst_dec_ss,
[0x2C] = z80_inst_inc_r,
[0x2D] = z80_inst_dec_r,
@@ -54,7 +54,7 @@ static DispatchTable instruction_table = {
[0x31] = z80_inst_ld_dd_nn,
[0x32] = z80_inst_ld_nn_a,
[0x33] = z80_inst_inc_ss,
[0x34] = z80_inst_unimplemented, // TODO
[0x34] = z80_inst_inc_hl,
[0x35] = z80_inst_unimplemented, // TODO
[0x36] = z80_inst_ld_hl_n,
[0x37] = z80_inst_unimplemented, // TODO
@@ -229,10 +229,10 @@ static DispatchTable instruction_table = {
[0xE0] = z80_inst_ret_cc,
[0xE1] = z80_inst_pop_qq,
[0xE2] = z80_inst_jp_cc_nn,
[0xE3] = z80_inst_unimplemented, // TODO
[0xE3] = z80_inst_ex_sp_hl,
[0xE4] = z80_inst_call_cc_nn,
[0xE5] = z80_inst_push_qq,
[0xE6] = z80_inst_unimplemented, // TODO
[0xE6] = z80_inst_and_n,
[0xE7] = z80_inst_rst_p,
[0xE8] = z80_inst_ret_cc,
[0xE9] = z80_inst_unimplemented, // TODO
@@ -336,9 +336,9 @@ static DispatchTable instruction_table_extended = {
[0x48] = z80_inst_in_r_c,
[0x49] = z80_inst_out_c_r,
[0x4A] = z80_inst_unimplemented, // TODO
[0x4B] = z80_inst_unimplemented, // TODO
[0x4B] = z80_inst_ld_dd_inn,
[0x4C] = z80_inst_unimplemented, // TODO
[0x4D] = z80_inst_unimplemented, // TODO
[0x4D] = z80_inst_reti,
[0x4E] = z80_inst_im,
[0x4F] = z80_inst_unimplemented, // TODO
[0x50] = z80_inst_in_r_c,
@@ -352,7 +352,7 @@ static DispatchTable instruction_table_extended = {
[0x58] = z80_inst_in_r_c,
[0x59] = z80_inst_out_c_r,
[0x5A] = z80_inst_unimplemented, // TODO
[0x5B] = z80_inst_unimplemented, // TODO
[0x5B] = z80_inst_ld_dd_inn,
[0x5C] = z80_inst_unimplemented, // TODO
[0x5D] = z80_inst_retn,
[0x5E] = z80_inst_im,
@@ -368,7 +368,7 @@ static DispatchTable instruction_table_extended = {
[0x68] = z80_inst_in_r_c,
[0x69] = z80_inst_out_c_r,
[0x6A] = z80_inst_unimplemented, // TODO
[0x6B] = z80_inst_unimplemented, // TODO
[0x6B] = z80_inst_ld_dd_inn,
[0x6C] = z80_inst_unimplemented, // TODO
[0x6D] = z80_inst_retn,
[0x6E] = z80_inst_im,
@@ -384,43 +384,43 @@ static DispatchTable instruction_table_extended = {
[0x78] = z80_inst_in_r_c,
[0x79] = z80_inst_out_c_r,
[0x7A] = z80_inst_unimplemented, // TODO
[0x7B] = z80_inst_unimplemented, // TODO
[0x7B] = z80_inst_ld_dd_inn,
[0x7C] = z80_inst_unimplemented, // TODO
[0x7D] = z80_inst_retn,
[0x7E] = z80_inst_im,
[0x7F] = z80_inst_nop2,
[0x80] = z80_inst_unimplemented, // TODO
[0x81] = z80_inst_unimplemented, // TODO
[0x82] = z80_inst_unimplemented, // TODO
[0x83] = z80_inst_unimplemented, // TODO
[0x84] = z80_inst_unimplemented, // TODO
[0x85] = z80_inst_unimplemented, // TODO
[0x86] = z80_inst_unimplemented, // TODO
[0x87] = z80_inst_unimplemented, // TODO
[0x88] = z80_inst_unimplemented, // TODO
[0x89] = z80_inst_unimplemented, // TODO
[0x8A] = z80_inst_unimplemented, // TODO
[0x8B] = z80_inst_unimplemented, // TODO
[0x8C] = z80_inst_unimplemented, // TODO
[0x8D] = z80_inst_unimplemented, // TODO
[0x8E] = z80_inst_unimplemented, // TODO
[0x8F] = z80_inst_unimplemented, // TODO
[0x90] = z80_inst_unimplemented, // TODO
[0x91] = z80_inst_unimplemented, // TODO
[0x92] = z80_inst_unimplemented, // TODO
[0x93] = z80_inst_unimplemented, // TODO
[0x94] = z80_inst_unimplemented, // TODO
[0x95] = z80_inst_unimplemented, // TODO
[0x96] = z80_inst_unimplemented, // TODO
[0x97] = z80_inst_unimplemented, // TODO
[0x98] = z80_inst_unimplemented, // TODO
[0x99] = z80_inst_unimplemented, // TODO
[0x9A] = z80_inst_unimplemented, // TODO
[0x9B] = z80_inst_unimplemented, // TODO
[0x9C] = z80_inst_unimplemented, // TODO
[0x9D] = z80_inst_unimplemented, // TODO
[0x9E] = z80_inst_unimplemented, // TODO
[0x9F] = z80_inst_unimplemented, // TODO
[0x80] = z80_inst_nop2,
[0x81] = z80_inst_nop2,
[0x82] = z80_inst_nop2,
[0x83] = z80_inst_nop2,
[0x84] = z80_inst_nop2,
[0x85] = z80_inst_nop2,
[0x86] = z80_inst_nop2,
[0x87] = z80_inst_nop2,
[0x88] = z80_inst_nop2,
[0x89] = z80_inst_nop2,
[0x8A] = z80_inst_nop2,
[0x8B] = z80_inst_nop2,
[0x8C] = z80_inst_nop2,
[0x8D] = z80_inst_nop2,
[0x8E] = z80_inst_nop2,
[0x8F] = z80_inst_nop2,
[0x90] = z80_inst_nop2,
[0x91] = z80_inst_nop2,
[0x92] = z80_inst_nop2,
[0x93] = z80_inst_nop2,
[0x94] = z80_inst_nop2,
[0x95] = z80_inst_nop2,
[0x96] = z80_inst_nop2,
[0x97] = z80_inst_nop2,
[0x98] = z80_inst_nop2,
[0x99] = z80_inst_nop2,
[0x9A] = z80_inst_nop2,
[0x9B] = z80_inst_nop2,
[0x9C] = z80_inst_nop2,
[0x9D] = z80_inst_nop2,
[0x9E] = z80_inst_nop2,
[0x9F] = z80_inst_nop2,
[0xA0] = z80_inst_ldi,
[0xA1] = z80_inst_unimplemented, // TODO
[0xA2] = z80_inst_ini,
@@ -584,70 +584,70 @@ static DispatchTable instruction_table_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_r,
[0x41] = z80_inst_bit_b_r,
[0x42] = z80_inst_bit_b_r,
[0x43] = z80_inst_bit_b_r,
[0x44] = z80_inst_bit_b_r,
[0x45] = z80_inst_bit_b_r,
[0x46] = z80_inst_bit_b_hl,
[0x47] = z80_inst_bit_b_r,
[0x48] = z80_inst_bit_b_r,
[0x49] = z80_inst_bit_b_r,
[0x4A] = z80_inst_bit_b_r,
[0x4B] = z80_inst_bit_b_r,
[0x4C] = z80_inst_bit_b_r,
[0x4D] = z80_inst_bit_b_r,
[0x4E] = z80_inst_bit_b_hl,
[0x4F] = z80_inst_bit_b_r,
[0x50] = z80_inst_bit_b_r,
[0x51] = z80_inst_bit_b_r,
[0x52] = z80_inst_bit_b_r,
[0x53] = z80_inst_bit_b_r,
[0x54] = z80_inst_bit_b_r,
[0x55] = z80_inst_bit_b_r,
[0x56] = z80_inst_bit_b_hl,
[0x57] = z80_inst_bit_b_r,
[0x58] = z80_inst_bit_b_r,
[0x59] = z80_inst_bit_b_r,
[0x5A] = z80_inst_bit_b_r,
[0x5B] = z80_inst_bit_b_r,
[0x5C] = z80_inst_bit_b_r,
[0x5D] = z80_inst_bit_b_r,
[0x5E] = z80_inst_bit_b_hl,
[0x5F] = z80_inst_bit_b_r,
[0x60] = z80_inst_bit_b_r,
[0x61] = z80_inst_bit_b_r,
[0x62] = z80_inst_bit_b_r,
[0x63] = z80_inst_bit_b_r,
[0x64] = z80_inst_bit_b_r,
[0x65] = z80_inst_bit_b_r,
[0x66] = z80_inst_bit_b_hl,
[0x67] = z80_inst_bit_b_r,
[0x68] = z80_inst_bit_b_r,
[0x69] = z80_inst_bit_b_r,
[0x6A] = z80_inst_bit_b_r,
[0x6B] = z80_inst_bit_b_r,
[0x6C] = z80_inst_bit_b_r,
[0x6D] = z80_inst_bit_b_r,
[0x6E] = z80_inst_bit_b_hl,
[0x6F] = z80_inst_bit_b_r,
[0x70] = z80_inst_bit_b_r,
[0x71] = z80_inst_bit_b_r,
[0x72] = z80_inst_bit_b_r,
[0x73] = z80_inst_bit_b_r,
[0x74] = z80_inst_bit_b_r,
[0x75] = z80_inst_bit_b_r,
[0x76] = z80_inst_bit_b_hl,
[0x77] = z80_inst_bit_b_r,
[0x78] = z80_inst_bit_b_r,
[0x79] = z80_inst_bit_b_r,
[0x7A] = z80_inst_bit_b_r,
[0x7B] = z80_inst_bit_b_r,
[0x7C] = z80_inst_bit_b_r,
[0x7D] = z80_inst_bit_b_r,
[0x7E] = z80_inst_bit_b_hl,
[0x7F] = z80_inst_bit_b_r,
[0x80] = z80_inst_unimplemented, // TODO
[0x81] = z80_inst_unimplemented, // TODO
[0x82] = z80_inst_unimplemented, // TODO


Loading…
Cancel
Save