Browse Source

Implement more load instructions.

master
Ben Kurtovic 8 years ago
parent
commit
cf1985bee9
4 changed files with 384 additions and 41 deletions
  1. +21
    -13
      src/mmu.c
  2. +3
    -2
      src/mmu.h
  3. +3
    -0
      src/z80.c
  4. +357
    -26
      src/z80_ops.inc.c

+ 21
- 13
src/mmu.c View File

@@ -119,7 +119,7 @@ static inline uint8_t bank_byte_read(const uint8_t* bank, uint16_t addr)
- http://www.smspower.org/Development/MemoryMap
- http://www.smspower.org/Development/Mappers
*/
uint8_t mmu_read_byte(MMU *mmu, uint16_t addr)
uint8_t mmu_read_byte(const MMU *mmu, uint16_t addr)
{
if (addr < 0x0400) // First kilobyte is unpaged, for interrupt handlers
return bank_byte_read(mmu->rom_banks[0], addr);
@@ -136,6 +136,26 @@ uint8_t mmu_read_byte(MMU *mmu, uint16_t addr)
}

/*
Read two bytes of memory from the given address.
*/
uint16_t mmu_read_double(const MMU *mmu, uint16_t addr)
{
return mmu_read_byte(mmu, addr) + (mmu_read_byte(mmu, addr + 1) << 8);
}

/*
Read four bytes of memory from the given address.
*/
uint32_t mmu_read_quad(const MMU *mmu, uint16_t addr)
{
return (
mmu_read_byte(mmu, addr) +
(mmu_read_byte(mmu, addr + 1) << 8) +
(mmu_read_byte(mmu, addr + 2) << 16) +
(mmu_read_byte(mmu, addr + 3) << 24));
}

/*
Write a byte of memory to the given address.

Return true if the byte was written, and false if it wasn't. Writes will
@@ -161,15 +181,3 @@ bool mmu_write_byte(MMU *mmu, uint16_t addr, uint8_t value)
return true;
}
}

/*
Read four bytes of memory from the given address.
*/
uint32_t mmu_read_quad(MMU *mmu, uint16_t addr)
{
return (
mmu_read_byte(mmu, addr) +
(mmu_read_byte(mmu, addr + 1) << 8) +
(mmu_read_byte(mmu, addr + 2) << 16) +
(mmu_read_byte(mmu, addr + 3) << 24));
}

+ 3
- 2
src/mmu.h View File

@@ -26,6 +26,7 @@ void mmu_init(MMU*);
void mmu_free(MMU*);
void mmu_load_rom(MMU*, const uint8_t*, size_t);
void mmu_power(MMU*);
uint8_t mmu_read_byte(MMU*, uint16_t);
uint8_t mmu_read_byte(const MMU*, uint16_t);
uint16_t mmu_read_double(const MMU*, uint16_t);
uint32_t mmu_read_quad(const MMU*, uint16_t);
bool mmu_write_byte(MMU*, uint16_t, uint8_t);
uint32_t mmu_read_quad(MMU*, uint16_t);

+ 3
- 0
src/z80.c View File

@@ -9,6 +9,7 @@
#define REG_BC 1
#define REG_DE 2
#define REG_HL 3
#define REG_SP 4

#define FLAG_CARRY 0
#define FLAG_SUBTRACT 1
@@ -89,6 +90,7 @@ static inline uint16_t get_pair(Z80 *z80, uint8_t pair)
case REG_BC: return (z80->regfile.b << 8) + z80->regfile.c;
case REG_DE: return (z80->regfile.d << 8) + z80->regfile.e;
case REG_HL: return (z80->regfile.h << 8) + z80->regfile.l;
case REG_SP: return z80->regfile.sp;
default: FATAL("invalid call: get_pair(z80, %u)", pair)
}
return 0;
@@ -104,6 +106,7 @@ static inline void set_pair(Z80 *z80, uint8_t pair, uint16_t value)
case REG_BC: z80->regfile.b = value >> 8; z80->regfile.c = value; break;
case REG_DE: z80->regfile.d = value >> 8; z80->regfile.e = value; break;
case REG_HL: z80->regfile.h = value >> 8; z80->regfile.l = value; break;
case REG_SP: z80->regfile.sp = value; break;
default: FATAL("invalid call: set_pair(z80, %u, 0x%04X)", pair, value)
}
}


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

@@ -24,17 +24,179 @@ static uint8_t z80_inst_unimplemented(Z80 *z80, uint8_t opcode)
return 2;
}

// LD r, r'

/*
NOP (0x00):
No operation is performed.
LD r, n (0x06, 0x0E, 0x16, 0x1E, 0x26, 0x2E, 0x3E):
Load the immediate value into the 8-bit register.
*/
static uint8_t z80_inst_nop(Z80 *z80, uint8_t opcode)
static uint8_t z80_inst_ld_r_n(Z80 *z80, uint8_t opcode)
{
(void) 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;
}

*reg = mmu_read_byte(z80->mmu, ++z80->regfile.pc);
z80->regfile.pc++;
return 4;
return 7;
}

// LD r, (HL)

// LD r, (IX+d)

// LD r, (IY+d)

// LD (HL), r

// LD (IX+d), r

// LD (IY+d), r

// LD (HL), n

// LD (IX+d), n

// LD (IY+d), n

// LD A, (BC)

// LD A, (DE)

// LD A, (nn)

// LD (BC), A

// LD (DE), A

// LD (nn), A

// LD A, I

// LD A, R

// LD I,A

// LD R, A

/*
LD dd, nn (0x01, 0x11, 0x21, 0x31):
Load the two-byte immediate into the 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;
}

set_pair(z80, pair, mmu_read_double(z80->mmu, ++z80->regfile.pc));
z80->regfile.pc += 2;
return 6;
}

// LD IX, nn

// LD IY, nn

// LD HL, (nn)

// LD dd, (nn)

// LD IX, (nn)

// LD IY, (nn)

// LD (nn), HL

// LD (nn), dd

// LD (nn), IX

// LD (nn), IY

// LD SP, HL

// LD SP, IX

// LD SP, IY

// PUSH qq

// PUSH IX

// PUSH IY

// POP qq

// POP IX

// POP IY

// EX DE, HL

// EX AF, AF′

// EXX

// EX (SP), HL

// EX (SP), IX

// EX (SP), IY

// LDI

// LDIR

// LDD

// LDDR

// CPI

// CPIR

// CPD

// CPDR

// ADD A, r

// ADD A, n

// ADD A, (HL)

// ADD A, (IX + d)

// ADD A, (IY + d)

// ADC A, s

// SUB s

// SBC A, s

// AND s

// OR s

// XOR s

// CP s

/*
INC r (0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x3C):
Increment the 8-bit register encoded in the opcode.
@@ -62,36 +224,205 @@ static uint8_t z80_inst_inc_r(Z80 *z80, uint8_t opcode)
return 4;
}

// INC (HL)

// INC (IX+d)

// INC (IY+d)

// DEC m

// DAA

// CPL

// NEG

// CCF

// SCF

/*
NOP (0x00):
No operation is performed.
*/
static uint8_t z80_inst_nop(Z80 *z80, uint8_t opcode)
{
(void) opcode;
z80->regfile.pc++;
return 4;
}

// HALT

// DI

// EI

// IM 0

// IM 1

// IM 2

// ADD HL, ss

// ADC HL, ss

// SBC HL, ss

// ADD IX, pp

// ADD IY, rr

/*
INC ss (0x03, 0x13, 0x23, 0x33):
Increment the 16-bit register encoded in the opcode.
*/
static uint8_t z80_inst_inc_ss(Z80 *z80, uint8_t opcode)
{
if (opcode == 0x33) {
z80->regfile.sp++;
} else {
uint8_t pair;
switch(opcode) {
case 0x03: pair = REG_BC; break;
case 0x13: pair = REG_DE; break;
case 0x23: pair = REG_HL; break;
}
set_pair(z80, pair, get_pair(z80, pair) + 1);
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;
}

set_pair(z80, pair, get_pair(z80, pair) + 1);
z80->regfile.pc++;
return 6;
}

// INC IX

// INC IY

// DEC ss

// DEC IX

// DEC IY

// RLCA

// RLA

// RRCA

// RRA

// RLC r

// RLC (HL)

// RLC (IX+d)

// RLC (IY+d)

// RL m

// RRC m

// RR m

// SLA m

// SRA m

// SRL m

// RLD

// RRD

// BIT b, r

// BIT b, (HL)

// BIT b, (IX+d)

// BIT b, (IY+d)

// SET b, r

// SET b, (HL)

// SET b, (IX+d)

// SET b, (IY+d)

// RES b, m

// JP nn

// JP cc, nn

// JR e

// JR C, e

// JR NC, e

// JR Z, e

// JR NZ, e

// JP (HL)

// JP (IX)

// JP (IY)

// DJNZ, e

// CALL nn

// CALL cc, nn

// RET

// RET cc

// RETI

// RETN

// RST p

// IN A, (n)

// IN r (C)

// INI

// INIR

// IND

// INDR

// OUT (n), A

// OUT (C), r

// OUTI

// OTIR

// OUTD

// OTDR

static uint8_t (*instruction_lookup_table[256])(Z80*, uint8_t) = {
[0x00] = z80_inst_nop,
[0x01] = z80_inst_unimplemented, // TODO
[0x01] = z80_inst_ld_dd_nn,
[0x02] = z80_inst_unimplemented, // TODO
[0x03] = z80_inst_inc_ss,
[0x04] = z80_inst_inc_r,
[0x05] = z80_inst_unimplemented, // TODO
[0x06] = z80_inst_unimplemented, // TODO
[0x06] = z80_inst_ld_r_n,
[0x07] = z80_inst_unimplemented, // TODO
[0x08] = z80_inst_unimplemented, // TODO
[0x09] = z80_inst_unimplemented, // TODO
@@ -99,15 +430,15 @@ static uint8_t (*instruction_lookup_table[256])(Z80*, uint8_t) = {
[0x0B] = z80_inst_unimplemented, // TODO
[0x0C] = z80_inst_inc_r,
[0x0D] = z80_inst_unimplemented, // TODO
[0x0E] = z80_inst_unimplemented, // TODO
[0x0E] = z80_inst_ld_r_n,
[0x0F] = z80_inst_unimplemented, // TODO
[0x10] = z80_inst_unimplemented, // TODO
[0x11] = z80_inst_unimplemented, // TODO
[0x11] = z80_inst_ld_dd_nn,
[0x12] = z80_inst_unimplemented, // TODO
[0x13] = z80_inst_inc_ss,
[0x14] = z80_inst_inc_r,
[0x15] = z80_inst_unimplemented, // TODO
[0x16] = z80_inst_unimplemented, // TODO
[0x16] = z80_inst_ld_r_n,
[0x17] = z80_inst_unimplemented, // TODO
[0x18] = z80_inst_unimplemented, // TODO
[0x19] = z80_inst_unimplemented, // TODO
@@ -115,15 +446,15 @@ static uint8_t (*instruction_lookup_table[256])(Z80*, uint8_t) = {
[0x1B] = z80_inst_unimplemented, // TODO
[0x1C] = z80_inst_inc_r,
[0x1D] = z80_inst_unimplemented, // TODO
[0x1E] = z80_inst_unimplemented, // TODO
[0x1E] = z80_inst_ld_r_n,
[0x1F] = z80_inst_unimplemented, // TODO
[0x20] = z80_inst_unimplemented, // TODO
[0x21] = z80_inst_unimplemented, // TODO
[0x21] = z80_inst_ld_dd_nn,
[0x22] = z80_inst_unimplemented, // TODO
[0x23] = z80_inst_inc_ss,
[0x24] = z80_inst_inc_r,
[0x25] = z80_inst_unimplemented, // TODO
[0x26] = z80_inst_unimplemented, // TODO
[0x26] = z80_inst_ld_r_n,
[0x27] = z80_inst_unimplemented, // TODO
[0x28] = z80_inst_unimplemented, // TODO
[0x29] = z80_inst_unimplemented, // TODO
@@ -131,10 +462,10 @@ static uint8_t (*instruction_lookup_table[256])(Z80*, uint8_t) = {
[0x2B] = z80_inst_unimplemented, // TODO
[0x2C] = z80_inst_inc_r,
[0x2D] = z80_inst_unimplemented, // TODO
[0x2E] = z80_inst_unimplemented, // TODO
[0x2E] = z80_inst_ld_r_n,
[0x2F] = z80_inst_unimplemented, // TODO
[0x30] = z80_inst_unimplemented, // TODO
[0x31] = z80_inst_unimplemented, // TODO
[0x31] = z80_inst_ld_dd_nn,
[0x32] = z80_inst_unimplemented, // TODO
[0x33] = z80_inst_inc_ss,
[0x34] = z80_inst_unimplemented, // TODO
@@ -147,7 +478,7 @@ static uint8_t (*instruction_lookup_table[256])(Z80*, uint8_t) = {
[0x3B] = z80_inst_unimplemented, // TODO
[0x3C] = z80_inst_inc_r,
[0x3D] = z80_inst_unimplemented, // TODO
[0x3E] = 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


Loading…
Cancel
Save