|
|
@@ -21,90 +21,150 @@ static uint8_t z80_inst_unimplemented(Z80 *z80, uint8_t opcode) |
|
|
|
z80->except = true; |
|
|
|
z80->exc_code = Z80_EXC_UNIMPLEMENTED_OPCODE; |
|
|
|
z80->exc_data = opcode; |
|
|
|
return 2; |
|
|
|
return 4; |
|
|
|
} |
|
|
|
|
|
|
|
// LD r, r' |
|
|
|
/* |
|
|
|
LD r, r' (0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x47, 0x48, 0x49, 0x4A, 0x4B, |
|
|
|
0x4C, 0x4D, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x57, 0x58, 0x59, |
|
|
|
0x5A, 0x5B, 0x5C, 0x5D, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, |
|
|
|
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6F, 0x78, 0x79, 0x7A, 0x7B, 0x7C, |
|
|
|
0x7D, 0x7F): |
|
|
|
Load r' (8-bit register) into r (8-bit register). |
|
|
|
*/ |
|
|
|
static uint8_t z80_inst_ld_r_r(Z80 *z80, uint8_t opcode) |
|
|
|
{ |
|
|
|
uint8_t *dst = extract_reg(z80, opcode), |
|
|
|
*src = extract_reg(z80, opcode << 3); |
|
|
|
*dst = *src; |
|
|
|
z80->regfile.pc++; |
|
|
|
return 4; |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
LD r, n (0x06, 0x0E, 0x16, 0x1E, 0x26, 0x2E, 0x3E): |
|
|
|
Load the immediate value into the 8-bit register. |
|
|
|
Load n (8-bit immediate) into r (8-bit register). |
|
|
|
*/ |
|
|
|
static uint8_t z80_inst_ld_r_n(Z80 *z80, uint8_t opcode) |
|
|
|
{ |
|
|
|
uint8_t *reg; |
|
|
|
|
|
|
|
switch(opcode) { |
|
|
|
case 0x3E: reg = &z80->regfile.a; break; |
|
|
|
case 0x06: reg = &z80->regfile.b; break; |
|
|
|
case 0x0E: reg = &z80->regfile.c; break; |
|
|
|
case 0x16: reg = &z80->regfile.d; break; |
|
|
|
case 0x1E: reg = &z80->regfile.e; break; |
|
|
|
case 0x26: reg = &z80->regfile.h; break; |
|
|
|
case 0x2E: reg = &z80->regfile.l; break; |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t *reg = extract_reg(z80, opcode); |
|
|
|
*reg = mmu_read_byte(z80->mmu, ++z80->regfile.pc); |
|
|
|
z80->regfile.pc++; |
|
|
|
return 7; |
|
|
|
} |
|
|
|
|
|
|
|
// LD r, (HL) |
|
|
|
/* |
|
|
|
LD r, (HL) (0x46, 0x4E, 0x56, 0x5E, 0x66, 0x6E, 0x7E): |
|
|
|
Load the contents of HL into r (8-bit register). |
|
|
|
*/ |
|
|
|
static uint8_t z80_inst_ld_r_hl(Z80 *z80, uint8_t opcode) |
|
|
|
{ |
|
|
|
uint8_t *reg = extract_reg(z80, opcode); |
|
|
|
*reg = mmu_read_byte(z80->mmu, get_pair(z80, REG_HL)); |
|
|
|
z80->regfile.pc++; |
|
|
|
return 7; |
|
|
|
} |
|
|
|
|
|
|
|
// LD r, (IX+d) |
|
|
|
/* |
|
|
|
LD r, (IX+d) |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_r_ix(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD r, (IY+d) |
|
|
|
/* |
|
|
|
LD r, (IY+d) |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_r_iy(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD (HL), r |
|
|
|
/* |
|
|
|
LD (HL), r |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_hl_r(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD (IX+d), r |
|
|
|
/* |
|
|
|
LD (IX+d), r |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_ix_r(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD (IY+d), r |
|
|
|
/* |
|
|
|
LD (IY+d), r |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_iy_r(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD (HL), n |
|
|
|
/* |
|
|
|
LD (HL), n |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_hl_n(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD (IX+d), n |
|
|
|
/* |
|
|
|
LD (IX+d), n |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_ix_n(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD (IY+d), n |
|
|
|
/* |
|
|
|
LD (IY+d), n |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_iy_n(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD A, (BC) |
|
|
|
/* |
|
|
|
LD A, (BC) |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_a_bc(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD A, (DE) |
|
|
|
/* |
|
|
|
LD A, (DE) |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_a_de(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD A, (nn) |
|
|
|
/* |
|
|
|
LD A, (nn) |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_a_nn(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD (BC), A |
|
|
|
/* |
|
|
|
LD (BC), A |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_bc_a(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD (DE), A |
|
|
|
/* |
|
|
|
LD (DE), A |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_de_a(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD (nn), A |
|
|
|
/* |
|
|
|
LD (nn), A |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_nn_a(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD A, I |
|
|
|
/* |
|
|
|
LD A, I |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_a_i(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD A, R |
|
|
|
/* |
|
|
|
LD A, R |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_a_r(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD I,A |
|
|
|
/* |
|
|
|
LD I,A |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_i_a(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
// LD R, A |
|
|
|
/* |
|
|
|
LD R, A |
|
|
|
*/ |
|
|
|
// static uint8_t z80_inst_ld_r_a(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
/* |
|
|
|
LD dd, nn (0x01, 0x11, 0x21, 0x31): |
|
|
|
Load the two-byte immediate into the 16-bit register. |
|
|
|
Load nn (16-bit immediate) into dd (16-bit register). |
|
|
|
*/ |
|
|
|
static uint8_t z80_inst_ld_dd_nn(Z80 *z80, uint8_t opcode) |
|
|
|
{ |
|
|
|
uint8_t pair; |
|
|
|
|
|
|
|
switch(opcode) { |
|
|
|
case 0x01: pair = REG_BC; break; |
|
|
|
case 0x11: pair = REG_DE; break; |
|
|
|
case 0x21: pair = REG_HL; break; |
|
|
|
case 0x31: pair = REG_SP; break; |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t pair = extract_pair(opcode); |
|
|
|
set_pair(z80, pair, mmu_read_double(z80->mmu, ++z80->regfile.pc)); |
|
|
|
z80->regfile.pc += 2; |
|
|
|
return 6; |
|
|
|
return 10; |
|
|
|
} |
|
|
|
|
|
|
|
// LD IX, nn |
|
|
@@ -151,7 +211,7 @@ static uint8_t z80_inst_ld_dd_nn(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
/* |
|
|
|
EXX (0xD9): |
|
|
|
Exchange the 2-byte registers with their shadows |
|
|
|
Exchange the 16-bit registers with their shadows |
|
|
|
(BC <=> BC', DE <=> DE', HL <=> HL'). |
|
|
|
*/ |
|
|
|
static uint8_t z80_inst_exx(Z80 *z80, uint8_t opcode) |
|
|
@@ -220,22 +280,11 @@ static uint8_t z80_inst_exx(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
/* |
|
|
|
INC r (0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x3C): |
|
|
|
Increment the 8-bit register encoded in the opcode. |
|
|
|
Increment r (8-bit register). |
|
|
|
*/ |
|
|
|
static uint8_t z80_inst_inc_r(Z80 *z80, uint8_t opcode) |
|
|
|
{ |
|
|
|
uint8_t *reg; |
|
|
|
|
|
|
|
switch(opcode) { |
|
|
|
case 0x3C: reg = &z80->regfile.a; break; |
|
|
|
case 0x04: reg = &z80->regfile.b; break; |
|
|
|
case 0x0C: reg = &z80->regfile.c; break; |
|
|
|
case 0x14: reg = &z80->regfile.d; break; |
|
|
|
case 0x1C: reg = &z80->regfile.e; break; |
|
|
|
case 0x24: reg = &z80->regfile.h; break; |
|
|
|
case 0x2C: reg = &z80->regfile.l; break; |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t *reg = extract_reg(z80, opcode); |
|
|
|
bool halfcarry = !!(((*reg & 0x0F) + 1) & 0x10); |
|
|
|
(*reg)++; |
|
|
|
update_flags(z80, 0, 0, *reg == 0x80, !!(*reg & 0x08), halfcarry, |
|
|
@@ -276,8 +325,7 @@ static uint8_t z80_inst_nop(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
/* |
|
|
|
HALT (0x76): |
|
|
|
Suspend CPU operation by repeatedly executing NOPs until an interrupt or |
|
|
|
reset. |
|
|
|
Suspend CPU operation: execute NOPs until an interrupt or reset. |
|
|
|
*/ |
|
|
|
static uint8_t z80_inst_halt(Z80 *z80, uint8_t opcode) |
|
|
|
{ |
|
|
@@ -330,19 +378,11 @@ static uint8_t z80_inst_ei(Z80 *z80, uint8_t opcode) |
|
|
|
|
|
|
|
/* |
|
|
|
INC ss (0x03, 0x13, 0x23, 0x33): |
|
|
|
Increment the 16-bit register encoded in the opcode. |
|
|
|
Increment ss (16-bit register). |
|
|
|
*/ |
|
|
|
static uint8_t z80_inst_inc_ss(Z80 *z80, uint8_t opcode) |
|
|
|
{ |
|
|
|
uint8_t pair; |
|
|
|
|
|
|
|
switch(opcode) { |
|
|
|
case 0x03: pair = REG_BC; break; |
|
|
|
case 0x13: pair = REG_DE; break; |
|
|
|
case 0x23: pair = REG_HL; break; |
|
|
|
case 0x33: pair = REG_SP; break; |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t pair = extract_pair(opcode); |
|
|
|
set_pair(z80, pair, get_pair(z80, pair) + 1); |
|
|
|
z80->regfile.pc++; |
|
|
|
return 6; |
|
|
@@ -533,54 +573,54 @@ static uint8_t (*instruction_lookup_table[256])(Z80*, uint8_t) = { |
|
|
|
[0x3D] = z80_inst_unimplemented, // TODO |
|
|
|
[0x3E] = z80_inst_ld_r_n, |
|
|
|
[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 |
|
|
|
[0x40] = z80_inst_ld_r_r, |
|
|
|
[0x41] = z80_inst_ld_r_r, |
|
|
|
[0x42] = z80_inst_ld_r_r, |
|
|
|
[0x43] = z80_inst_ld_r_r, |
|
|
|
[0x44] = z80_inst_ld_r_r, |
|
|
|
[0x45] = z80_inst_ld_r_r, |
|
|
|
[0x46] = z80_inst_ld_r_hl, |
|
|
|
[0x47] = z80_inst_ld_r_r, |
|
|
|
[0x48] = z80_inst_ld_r_r, |
|
|
|
[0x49] = z80_inst_ld_r_r, |
|
|
|
[0x4A] = z80_inst_ld_r_r, |
|
|
|
[0x4B] = z80_inst_ld_r_r, |
|
|
|
[0x4C] = z80_inst_ld_r_r, |
|
|
|
[0x4D] = z80_inst_ld_r_r, |
|
|
|
[0x4E] = z80_inst_ld_r_hl, |
|
|
|
[0x4F] = z80_inst_ld_r_r, |
|
|
|
[0x50] = z80_inst_ld_r_r, |
|
|
|
[0x51] = z80_inst_ld_r_r, |
|
|
|
[0x52] = z80_inst_ld_r_r, |
|
|
|
[0x53] = z80_inst_ld_r_r, |
|
|
|
[0x54] = z80_inst_ld_r_r, |
|
|
|
[0x55] = z80_inst_ld_r_r, |
|
|
|
[0x56] = z80_inst_ld_r_hl, |
|
|
|
[0x57] = z80_inst_ld_r_r, |
|
|
|
[0x58] = z80_inst_ld_r_r, |
|
|
|
[0x59] = z80_inst_ld_r_r, |
|
|
|
[0x5A] = z80_inst_ld_r_r, |
|
|
|
[0x5B] = z80_inst_ld_r_r, |
|
|
|
[0x5C] = z80_inst_ld_r_r, |
|
|
|
[0x5D] = z80_inst_ld_r_r, |
|
|
|
[0x5E] = z80_inst_ld_r_hl, |
|
|
|
[0x5F] = z80_inst_ld_r_r, |
|
|
|
[0x60] = z80_inst_ld_r_r, |
|
|
|
[0x61] = z80_inst_ld_r_r, |
|
|
|
[0x62] = z80_inst_ld_r_r, |
|
|
|
[0x63] = z80_inst_ld_r_r, |
|
|
|
[0x64] = z80_inst_ld_r_r, |
|
|
|
[0x65] = z80_inst_ld_r_r, |
|
|
|
[0x66] = z80_inst_ld_r_hl, |
|
|
|
[0x67] = z80_inst_ld_r_r, |
|
|
|
[0x68] = z80_inst_ld_r_r, |
|
|
|
[0x69] = z80_inst_ld_r_r, |
|
|
|
[0x6A] = z80_inst_ld_r_r, |
|
|
|
[0x6B] = z80_inst_ld_r_r, |
|
|
|
[0x6C] = z80_inst_ld_r_r, |
|
|
|
[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 |
|
|
@@ -589,14 +629,14 @@ static uint8_t (*instruction_lookup_table[256])(Z80*, uint8_t) = { |
|
|
|
[0x75] = z80_inst_unimplemented, // TODO |
|
|
|
[0x76] = z80_inst_halt, |
|
|
|
[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 |
|
|
|
[0x78] = z80_inst_ld_r_r, |
|
|
|
[0x79] = z80_inst_ld_r_r, |
|
|
|
[0x7A] = z80_inst_ld_r_r, |
|
|
|
[0x7B] = z80_inst_ld_r_r, |
|
|
|
[0x7C] = z80_inst_ld_r_r, |
|
|
|
[0x7D] = z80_inst_ld_r_r, |
|
|
|
[0x7E] = z80_inst_ld_r_hl, |
|
|
|
[0x7F] = z80_inst_ld_r_r, |
|
|
|
[0x80] = z80_inst_unimplemented, // TODO |
|
|
|
[0x81] = z80_inst_unimplemented, // TODO |
|
|
|
[0x82] = z80_inst_unimplemented, // TODO |
|
|
|