Browse Source

Fix assorted bugs.

master
Ben Kurtovic 8 years ago
parent
commit
af58cedce3
4 changed files with 69 additions and 46 deletions
  1. +1
    -1
      src/gamegear.c
  2. +15
    -1
      src/z80.c
  3. +27
    -0
      src/z80_flags.inc.c
  4. +26
    -44
      src/z80_ops.inc.c

+ 1
- 1
src/gamegear.c View File

@@ -141,10 +141,10 @@ static bool simulate_frame(GameGear *gg)
bool except;

for (line = 0; line < VDP_LINES_PER_FRAME; line++) {
vdp_simulate_line(&gg->vdp);
except = z80_do_cycles(&gg->cpu, CYCLES_PER_LINE);
if (except)
return true;
vdp_simulate_line(&gg->vdp);
}
return false;
}


+ 15
- 1
src/z80.c View File

@@ -178,7 +178,7 @@ static inline uint8_t* extract_reg(Z80 *z80, uint8_t opcode)
}

/*
Extract a register pair from the given opcode and return a pointer to it.
Extract a ss/dd register pair from the given opcode and return a pointer.
*/
static inline uint16_t* extract_pair(Z80 *z80, uint8_t opcode)
{
@@ -192,6 +192,20 @@ static inline uint16_t* extract_pair(Z80 *z80, uint8_t opcode)
}

/*
Extract a qq register pair from the given opcode and return a pointer.
*/
static inline uint16_t* extract_pair_qq(Z80 *z80, uint8_t opcode)
{
switch (opcode & 0x30) {
case 0x00: return &z80->regs.bc;
case 0x10: return &z80->regs.de;
case 0x20: return &z80->regs.hl;
case 0x30: return &z80->regs.af;
}
FATAL("invalid call: extract_pair_qq(z80, 0x%02X)", opcode)
}

/*
Extract a condition from the given opcode.
*/
static inline bool extract_cond(const Z80 *z80, uint8_t opcode)


+ 27
- 0
src/z80_flags.inc.c View File

@@ -157,6 +157,33 @@ static inline void set_flags_neg(Z80 *z80)
HALF(0, -, val), F5(res), ZERO(res), SIGN(res), 0xFF);
}

/*
Set the flags for a LDI/LDIR/LDD/LDDR instruction.
*/
static inline void set_flags_blockxfer(Z80 *z80, uint8_t val)
{
bool pv = z80->regs.bc != 0;
uint8_t res = val + z80->regs.a;
set_flags(z80, 0, 0, pv, res & 0x08, 0, res & 0x02, 0, 0, 0x3E);
}

/*
Set the flags for an IN instruction.
*/
static inline void set_flags_in(Z80 *z80, uint8_t val)
{
set_flags(z80, 0, 0, PARITY(val), F3(val), 0, F5(val), ZERO(val),
SIGN(val), 0xFE);
}

/*
Set the flags for an INI/INIR/IND/INDR/OUTI/OTIR/OUTD/OTDR instruction.
*/
static inline void set_flags_blockio(Z80 *z80)
{
set_flags_dec(z80, z80->regs.b);
}

#undef POS
#undef NEG
#undef CARRY


+ 26
- 44
src/z80_ops.inc.c View File

@@ -311,7 +311,7 @@ static uint8_t z80_inst_ld_inn_dd(Z80 *z80, uint8_t opcode)
uint16_t addr = mmu_read_double(z80->mmu, ++z80->regs.pc);
mmu_write_double(z80->mmu, addr, *extract_pair(z80, opcode));
z80->regs.pc += 2;
return 16;
return 20;
}

/*
@@ -357,7 +357,7 @@ static uint8_t z80_inst_ld_sp_ixy(Z80 *z80, uint8_t opcode)
*/
static uint8_t z80_inst_push_qq(Z80 *z80, uint8_t opcode)
{
stack_push(z80, *extract_pair(z80, opcode));
stack_push(z80, *extract_pair_qq(z80, opcode));
z80->regs.pc++;
return 11;
}
@@ -380,7 +380,7 @@ static uint8_t z80_inst_push_ixy(Z80 *z80, uint8_t opcode)
*/
static uint8_t z80_inst_pop_qq(Z80 *z80, uint8_t opcode)
{
*extract_pair(z80, opcode) = stack_pop(z80);
*extract_pair_qq(z80, opcode) = stack_pop(z80);
z80->regs.pc++;
return 10;
}
@@ -479,14 +479,14 @@ static uint8_t z80_inst_ex_sp_ixy(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_ldi(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint16_t value = mmu_read_double(z80->mmu, z80->regs.hl);
mmu_write_double(z80->mmu, z80->regs.de, value);
uint8_t value = mmu_read_byte(z80->mmu, z80->regs.hl);
mmu_write_byte(z80->mmu, z80->regs.de, value);

z80->regs.hl++;
z80->regs.de++;
z80->regs.bc--;

set_flags(z80, 0, 0, z80->regs.bc == 0, 0, 0, 0, 0, 0, 0x16);
set_flags_blockxfer(z80, value);
z80->regs.pc++;
return 16;
}
@@ -511,14 +511,14 @@ static uint8_t z80_inst_ldir(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_ldd(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint16_t value = mmu_read_double(z80->mmu, z80->regs.hl);
mmu_write_double(z80->mmu, z80->regs.de, value);
uint8_t value = mmu_read_byte(z80->mmu, z80->regs.hl);
mmu_write_byte(z80->mmu, z80->regs.de, value);

z80->regs.hl--;
z80->regs.de--;
z80->regs.bc--;

set_flags(z80, 0, 0, z80->regs.bc == 0, 0, 0, 0, 0, 0, 0x16);
set_flags_blockxfer(z80, value);
z80->regs.pc++;
return 16;
}
@@ -1737,7 +1737,7 @@ static uint8_t z80_inst_bit_b_hl(Z80 *z80, uint8_t opcode)

set_flags_bit(z80, val, bit);
z80->regs.pc++;
return 8;
return 12;
}

/*
@@ -1752,7 +1752,7 @@ static uint8_t z80_inst_bit_b_ixy(Z80 *z80, uint8_t opcode)

set_flags_bit(z80, val, bit);
z80->regs.pc++;
return 8;
return 20;
}

// TODO: SET b, r
@@ -1775,7 +1775,7 @@ static uint8_t z80_inst_res_b_hl(Z80 *z80, uint8_t opcode)
val &= ~(1 << bit);
mmu_write_byte(z80->mmu, z80->regs.hl, val);
z80->regs.pc++;
return 8;
return 15;
}

// TODO: RES b, (IXY+d)
@@ -1981,12 +1981,10 @@ static uint8_t z80_inst_in_a_n(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_in_r_c(Z80 *z80, uint8_t opcode)
{
uint8_t data = read_port(z80, z80->regs.c);
bool parity = !(__builtin_popcount(data) % 2);

if (opcode != 0x70)
*extract_reg(z80, opcode) = data;
set_flags(z80, 0, 0, parity, !!(data & 0x08), 0, !!(data & 0x20),
data == 0, !!(data & 0x80), 0xFE);
set_flags_in(z80, data);
z80->regs.pc++;
return 12;
}
@@ -1998,15 +1996,11 @@ static uint8_t z80_inst_in_r_c(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_ini(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint8_t data = read_port(z80, z80->regs.c), *b = &z80->regs.b;
bool h = !!(((*b & 0x0F) - 1) & 0x10);
mmu_write_byte(z80->mmu, z80->regs.hl, read_port(z80, z80->regs.c));
set_flags_blockio(z80);

mmu_write_byte(z80->mmu, z80->regs.hl, data);
z80->regs.hl++;
(*b)--;

set_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20),
*b == 0, !!(*b & 0x80), 0xFE);
z80->regs.b--;
z80->regs.pc++;
return 16;
}
@@ -2031,15 +2025,11 @@ static uint8_t z80_inst_inir(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_ind(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint8_t data = read_port(z80, z80->regs.c), *b = &z80->regs.b;
bool h = !!(((*b & 0x0F) - 1) & 0x10);
mmu_write_byte(z80->mmu, z80->regs.hl, read_port(z80, z80->regs.c));
set_flags_blockio(z80);

mmu_write_byte(z80->mmu, z80->regs.hl, data);
z80->regs.hl--;
(*b)--;

set_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20),
*b == 0, !!(*b & 0x80), 0xFE);
z80->regs.b--;
z80->regs.pc++;
return 16;
}
@@ -2090,15 +2080,11 @@ static uint8_t z80_inst_out_c_r(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_outi(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint8_t *b = &z80->regs.b;
bool h = !!(((*b & 0x0F) - 1) & 0x10);

write_port(z80, z80->regs.c, mmu_read_byte(z80->mmu, z80->regs.hl));
z80->regs.hl++;
(*b)--;
set_flags_blockio(z80);

set_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20),
*b == 0, !!(*b & 0x80), 0xFE);
z80->regs.hl++;
z80->regs.b--;
z80->regs.pc++;
return 16;
}
@@ -2123,15 +2109,11 @@ static uint8_t z80_inst_otir(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_outd(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint8_t *b = &z80->regs.b;
bool h = !!(((*b & 0x0F) - 1) & 0x10);

write_port(z80, z80->regs.c, mmu_read_byte(z80->mmu, z80->regs.hl));
z80->regs.hl--;
(*b)--;
set_flags_blockio(z80);

set_flags(z80, 0, 1, *b == 0x7F, !!(*b & 0x08), h, !!(*b & 0x20),
*b == 0, !!(*b & 0x80), 0xFE);
z80->regs.hl--;
z80->regs.b--;
z80->regs.pc++;
return 16;
}


Loading…
Cancel
Save