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/MemoryMap
- http://www.smspower.org/Development/Mappers - 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 if (addr < 0x0400) // First kilobyte is unpaged, for interrupt handlers
return bank_byte_read(mmu->rom_banks[0], addr); 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. Write a byte of memory to the given address.


Return true if the byte was written, and false if it wasn't. Writes will 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; 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_free(MMU*);
void mmu_load_rom(MMU*, const uint8_t*, size_t); void mmu_load_rom(MMU*, const uint8_t*, size_t);
void mmu_power(MMU*); 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); 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_BC 1
#define REG_DE 2 #define REG_DE 2
#define REG_HL 3 #define REG_HL 3
#define REG_SP 4


#define FLAG_CARRY 0 #define FLAG_CARRY 0
#define FLAG_SUBTRACT 1 #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_BC: return (z80->regfile.b << 8) + z80->regfile.c;
case REG_DE: return (z80->regfile.d << 8) + z80->regfile.e; case REG_DE: return (z80->regfile.d << 8) + z80->regfile.e;
case REG_HL: return (z80->regfile.h << 8) + z80->regfile.l; 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) default: FATAL("invalid call: get_pair(z80, %u)", pair)
} }
return 0; 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_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_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_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) 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; 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++; 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): INC r (0x04, 0x0C, 0x14, 0x1C, 0x24, 0x2C, 0x3C):
Increment the 8-bit register encoded in the opcode. 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; 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): INC ss (0x03, 0x13, 0x23, 0x33):
Increment the 16-bit register encoded in the opcode. Increment the 16-bit register encoded in the opcode.
*/ */
static uint8_t z80_inst_inc_ss(Z80 *z80, uint8_t 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++; z80->regfile.pc++;
return 6; 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) = { static uint8_t (*instruction_lookup_table[256])(Z80*, uint8_t) = {
[0x00] = z80_inst_nop, [0x00] = z80_inst_nop,
[0x01] = z80_inst_unimplemented, // TODO
[0x01] = z80_inst_ld_dd_nn,
[0x02] = z80_inst_unimplemented, // TODO [0x02] = z80_inst_unimplemented, // TODO
[0x03] = z80_inst_inc_ss, [0x03] = z80_inst_inc_ss,
[0x04] = z80_inst_inc_r, [0x04] = z80_inst_inc_r,
[0x05] = z80_inst_unimplemented, // TODO [0x05] = z80_inst_unimplemented, // TODO
[0x06] = z80_inst_unimplemented, // TODO
[0x06] = z80_inst_ld_r_n,
[0x07] = z80_inst_unimplemented, // TODO [0x07] = z80_inst_unimplemented, // TODO
[0x08] = z80_inst_unimplemented, // TODO [0x08] = z80_inst_unimplemented, // TODO
[0x09] = 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 [0x0B] = z80_inst_unimplemented, // TODO
[0x0C] = z80_inst_inc_r, [0x0C] = z80_inst_inc_r,
[0x0D] = z80_inst_unimplemented, // TODO [0x0D] = z80_inst_unimplemented, // TODO
[0x0E] = z80_inst_unimplemented, // TODO
[0x0E] = z80_inst_ld_r_n,
[0x0F] = z80_inst_unimplemented, // TODO [0x0F] = z80_inst_unimplemented, // TODO
[0x10] = 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 [0x12] = z80_inst_unimplemented, // TODO
[0x13] = z80_inst_inc_ss, [0x13] = z80_inst_inc_ss,
[0x14] = z80_inst_inc_r, [0x14] = z80_inst_inc_r,
[0x15] = z80_inst_unimplemented, // TODO [0x15] = z80_inst_unimplemented, // TODO
[0x16] = z80_inst_unimplemented, // TODO
[0x16] = z80_inst_ld_r_n,
[0x17] = z80_inst_unimplemented, // TODO [0x17] = z80_inst_unimplemented, // TODO
[0x18] = z80_inst_unimplemented, // TODO [0x18] = z80_inst_unimplemented, // TODO
[0x19] = 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 [0x1B] = z80_inst_unimplemented, // TODO
[0x1C] = z80_inst_inc_r, [0x1C] = z80_inst_inc_r,
[0x1D] = z80_inst_unimplemented, // TODO [0x1D] = z80_inst_unimplemented, // TODO
[0x1E] = z80_inst_unimplemented, // TODO
[0x1E] = z80_inst_ld_r_n,
[0x1F] = z80_inst_unimplemented, // TODO [0x1F] = z80_inst_unimplemented, // TODO
[0x20] = 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 [0x22] = z80_inst_unimplemented, // TODO
[0x23] = z80_inst_inc_ss, [0x23] = z80_inst_inc_ss,
[0x24] = z80_inst_inc_r, [0x24] = z80_inst_inc_r,
[0x25] = z80_inst_unimplemented, // TODO [0x25] = z80_inst_unimplemented, // TODO
[0x26] = z80_inst_unimplemented, // TODO
[0x26] = z80_inst_ld_r_n,
[0x27] = z80_inst_unimplemented, // TODO [0x27] = z80_inst_unimplemented, // TODO
[0x28] = z80_inst_unimplemented, // TODO [0x28] = z80_inst_unimplemented, // TODO
[0x29] = 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 [0x2B] = z80_inst_unimplemented, // TODO
[0x2C] = z80_inst_inc_r, [0x2C] = z80_inst_inc_r,
[0x2D] = z80_inst_unimplemented, // TODO [0x2D] = z80_inst_unimplemented, // TODO
[0x2E] = z80_inst_unimplemented, // TODO
[0x2E] = z80_inst_ld_r_n,
[0x2F] = z80_inst_unimplemented, // TODO [0x2F] = z80_inst_unimplemented, // TODO
[0x30] = 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 [0x32] = z80_inst_unimplemented, // TODO
[0x33] = z80_inst_inc_ss, [0x33] = z80_inst_inc_ss,
[0x34] = z80_inst_unimplemented, // TODO [0x34] = z80_inst_unimplemented, // TODO
@@ -147,7 +478,7 @@ static uint8_t (*instruction_lookup_table[256])(Z80*, uint8_t) = {
[0x3B] = z80_inst_unimplemented, // TODO [0x3B] = z80_inst_unimplemented, // TODO
[0x3C] = z80_inst_inc_r, [0x3C] = z80_inst_inc_r,
[0x3D] = z80_inst_unimplemented, // TODO [0x3D] = z80_inst_unimplemented, // TODO
[0x3E] = z80_inst_unimplemented, // TODO
[0x3E] = z80_inst_ld_r_n,
[0x3F] = z80_inst_unimplemented, // TODO [0x3F] = z80_inst_unimplemented, // TODO
[0x40] = z80_inst_unimplemented, // TODO [0x40] = z80_inst_unimplemented, // TODO
[0x41] = z80_inst_unimplemented, // TODO [0x41] = z80_inst_unimplemented, // TODO


Loading…
Cancel
Save