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; bool except;


for (line = 0; line < VDP_LINES_PER_FRAME; line++) { for (line = 0; line < VDP_LINES_PER_FRAME; line++) {
vdp_simulate_line(&gg->vdp);
except = z80_do_cycles(&gg->cpu, CYCLES_PER_LINE); except = z80_do_cycles(&gg->cpu, CYCLES_PER_LINE);
if (except) if (except)
return true; return true;
vdp_simulate_line(&gg->vdp);
} }
return false; 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) 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. Extract a condition from the given opcode.
*/ */
static inline bool extract_cond(const Z80 *z80, uint8_t 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); 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 POS
#undef NEG #undef NEG
#undef CARRY #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); uint16_t addr = mmu_read_double(z80->mmu, ++z80->regs.pc);
mmu_write_double(z80->mmu, addr, *extract_pair(z80, opcode)); mmu_write_double(z80->mmu, addr, *extract_pair(z80, opcode));
z80->regs.pc += 2; 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) 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++; z80->regs.pc++;
return 11; 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) 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++; z80->regs.pc++;
return 10; 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) static uint8_t z80_inst_ldi(Z80 *z80, uint8_t opcode)
{ {
(void) 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.hl++;
z80->regs.de++; z80->regs.de++;
z80->regs.bc--; 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++; z80->regs.pc++;
return 16; 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) static uint8_t z80_inst_ldd(Z80 *z80, uint8_t opcode)
{ {
(void) 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.hl--;
z80->regs.de--; z80->regs.de--;
z80->regs.bc--; 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++; z80->regs.pc++;
return 16; 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); set_flags_bit(z80, val, bit);
z80->regs.pc++; 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); set_flags_bit(z80, val, bit);
z80->regs.pc++; z80->regs.pc++;
return 8;
return 20;
} }


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


// TODO: RES b, (IXY+d) // 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) static uint8_t z80_inst_in_r_c(Z80 *z80, uint8_t opcode)
{ {
uint8_t data = read_port(z80, z80->regs.c); uint8_t data = read_port(z80, z80->regs.c);
bool parity = !(__builtin_popcount(data) % 2);

if (opcode != 0x70) if (opcode != 0x70)
*extract_reg(z80, opcode) = data; *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++; z80->regs.pc++;
return 12; 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) static uint8_t z80_inst_ini(Z80 *z80, uint8_t opcode)
{ {
(void) 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++; 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++; z80->regs.pc++;
return 16; 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) static uint8_t z80_inst_ind(Z80 *z80, uint8_t opcode)
{ {
(void) 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--; 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++; z80->regs.pc++;
return 16; 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) static uint8_t z80_inst_outi(Z80 *z80, uint8_t opcode)
{ {
(void) 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)); 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++; z80->regs.pc++;
return 16; 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) static uint8_t z80_inst_outd(Z80 *z80, uint8_t opcode)
{ {
(void) 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)); 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++; z80->regs.pc++;
return 16; return 16;
} }


Loading…
Cancel
Save