@@ -10,6 +10,8 @@ | |||||
#define SIGN(x) NEG(x) | #define SIGN(x) NEG(x) | ||||
#define SUB 1 | #define SUB 1 | ||||
#define CARRY2(lh, op, rh) (((lh) op (rh)) & 0x10000) | |||||
#define OV_ADD(lh, rh, res) \ | #define OV_ADD(lh, rh, res) \ | ||||
(POS(lh) && POS(rh) && NEG(res) || NEG(lh) && NEG(rh) && POS(res)) | (POS(lh) && POS(rh) && NEG(res) || NEG(lh) && NEG(rh) && POS(res)) | ||||
#define OV_SUB(lh, rh, res) \ | #define OV_SUB(lh, rh, res) \ | ||||
@@ -82,9 +84,67 @@ static inline void set_flags_dec(Z80 *z80, uint8_t val) | |||||
F5(res), ZERO(res), SIGN(res), 0xFE); | F5(res), ZERO(res), SIGN(res), 0xFE); | ||||
} | } | ||||
// set_flags(Z80 *z80, | |||||
// bool c, bool n, bool pv, bool f3, bool h, bool f5, bool z, bool s, | |||||
// uint8_t mask) | |||||
/* | |||||
Set the flags for a 16-bit ADD instruction. | |||||
*/ | |||||
static inline void set_flags_add16(Z80 *z80, uint16_t lh, uint16_t rh) | |||||
{ | |||||
uint16_t res = lh + rh; | |||||
set_flags(z80, CARRY2(lh, +, rh), !SUB, 0, F3(res >> 8), | |||||
HALF(lh >> 8, +, rh >> 8), F5(res >> 8), 0, 0, 0x3B); | |||||
} | |||||
/* | |||||
Set the flags for a 16-bit ADC instruction. | |||||
*/ | |||||
static inline void set_flags_adc16(Z80 *z80, uint16_t lh, uint32_t rh) | |||||
{ | |||||
uint16_t res = lh + rh; | |||||
set_flags(z80, CARRY2(lh, +, rh), !SUB, OV_ADD(lh >> 8, rh >> 8, res >> 8), | |||||
F3(res >> 8), HALF(lh >> 8, +, rh >> 8), F5(res >> 8), ZERO(res), | |||||
SIGN(res >> 8), 0xFF); | |||||
} | |||||
/* | |||||
Set the flags for a 16-bit SBC instruction. | |||||
*/ | |||||
static inline void set_flags_sbc16(Z80 *z80, uint16_t lh, uint32_t rh) | |||||
{ | |||||
uint16_t res = lh - rh; | |||||
set_flags(z80, CARRY2(lh, -, rh), SUB, OV_SUB(lh >> 8, rh >> 8, res >> 8), | |||||
F3(res >> 8), HALF(lh >> 8, -, rh >> 8), F5(res >> 8), ZERO(res), | |||||
SIGN(res >> 8), 0xFF); | |||||
} | |||||
/* | |||||
Set the flags for a BIT instruction. | |||||
*/ | |||||
static inline void set_flags_bit(Z80 *z80, uint8_t val, uint8_t bit) | |||||
{ | |||||
bool z = ZERO((val >> bit) & 1); | |||||
if (z) | |||||
set_flags(z80, 0, 0, z, 0, 1, 0, z, 0, 0xFE); | |||||
else | |||||
set_flags(z80, 0, 0, z, bit == 3, 1, bit == 5, z, bit == 7, 0xFE); | |||||
} | |||||
/* | |||||
Set the flags for a RLCA/RLA/RRCA/RRA instruction. | |||||
*/ | |||||
static inline void set_flags_bitrota(Z80 *z80, uint8_t bit) | |||||
{ | |||||
uint8_t a = z80->regs.a; | |||||
set_flags(z80, bit, 0, 0, F3(a), 0, F5(a), 0, 0, 0x3B); | |||||
} | |||||
/* | |||||
Set the flags for a RLC/RL/RRC/RR/SLA/SRA/SL1/SRL instruction. | |||||
*/ | |||||
static inline void set_flags_bitshift(Z80 *z80, uint8_t res, uint8_t bit) | |||||
{ | |||||
set_flags(z80, bit, 0, PARITY(res), F3(res), 0, F5(res), ZERO(res), | |||||
SIGN(res), 0xFF); | |||||
} | |||||
#undef POS | #undef POS | ||||
#undef NEG | #undef NEG | ||||
@@ -93,6 +153,7 @@ static inline void set_flags_dec(Z80 *z80, uint8_t val) | |||||
#undef ZERO | #undef ZERO | ||||
#undef SIGN | #undef SIGN | ||||
#undef SUB | #undef SUB | ||||
#undef CARRY2 | |||||
#undef OV_ADD | #undef OV_ADD | ||||
#undef OV_SUB | #undef OV_SUB | ||||
#undef PARITY | #undef PARITY | ||||
@@ -534,7 +534,7 @@ static uint8_t z80_inst_lddr(Z80 *z80, uint8_t opcode) | |||||
return 21; | return 21; | ||||
} | } | ||||
// TODO; CPI | |||||
// TODO: CPI | |||||
// TODO: CPIR | // TODO: CPIR | ||||
@@ -1115,8 +1115,6 @@ static uint8_t z80_inst_dec_ixy(Z80 *z80, uint8_t opcode) | |||||
return 23; | return 23; | ||||
} | } | ||||
// ---------------------------------------------------------------------------- | |||||
// TODO: DAA | // TODO: DAA | ||||
// TODO: CPL | // TODO: CPL | ||||
@@ -1212,18 +1210,27 @@ static uint8_t z80_inst_im(Z80 *z80, uint8_t opcode) | |||||
static uint8_t z80_inst_add_hl_ss(Z80 *z80, uint8_t opcode) | static uint8_t z80_inst_add_hl_ss(Z80 *z80, uint8_t opcode) | ||||
{ | { | ||||
uint16_t lh = z80->regs.hl, rh = *extract_pair(z80, opcode); | uint16_t lh = z80->regs.hl, rh = *extract_pair(z80, opcode); | ||||
uint16_t value = lh + rh; | |||||
z80->regs.hl = value; | |||||
bool h = !!(((lh & 0x0FFF) + (rh & 0x0FFF)) & 0x1000); | |||||
set_flags(z80, (lh + rh) != value, 0, 0, !!(value & 0x0800), h, | |||||
!!(value & 0x2000), 0, 0, 0x3B); | |||||
z80->regs.hl += rh; | |||||
set_flags_add16(z80, lh, rh); | |||||
z80->regs.pc++; | z80->regs.pc++; | ||||
return 11; | return 11; | ||||
} | } | ||||
// TODO: ADC HL, ss | |||||
/* | |||||
ADC HL, ss | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_adc_hl_ss(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
uint16_t lh = z80->regs.hl; | |||||
uint32_t rh = *extract_pair(z80, opcode) + get_flag(z80, FLAG_CARRY); | |||||
z80->regs.hl += rh; | |||||
set_flags_adc16(z80, lh, rh); | |||||
z80->regs.pc++; | |||||
return 15; | |||||
} | |||||
/* | /* | ||||
SBC HL, ss (0xED42, 0xED52, 0xED62, 0xED72): | SBC HL, ss (0xED42, 0xED52, 0xED62, 0xED72): | ||||
@@ -1231,24 +1238,29 @@ static uint8_t z80_inst_add_hl_ss(Z80 *z80, uint8_t opcode) | |||||
*/ | */ | ||||
static uint8_t z80_inst_sbc_hl_ss(Z80 *z80, uint8_t opcode) | static uint8_t z80_inst_sbc_hl_ss(Z80 *z80, uint8_t opcode) | ||||
{ | { | ||||
uint16_t minu = z80->regs.hl; | |||||
uint16_t subtra = *extract_pair(z80, opcode) + get_flag(z80, FLAG_CARRY); | |||||
uint16_t value = minu - subtra; | |||||
z80->regs.hl = value; | |||||
uint16_t lh = z80->regs.hl; | |||||
uint32_t rh = *extract_pair(z80, opcode) + get_flag(z80, FLAG_CARRY); | |||||
z80->regs.hl -= rh; | |||||
bool c = (minu - subtra) != value; | |||||
bool ov = (minu - subtra) != ((int16_t) value); | |||||
bool hc = !!(((minu & 0x0FFF) - (subtra & 0x0FFF)) & 0x1000); | |||||
set_flags_sbc16(z80, lh, rh); | |||||
z80->regs.pc++; | |||||
return 15; | |||||
} | |||||
set_flags(z80, c, 1, ov, !!(value & 0x0800), hc, | |||||
!!(value & 0x2000), value == 0, !!(value & 0x8000), 0xFF); | |||||
/* | |||||
ADD IXY, pp | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_add_ixy_ss(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
uint16_t lh = *z80->regs.ixy, rh = *extract_pair(z80, opcode); | |||||
*z80->regs.ixy += rh; | |||||
set_flags_add16(z80, lh, rh); | |||||
z80->regs.pc++; | z80->regs.pc++; | ||||
return 15; | return 15; | ||||
} | } | ||||
// TODO: ADD IXY, pp | |||||
/* | /* | ||||
INC ss (0x03, 0x13, 0x23, 0x33): | INC ss (0x03, 0x13, 0x23, 0x33): | ||||
Increment ss (16-bit register). | Increment ss (16-bit register). | ||||
@@ -1260,7 +1272,17 @@ static uint8_t z80_inst_inc_ss(Z80 *z80, uint8_t opcode) | |||||
return 6; | return 6; | ||||
} | } | ||||
// TODO: INC IXY | |||||
/* | |||||
INC IXY | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_inc_xy(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
(*z80->regs.ixy)++; | |||||
z80->regs.pc++; | |||||
return 6; | |||||
} | |||||
/* | /* | ||||
DEC ss (0x0B, 0x1B, 0x2B, 0x3B): | DEC ss (0x0B, 0x1B, 0x2B, 0x3B): | ||||
@@ -1273,57 +1295,397 @@ static uint8_t z80_inst_dec_ss(Z80 *z80, uint8_t opcode) | |||||
return 6; | return 6; | ||||
} | } | ||||
// TODO: DEC IXY | |||||
/* | |||||
DEC IXY | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_dec_xy(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
(*z80->regs.ixy)--; | |||||
z80->regs.pc++; | |||||
return 6; | |||||
} | |||||
/* | |||||
RLCA (0x07): | |||||
Rotate A left one bit. Bit 7 is copied to bit 0 and the carry flag. | |||||
*/ | |||||
static uint8_t z80_inst_rlca(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t bit = (z80->regs.a & 0x80) >> 7; | |||||
z80->regs.a <<= 1; | |||||
z80->regs.a |= bit; | |||||
set_flags_bitrota(z80, bit); | |||||
z80->regs.pc++; | |||||
return 4; | |||||
} | |||||
/* | |||||
RLA (0x17): | |||||
Rotate A left one bit. Carry flag is copied to bit 0, and bit 7 is copied | |||||
to the carry flag. | |||||
*/ | |||||
static uint8_t z80_inst_rla(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t carry = get_flag(z80, FLAG_CARRY); | |||||
uint8_t bit = (z80->regs.a & 0x80) >> 7; | |||||
z80->regs.a <<= 1; | |||||
z80->regs.a |= carry; | |||||
set_flags_bitrota(z80, bit); | |||||
z80->regs.pc++; | |||||
return 4; | |||||
} | |||||
/* | |||||
RRCA (0x0F): | |||||
Rotate A right one bit. Bit 0 is copied to bit 7 and the carry flag. | |||||
*/ | |||||
static uint8_t z80_inst_rrca(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t bit = z80->regs.a & 0x01; | |||||
z80->regs.a >>= 1; | |||||
z80->regs.a |= (bit << 7); | |||||
set_flags_bitrota(z80, bit); | |||||
z80->regs.pc++; | |||||
return 4; | |||||
} | |||||
/* | |||||
RRA (0x1F): | |||||
Rotate A right one bit. Carry flag is copied to bit 7, and bit 0 is copied | |||||
to the carry flag. | |||||
*/ | |||||
static uint8_t z80_inst_rra(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t carry = get_flag(z80, FLAG_CARRY); | |||||
uint8_t bit = z80->regs.a & 0x01; | |||||
z80->regs.a >>= 1; | |||||
z80->regs.a |= (carry << 7); | |||||
set_flags_bitrota(z80, bit); | |||||
z80->regs.pc++; | |||||
return 4; | |||||
} | |||||
/* | |||||
RLC r | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_rlc_r(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
uint8_t *reg = extract_reg(z80, opcode << 3); | |||||
uint8_t bit = ((*reg) & 0x80) >> 7; | |||||
(*reg) <<= 1; | |||||
(*reg) |= bit; | |||||
set_flags_bitshift(z80, *reg, bit); | |||||
z80->regs.pc++; | |||||
return 8; | |||||
} | |||||
/* | |||||
RLC (HL) | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_rlc_hl(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t val = mmu_read_byte(z80->mmu, z80->regs.hl); | |||||
uint8_t bit = (val & 0x80) >> 7; | |||||
val <<= 1; | |||||
val |= bit; | |||||
mmu_write_byte(z80->mmu, z80->regs.hl, val); | |||||
set_flags_bitshift(z80, val, bit); | |||||
z80->regs.pc++; | |||||
return 15; | |||||
} | |||||
/* | |||||
RLC (IXY+d) | |||||
TODO | |||||
*/ | |||||
/* | |||||
RL r | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_rl_r(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
uint8_t *reg = extract_reg(z80, opcode << 3); | |||||
uint8_t carry = get_flag(z80, FLAG_CARRY); | |||||
uint8_t bit = ((*reg) & 0x80) >> 7; | |||||
(*reg) <<= 1; | |||||
(*reg) |= carry; | |||||
set_flags_bitshift(z80, *reg, bit); | |||||
z80->regs.pc++; | |||||
return 8; | |||||
} | |||||
/* | |||||
RL (HL) | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_rl_hl(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t val = mmu_read_byte(z80->mmu, z80->regs.hl); | |||||
uint8_t carry = get_flag(z80, FLAG_CARRY); | |||||
uint8_t bit = (val & 0x80) >> 7; | |||||
val <<= 1; | |||||
val |= carry; | |||||
mmu_write_byte(z80->mmu, z80->regs.hl, val); | |||||
set_flags_bitshift(z80, val, bit); | |||||
z80->regs.pc++; | |||||
return 15; | |||||
} | |||||
/* | |||||
RL (IXY+d) | |||||
TODO | |||||
*/ | |||||
/* | |||||
RRC r | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_rrc_r(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
uint8_t *reg = extract_reg(z80, opcode << 3); | |||||
uint8_t bit = (*reg) & 0x01; | |||||
(*reg) >>= 1; | |||||
(*reg) |= (bit << 7); | |||||
set_flags_bitshift(z80, *reg, bit); | |||||
z80->regs.pc++; | |||||
return 8; | |||||
} | |||||
/* | |||||
RRC (HL) | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_rrc_hl(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t val = mmu_read_byte(z80->mmu, z80->regs.hl); | |||||
uint8_t bit = (val) & 0x01; | |||||
val >>= 1; | |||||
val |= (bit << 7); | |||||
// TODO: RLCA | |||||
mmu_write_byte(z80->mmu, z80->regs.hl, val); | |||||
set_flags_bitshift(z80, val, bit); | |||||
z80->regs.pc++; | |||||
return 15; | |||||
} | |||||
// TODO: RLA | |||||
/* | |||||
RRC (IXY+d) | |||||
TODO | |||||
*/ | |||||
// TODO: RRCA | |||||
/* | |||||
RR r | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_rr_r(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
uint8_t *reg = extract_reg(z80, opcode << 3); | |||||
uint8_t carry = get_flag(z80, FLAG_CARRY); | |||||
uint8_t bit = (*reg) & 0x01; | |||||
(*reg) >>= 1; | |||||
(*reg) |= (carry << 7); | |||||
// TODO: RRA | |||||
set_flags_bitshift(z80, *reg, bit); | |||||
z80->regs.pc++; | |||||
return 8; | |||||
} | |||||
// TODO: RLC r | |||||
/* | |||||
RR (HL) | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_rr_hl(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t val = mmu_read_byte(z80->mmu, z80->regs.hl); | |||||
uint8_t carry = get_flag(z80, FLAG_CARRY); | |||||
uint8_t bit = (val) & 0x01; | |||||
val >>= 1; | |||||
val |= (carry << 7); | |||||
// TODO: RLC (HL) | |||||
mmu_write_byte(z80->mmu, z80->regs.hl, val); | |||||
set_flags_bitshift(z80, val, bit); | |||||
z80->regs.pc++; | |||||
return 15; | |||||
} | |||||
/* | |||||
RR (IXY+d) | |||||
TODO | |||||
*/ | |||||
/* | |||||
SLA r | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_sla_r(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
uint8_t *reg = extract_reg(z80, opcode << 3); | |||||
uint8_t msb = ((*reg) & 0x80) >> 7; | |||||
(*reg) <<= 1; | |||||
// TODO: RLC (IXY+d) | |||||
set_flags_bitshift(z80, *reg, msb); | |||||
z80->regs.pc++; | |||||
return 8; | |||||
} | |||||
// TODO: RL r | |||||
/* | |||||
SLA (HL) | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_sla_hl(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t val = mmu_read_byte(z80->mmu, z80->regs.hl); | |||||
uint8_t msb = (val & 0x80) >> 7; | |||||
val <<= 1; | |||||
// TODO: RL (HL) | |||||
mmu_write_byte(z80->mmu, z80->regs.hl, val); | |||||
set_flags_bitshift(z80, val, msb); | |||||
z80->regs.pc++; | |||||
return 15; | |||||
} | |||||
// TODO: RL (IXY+d) | |||||
/* | |||||
SLA (IXY+d) | |||||
TODO | |||||
*/ | |||||
// TODO: RRC r | |||||
/* | |||||
SRA r | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_sra_r(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
uint8_t *reg = extract_reg(z80, opcode << 3); | |||||
uint8_t msb = (*reg) & 0x80, lsb = (*reg) & 0x01; | |||||
(*reg) >>= 1; | |||||
(*reg) |= msb; | |||||
// TODO: RRC (HL) | |||||
set_flags_bitshift(z80, *reg, lsb); | |||||
z80->regs.pc++; | |||||
return 8; | |||||
} | |||||
// TODO: RRC (IXY+d) | |||||
/* | |||||
SRA (HL) | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_sra_hl(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t val = mmu_read_byte(z80->mmu, z80->regs.hl); | |||||
uint8_t msb = val & 0x80, lsb = val & 0x01; | |||||
val >>= 1; | |||||
val |= msb; | |||||
// TODO: RR r | |||||
mmu_write_byte(z80->mmu, z80->regs.hl, val); | |||||
set_flags_bitshift(z80, val, lsb); | |||||
z80->regs.pc++; | |||||
return 8; | |||||
} | |||||
// TODO: RR (HL) | |||||
/* | |||||
SRA (IXY+d) | |||||
TODO | |||||
*/ | |||||
// TODO: RR (IXY+d) | |||||
/* | |||||
SL1 r | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_sl1_r(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
uint8_t *reg = extract_reg(z80, opcode << 3); | |||||
uint8_t msb = ((*reg) & 0x80) >> 7; | |||||
(*reg) <<= 1; | |||||
(*reg) |= 1; | |||||
// TODO: SLA r | |||||
set_flags_bitshift(z80, *reg, msb); | |||||
z80->regs.pc++; | |||||
return 8; | |||||
} | |||||
// TODO: SLA (HL) | |||||
/* | |||||
SL1 (HL) | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_sl1_hl(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t val = mmu_read_byte(z80->mmu, z80->regs.hl); | |||||
uint8_t msb = (val & 0x80) >> 7; | |||||
val <<= 1; | |||||
val |= 1; | |||||
// TODO: SLA (IXY+d) | |||||
mmu_write_byte(z80->mmu, z80->regs.hl, val); | |||||
set_flags_bitshift(z80, val, msb); | |||||
z80->regs.pc++; | |||||
return 15; | |||||
} | |||||
// TODO: SRA r | |||||
/* | |||||
SL1 (IXY+d) | |||||
TODO | |||||
*/ | |||||
// TODO: SRA (HL) | |||||
/* | |||||
SRL r | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_srl_r(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
uint8_t *reg = extract_reg(z80, opcode << 3); | |||||
uint8_t lsb = (*reg) & 0x01; | |||||
(*reg) >>= 1; | |||||
// TODO: SRA (IXY+d) | |||||
set_flags_bitshift(z80, *reg, lsb); | |||||
z80->regs.pc++; | |||||
return 8; | |||||
} | |||||
// TODO: SRL r | |||||
/* | |||||
SRL (HL) | |||||
TODO | |||||
*/ | |||||
static uint8_t z80_inst_srl_hl(Z80 *z80, uint8_t opcode) | |||||
{ | |||||
(void) opcode; | |||||
uint8_t val = mmu_read_byte(z80->mmu, z80->regs.hl); | |||||
uint8_t lsb = val & 0x01; | |||||
val >>= 1; | |||||
// TODO: SRL (HL) | |||||
mmu_write_byte(z80->mmu, z80->regs.hl, val); | |||||
set_flags_bitshift(z80, val, lsb); | |||||
z80->regs.pc++; | |||||
return 8; | |||||
} | |||||
// TODO: SRL (IXY+d) | |||||
/* | |||||
SRL (IXY+d) | |||||
TODO | |||||
*/ | |||||
// TODO: RLD | // TODO: RLD | ||||
@@ -1341,13 +1703,10 @@ static uint8_t z80_inst_dec_ss(Z80 *z80, uint8_t opcode) | |||||
*/ | */ | ||||
static uint8_t z80_inst_bit_b_r(Z80 *z80, uint8_t opcode) | static uint8_t z80_inst_bit_b_r(Z80 *z80, uint8_t opcode) | ||||
{ | { | ||||
uint8_t *reg = extract_reg(z80, opcode << 3); | |||||
uint8_t val = *extract_reg(z80, opcode << 3); | |||||
uint8_t bit = (opcode >> 3) & 0x07; | uint8_t bit = (opcode >> 3) & 0x07; | ||||
bool z = (((*reg) >> bit) & 1) == 0; | |||||
if (z) | |||||
set_flags(z80, 0, 0, 1, 0, 1, 0, 1, 0, 0xFE); | |||||
else | |||||
set_flags(z80, 0, 0, 0, bit == 3, 1, bit == 5, 0, bit == 7, 0xFE); | |||||
set_flags_bit(z80, val, bit); | |||||
z80->regs.pc++; | z80->regs.pc++; | ||||
return 8; | return 8; | ||||
} | } | ||||
@@ -1361,11 +1720,8 @@ static uint8_t z80_inst_bit_b_hl(Z80 *z80, uint8_t opcode) | |||||
{ | { | ||||
uint8_t val = mmu_read_byte(z80->mmu, z80->regs.hl); | uint8_t val = mmu_read_byte(z80->mmu, z80->regs.hl); | ||||
uint8_t bit = (opcode >> 3) & 0x07; | uint8_t bit = (opcode >> 3) & 0x07; | ||||
bool z = ((val >> bit) & 1) == 0; | |||||
if (z) | |||||
set_flags(z80, 0, 0, 1, 0, 1, 0, 1, 0, 0xFE); | |||||
else | |||||
set_flags(z80, 0, 0, 0, bit == 3, 1, bit == 5, 0, bit == 7, 0xFE); | |||||
set_flags_bit(z80, val, bit); | |||||
z80->regs.pc++; | z80->regs.pc++; | ||||
return 8; | return 8; | ||||
} | } | ||||
@@ -1379,11 +1735,8 @@ static uint8_t z80_inst_bit_b_ixy(Z80 *z80, uint8_t opcode) | |||||
uint16_t addr = get_index_addr(z80, z80->regs.pc - 1); | uint16_t addr = get_index_addr(z80, z80->regs.pc - 1); | ||||
uint8_t val = mmu_read_byte(z80->mmu, addr); | uint8_t val = mmu_read_byte(z80->mmu, addr); | ||||
uint8_t bit = (opcode >> 3) & 0x07; | uint8_t bit = (opcode >> 3) & 0x07; | ||||
bool z = ((val >> bit) & 1) == 0; | |||||
if (z) | |||||
set_flags(z80, 0, 0, 1, 0, 1, 0, 1, 0, 0xFE); | |||||
else | |||||
set_flags(z80, 0, 0, 0, bit == 3, 1, bit == 5, 0, bit == 7, 0xFE); | |||||
set_flags_bit(z80, val, bit); | |||||
z80->regs.pc++; | z80->regs.pc++; | ||||
return 8; | return 8; | ||||
} | } | ||||
@@ -9,7 +9,7 @@ static DispatchTable instruction_table = { | |||||
[0x04] = z80_inst_inc_r, | [0x04] = z80_inst_inc_r, | ||||
[0x05] = z80_inst_dec_r, | [0x05] = z80_inst_dec_r, | ||||
[0x06] = z80_inst_ld_r_n, | [0x06] = z80_inst_ld_r_n, | ||||
[0x07] = z80_inst_unimplemented, // TODO | |||||
[0x07] = z80_inst_rlca, | |||||
[0x08] = z80_inst_ex_af_af, | [0x08] = z80_inst_ex_af_af, | ||||
[0x09] = z80_inst_add_hl_ss, | [0x09] = z80_inst_add_hl_ss, | ||||
[0x0A] = z80_inst_ld_a_bcde, | [0x0A] = z80_inst_ld_a_bcde, | ||||
@@ -17,7 +17,7 @@ static DispatchTable instruction_table = { | |||||
[0x0C] = z80_inst_inc_r, | [0x0C] = z80_inst_inc_r, | ||||
[0x0D] = z80_inst_dec_r, | [0x0D] = z80_inst_dec_r, | ||||
[0x0E] = z80_inst_ld_r_n, | [0x0E] = z80_inst_ld_r_n, | ||||
[0x0F] = z80_inst_unimplemented, // TODO | |||||
[0x0F] = z80_inst_rrca, | |||||
[0x10] = z80_inst_djnz_e, | [0x10] = z80_inst_djnz_e, | ||||
[0x11] = z80_inst_ld_dd_nn, | [0x11] = z80_inst_ld_dd_nn, | ||||
[0x12] = z80_inst_ld_bcde_a, | [0x12] = z80_inst_ld_bcde_a, | ||||
@@ -25,7 +25,7 @@ static DispatchTable instruction_table = { | |||||
[0x14] = z80_inst_inc_r, | [0x14] = z80_inst_inc_r, | ||||
[0x15] = z80_inst_dec_r, | [0x15] = z80_inst_dec_r, | ||||
[0x16] = z80_inst_ld_r_n, | [0x16] = z80_inst_ld_r_n, | ||||
[0x17] = z80_inst_unimplemented, // TODO | |||||
[0x17] = z80_inst_rla, | |||||
[0x18] = z80_inst_jr_e, | [0x18] = z80_inst_jr_e, | ||||
[0x19] = z80_inst_add_hl_ss, | [0x19] = z80_inst_add_hl_ss, | ||||
[0x1A] = z80_inst_ld_a_bcde, | [0x1A] = z80_inst_ld_a_bcde, | ||||
@@ -33,7 +33,7 @@ static DispatchTable instruction_table = { | |||||
[0x1C] = z80_inst_inc_r, | [0x1C] = z80_inst_inc_r, | ||||
[0x1D] = z80_inst_dec_r, | [0x1D] = z80_inst_dec_r, | ||||
[0x1E] = z80_inst_ld_r_n, | [0x1E] = z80_inst_ld_r_n, | ||||
[0x1F] = z80_inst_unimplemented, // TODO | |||||
[0x1F] = z80_inst_rra, | |||||
[0x20] = z80_inst_jr_cc_e, | [0x20] = z80_inst_jr_cc_e, | ||||
[0x21] = z80_inst_ld_dd_nn, | [0x21] = z80_inst_ld_dd_nn, | ||||
[0x22] = z80_inst_ld_inn_hl, | [0x22] = z80_inst_ld_inn_hl, | ||||
@@ -335,7 +335,7 @@ static DispatchTable instruction_table_extended = { | |||||
[0x47] = z80_inst_ld_i_a, | [0x47] = z80_inst_ld_i_a, | ||||
[0x48] = z80_inst_in_r_c, | [0x48] = z80_inst_in_r_c, | ||||
[0x49] = z80_inst_out_c_r, | [0x49] = z80_inst_out_c_r, | ||||
[0x4A] = z80_inst_unimplemented, // TODO | |||||
[0x4A] = z80_inst_adc_hl_ss, | |||||
[0x4B] = z80_inst_ld_dd_inn, | [0x4B] = z80_inst_ld_dd_inn, | ||||
[0x4C] = z80_inst_unimplemented, // TODO | [0x4C] = z80_inst_unimplemented, // TODO | ||||
[0x4D] = z80_inst_reti, | [0x4D] = z80_inst_reti, | ||||
@@ -351,7 +351,7 @@ static DispatchTable instruction_table_extended = { | |||||
[0x57] = z80_inst_unimplemented, // TODO | [0x57] = z80_inst_unimplemented, // TODO | ||||
[0x58] = z80_inst_in_r_c, | [0x58] = z80_inst_in_r_c, | ||||
[0x59] = z80_inst_out_c_r, | [0x59] = z80_inst_out_c_r, | ||||
[0x5A] = z80_inst_unimplemented, // TODO | |||||
[0x5A] = z80_inst_adc_hl_ss, | |||||
[0x5B] = z80_inst_ld_dd_inn, | [0x5B] = z80_inst_ld_dd_inn, | ||||
[0x5C] = z80_inst_unimplemented, // TODO | [0x5C] = z80_inst_unimplemented, // TODO | ||||
[0x5D] = z80_inst_retn, | [0x5D] = z80_inst_retn, | ||||
@@ -367,7 +367,7 @@ static DispatchTable instruction_table_extended = { | |||||
[0x67] = z80_inst_unimplemented, // TODO | [0x67] = z80_inst_unimplemented, // TODO | ||||
[0x68] = z80_inst_in_r_c, | [0x68] = z80_inst_in_r_c, | ||||
[0x69] = z80_inst_out_c_r, | [0x69] = z80_inst_out_c_r, | ||||
[0x6A] = z80_inst_unimplemented, // TODO | |||||
[0x6A] = z80_inst_adc_hl_ss, | |||||
[0x6B] = z80_inst_ld_dd_inn, | [0x6B] = z80_inst_ld_dd_inn, | ||||
[0x6C] = z80_inst_unimplemented, // TODO | [0x6C] = z80_inst_unimplemented, // TODO | ||||
[0x6D] = z80_inst_retn, | [0x6D] = z80_inst_retn, | ||||
@@ -383,7 +383,7 @@ static DispatchTable instruction_table_extended = { | |||||
[0x77] = z80_inst_nop2, | [0x77] = z80_inst_nop2, | ||||
[0x78] = z80_inst_in_r_c, | [0x78] = z80_inst_in_r_c, | ||||
[0x79] = z80_inst_out_c_r, | [0x79] = z80_inst_out_c_r, | ||||
[0x7A] = z80_inst_unimplemented, // TODO | |||||
[0x7A] = z80_inst_adc_hl_ss, | |||||
[0x7B] = z80_inst_ld_dd_inn, | [0x7B] = z80_inst_ld_dd_inn, | ||||
[0x7C] = z80_inst_unimplemented, // TODO | [0x7C] = z80_inst_unimplemented, // TODO | ||||
[0x7D] = z80_inst_retn, | [0x7D] = z80_inst_retn, | ||||
@@ -520,70 +520,70 @@ static DispatchTable instruction_table_extended = { | |||||
}; | }; | ||||
static DispatchTable instruction_table_bits = { | static DispatchTable instruction_table_bits = { | ||||
[0x00] = z80_inst_unimplemented, // TODO | |||||
[0x01] = z80_inst_unimplemented, // TODO | |||||
[0x02] = z80_inst_unimplemented, // TODO | |||||
[0x03] = z80_inst_unimplemented, // TODO | |||||
[0x04] = z80_inst_unimplemented, // TODO | |||||
[0x05] = z80_inst_unimplemented, // TODO | |||||
[0x06] = z80_inst_unimplemented, // TODO | |||||
[0x07] = z80_inst_unimplemented, // TODO | |||||
[0x08] = z80_inst_unimplemented, // TODO | |||||
[0x09] = z80_inst_unimplemented, // TODO | |||||
[0x0A] = z80_inst_unimplemented, // TODO | |||||
[0x0B] = z80_inst_unimplemented, // TODO | |||||
[0x0C] = z80_inst_unimplemented, // TODO | |||||
[0x0D] = z80_inst_unimplemented, // TODO | |||||
[0x0E] = z80_inst_unimplemented, // TODO | |||||
[0x0F] = z80_inst_unimplemented, // TODO | |||||
[0x10] = z80_inst_unimplemented, // TODO | |||||
[0x11] = z80_inst_unimplemented, // TODO | |||||
[0x12] = z80_inst_unimplemented, // TODO | |||||
[0x13] = z80_inst_unimplemented, // TODO | |||||
[0x14] = z80_inst_unimplemented, // TODO | |||||
[0x15] = z80_inst_unimplemented, // TODO | |||||
[0x16] = z80_inst_unimplemented, // TODO | |||||
[0x17] = z80_inst_unimplemented, // TODO | |||||
[0x18] = z80_inst_unimplemented, // TODO | |||||
[0x19] = z80_inst_unimplemented, // TODO | |||||
[0x1A] = z80_inst_unimplemented, // TODO | |||||
[0x1B] = z80_inst_unimplemented, // TODO | |||||
[0x1C] = z80_inst_unimplemented, // TODO | |||||
[0x1D] = z80_inst_unimplemented, // TODO | |||||
[0x1E] = z80_inst_unimplemented, // TODO | |||||
[0x1F] = z80_inst_unimplemented, // TODO | |||||
[0x20] = z80_inst_unimplemented, // TODO | |||||
[0x21] = z80_inst_unimplemented, // TODO | |||||
[0x22] = z80_inst_unimplemented, // TODO | |||||
[0x23] = z80_inst_unimplemented, // TODO | |||||
[0x24] = z80_inst_unimplemented, // TODO | |||||
[0x25] = z80_inst_unimplemented, // TODO | |||||
[0x26] = z80_inst_unimplemented, // TODO | |||||
[0x27] = z80_inst_unimplemented, // TODO | |||||
[0x28] = z80_inst_unimplemented, // TODO | |||||
[0x29] = z80_inst_unimplemented, // TODO | |||||
[0x2A] = z80_inst_unimplemented, // TODO | |||||
[0x2B] = z80_inst_unimplemented, // TODO | |||||
[0x2C] = z80_inst_unimplemented, // TODO | |||||
[0x2D] = z80_inst_unimplemented, // TODO | |||||
[0x2E] = z80_inst_unimplemented, // TODO | |||||
[0x2F] = z80_inst_unimplemented, // TODO | |||||
[0x30] = z80_inst_unimplemented, // TODO | |||||
[0x31] = z80_inst_unimplemented, // TODO | |||||
[0x32] = z80_inst_unimplemented, // TODO | |||||
[0x33] = z80_inst_unimplemented, // TODO | |||||
[0x34] = z80_inst_unimplemented, // TODO | |||||
[0x35] = z80_inst_unimplemented, // TODO | |||||
[0x36] = z80_inst_unimplemented, // TODO | |||||
[0x37] = z80_inst_unimplemented, // TODO | |||||
[0x38] = z80_inst_unimplemented, // TODO | |||||
[0x39] = z80_inst_unimplemented, // TODO | |||||
[0x3A] = z80_inst_unimplemented, // TODO | |||||
[0x3B] = z80_inst_unimplemented, // TODO | |||||
[0x3C] = z80_inst_unimplemented, // TODO | |||||
[0x3D] = z80_inst_unimplemented, // TODO | |||||
[0x3E] = z80_inst_unimplemented, // TODO | |||||
[0x3F] = z80_inst_unimplemented, // TODO | |||||
[0x00] = z80_inst_rlc_r, | |||||
[0x01] = z80_inst_rlc_r, | |||||
[0x02] = z80_inst_rlc_r, | |||||
[0x03] = z80_inst_rlc_r, | |||||
[0x04] = z80_inst_rlc_r, | |||||
[0x05] = z80_inst_rlc_r, | |||||
[0x06] = z80_inst_rlc_hl, | |||||
[0x07] = z80_inst_rlc_r, | |||||
[0x08] = z80_inst_rrc_r, | |||||
[0x09] = z80_inst_rrc_r, | |||||
[0x0A] = z80_inst_rrc_r, | |||||
[0x0B] = z80_inst_rrc_r, | |||||
[0x0C] = z80_inst_rrc_r, | |||||
[0x0D] = z80_inst_rrc_r, | |||||
[0x0E] = z80_inst_rrc_hl, | |||||
[0x0F] = z80_inst_rrc_r, | |||||
[0x10] = z80_inst_rl_r, | |||||
[0x11] = z80_inst_rl_r, | |||||
[0x12] = z80_inst_rl_r, | |||||
[0x13] = z80_inst_rl_r, | |||||
[0x14] = z80_inst_rl_r, | |||||
[0x15] = z80_inst_rl_r, | |||||
[0x16] = z80_inst_rl_hl, | |||||
[0x17] = z80_inst_rl_r, | |||||
[0x18] = z80_inst_rr_r, | |||||
[0x19] = z80_inst_rr_r, | |||||
[0x1A] = z80_inst_rr_r, | |||||
[0x1B] = z80_inst_rr_r, | |||||
[0x1C] = z80_inst_rr_r, | |||||
[0x1D] = z80_inst_rr_r, | |||||
[0x1E] = z80_inst_rr_hl, | |||||
[0x1F] = z80_inst_rr_r, | |||||
[0x20] = z80_inst_sla_r, | |||||
[0x21] = z80_inst_sla_r, | |||||
[0x22] = z80_inst_sla_r, | |||||
[0x23] = z80_inst_sla_r, | |||||
[0x24] = z80_inst_sla_r, | |||||
[0x25] = z80_inst_sla_r, | |||||
[0x26] = z80_inst_sla_hl, | |||||
[0x27] = z80_inst_sla_r, | |||||
[0x28] = z80_inst_sra_r, | |||||
[0x29] = z80_inst_sra_r, | |||||
[0x2A] = z80_inst_sra_r, | |||||
[0x2B] = z80_inst_sra_r, | |||||
[0x2C] = z80_inst_sra_r, | |||||
[0x2D] = z80_inst_sra_r, | |||||
[0x2E] = z80_inst_sra_hl, | |||||
[0x2F] = z80_inst_sra_r, | |||||
[0x30] = z80_inst_sl1_r, | |||||
[0x31] = z80_inst_sl1_r, | |||||
[0x32] = z80_inst_sl1_r, | |||||
[0x33] = z80_inst_sl1_r, | |||||
[0x34] = z80_inst_sl1_r, | |||||
[0x35] = z80_inst_sl1_r, | |||||
[0x36] = z80_inst_sl1_hl, | |||||
[0x37] = z80_inst_sl1_r, | |||||
[0x38] = z80_inst_srl_r, | |||||
[0x39] = z80_inst_srl_r, | |||||
[0x3A] = z80_inst_srl_r, | |||||
[0x3B] = z80_inst_srl_r, | |||||
[0x3C] = z80_inst_srl_r, | |||||
[0x3D] = z80_inst_srl_r, | |||||
[0x3E] = z80_inst_srl_hl, | |||||
[0x3F] = z80_inst_srl_r, | |||||
[0x40] = z80_inst_bit_b_r, | [0x40] = z80_inst_bit_b_r, | ||||
[0x41] = z80_inst_bit_b_r, | [0x41] = z80_inst_bit_b_r, | ||||
[0x42] = z80_inst_bit_b_r, | [0x42] = z80_inst_bit_b_r, | ||||
@@ -788,7 +788,7 @@ static DispatchTable instruction_table_index = { | |||||
[0x06] = z80_inst_nop2, | [0x06] = z80_inst_nop2, | ||||
[0x07] = z80_inst_nop2, | [0x07] = z80_inst_nop2, | ||||
[0x08] = z80_inst_nop2, | [0x08] = z80_inst_nop2, | ||||
[0x09] = z80_inst_unimplemented, // TODO | |||||
[0x09] = z80_inst_add_ixy_ss, | |||||
[0x0A] = z80_inst_nop2, | [0x0A] = z80_inst_nop2, | ||||
[0x0B] = z80_inst_nop2, | [0x0B] = z80_inst_nop2, | ||||
[0x0C] = z80_inst_nop2, | [0x0C] = z80_inst_nop2, | ||||
@@ -804,7 +804,7 @@ static DispatchTable instruction_table_index = { | |||||
[0x16] = z80_inst_nop2, | [0x16] = z80_inst_nop2, | ||||
[0x17] = z80_inst_nop2, | [0x17] = z80_inst_nop2, | ||||
[0x18] = z80_inst_nop2, | [0x18] = z80_inst_nop2, | ||||
[0x19] = z80_inst_unimplemented, // TODO | |||||
[0x19] = z80_inst_add_ixy_ss, | |||||
[0x1A] = z80_inst_nop2, | [0x1A] = z80_inst_nop2, | ||||
[0x1B] = z80_inst_nop2, | [0x1B] = z80_inst_nop2, | ||||
[0x1C] = z80_inst_nop2, | [0x1C] = z80_inst_nop2, | ||||
@@ -814,15 +814,15 @@ static DispatchTable instruction_table_index = { | |||||
[0x20] = z80_inst_nop2, | [0x20] = z80_inst_nop2, | ||||
[0x21] = z80_inst_ld_ixy_nn, | [0x21] = z80_inst_ld_ixy_nn, | ||||
[0x22] = z80_inst_ld_inn_ixy, | [0x22] = z80_inst_ld_inn_ixy, | ||||
[0x23] = z80_inst_unimplemented, // TODO | |||||
[0x23] = z80_inst_inc_xy, | |||||
[0x24] = z80_inst_unimplemented, // TODO | [0x24] = z80_inst_unimplemented, // TODO | ||||
[0x25] = z80_inst_unimplemented, // TODO | [0x25] = z80_inst_unimplemented, // TODO | ||||
[0x26] = z80_inst_unimplemented, // TODO | [0x26] = z80_inst_unimplemented, // TODO | ||||
[0x27] = z80_inst_nop2, | [0x27] = z80_inst_nop2, | ||||
[0x28] = z80_inst_nop2, | [0x28] = z80_inst_nop2, | ||||
[0x29] = z80_inst_unimplemented, // TODO | |||||
[0x29] = z80_inst_add_ixy_ss, | |||||
[0x2A] = z80_inst_ld_ixy_inn, | [0x2A] = z80_inst_ld_ixy_inn, | ||||
[0x2B] = z80_inst_unimplemented, // TODO | |||||
[0x2B] = z80_inst_dec_xy, | |||||
[0x2C] = z80_inst_unimplemented, // TODO | [0x2C] = z80_inst_unimplemented, // TODO | ||||
[0x2D] = z80_inst_unimplemented, // TODO | [0x2D] = z80_inst_unimplemented, // TODO | ||||
[0x2E] = z80_inst_unimplemented, // TODO | [0x2E] = z80_inst_unimplemented, // TODO | ||||
@@ -836,7 +836,7 @@ static DispatchTable instruction_table_index = { | |||||
[0x36] = z80_inst_ld_ixy_n, | [0x36] = z80_inst_ld_ixy_n, | ||||
[0x37] = z80_inst_nop2, | [0x37] = z80_inst_nop2, | ||||
[0x38] = z80_inst_nop2, | [0x38] = z80_inst_nop2, | ||||
[0x39] = z80_inst_unimplemented, // TODO | |||||
[0x39] = z80_inst_add_ixy_ss, | |||||
[0x3A] = z80_inst_nop2, | [0x3A] = z80_inst_nop2, | ||||
[0x3B] = z80_inst_nop2, | [0x3B] = z80_inst_nop2, | ||||
[0x3C] = z80_inst_nop2, | [0x3C] = z80_inst_nop2, | ||||