| @@ -72,7 +72,7 @@ void z80_power(Z80 *z80) | |||||
| regfile->ix = 0xFFFF; | regfile->ix = 0xFFFF; | ||||
| regfile->iy = 0xFFFF; | regfile->iy = 0xFFFF; | ||||
| regfile->sp = 0xFFFF; | |||||
| regfile->sp = 0xFFF0; | |||||
| regfile->pc = 0x0000; | regfile->pc = 0x0000; | ||||
| regfile->i = 0xFF; | regfile->i = 0xFF; | ||||
| @@ -261,6 +261,17 @@ static inline bool extract_cond(const Z80 *z80, uint8_t opcode) | |||||
| } | } | ||||
| /* | /* | ||||
| Extract the current index register. | |||||
| */ | |||||
| static inline uint16_t* extract_index(Z80 *z80) | |||||
| { | |||||
| 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 the CPU's current interrupt mode. | Return the CPU's current interrupt mode. | ||||
| */ | */ | ||||
| static inline uint8_t get_interrupt_mode(const Z80 *z80) | static inline uint8_t get_interrupt_mode(const Z80 *z80) | ||||
| @@ -63,7 +63,7 @@ static uint8_t z80_inst_ld_r_n(Z80 *z80, uint8_t opcode) | |||||
| /* | /* | ||||
| LD r, (HL) (0x46, 0x4E, 0x56, 0x5E, 0x66, 0x6E, 0x7E): | LD r, (HL) (0x46, 0x4E, 0x56, 0x5E, 0x66, 0x6E, 0x7E): | ||||
| Load the contents of HL into r (8-bit register). | |||||
| Load the memory pointed to by HL into r (8-bit register). | |||||
| */ | */ | ||||
| static uint8_t z80_inst_ld_r_hl(Z80 *z80, uint8_t opcode) | static uint8_t z80_inst_ld_r_hl(Z80 *z80, uint8_t opcode) | ||||
| { | { | ||||
| @@ -84,9 +84,17 @@ static uint8_t z80_inst_ld_r_hl(Z80 *z80, uint8_t opcode) | |||||
| // static uint8_t z80_inst_ld_r_iy(Z80 *z80, uint8_t opcode) | // static uint8_t z80_inst_ld_r_iy(Z80 *z80, uint8_t opcode) | ||||
| /* | /* | ||||
| LD (HL), r | |||||
| LD (HL), r (0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x77): | |||||
| Load r (8-bit register) into the memory pointed to by HL. | |||||
| */ | */ | ||||
| // static uint8_t z80_inst_ld_hl_r(Z80 *z80, uint8_t opcode) | |||||
| static uint8_t z80_inst_ld_hl_r(Z80 *z80, uint8_t opcode) | |||||
| { | |||||
| uint8_t *reg = extract_reg(z80, opcode << 3); | |||||
| uint16_t addr = get_pair(z80, REG_HL); | |||||
| mmu_write_byte(z80->mmu, addr, *reg); | |||||
| z80->regfile.pc++; | |||||
| return 7; | |||||
| } | |||||
| /* | /* | ||||
| LD (IX+d), r | LD (IX+d), r | ||||
| @@ -230,9 +238,17 @@ static uint8_t z80_inst_push_qq(Z80 *z80, uint8_t opcode) | |||||
| return 11; | return 11; | ||||
| } | } | ||||
| // PUSH IX | |||||
| // PUSH IY | |||||
| /* | |||||
| PUSH IXY (0xDDE5, 0xFDE5): | |||||
| Push IX or IY onto the stack, and decrement SP by two. | |||||
| */ | |||||
| static uint8_t z80_inst_push_ixy(Z80 *z80, uint8_t opcode) | |||||
| { | |||||
| (void) opcode; | |||||
| stack_push(z80, *extract_index(z80)); | |||||
| z80->regfile.pc++; | |||||
| return 15; | |||||
| } | |||||
| /* | /* | ||||
| POP qq (0xC1, 0xD1, 0xE1, 0xF1): | POP qq (0xC1, 0xD1, 0xE1, 0xF1): | ||||
| @@ -246,9 +262,17 @@ static uint8_t z80_inst_pop_qq(Z80 *z80, uint8_t opcode) | |||||
| return 10; | return 10; | ||||
| } | } | ||||
| // POP IX | |||||
| // POP IY | |||||
| /* | |||||
| POP IXY (0xDDE1, 0xFDE1): | |||||
| Pop IX or IY from the stack, and increment SP by two. | |||||
| */ | |||||
| static uint8_t z80_inst_pop_ixy(Z80 *z80, uint8_t opcode) | |||||
| { | |||||
| (void) opcode; | |||||
| *extract_index(z80) = stack_pop(z80); | |||||
| z80->regfile.pc++; | |||||
| return 14; | |||||
| } | |||||
| // EX DE, HL | // EX DE, HL | ||||
| @@ -632,7 +656,24 @@ static uint8_t z80_inst_jr_cc_e(Z80 *z80, uint8_t opcode) | |||||
| // JP (IY) | // JP (IY) | ||||
| // DJNZ, e | |||||
| /* | |||||
| DJNZ, e (0x10): | |||||
| Decrement b and relative jump e (signed 8-bit immediate) if non-zero. | |||||
| */ | |||||
| static uint8_t z80_inst_djnz_e(Z80 *z80, uint8_t opcode) | |||||
| { | |||||
| (void) opcode; | |||||
| z80->regfile.b--; | |||||
| if (z80->regfile.b != 0) { | |||||
| int8_t jump = mmu_read_byte(z80->mmu, z80->regfile.pc + 1); | |||||
| z80->regfile.pc += jump + 2; | |||||
| return 13; | |||||
| } else { | |||||
| z80->regfile.pc += 2; | |||||
| return 8; | |||||
| } | |||||
| } | |||||
| /* | /* | ||||
| CALL nn (0xCD): | CALL nn (0xCD): | ||||
| @@ -18,7 +18,7 @@ static DispatchTable instruction_table = { | |||||
| [0x0D] = z80_inst_unimplemented, // TODO | [0x0D] = z80_inst_unimplemented, // TODO | ||||
| [0x0E] = z80_inst_ld_r_n, | [0x0E] = z80_inst_ld_r_n, | ||||
| [0x0F] = z80_inst_unimplemented, // TODO | [0x0F] = z80_inst_unimplemented, // TODO | ||||
| [0x10] = z80_inst_unimplemented, // TODO | |||||
| [0x10] = z80_inst_djnz_e, | |||||
| [0x11] = z80_inst_ld_dd_nn, | [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, | ||||
| @@ -114,14 +114,14 @@ static DispatchTable instruction_table = { | |||||
| [0x6D] = z80_inst_ld_r_r, | [0x6D] = z80_inst_ld_r_r, | ||||
| [0x6E] = z80_inst_ld_r_hl, | [0x6E] = z80_inst_ld_r_hl, | ||||
| [0x6F] = z80_inst_ld_r_r, | [0x6F] = z80_inst_ld_r_r, | ||||
| [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_hl_r, | |||||
| [0x71] = z80_inst_ld_hl_r, | |||||
| [0x72] = z80_inst_ld_hl_r, | |||||
| [0x73] = z80_inst_ld_hl_r, | |||||
| [0x74] = z80_inst_ld_hl_r, | |||||
| [0x75] = z80_inst_ld_hl_r, | |||||
| [0x76] = z80_inst_halt, | [0x76] = z80_inst_halt, | ||||
| [0x77] = z80_inst_unimplemented, // TODO | |||||
| [0x77] = z80_inst_ld_hl_r, | |||||
| [0x78] = z80_inst_ld_r_r, | [0x78] = z80_inst_ld_r_r, | ||||
| [0x79] = z80_inst_ld_r_r, | [0x79] = z80_inst_ld_r_r, | ||||
| [0x7A] = z80_inst_ld_r_r, | [0x7A] = z80_inst_ld_r_r, | ||||
| @@ -1004,11 +1004,11 @@ static DispatchTable instruction_table_index = { | |||||
| [0xDE] = z80_inst_nop2, | [0xDE] = z80_inst_nop2, | ||||
| [0xDF] = z80_inst_nop2, | [0xDF] = z80_inst_nop2, | ||||
| [0xE0] = z80_inst_nop2, | [0xE0] = z80_inst_nop2, | ||||
| [0xE1] = z80_inst_unimplemented, // TODO | |||||
| [0xE1] = z80_inst_pop_ixy, | |||||
| [0xE2] = z80_inst_nop2, | [0xE2] = z80_inst_nop2, | ||||
| [0xE3] = z80_inst_unimplemented, // TODO | [0xE3] = z80_inst_unimplemented, // TODO | ||||
| [0xE4] = z80_inst_nop2, | [0xE4] = z80_inst_nop2, | ||||
| [0xE5] = z80_inst_unimplemented, // TODO | |||||
| [0xE5] = z80_inst_push_ixy, | |||||
| [0xE6] = z80_inst_nop2, | [0xE6] = z80_inst_nop2, | ||||
| [0xE7] = z80_inst_nop2, | [0xE7] = z80_inst_nop2, | ||||
| [0xE8] = z80_inst_nop2, | [0xE8] = z80_inst_nop2, | ||||