Browse Source

More instructions, mainly index-related; tweaks.

master
Ben Kurtovic 8 years ago
parent
commit
80e361c111
5 changed files with 165 additions and 44 deletions
  1. +6
    -2
      src/disassembler/arguments.c
  2. +4
    -6
      src/z80.c
  3. +1
    -0
      src/z80.h
  4. +135
    -17
      src/z80_ops.inc.c
  5. +19
    -19
      src/z80_tables.inc.c

+ 6
- 2
src/disassembler/arguments.c View File

@@ -370,8 +370,12 @@ static void decode_immediate(
sprintf(arg, "($%04X)", bytes[shift + 1] + (bytes[shift + 2] << 8));
break;
case AT_IX_IY: // Indexed offset
format = bytes[0] == 0xDD ? "(ix%+hhd)" : "(iy%+hhd)";
sprintf(arg, format, (int8_t) bytes[shift + 1]);
if (bytes[shift + 1]) {
format = bytes[0] == 0xDD ? "(ix%+hhd)" : "(iy%+hhd)";
sprintf(arg, format, (int8_t) bytes[shift + 1]);
} else {
sprintf(arg, bytes[0] == 0xDD ? "(ix)" : "(iy)");
}
break;
case AT_PORT_IM: // Immediate port
sprintf(arg, "($%02X)", bytes[shift + 1]);


+ 4
- 6
src/z80.c View File

@@ -72,6 +72,7 @@ void z80_power(Z80 *z80)
regfile->iff1 = regfile->iff2 = 0;

z80->except = false;
z80->last_index = NULL;
z80->pending_cycles = 0;

z80->trace.fresh = true;
@@ -251,14 +252,11 @@ static inline bool extract_cond(const Z80 *z80, uint8_t opcode)
}

/*
Extract the current index register.
Return the address signified by a indirect index instruction.
*/
static inline uint16_t* extract_index(Z80 *z80)
static inline uint16_t get_index_addr(Z80 *z80, int8_t offset)
{
uint8_t prefix = mmu_read_byte(z80->mmu, z80->regfile.pc - 1);
if (prefix != 0xDD && prefix != 0xFD)
FATAL("invalid call: extract_index(z80, 0x%02X)", prefix)
return prefix == 0xDD ? &z80->regfile.ix : &z80->regfile.iy;
return *z80->last_index + offset;
}

/*


+ 1
- 0
src/z80.h View File

@@ -36,6 +36,7 @@ typedef struct {
IO *io;
bool except;
uint8_t exc_code, exc_data;
uint16_t *last_index;
double pending_cycles;
Z80TraceInfo trace;
} Z80;


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

@@ -74,9 +74,18 @@ static uint8_t z80_inst_ld_r_hl(Z80 *z80, uint8_t opcode)
}

/*
LD r, (IXY+d)
LD r, (IXY+d) (0xDD46, 0xDD4E, 0xDD56, 0xDD5E, 0xDD66, 0xDD6E, 0xDD7E,
0xFD46, 0xFD4E, 0xFD56, 0xFD5E, 0xFD66, 0xFD6E, 0xFD7E):
Load (IX+d) or (IY+d) into r (8-bit register).
*/
// static uint8_t z80_inst_ld_r_ixy(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_ld_r_ixy(Z80 *z80, uint8_t opcode)
{
uint8_t *reg = extract_reg(z80, opcode);
uint16_t addr = get_index_addr(z80, ++z80->regfile.pc);
*reg = mmu_read_byte(z80->mmu, addr);
z80->regfile.pc++;
return 19;
}

/*
LD (HL), r (0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x77):
@@ -92,9 +101,18 @@ static uint8_t z80_inst_ld_hl_r(Z80 *z80, uint8_t opcode)
}

/*
LD (IXY+d), r
LD (IXY+d), r (0xDD70, 0xDD71, 0xDD72, 0xDD73, 0xDD74, 0xDD75, 0xDD77,
0xFD70, 0xFD71, 0xFD72, 0xFD73, 0xFD74, 0xFD75, 0xFD77):
Load r (8-bit register) into (IX+d) or (IY+d).
*/
// static uint8_t z80_inst_ld_ixy_r(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_ld_ixy_r(Z80 *z80, uint8_t opcode)
{
uint8_t *reg = extract_reg(z80, opcode << 3);
uint16_t addr = get_index_addr(z80, ++z80->regfile.pc);
mmu_write_byte(z80->mmu, addr, *reg);
z80->regfile.pc++;
return 19;
}

/*
LD (HL), n (0x36):
@@ -111,9 +129,18 @@ static uint8_t z80_inst_ld_hl_n(Z80 *z80, uint8_t opcode)
}

/*
LD (IXY+d), n
LD (IXY+d), n (0xDD36, 0xFD36):
Load n (8-bit immediate) into (IX+d) or (IY+d).
*/
// static uint8_t z80_inst_ld_ixy_n(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_ld_ixy_n(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint16_t addr = get_index_addr(z80, ++z80->regfile.pc);
uint8_t byte = mmu_read_byte(z80->mmu, ++z80->regfile.pc);
mmu_write_byte(z80->mmu, addr, byte);
z80->regfile.pc++;
return 19;
}

/*
LD A, (BC/DE)
@@ -169,7 +196,7 @@ static uint8_t z80_inst_ld_nn_a(Z80 *z80, uint8_t opcode)
// 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)

@@ -190,7 +217,17 @@ static uint8_t z80_inst_ld_dd_nn(Z80 *z80, uint8_t opcode)
return 10;
}

// LD IXY, nn
/*
LD IXY, nn (0xDD21, 0xFD21):
Load nn (16-bit immediate) into IX or IY.
*/
static uint8_t z80_inst_ld_ixy_nn(Z80 *z80, uint8_t opcode)
{
(void) opcode;
*z80->last_index = mmu_read_double(z80->mmu, ++z80->regfile.pc);
z80->regfile.pc += 2;
return 14;
}

/*
LD HL, (nn) (0x2A):
@@ -221,6 +258,7 @@ static uint8_t z80_inst_ld_dd_inn(Z80 *z80, uint8_t opcode)
}

// LD IXY, (nn)
// static uint8_t z80_inst_ld_ixy_inn(Z80 *z80, uint8_t opcode)

/*
LD (nn), HL: (0x22):
@@ -262,7 +300,7 @@ static uint8_t z80_inst_push_qq(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_push_ixy(Z80 *z80, uint8_t opcode)
{
(void) opcode;
stack_push(z80, *extract_index(z80));
stack_push(z80, *z80->last_index);
z80->regfile.pc++;
return 15;
}
@@ -286,7 +324,7 @@ static uint8_t z80_inst_pop_qq(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_pop_ixy(Z80 *z80, uint8_t opcode)
{
(void) opcode;
*extract_index(z80) = stack_pop(z80);
*z80->last_index = stack_pop(z80);
z80->regfile.pc++;
return 14;
}
@@ -444,9 +482,15 @@ static uint8_t z80_inst_lddr(Z80 *z80, uint8_t opcode)

// ADD A, (IXY+d)

// ADC A, s
// ADC A, r

// SUB s
// ADC A, n

// ADC A, (HL)

// ADC A, (IXY+d)

// SUB r

/*
SUB n (0xD6):
@@ -469,9 +513,19 @@ static uint8_t z80_inst_sub_n(Z80 *z80, uint8_t opcode)
return 7;
}

// SBC A, s
// SUB (HL)

// SUB (IXY+d)

// SBC A, r

// AND s
// SBC A, n

// SBC A, (HL)

// SBC A, (IXY+d)

// AND r

/*
AND n (0xE6):
@@ -491,7 +545,9 @@ static uint8_t z80_inst_and_n(Z80 *z80, uint8_t opcode)
return 7;
}

// OR s
// AND (HL)

// AND (IXY+d)

/*
OR r (0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB7):
@@ -528,7 +584,26 @@ static uint8_t z80_inst_or_n(Z80 *z80, uint8_t opcode)
return 7;
}

// XOR s
// OR (HL)

/*
OR (IXY+d) (0xDDB6, 0xFDB6):
Bitwise OR A with (IX+d) or (IY+d).
*/
static uint8_t z80_inst_or_ixy(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint8_t addr = get_index_addr(z80, ++z80->regfile.pc);
uint8_t val = mmu_read_byte(z80->mmu, addr);
uint8_t a = (z80->regfile.a |= val);

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

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

/*
XOR r (0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAF):
@@ -547,7 +622,27 @@ static uint8_t z80_inst_xor_r(Z80 *z80, uint8_t opcode)
return 4;
}

// CP s
/*
XOR n (0xEE):
Bitwise XOR A with n (8-bit immediate).
*/
static uint8_t z80_inst_xor_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), 0, !!(a & 0x20), a == 0,
!!(a & 0x80), 0xFF);

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

// XOR (HL)

// XOR (IXY+d)

/*
CP r (0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBF):
@@ -589,6 +684,28 @@ static uint8_t z80_inst_cp_n(Z80 *z80, uint8_t opcode)
}

/*
CP (HL) (0xBE):
Set flags as if the memory pointed to by HL had been subtracted from A.
*/
static uint8_t z80_inst_cp_hl(Z80 *z80, uint8_t opcode)
{
(void) opcode;
uint8_t n = mmu_read_byte(z80->mmu, get_pair(z80, REG_HL));
uint8_t d = z80->regfile.a - n;

bool c = (z80->regfile.a - n) != d;
bool v = (z80->regfile.a - n) != ((int8_t) d);
bool h = !!(((z80->regfile.a & 0x0F) - (n & 0x0F)) & 0x10);
update_flags(z80, c, 1, v, !!(n & 0x08), h, !!(n & 0x20), d == 0,
!!(d & 0x80), 0xFF);

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

// CP (IXY+d)

/*
INC r (0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x3C):
Increment r (8-bit register).
*/
@@ -1280,6 +1397,7 @@ static uint8_t z80_prefix_bits(Z80 *z80, uint8_t opcode)
*/
static uint8_t z80_prefix_index(Z80 *z80, uint8_t opcode)
{
z80->last_index = (opcode == 0xDD) ? &z80->regfile.ix : &z80->regfile.iy;
opcode = mmu_read_byte(z80->mmu, ++z80->regfile.pc);
return (*instruction_table_index[opcode])(z80, opcode);
}


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

@@ -192,7 +192,7 @@ static DispatchTable instruction_table = {
[0xBB] = z80_inst_cp_r,
[0xBC] = z80_inst_cp_r,
[0xBD] = z80_inst_cp_r,
[0xBE] = z80_inst_unimplemented, // TODO
[0xBE] = z80_inst_cp_hl,
[0xBF] = z80_inst_cp_r,
[0xC0] = z80_inst_ret_cc,
[0xC1] = z80_inst_pop_qq,
@@ -240,7 +240,7 @@ static DispatchTable instruction_table = {
[0xEB] = z80_inst_ex_de_hl,
[0xEC] = z80_inst_call_cc_nn,
[0xED] = z80_prefix_extended,
[0xEE] = z80_inst_unimplemented, // TODO
[0xEE] = z80_inst_xor_n,
[0xEF] = z80_inst_rst_p,
[0xF0] = z80_inst_ret_cc,
[0xF1] = z80_inst_pop_qq,
@@ -812,7 +812,7 @@ static DispatchTable instruction_table_index = {
[0x1E] = z80_inst_nop2,
[0x1F] = z80_inst_nop2,
[0x20] = z80_inst_nop2,
[0x21] = z80_inst_unimplemented, // TODO
[0x21] = z80_inst_ld_ixy_nn,
[0x22] = z80_inst_unimplemented, // TODO
[0x23] = z80_inst_unimplemented, // TODO
[0x24] = z80_inst_unimplemented, // TODO
@@ -833,7 +833,7 @@ static DispatchTable instruction_table_index = {
[0x33] = z80_inst_nop2,
[0x34] = z80_inst_unimplemented, // TODO
[0x35] = z80_inst_unimplemented, // TODO
[0x36] = z80_inst_unimplemented, // TODO
[0x36] = z80_inst_ld_ixy_n,
[0x37] = z80_inst_nop2,
[0x38] = z80_inst_nop2,
[0x39] = z80_inst_unimplemented, // TODO
@@ -849,7 +849,7 @@ static DispatchTable instruction_table_index = {
[0x43] = z80_inst_nop2,
[0x44] = z80_inst_unimplemented, // TODO
[0x45] = z80_inst_unimplemented, // TODO
[0x46] = z80_inst_unimplemented, // TODO
[0x46] = z80_inst_ld_r_ixy,
[0x47] = z80_inst_nop2,
[0x48] = z80_inst_nop2,
[0x49] = z80_inst_nop2,
@@ -857,7 +857,7 @@ static DispatchTable instruction_table_index = {
[0x4B] = z80_inst_nop2,
[0x4C] = z80_inst_unimplemented, // TODO
[0x4D] = z80_inst_unimplemented, // TODO
[0x4E] = z80_inst_unimplemented, // TODO
[0x4E] = z80_inst_ld_r_ixy,
[0x4F] = z80_inst_nop2,
[0x50] = z80_inst_nop2,
[0x51] = z80_inst_nop2,
@@ -865,7 +865,7 @@ static DispatchTable instruction_table_index = {
[0x53] = z80_inst_nop2,
[0x54] = z80_inst_unimplemented, // TODO
[0x55] = z80_inst_unimplemented, // TODO
[0x56] = z80_inst_unimplemented, // TODO
[0x56] = z80_inst_ld_r_ixy,
[0x57] = z80_inst_nop2,
[0x58] = z80_inst_nop2,
[0x59] = z80_inst_nop2,
@@ -873,7 +873,7 @@ static DispatchTable instruction_table_index = {
[0x5B] = z80_inst_nop2,
[0x5C] = z80_inst_unimplemented, // TODO
[0x5D] = z80_inst_unimplemented, // TODO
[0x5E] = z80_inst_unimplemented, // TODO
[0x5E] = z80_inst_ld_r_ixy,
[0x5F] = z80_inst_nop2,
[0x60] = z80_inst_unimplemented, // TODO
[0x61] = z80_inst_unimplemented, // TODO
@@ -881,7 +881,7 @@ static DispatchTable instruction_table_index = {
[0x63] = z80_inst_unimplemented, // TODO
[0x64] = z80_inst_unimplemented, // TODO
[0x65] = z80_inst_unimplemented, // TODO
[0x66] = z80_inst_unimplemented, // TODO
[0x66] = z80_inst_ld_r_ixy,
[0x67] = z80_inst_unimplemented, // TODO
[0x68] = z80_inst_unimplemented, // TODO
[0x69] = z80_inst_unimplemented, // TODO
@@ -889,23 +889,23 @@ static DispatchTable instruction_table_index = {
[0x6B] = z80_inst_unimplemented, // TODO
[0x6C] = z80_inst_unimplemented, // TODO
[0x6D] = z80_inst_unimplemented, // TODO
[0x6E] = z80_inst_unimplemented, // TODO
[0x6E] = z80_inst_ld_r_ixy,
[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
[0x70] = z80_inst_ld_ixy_r,
[0x71] = z80_inst_ld_ixy_r,
[0x72] = z80_inst_ld_ixy_r,
[0x73] = z80_inst_ld_ixy_r,
[0x74] = z80_inst_ld_ixy_r,
[0x75] = z80_inst_ld_ixy_r,
[0x76] = z80_inst_nop2,
[0x77] = z80_inst_unimplemented, // TODO
[0x77] = z80_inst_ld_ixy_r,
[0x78] = z80_inst_nop2,
[0x79] = z80_inst_nop2,
[0x7A] = z80_inst_nop2,
[0x7B] = z80_inst_nop2,
[0x7C] = z80_inst_unimplemented, // TODO
[0x7D] = z80_inst_unimplemented, // TODO
[0x7E] = z80_inst_unimplemented, // TODO
[0x7E] = z80_inst_ld_r_ixy,
[0x7F] = z80_inst_nop2,
[0x80] = z80_inst_nop2,
[0x81] = z80_inst_nop2,
@@ -961,7 +961,7 @@ static DispatchTable instruction_table_index = {
[0xB3] = z80_inst_nop2,
[0xB4] = z80_inst_unimplemented, // TODO
[0xB5] = z80_inst_unimplemented, // TODO
[0xB6] = z80_inst_unimplemented, // TODO
[0xB6] = z80_inst_or_ixy,
[0xB7] = z80_inst_nop2,
[0xB8] = z80_inst_nop2,
[0xB9] = z80_inst_nop2,


Loading…
Cancel
Save