Flesh out TLCS870 core (#3763)

* rewrote most of the execution for my tlcs870 core

* no longer the case (nw)

* note updates (nw)

* address concerns, const qualify more things where possible (nw)

* more const (nw)

* oops (nw)

* consistency (nw)
This commit is contained in:
David Haywood 2018-07-23 01:24:10 +01:00 committed by Vas Crabb
parent fedf58aa42
commit 88b1546f30
10 changed files with 3311 additions and 3049 deletions

View File

@ -2383,6 +2383,11 @@ end
if (CPUS["TLCS870"]~=null) then
files {
MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870.cpp",
MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870_ops.cpp",
MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp",
MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870_ops_src.cpp",
MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870_ops_dst.cpp",
MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp",
MAME_DIR .. "src/devices/cpu/tlcs870/tlcs870.h",
}
end

File diff suppressed because it is too large Load Diff

View File

@ -8,80 +8,6 @@
class tlcs870_device : public cpu_device
{
protected:
enum _e_op {
UNKNOWN = 0x00,
CALL, CALLP, CALLV, CLR, CPL,
DAA, DAS, DEC, /*DI,*/ DIV,
/*EI,*/
INC,
/*J,*/ JP, JR, JRS,
LD, LDW,
MCMP, MUL,
NOP,
POP, PUSH,
RET, RETI, RETN, ROLC, ROLD, RORC, RORD,
SET, SHLC, SHRC, SWAP, SWI,
/*TEST,*/ XCH,
ALU_ADDC,
ALU_ADD,
ALU_SUBB,
ALU_SUB,
ALU_AND,
ALU_XOR,
ALU_OR,
ALU_CMP
};
enum _regs8 {
REG_A,
REG_W,
REG_C,
REG_B,
REG_E,
REG_D,
REG_L,
REG_H
};
enum _regs16 {
REG_WA,
REG_BC,
REG_DE,
REG_HL
};
enum _regs16p {
pREG_DE,
pREG_HL
};
enum _regs_debugger {
DEBUGGER_REG_A,
DEBUGGER_REG_W,
DEBUGGER_REG_C,
DEBUGGER_REG_B,
DEBUGGER_REG_E,
DEBUGGER_REG_D,
DEBUGGER_REG_L,
DEBUGGER_REG_H,
DEBUGGER_REG_WA,
DEBUGGER_REG_BC,
DEBUGGER_REG_DE,
DEBUGGER_REG_HL
};
enum _conditions {
COND_EQ_Z,
COND_NE_NZ,
COND_LT_CS,
COND_GE_CC,
COND_LE,
COND_GT,
COND_T,
COND_F
};
// construction/destruction
tlcs870_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor program_map);
@ -113,6 +39,67 @@ protected:
uint32_t m_debugger_temp;
private:
enum _regs8
{
REG_A,
REG_W,
REG_C,
REG_B,
REG_E,
REG_D,
REG_L,
REG_H
};
enum _regs16
{
REG_WA,
REG_BC,
REG_DE,
REG_HL
};
enum _regs_debugger
{
DEBUGGER_REG_A,
DEBUGGER_REG_W,
DEBUGGER_REG_C,
DEBUGGER_REG_B,
DEBUGGER_REG_E,
DEBUGGER_REG_D,
DEBUGGER_REG_L,
DEBUGGER_REG_H,
DEBUGGER_REG_WA,
DEBUGGER_REG_BC,
DEBUGGER_REG_DE,
DEBUGGER_REG_HL
};
enum _conditions
{
COND_EQ_Z,
COND_NE_NZ,
COND_LT_CS,
COND_GE_CC,
COND_LE,
COND_GT,
COND_T,
COND_F
};
enum _srcdst_addressingmode
{
ADDR_IN_IMM_X,
ADDR_IN_PC_PLUS_REG_A,
ADDR_IN_DE,
ADDR_IN_HL,
ADDR_IN_HL_PLUS_IMM_D,
ADDR_IN_HL_PLUS_REG_C,
ADDR_IN_HLINC,
ADDR_IN_DECHL
};
address_space_config m_program_config;
address_space_config m_io_config;
required_shared_ptr<uint8_t> m_intram;
@ -124,18 +111,8 @@ private:
int m_icount;
// Work registers
uint16_t m_op;
int m_param2_type;
uint16_t m_param2;
int m_param1_type;
uint16_t m_param1;
uint16_t m_temppc; // this is just PPC? use generic reg?
uint8_t m_bitpos;
uint8_t m_flagsaffected;
uint8_t m_cycles;
uint16_t m_tmppc;
uint32_t m_addr;
uint16_t m_F;
@ -143,34 +120,225 @@ private:
/* CPU registers */
uint8_t m_RBS; // register base (4-bits)
inline uint8_t RM8 (uint32_t a);
inline uint16_t RM16(uint32_t a);
inline void WM8 (uint32_t a, uint8_t v);
inline void WM16(uint32_t a, uint16_t v);
inline uint8_t RX8 (uint32_t a, uint32_t base);
inline uint16_t RX16(uint32_t a, uint32_t base);
inline void WX8 (uint32_t a, uint8_t v, uint32_t base);
inline void WX16(uint32_t a, uint16_t v, uint32_t base);
inline uint8_t READ8();
inline uint16_t READ16();
void decode();
void decode_register_prefix(uint8_t b0);
void decode_source(int type, uint16_t val);
void decode_dest(uint8_t b0);
uint8_t RM8(const uint32_t a) { return m_program->read_byte(a); }
uint16_t RM16(const uint32_t a) { return RM8(a) | (RM8((a + 1) & 0xffff) << 8); }
void setbit_param(uint16_t param_type, uint16_t param, uint8_t bit, bool do_flag);
uint8_t getbit_param(uint16_t param_type, uint16_t param);
void WM8(const uint32_t a, const uint8_t v) { m_program->write_byte(a, v); }
void WM16(const uint32_t a, const uint16_t v) { WM8(a, v); WM8((a + 1) & 0xffff, v >> 8); }
uint16_t get_addr(uint16_t param_type, uint16_t param_val);
uint16_t get_source_val(uint16_t param_type, uint16_t param_val);
void set_dest_val(uint16_t param_type, uint16_t param_val, uint16_t dest_val);
uint8_t RX8(const uint32_t a, const uint32_t base) { return m_program->read_byte(base | a); }
uint16_t RX16(const uint32_t a, const uint32_t base) { return RX8(a, base) | (RX8((a + 1) & 0xffff, base) << 8); }
uint8_t get_reg8(int reg);
void set_reg8(int reg, uint8_t val);
uint16_t get_reg16(int reg);
void set_reg16(int reg, uint16_t val);
void WX8(const uint32_t a, const uint8_t v, const uint32_t base) { m_program->write_byte(base | a, v); }
void WX16(const uint32_t a, const uint16_t v, const uint32_t base) { WX8(a, v, base); WX8((a + 1) & 0xffff, v >> 8, base); }
uint8_t READ8() { const uint8_t b0 = RM8(m_addr++); m_addr &= 0xffff; return b0; }
uint16_t READ16() { const uint8_t b0 = READ8(); return b0 | (READ8() << 8); }
uint16_t get_addr(uint16_t opbyte0, uint16_t val);
const uint8_t get_reg8(const int reg);
void set_reg8(const int reg, uint8_t val);
const uint16_t get_reg16(const int reg);
void set_reg16(const int reg, uint16_t val);
const int FLAG_J = 0x80;
const int FLAG_Z = 0x40;
const int FLAG_C = 0x20;
const int FLAG_H = 0x10;
void clear_JF() { m_F &= ~FLAG_J; };
void clear_ZF() { m_F &= ~FLAG_Z; };
void clear_CF() { m_F &= ~FLAG_C; };
void clear_HF() { m_F &= ~FLAG_H; };
void set_JF() { m_F |= FLAG_J; };
void set_ZF() { m_F |= FLAG_Z; };
void set_CF() { m_F |= FLAG_C; };
void set_HF() { m_F |= FLAG_H; };
const int is_JF() { return ((m_F & FLAG_J) ? 1 : 0); };
const int is_ZF() { return ((m_F & FLAG_Z) ? 1 : 0); };
const int is_CF() { return ((m_F & FLAG_C) ? 1 : 0); };
const int is_HF() { return ((m_F & FLAG_H) ? 1 : 0); };
bool stream_arg(std::ostream &stream, uint32_t pc, const char *pre, const uint16_t mode, const uint16_t r, const uint16_t rb);
// tlcs870_ops.cpp
void decode();
void do_illegal(const uint8_t opbyte0);
void do_NOP(const uint8_t opbyte0);
void do_SWAP_A(const uint8_t opbyte0);
void do_MUL_W_A(const uint8_t opbyte0);
void do_DIV_WA_C(const uint8_t opbyte0);
void do_RETI(const uint8_t opbyte0);
void do_RET(const uint8_t opbyte0);
void do_POP_PSW(const uint8_t opbyte0);
void do_PUSH_PSW(const uint8_t opbyte0);
void do_DAA_A(const uint8_t opbyte0);
void do_DAS_A(const uint8_t opbyte0);
void do_CLR_CF(const uint8_t opbyte0);
void do_SET_CF(const uint8_t opbyte0);
void do_CPL_CF(const uint8_t opbyte0);
void do_LD_RBS_n(const uint8_t opbyte0);
void do_INC_rr(const uint8_t opbyte0);
void do_LD_rr_mn(const uint8_t opbyte0);
void do_DEC_rr(const uint8_t opbyte0);
void do_SHLC_A(const uint8_t opbyte0);
void do_SHRC_A(const uint8_t opbyte0);
void do_ROLC_A(const uint8_t opbyte0);
void do_RORC_A(const uint8_t opbyte0);
void do_INC_inx(const uint8_t opbyte0);
void do_INC_inHL(const uint8_t opbyte0);
void do_LD_A_inx(const uint8_t opbyte0);
void do_LD_A_inHL(const uint8_t opbyte0);
void do_LDW_inx_mn(const uint8_t opbyte0);
void do_LDW_inHL_mn(const uint8_t opbyte0);
void do_LD_inx_iny(const uint8_t opbyte0);
void do_DEC_inx(const uint8_t opbyte0);
void do_DEC_inHL(const uint8_t opbyte0);
void do_LD_inx_A(const uint8_t opbyte0);
void do_LD_inHL_A(const uint8_t opbyte0);
void do_LD_inx_n(const uint8_t opbyte0);
void do_LD_inHL_n(const uint8_t opbyte0);
void do_CLR_inx(const uint8_t opbyte0);
void do_CLR_inHL(const uint8_t opbyte0);
void do_LD_r_n(const uint8_t opbyte0);
void do_SET_inxbit(const uint8_t opbyte0);
void do_CLR_inxbit(const uint8_t opbyte0);
void do_LD_A_r(const uint8_t opbyte0);
void do_LD_r_A(const uint8_t opbyte0);
void do_INC_r(const uint8_t opbyte0);
void do_DEC_r(const uint8_t opbyte0);
void do_ALUOP_A_n(const uint8_t opbyte0);
void do_ALUOP_A_inx(const uint8_t opbyte0);
void do_JRS_T_a(const uint8_t opbyte0);
void do_JRS_F_a(const uint8_t opbyte0);
void do_CALLV_n(const uint8_t opbyte0);
void do_JR_cc_a(const uint8_t opbyte0);
void do_LD_CF_inxbit(const uint8_t opbyte0);
void do_LD_SP_mn(const uint8_t opbyte0);
void do_JR_a(const uint8_t opbyte0);
void do_CALL_mn(const uint8_t opbyte0);
void do_CALLP_n(const uint8_t opbyte0);
void do_JP_mn(const uint8_t opbyte0);
void do_ff_opcode(const uint8_t opbyte0);
// tlcs870_ops_src.cpp
void do_e0_opcode(const uint8_t opbyte0);
void do_e1_to_e3_opcode(const uint8_t opbyte0);
void do_e4_opcode(const uint8_t opbyte0);
void do_e5_to_e7_opcode(const uint8_t opbyte0);
void do_e0_to_e7_opcode(uint8_t opbyte0, uint16_t srcaddr);
void do_e0_to_e7_oprand_illegal(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_ROLD_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_RORD_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_LD_rr_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_INC_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_LD_inx_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_LD_inHL_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_DEC_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_MCMP_insrc_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_SET_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_CLR_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_LD_r_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_ALUOP_insrc_inHL(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_ALUOP_insrc_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_ALUOP_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_XCH_r_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_CPL_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_LD_insrcbit_CF(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_XOR_CF_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_LD_CF_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_CALL_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
void do_JP_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr);
uint16_t do_alu(int op, uint16_t param1, uint16_t param2);
// tlcs870_ops_dst.cpp
void do_f0_opcode(const uint8_t opbyte0);
void do_f2_to_f3_opcode(const uint8_t opbyte0);
void do_f4_opcode(const uint8_t opbyte0);
void do_f6_to_f7_opcode(const uint8_t opbyte0);
void do_f0_to_f7_opcode(const uint8_t opbyte0, const uint16_t dstaddr);
void do_f0_to_f7_oprand_illegal_opcode(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr);
void do_LD_indst_rr(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr);
void do_LD_indst_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr);
void do_LD_indst_r(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr);
// tlcs870_ops_reg.cpp
void do_regprefixtype_opcode(const uint8_t opbyte0);
void do_regprefixtype_oprand_illegal(const uint8_t opbyte0, const uint8_t opbyte1);
void do_SWAP_g(const uint8_t opbyte0, const uint8_t opbyte1);
void do_MUL_gg(const uint8_t opbyte0, const uint8_t opbyte1);
void do_DIV_gg_C(const uint8_t opbyte0, const uint8_t opbyte1);
void do_RETN(const uint8_t opbyte0, const uint8_t opbyte1);
void do_POP_gg(const uint8_t opbyte0, const uint8_t opbyte1);
void do_PUSH_gg(const uint8_t opbyte0, const uint8_t opbyte1);
void do_DAA_g(const uint8_t opbyte0, const uint8_t opbyte1);
void do_DAS_g(const uint8_t opbyte0, const uint8_t opbyte1);
void do_XCH_rr_gg(const uint8_t opbyte0, const uint8_t opbyte1);
void do_LD_rr_gg(const uint8_t opbyte0, const uint8_t opbyte1);
void do_SHLC_g(const uint8_t opbyte0, const uint8_t opbyte1);
void do_SHRC_g(const uint8_t opbyte0, const uint8_t opbyte1);
void do_ROLC_g(const uint8_t opbyte0, const uint8_t opbyte1);
void do_RORC_g(const uint8_t opbyte0, const uint8_t opbyte1);
void do_ALUOP_WA_gg(const uint8_t opbyte0, const uint8_t opbyte1);
void do_ALUOP_gg_mn(const uint8_t opbyte0, const uint8_t opbyte1);
void do_SET_gbit(const uint8_t opbyte0, const uint8_t opbyte1);
void do_CLR_gbit(const uint8_t opbyte0, const uint8_t opbyte1);
void do_LD_r_g(const uint8_t opbyte0, const uint8_t opbyte1);
void do_ALUOP_A_g(const uint8_t opbyte0, const uint8_t opbyte1);
void do_ALUOP_g_A(const uint8_t opbyte0, const uint8_t opbyte1);
void do_ALUOP_g_n(const uint8_t opbyte0, const uint8_t opbyte1);
void do_SET_inppbit(const uint8_t opbyte0, const uint8_t opbyte1);
void do_CLR_inppbit(const uint8_t opbyte0, const uint8_t opbyte1);
void do_CPL_inppbit(const uint8_t opbyte0, const uint8_t opbyte1);
void do_LD_inppbit_CF(const uint8_t opbyte0, const uint8_t opbyte1);
void do_LD_CF_inppbit(const uint8_t opbyte0, const uint8_t opbyte1);
void do_XCH_r_g(const uint8_t opbyte0, const uint8_t opbyte1);
void do_CPL_gbit(const uint8_t opbyte0, const uint8_t opbyte1);
void do_LD_gbit_CF(const uint8_t opbyte0, const uint8_t opbyte1);
void do_XOR_CF_gbit(const uint8_t opbyte0, const uint8_t opbyte1);
void do_LD_CF_gbit(const uint8_t opbyte0, const uint8_t opbyte1);
void do_LD_SP_gg(const uint8_t opbyte0, const uint8_t opbyte1);
void do_LD_gg_SP(const uint8_t opbyte0, const uint8_t opbyte1);
void do_CALL_gg(const uint8_t opbyte0, const uint8_t opbyte1);
void do_JP_gg(const uint8_t opbyte0, const uint8_t opbyte1);
void handle_div(const int reg);
void handle_mul(const int reg);
void handle_swap(const int reg);
uint8_t handle_SHLC(uint8_t val);
uint8_t handle_SHRC(uint8_t val);
uint8_t handle_DAS(uint8_t val);
uint8_t handle_DAA(uint8_t val);
uint8_t handle_ROLC(uint8_t val);
uint8_t handle_RORC(uint8_t val);
void handle_take_interrupt(int level);
const bool check_jump_condition(int param1);
const uint8_t get_PSW();
void set_PSW(uint8_t data);
};

View File

@ -0,0 +1,951 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/*************************************************************************************************************
Toshiba TLCS-870 Series MCUs
(src) prefix ops (e0 to e7 subtable)
(src) address depends on the first byte of the opcode
E0 (x)
E1 (PC+A)
E2 (DE)
E3 (HL)
E4 (HL+d)
E5 (HL+)
E6 (-HL)
note, in cases where the address is an immediate value, not a register (x) and (HL+d) the
immediate value is directly after the first byte of the opcode
*************************************************************************************************************/
#include "emu.h"
#include "tlcs870.h"
#include "tlcs870d.h"
#include "debugger.h"
// Main dispatch handlers for these
void tlcs870_device::decode()
{
const uint8_t opbyte0 = READ8();
switch (opbyte0)
{
case 0x00:
do_NOP(opbyte0); break;
case 0x01:
do_SWAP_A(opbyte0); break;
case 0x02:
do_MUL_W_A(opbyte0); break;
case 0x03:
do_DIV_WA_C(opbyte0); break;
case 0x04:
do_RETI(opbyte0); break;
case 0x05:
do_RET(opbyte0); break;
case 0x06:
do_POP_PSW(opbyte0); break;
case 0x07:
do_PUSH_PSW(opbyte0); break;
case 0x0a:
do_DAA_A(opbyte0); break;
case 0x0b:
do_DAS_A(opbyte0); break;
case 0x0c:
do_CLR_CF(opbyte0); break;
case 0x0d:
do_SET_CF(opbyte0); break;
case 0x0e:
do_CPL_CF(opbyte0); break;
case 0x0f:
do_LD_RBS_n(opbyte0); break;
case 0x10: case 0x11: case 0x12: case 0x13:
do_INC_rr(opbyte0); break;
case 0x14: case 0x15: case 0x16: case 0x17:
do_LD_rr_mn(opbyte0); break;
case 0x18: case 0x19: case 0x1a: case 0x1b:
do_DEC_rr(opbyte0); break;
case 0x1c:
do_SHLC_A(opbyte0); break;
case 0x1d:
do_SHRC_A(opbyte0); break;
case 0x1e:
do_ROLC_A(opbyte0); break;
case 0x1f:
do_RORC_A(opbyte0); break;
case 0x20:
do_INC_inx(opbyte0); break;
case 0x21:
do_INC_inHL(opbyte0); break;
case 0x22:
do_LD_A_inx(opbyte0); break;
case 0x23:
do_LD_A_inHL(opbyte0); break;
case 0x24:
do_LDW_inx_mn(opbyte0); break;
case 0x25:
do_LDW_inHL_mn(opbyte0); break;
case 0x26:
do_LD_inx_iny(opbyte0); break;
case 0x28:
do_DEC_inx(opbyte0); break;
case 0x29:
do_DEC_inHL(opbyte0); break;
case 0x2a:
do_LD_inx_A(opbyte0); break;
case 0x2b:
do_LD_inHL_A(opbyte0); break;
case 0x2c:
do_LD_inx_n(opbyte0); break;
case 0x2d:
do_LD_inHL_n(opbyte0); break;
case 0x2e:
do_CLR_inx(opbyte0); break;
case 0x2f:
do_CLR_inHL(opbyte0); break;
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
do_LD_r_n(opbyte0); break;
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
do_SET_inxbit(opbyte0); break;
case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
do_CLR_inxbit(opbyte0); break;
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
do_LD_A_r(opbyte0); break;
case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
do_LD_r_A(opbyte0); break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
do_INC_r(opbyte0); break;
case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
do_DEC_r(opbyte0); break;
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
do_ALUOP_A_n(opbyte0); break;
case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
do_ALUOP_A_inx(opbyte0); break;
case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f:
case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: case 0x9d: case 0x9e: case 0x9f:
do_JRS_T_a(opbyte0); break;
case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf:
do_JRS_F_a(opbyte0); break;
case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
do_CALLV_n(opbyte0); break;
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
do_JR_cc_a(opbyte0); break;
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
do_LD_CF_inxbit(opbyte0); break;
case 0xe0:
do_e0_opcode(opbyte0); break;
case 0xe1: case 0xe2: case 0xe3:
do_e1_to_e3_opcode(opbyte0); break;
case 0xe4:
do_e4_opcode(opbyte0); break;
case 0xe5: case 0xe6: case 0xe7:
do_e5_to_e7_opcode(opbyte0); break;
case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef:
do_regprefixtype_opcode(opbyte0); break;
case 0xf0:
do_f0_opcode(opbyte0); break;
case 0xf2: case 0xf3:
do_f2_to_f3_opcode(opbyte0); break;
case 0xf4:
do_f4_opcode(opbyte0); break;
case 0xf6: case 0xf7:
do_f6_to_f7_opcode(opbyte0); break;
case 0xfa:
do_LD_SP_mn(opbyte0); break;
case 0xfb:
do_JR_a(opbyte0); break;
case 0xfc:
do_CALL_mn(opbyte0); break;
case 0xfd:
do_CALLP_n(opbyte0); break;
case 0xfe:
do_JP_mn(opbyte0); break;
case 0xff:
do_ff_opcode(opbyte0); break;
default:
do_illegal(opbyte0); break;
}
}
void tlcs870_device::do_illegal(const uint8_t opbyte0)
{
logerror("illegal opcode %02x\n", opbyte0);
}
void tlcs870_device::do_NOP(const uint8_t opbyte0)
{
// NOP
}
void tlcs870_device::do_SWAP_A(const uint8_t opbyte0)
{
// SWAP A
handle_swap(REG_A);
}
void tlcs870_device::do_MUL_W_A(const uint8_t opbyte0)
{
// MUL W,A
handle_mul(REG_WA);
}
void tlcs870_device::do_DIV_WA_C(const uint8_t opbyte0)
{
// DIV WA,C
handle_div(REG_WA);
}
void tlcs870_device::do_RETI(const uint8_t opbyte0)
{
// RETI
// Return from maskable interrupt service (how does this differ from RETN?)
m_sp.d += 3;
m_addr = RM16(m_sp.d - 2);
set_PSW(RM8(m_sp.d - 1));
}
void tlcs870_device::do_RET(const uint8_t opbyte0)
{
// RET
m_sp.d += 2;
m_addr = RM16(m_sp.d - 1);
};
void tlcs870_device::do_POP_PSW(const uint8_t opbyte0)
{
// POP PSW
m_sp.d += 2;
const uint16_t val = RM16(m_sp.d - 1);
set_PSW(val);
}
void tlcs870_device::do_PUSH_PSW(const uint8_t opbyte0)
{
// PUSH PSW:
const uint16_t val = get_PSW();
WM16(m_sp.d - 1, val);
m_sp.d -= 2;
}
void tlcs870_device::do_DAA_A(const uint8_t opbyte0)
{
// DAA A
uint8_t val = get_reg8(REG_A);
val = handle_DAA(val);
set_reg8(REG_A, val);
}
void tlcs870_device::do_DAS_A(const uint8_t opbyte0)
{
// DAS A
uint8_t val = get_reg8(REG_A);
val = handle_DAS(val);
set_reg8(REG_A, val);
}
void tlcs870_device::do_CLR_CF(const uint8_t opbyte0)
{
// CLR CF
clear_CF();
set_JF();
}
void tlcs870_device::do_SET_CF(const uint8_t opbyte0)
{
// SET CF
set_CF();
clear_JF();
}
void tlcs870_device::do_CPL_CF(const uint8_t opbyte0)
{
// CPL CF
if (is_CF())
{
set_JF();
clear_CF();
}
else
{
clear_JF();
set_CF();
}
}
void tlcs870_device::do_LD_RBS_n(const uint8_t opbyte0) // register bank switching
{
// LD RBS,n
const uint8_t param = READ8();
m_RBS = param & 0x0f;
set_JF();
}
void tlcs870_device::do_INC_rr(const uint8_t opbyte0)
{
// INC rr
const int reg = opbyte0 & 3;
uint16_t temp = get_reg16(reg);
temp++;
set_reg16(reg, temp);
if (temp == 0x0000)
{
set_ZF();
set_JF();
}
else
{
// do we clear?
clear_ZF();
clear_JF();
}
}
void tlcs870_device::do_LD_rr_mn(const uint8_t opbyte0)
{
// LD rr,mn
const uint16_t val = READ16(); // 16-bit
set_reg16(opbyte0 & 3, val);
set_JF();
}
void tlcs870_device::do_DEC_rr(const uint8_t opbyte0)
{
// DEC rr
const int reg = opbyte0 & 3;
uint16_t temp = get_reg16(reg);
temp--;
set_reg16(reg, temp);
if (temp == 0xffff)
{
set_JF();
}
else
{
// do we clear?
clear_JF();
}
if (temp == 0x0000) // check
{
set_ZF();
}
else
{
set_ZF();
}
}
void tlcs870_device::do_SHLC_A(const uint8_t opbyte0)
{
// SHLC A
uint8_t val = get_reg8(REG_A);
val = handle_SHLC(val);
set_reg8(REG_A, val);
}
void tlcs870_device::do_SHRC_A(const uint8_t opbyte0)
{
// SHRC A
uint8_t val = get_reg8(REG_A);
val = handle_SHRC(val);
set_reg8(REG_A, val);
}
void tlcs870_device::do_ROLC_A(const uint8_t opbyte0)
{
// ROLC A
uint8_t val = get_reg8(REG_A);
val = handle_ROLC(val);
set_reg8(REG_A, val);
}
void tlcs870_device::do_RORC_A(const uint8_t opbyte0)
{
// RORC A
uint8_t val = get_reg8(REG_A);
val = handle_RORC(val);
set_reg8(REG_A, val);
}
void tlcs870_device::do_INC_inx(const uint8_t opbyte0)
{
// INC (x)
const uint16_t srcaddr = READ8();
uint8_t val = RM8(srcaddr);
val++;
if (val == 0)
{
set_ZF();
set_JF();
}
else
{
clear_ZF();
clear_JF();
}
// WRITE
WM8(srcaddr, val);
}
void tlcs870_device::do_INC_inHL(const uint8_t opbyte0)
{
// INC (HL)
const uint16_t addr = get_reg16(REG_HL);
uint8_t val = RM8(addr);
val++;
if (val == 0)
{
set_ZF();
set_JF();
}
else
{
clear_ZF();
clear_JF();
}
WM8(addr, val);
}
void tlcs870_device::do_LD_A_inx(const uint8_t opbyte0)
{
// LD A,(x)
const uint16_t srcaddr = READ8();
const uint8_t val = RM8(srcaddr);
set_reg8(REG_A, val);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
}
void tlcs870_device::do_LD_A_inHL(const uint8_t opbyte0)
{
// LD A,(HL)
const uint16_t srcaddr = get_reg16(REG_HL);
const uint8_t val = RM8(srcaddr);
set_reg8(REG_A, val);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
}
void tlcs870_device::do_LD_inx_iny(const uint8_t opbyte0)
{
// LD (x),(y)
const uint16_t srcaddr = READ8();
const uint16_t dstaddr = READ8();
const uint8_t val = RM8(srcaddr);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
WM8(dstaddr, val);
}
void tlcs870_device::do_DEC_inx(const uint8_t opbyte0)
{
// DEC (x)
const uint16_t addr = READ8();
uint8_t temp = RM8(addr);
temp--;
WM8(addr, temp);
if (temp == 0xff)
{
set_JF();
}
else
{
// do we clear?
clear_JF();
}
if (temp == 0x00)
{
set_ZF();
}
else
{
set_ZF();
}
}
void tlcs870_device::do_DEC_inHL(const uint8_t opbyte0)
{
// DEC (HL)
const uint16_t addr = get_reg16(REG_HL);
uint8_t temp = RM8(addr);
temp--;
WM8(addr, temp);
if (temp == 0xff)
{
set_JF();
}
else
{
// do we clear?
clear_JF();
}
if (temp == 0x00)
{
set_ZF();
}
else
{
set_ZF();
}
}
void tlcs870_device::do_LD_inx_A(const uint8_t opbyte0)
{
// LD (x),A
const uint16_t dstaddr = READ8();
const uint8_t val = get_reg8(REG_A);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
WM8(dstaddr, val);
}
void tlcs870_device::do_LD_inHL_A(const uint8_t opbyte0)
{
// LD (HL),A
const uint8_t val = get_reg8(REG_A);
set_JF();
const uint16_t addr = get_reg16(REG_HL);
WM8(addr, val);
}
void tlcs870_device::do_LD_inx_n(const uint8_t opbyte0)
{
// LD (x),n
const uint16_t dstaddr = READ8();
const uint8_t val = READ8();
set_JF();
WM8(dstaddr, val);
}
void tlcs870_device::do_LD_inHL_n(const uint8_t opbyte0)
{
// LD (HL),n
const uint8_t val = READ8();
const uint16_t addr = get_reg16(REG_HL);
set_JF();
WM8(addr, val);
}
void tlcs870_device::do_CLR_inx(const uint8_t opbyte0)
{
// CLR (x)
const uint16_t addr = READ8();
WM8(addr, 0);
set_JF();
}
void tlcs870_device::do_CLR_inHL(const uint8_t opbyte0)
{
// CLR (HL)
const uint16_t addr = get_reg16(REG_HL);
WM8(addr, 0);
set_JF();
}
void tlcs870_device::do_LD_r_n(const uint8_t opbyte0)
{
// LD r,n
const uint8_t param1 = opbyte0 & 7;
const uint8_t param2 = READ8();
set_reg8(param1, param2);
set_JF();
}
void tlcs870_device::do_SET_inxbit(const uint8_t opbyte0)
{
// SET (x).b
// 0100 0bbb xxxx xxxx
// (opbyte0 == 0x40) && (opval == 0x3a) is EI
const uint8_t srcaddr = READ8();
uint8_t val = RM8(srcaddr);
const uint8_t bitpos = opbyte0 & 0x7;
const int bitused = (1 << bitpos);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val |= bitused;
WM8(srcaddr, val);
}
void tlcs870_device::do_CLR_inxbit(const uint8_t opbyte0)
{
// CLR (x).b
// 0100 1bbb xxxx xxxx
// (opbyte0 == 0x48) && (opval == 0x3a) is DI
const uint8_t srcaddr = READ8();
uint8_t val = RM8(srcaddr);
const uint8_t bitpos = opbyte0 & 0x7;
const int bitused = (1 << bitpos);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val &= ~bitused;
WM8(srcaddr, val);
}
void tlcs870_device::do_LD_A_r(const uint8_t opbyte0)
{
// LD A,r
// 0101 0rrr
const uint8_t val = get_reg8(opbyte0 & 0x7);
set_reg8(REG_A, val);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
}
void tlcs870_device::do_LD_r_A(const uint8_t opbyte0)
{
// LD r,A
// 0101 1rrr
const uint8_t val = get_reg8(REG_A);
set_reg8(opbyte0 & 0x7, val);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
}
void tlcs870_device::do_INC_r(const uint8_t opbyte0)
{
// INC r
const int reg = opbyte0 & 7;
uint8_t temp = get_reg8(reg);
temp++;
set_reg8(reg, temp);
if (temp == 0x00)
{
set_ZF();
set_JF();
}
else
{
// do we clear?
clear_ZF();
clear_JF();
}
}
void tlcs870_device::do_DEC_r(const uint8_t opbyte0)
{
// DEC r
const int reg = opbyte0 & 7;
uint8_t temp = get_reg8(reg);
temp--;
set_reg8(reg, temp);
if (temp == 0xff)
{
set_JF();
}
else
{
// do we clear?
clear_JF();
}
if (temp == 0x00)
{
set_ZF();
}
else
{
set_ZF();
}
}
void tlcs870_device::do_JRS_T_a(const uint8_t opbyte0)
{
// JRS T,a
const int param1 = 6;
int val = opbyte0 & 0x1f;
if (val & 0x10) val -= 0x20;
const bool takejump = check_jump_condition(param1);
if (takejump)
{
m_addr = m_tmppc + 2 + val;
set_JF();
}
}
void tlcs870_device::do_JRS_F_a(const uint8_t opbyte0)
{
// JRS F,a
const int param1 = 7;
int val = opbyte0 & 0x1f;
if (val & 0x10) val -= 0x20;
const bool takejump = check_jump_condition(param1);
if (takejump)
{
m_addr = m_tmppc + 2 + val;
set_JF();
}
}
void tlcs870_device::do_CALLV_n(const uint8_t opbyte0)
{
// CALLV n
const uint16_t addr = 0xffc0 + ((opbyte0 & 0xf) * 2);
WM16(m_sp.d - 1, m_addr);
m_sp.d -= 2;
m_addr = addr;
}
void tlcs870_device::do_JR_cc_a(const uint8_t opbyte0)
{
// JR cc,a
const int param1 = opbyte0 & 0x7;
int val = READ8();
if (val & 0x80) val -= 0x100;
bool takejump = check_jump_condition(param1);
if (takejump)
{
m_addr = m_tmppc + 2 + val;
set_JF();
}
}
void tlcs870_device::do_LD_CF_inxbit(const uint8_t opbyte0)
{
// LD CF, (x).b aka TEST (x).b
const uint16_t srcaddr = READ8();
const uint8_t val = RM8(srcaddr);
const uint8_t bitpos = opbyte0 & 0x7;
const int bitused = (1 << bitpos);
uint8_t bit = val & bitused;
bit ? set_CF() : clear_CF();
// for this optype of operation ( LD CF, *.b ) the Jump Flag always ends up the inverse of the Carry Flag
bit ? clear_JF() : set_JF();
}
void tlcs870_device::do_LD_SP_mn(const uint8_t opbyte0)
{
// LD SP,mn
// Flags / Cycles 1--- / 3
const uint16_t param = READ16();
m_sp.d = param;
set_JF();
}
void tlcs870_device::do_JR_a(const uint8_t opbyte0)
{
// JR a
int val = READ8();
if (val & 0x80) val -= 0x100;
m_addr = m_tmppc + 2 + val;;
set_JF();
}
void tlcs870_device::do_CALL_mn(const uint8_t opbyte0)
{
// CALL mn
const uint16_t addr = READ16();
WM16(m_sp.d - 1, m_addr);
m_sp.d -= 2;
m_addr = addr;
}
void tlcs870_device::do_CALLP_n(const uint8_t opbyte0)
{
// CALLP n
const uint16_t addr = READ8() + 0xff00;
WM16(m_sp.d - 1, m_addr);
m_sp.d -= 2;
m_addr = addr;
}
void tlcs870_device::do_JP_mn(const uint8_t opbyte0)
{
// JP mn
const int param2 = READ16();
m_addr = param2;
set_JF();
}
void tlcs870_device::do_ff_opcode(const uint8_t opbyte0)
{
// SWI
handle_take_interrupt(0x0e);
}
/**********************************************************************************************************************/
// ALU Operations
/**********************************************************************************************************************/
void tlcs870_device::do_ALUOP_A_n(const uint8_t opbyte0)
{
// (ALU OP) A,n
// 0111 0000 nnnn nnnn ADDC A,n
// 0111 0001 nnnn nnnn ADD A,n
const int aluop = (opbyte0 & 0x7);
const uint8_t val = READ8();
const uint8_t result = do_alu(aluop, get_reg8(REG_A), val);
if (aluop != 0x07) // CMP doesn't write back
{
set_reg8(REG_A, result);
}
}
void tlcs870_device::do_ALUOP_A_inx(const uint8_t opbyte0)
{
// (ALU OP) A,(x)
// 0111 1000 nnnn nnnn ADDC A,(x)
// 0111 1001 nnnn nnnn ADD A,(x)
const int aluop = (opbyte0 & 0x7);
const uint16_t addr = READ8();
const uint8_t val = RM8(addr);
const uint8_t result = do_alu(aluop, get_reg8(REG_A), val);
if (aluop != 0x07) // CMP doesn't write back
{
set_reg8(REG_A, result);
}
}
/**********************************************************************************************************************/
// 16-bit loads
/**********************************************************************************************************************/
void tlcs870_device::do_LDW_inx_mn(const uint8_t opbyte0)
{
// LDW (x),mn
const uint16_t dstaddr = READ8();
const uint16_t val = READ16();
WM16(dstaddr, val);
set_JF(); // only JF changes
}
void tlcs870_device::do_LDW_inHL_mn(const uint8_t opbyte0)
{
// LDW (HL),mn
// m_op = LDW;
const uint16_t dstaddr = get_reg16(REG_HL);
const uint16_t val = READ16();
WM16(dstaddr, val);
set_JF(); // only JF changes
}

View File

@ -0,0 +1,127 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/*************************************************************************************************************
Toshiba TLCS-870 Series MCUs
(dst) prefix ops (f0 to f7 subtable)
(dst) address depends on the first byte of the opcode
F0 (x)
F1 invalid (would be (PC+A) based on the src table, check for undefined behavior?)
F2 (DE)
F3 (HL)
F4 (HL+d)
F5 invalid (would be (HL+) based on the src table, check for undefined behavior?)
F6 (-HL)
note, in cases where the address is an immediate value, not a register (x) and (HL+d) the
immediate value is directly after the first byte of the opcode
*************************************************************************************************************/
#include "emu.h"
#include "tlcs870.h"
#include "tlcs870d.h"
#include "debugger.h"
// Main dispatch handlers for these
void tlcs870_device::do_f0_opcode(const uint8_t opbyte0)
{
// 1111 0000 xxxx xxxx 0101 0rrr
// destination memory prefix (dst)
const uint16_t dstaddr = get_addr((opbyte0 & 0x7), READ8());
do_f0_to_f7_opcode(opbyte0, dstaddr);
}
void tlcs870_device::do_f2_to_f3_opcode(const uint8_t opbyte0)
{
// 0xf2: 1111 001p 0101 0rrr
// 0xf3: 1111 001p 0101 0rrr
// destination memory prefix (dst)
const uint16_t dstaddr = get_addr((opbyte0 & 0x7), 0);
do_f0_to_f7_opcode(opbyte0, dstaddr);
}
void tlcs870_device::do_f4_opcode(const uint8_t opbyte0)
{
// 0xf4: 1111 0100 dddd dddd 0101 0rrr
// destination memory prefix (dst)
const uint16_t dstaddr = get_addr((opbyte0 & 0x7), READ8());
do_f0_to_f7_opcode(opbyte0, dstaddr);
}
void tlcs870_device::do_f6_to_f7_opcode(const uint8_t opbyte0)
{
// 0xf6: 1110 0110 0101 0rrr
// 0xf7: 1111 0111 0101 0rrr
// destination memory prefix (dst)
const uint16_t dstaddr = get_addr((opbyte0 & 0x7), 0);
do_f0_to_f7_opcode(opbyte0, dstaddr);
}
// f0 - f7 use this table
// note, same table is shown as above in manual, there's no overlap between src/dest, but they're not compatible
void tlcs870_device::do_f0_to_f7_opcode(const uint8_t opbyte0, const uint16_t dstaddr)
{
const uint8_t opbyte1 = READ8();
switch (opbyte1)
{
case 0x10: case 0x11: case 0x12: case 0x13:
do_LD_indst_rr(opbyte0, opbyte1, dstaddr); break;
case 0x2c:
do_LD_indst_n(opbyte0, opbyte1, dstaddr); break;
case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57:
do_LD_indst_r(opbyte0, opbyte1, dstaddr); break;
default:
do_f0_to_f7_oprand_illegal_opcode(opbyte0, opbyte1, dstaddr); break;
}
}
// Actual handlers
/**********************************************************************************************************************/
// (16-bit)
/**********************************************************************************************************************/
void tlcs870_device::do_LD_indst_rr(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr)
{
// LD (dst),rr
// (dst) can only be (x) (pp) or (HL+d) ? not (HL+) or (-HL) ?
const uint16_t val = get_reg16(opbyte1 & 0x3);
WM16(dstaddr, val);
set_JF();
}
/**********************************************************************************************************************/
// (8-bit)
/**********************************************************************************************************************/
void tlcs870_device::do_LD_indst_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr)
{
// LD (dst),n
// (dst) can only be (DE), (HL+), (-HL), or (HL+d) because (x) and (HL) are redundant encodings?
const uint16_t n = READ8();
WM8(dstaddr, n);
set_JF();
}
void tlcs870_device::do_LD_indst_r(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr)
{
// LD (dst),r
const uint8_t reg = get_reg8(opbyte1 & 0x7);
WM8(dstaddr, reg);
set_JF();
}
void tlcs870_device::do_f0_to_f7_oprand_illegal_opcode(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t dstaddr)
{
logerror("illegal dst prefix opcode %02x %02x (dst addr %04x)\n", opbyte0, opbyte1, dstaddr);
}

View File

@ -0,0 +1,500 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/*************************************************************************************************************
Toshiba TLCS-870 Series MCUs
*************************************************************************************************************/
#include "emu.h"
#include "tlcs870.h"
#include "tlcs870d.h"
#include "debugger.h"
// General Helpers
const uint8_t tlcs870_device::get_reg8(const int reg)
{
return m_intram[((m_RBS & 0xf) * 8) + (reg & 0x7)];
}
void tlcs870_device::set_reg8(const int reg, uint8_t val)
{
m_intram[((m_RBS & 0xf) * 8) + (reg & 0x7)] = val;
}
const uint16_t tlcs870_device::get_reg16(const int reg)
{
uint16_t res = 0;
res |= get_reg8(((reg & 0x3) * 2) + 1) << 8;
res |= get_reg8(((reg & 0x3) * 2) + 0) << 0;
return res;
}
void tlcs870_device::set_reg16(const int reg, uint16_t val)
{
set_reg8(((reg & 0x3) * 2) + 1, (val & 0xff00) >> 8);
set_reg8(((reg & 0x3) * 2) + 0, (val & 0x00ff) >> 0);
}
const uint8_t tlcs870_device::get_PSW()
{
return (m_F & 0xf0) | (m_RBS & 0x0f);
}
void tlcs870_device::set_PSW(uint8_t data)
{
// used by the push/pop opcodes, flags can't be written by memory access
m_F = data & 0xf0;
m_RBS = data & 0xf0;
}
void tlcs870_device::handle_div(const int reg)
{
const uint16_t temp16 = get_reg16(reg);
const uint8_t temp8 = get_reg8(REG_C);
if (!temp8)
{
// divide by zero
set_CF();
// does the ZF change too?
}
else
{
const uint16_t tempres16 = temp16 / temp8;
const uint8_t tempres8 = temp16 % temp8;
const uint16_t tempfull = (tempres8 << 8) | (tempres16 & 0x00ff);
set_reg16(reg, tempfull);
if (tempres16 & 0xff00)
{
// result is also 'undefined' in this case
set_CF();
}
else
{
clear_CF();
}
if (!tempres8)
{
set_ZF();
set_JF();
}
else
{
clear_ZF();
clear_JF();
}
}
}
void tlcs870_device::handle_mul(const int reg)
{
const uint16_t temp16 = get_reg16(reg);
const uint16_t tempres = (temp16 & 0xff) * ((temp16 & 0xff00) >> 8);
set_reg16(reg, temp16);
if (!(tempres & 0xff00))
{
set_ZF();
set_JF();
}
else
{
clear_ZF();
clear_JF();
}
}
void tlcs870_device::handle_swap(const int reg)
{
uint8_t temp = get_reg8(reg);
temp = ((temp & 0x0f) << 4) | ((temp & 0xf0) >> 4);
set_reg8(reg, temp);
set_JF();
}
uint16_t tlcs870_device::get_addr(uint16_t opbyte0, uint16_t val)
{
uint16_t addr = 0x0000;
switch (opbyte0)
{
case ADDR_IN_IMM_X:
addr = val;
break;
case ADDR_IN_PC_PLUS_REG_A:
addr = m_tmppc + 2 + get_reg8(REG_A);
break;
case ADDR_IN_DE:
addr = get_reg16(REG_DE);
break;
case ADDR_IN_HL:
addr = get_reg16(REG_HL);
break;
case ADDR_IN_HL_PLUS_IMM_D:
addr = get_reg16(REG_HL) + val;
break;
case ADDR_IN_HL_PLUS_REG_C:
addr = get_reg16(REG_HL) + get_reg8(REG_C);
break;
case ADDR_IN_HLINC:
{
uint16_t tmpHL = get_reg16(REG_HL);
addr = tmpHL;
tmpHL++;
set_reg16(REG_HL, tmpHL);
break;
}
case ADDR_IN_DECHL:
{
uint16_t tmpHL = get_reg16(REG_HL);
tmpHL--;
set_reg16(REG_HL, tmpHL);
addr = tmpHL;
break;
}
}
return addr;
}
const bool tlcs870_device::check_jump_condition(int param1)
{
bool takejump = true;
switch (param1)
{
case COND_EQ_Z:
if (is_ZF() == 1) takejump = true;
else takejump = false;
break;
case COND_NE_NZ:
if (is_ZF() == 0) takejump = true;
else takejump = false;
break;
case COND_LT_CS:
if (is_CF() == 1) takejump = true;
else takejump = false;
break;
case COND_GE_CC:
if (is_CF() == 0) takejump = true;
else takejump = false;
break;
case COND_LE:
if ((is_CF() || is_ZF()) == 1) takejump = true;
else takejump = false;
break;
case COND_GT:
if ((is_CF() || is_ZF()) == 0) takejump = true;
else takejump = false;
break;
case COND_T:
if (is_JF() == 1) takejump = true;
else takejump = false;
break;
case COND_F:
if (is_JF() == 0) takejump = true;
else takejump = false;
break;
}
return takejump;
}
uint16_t tlcs870_device::do_alu(int op, uint16_t param1, uint16_t param2)
{
uint16_t result = 0x00;
// TODO: flags
switch (op)
{
case 0x0: // ADDC
result = param1 + param2;
result += is_CF();
break;
case 0x1: // ADD
result = param1 + param2;
break;
case 0x2: // SUBB
result = param1 - param2;
result -= is_CF();
break;
case 0x3: // SUB
result = param1 - param2;
break;
case 0x4: // AND
result = param1 & param2;
break;
case 0x5: // XOR
result = param1 ^ param2;
break;
case 0x6: // OR
result = param1 | param2;
break;
case 0x7: // CMP
if (param1 < param2)
{
set_CF();
}
else
{
clear_CF();
}
break;
}
return result;
}
uint8_t tlcs870_device::handle_SHLC(uint8_t val)
{
if (val & 0x80)
{
set_CF();
}
else
{
clear_CF();
}
val = (val << 1);
// JF gets set to CF
if (is_CF())
{
set_JF();
}
else
{
clear_JF();
}
if (val == 0)
{
set_ZF();
}
else
{
clear_ZF();
}
return val;
}
uint8_t tlcs870_device::handle_SHRC(uint8_t val)
{
if (val & 0x01)
{
set_CF();
}
else
{
clear_CF();
}
val = (val >> 1);
// JF gets set to CF
if (is_CF())
{
set_JF();
}
else
{
clear_JF();
}
if (val == 0)
{
set_ZF();
}
else
{
clear_ZF();
}
return val;
}
uint8_t tlcs870_device::handle_DAS(uint8_t val)
{
if (((val & 0x0f) > 9) || (is_HF() == 1))
{
val = val - 0x06;
set_HF();
}
else
{
clear_HF();
}
if ((val > 0x9f) || (is_CF() == 1))
{
val = val - 0x60;
set_CF();
}
else
{
clear_CF();
}
return val;
}
uint8_t tlcs870_device::handle_DAA(uint8_t val)
{
if (((val & 0x0f) > 9) || (is_HF() == 1))
{
val = val + 0x06;
set_HF();
}
else
{
clear_HF();
}
if ((val > 0x9f) || (is_CF() == 1))
{
val = val + 0x60;
set_CF();
}
else
{
clear_CF();
}
return val;
}
uint8_t tlcs870_device::handle_ROLC(uint8_t val)
{
const int tempcarry = is_CF();
if (val & 0x80)
{
set_CF();
}
else
{
clear_CF();
}
val = (val << 1) | tempcarry;
// JF gets set to CF
if (is_CF())
{
set_JF();
}
else
{
clear_JF();
}
if (val == 0)
{
set_ZF();
}
else
{
clear_ZF();
}
return val;
}
uint8_t tlcs870_device::handle_RORC(uint8_t val)
{
const int tempcarry = (is_CF()) << 7;
if (val & 0x01)
{
set_CF();
}
else
{
clear_CF();
}
val = (val >> 1) | tempcarry;
// JF gets set to CF
if (is_CF())
{
set_JF();
}
else
{
clear_JF();
}
if (val == 0)
{
set_ZF();
}
else
{
clear_ZF();
}
return val;
}
/*
(Priority Low - 15)
FFE0 INT5 (External Interrupt 5)
FFE2 INTTC2 (16-bit TC2 Interrupt)
FFE4 INTSIO2 (Serial Interface 2 Interrupt)
FFE6 INT4 (External Interrupt 4)
FFE8 INT3 (External Interrupt 3)
FFEA INTTC4 (8-bit TC4 Interrupt)
FFEC INTSIO1 (Serial Interface 1 Interrupt)
FFEE INTTC3 (8-bit TC3 Interrupt)
FFF0 INT2 (External Interrupt 2)
FFF2 INTTBT (Time Base Timer Interrupt)
FFF4 INT1 (External Interrupt 1)
FFF6 INTTC1 (16-bit TC1 Interrupt)
FFF8 INT0 (External Interrupt 0)
FFFA INTWDT (Watchdog Timer Interrupt)
FFFC INTSW (Software Interrupt)
FFFE RESET (Reset Vector)
(Priority High - 0)
*/
void tlcs870_device::handle_take_interrupt(int level)
{
WM8(m_sp.d - 1, get_PSW());
WM16(m_sp.d - 2, m_addr);
m_sp.d -= 3;
m_addr = RM16(0xffe0 + ((level &0xf)*2));
}

View File

@ -0,0 +1,760 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/*************************************************************************************************************
Toshiba TLCS-870 Series MCUs
(reg) prefix ops (e8 to ef subtable)
(reg) implies one of the follow registers
(8-bit mode operations)
E8 A
E9 W
EA C
EB B
EC E
ED D
EE L
EF H
(16-bit mode operations)
E8 invalid
E9 invalid
EA invalid
EB invalid
EC WA
ED BC
EE DE
EF HL
(RETN operation - special)
E8 RETN
E9-EF invalid
*************************************************************************************************************/
#include "emu.h"
#include "tlcs870.h"
#include "tlcs870d.h"
#include "debugger.h"
// Main dispatch handlers for these
void tlcs870_device::do_regprefixtype_opcode(const uint8_t opbyte0)
{
// register prefix: g/gg
uint8_t opbyte1 = READ8();
switch (opbyte1)
{
case 0x01:
do_SWAP_g(opbyte0, opbyte1); break;
case 0x02:
do_MUL_gg(opbyte0, opbyte1); break;
case 0x03:
do_DIV_gg_C(opbyte0, opbyte1); break;
case 0x04:
do_RETN(opbyte0, opbyte1); break;
case 0x06:
do_POP_gg(opbyte0, opbyte1); break;
case 0x07:
do_PUSH_gg(opbyte0, opbyte1); break;
case 0x0a:
do_DAA_g(opbyte0, opbyte1); break;
case 0x0b:
do_DAS_g(opbyte0, opbyte1); break;
case 0x10: case 0x11: case 0x12: case 0x13:
do_XCH_rr_gg(opbyte0, opbyte1); break;
case 0x14: case 0x15: case 0x16: case 0x17:
do_LD_rr_gg(opbyte0, opbyte1); break;
case 0x1c:
do_SHLC_g(opbyte0, opbyte1); break;
case 0x1d:
do_SHRC_g(opbyte0, opbyte1); break;
case 0x1e:
do_ROLC_g(opbyte0, opbyte1); break;
case 0x1f:
do_RORC_g(opbyte0, opbyte1); break;
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
do_ALUOP_WA_gg(opbyte0, opbyte1); break;
case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
do_ALUOP_gg_mn(opbyte0, opbyte1); break;
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
do_SET_gbit(opbyte0, opbyte1); break;
case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
do_CLR_gbit(opbyte0, opbyte1); break;
case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
do_LD_r_g(opbyte0, opbyte1); break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
do_ALUOP_A_g(opbyte0, opbyte1); break;
case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f:
do_ALUOP_g_A(opbyte0, opbyte1); break;
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
do_ALUOP_g_n(opbyte0, opbyte1); break;
case 0x82: case 0x83:
do_SET_inppbit(opbyte0, opbyte1); break;
case 0x8a: case 0x8b:
do_CLR_inppbit(opbyte0, opbyte1); break;
case 0x92: case 0x93:
do_CPL_inppbit(opbyte0, opbyte1); break;
case 0x9a: case 0x9b:
do_LD_inppbit_CF(opbyte0, opbyte1); break;
case 0x9e: case 0x9f:
do_LD_CF_inppbit(opbyte0, opbyte1); break;
case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
do_XCH_r_g(opbyte0, opbyte1); break;
case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
do_CPL_gbit(opbyte0, opbyte1); break;
case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
do_LD_gbit_CF(opbyte0, opbyte1); break;
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
do_XOR_CF_gbit(opbyte0, opbyte1); break;
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
do_LD_CF_gbit(opbyte0, opbyte1); break;
case 0xfa:
do_LD_SP_gg(opbyte0, opbyte1); break;
case 0xfb:
do_LD_gg_SP(opbyte0, opbyte1); break;
case 0xfc:
do_CALL_gg(opbyte0, opbyte1); break;
case 0xfe:
do_JP_gg(opbyte0, opbyte1); break;
default:
do_regprefixtype_oprand_illegal(opbyte0, opbyte1); break;
}
}
// Actual handlers
/**********************************************************************************************************************/
// (Special)
/**********************************************************************************************************************/
void tlcs870_device::do_regprefixtype_oprand_illegal(const uint8_t opbyte0, const uint8_t opbyte1)
{
logerror("illegal reg prefix opcode %02x %02x\n", opbyte0, opbyte1);
}
void tlcs870_device::do_RETN(const uint8_t opbyte0, const uint8_t opbyte1)
{
// with E8 only
if (opbyte0 == 0xe8)
{
// RETN
// Return from non-maskable interrupt service (how does this differ from RETI?)
m_sp.d += 3;
m_addr = RM16(m_sp.d - 2);
set_PSW(RM8(m_sp.d - 1));
}
else
{
do_regprefixtype_oprand_illegal(opbyte0, opbyte1);
}
}
/**********************************************************************************************************************/
// (8-bit)
/**********************************************************************************************************************/
void tlcs870_device::do_SWAP_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
// SWAP g
const uint8_t reg = opbyte0 & 0x7;
handle_swap(reg);
}
void tlcs870_device::do_DAA_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
// DAA g
// 1110 1ggg 0000 1010
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_DAA(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_DAS_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
// DAS g
// 1110 1ggg 0000 1011
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_DAS(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_SHLC_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
// SHLC g
// Logical Shift Left with Carry Flag
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_SHLC(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_SHRC_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
// SHRC g
// Logical Shift Right with Carry Flag
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_SHRC(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_ROLC_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
// ROLC g
// Rotate Left through Carry flag
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_ROLC(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_RORC_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
// RORC g
// Rotate Right through Carry flag
uint8_t val = get_reg8(opbyte0 & 0x7);
val = handle_RORC(val);
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_LD_r_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
// LD r,g
// 1110 1ggg 0101 1rrr
const uint8_t val = get_reg8(opbyte0 & 0x7);
set_reg8(opbyte1 & 0x7, val);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
}
void tlcs870_device::do_XCH_r_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
// XCH r,g
// 1110 1ggg 1010 1rrr
const uint8_t val = get_reg8(opbyte0 & 0x7);
const uint8_t r = get_reg8(opbyte1 & 0x7);
set_reg8(opbyte1 & 0x7, val);
set_reg8(opbyte0 & 0x7, r);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
}
/**********************************************************************************************************************/
// (ALU handlers)
/**********************************************************************************************************************/
void tlcs870_device::do_ALUOP_A_g(const uint8_t opbyte0, const uint8_t opbyte1)
{
// (ALU OP) A,g
/*
1110 1ggg 0110 0000 ADDC A,g
1110 1ggg 0110 0001 ADD A,g
1110 1ggg 0110 0010 SUBB A,g
1110 1ggg 0110 0011 SUB A,g
1110 1ggg 0110 0100 AND A,g
1110 1ggg 0110 0101 XOR A,g
1110 1ggg 0110 0110 OR A,g
1110 1ggg 0110 0111 CMP A,g
*/
const int aluop = (opbyte1 & 0x7);
const uint8_t result = do_alu(aluop, get_reg8(REG_A), get_reg8(opbyte0 & 0x7));
if (aluop != 0x07) // CMP doesn't write back
{
set_reg8(REG_A, result);
}
}
void tlcs870_device::do_ALUOP_g_A(const uint8_t opbyte0, const uint8_t opbyte1)
{
// (ALU OP) g,A
/*
1110 1ggg 0110 1000 ADDC A,g
1110 1ggg 0110 1001 ADD A,g
1110 1ggg 0110 1010 SUBB A,g
1110 1ggg 0110 1011 SUB A,g
1110 1ggg 0110 1100 AND A,g
1110 1ggg 0110 1101 XOR A,g
1110 1ggg 0110 1110 OR A,g
1110 1ggg 0110 1111 CMP A,g
*/
const int aluop = (opbyte1 & 0x7);
const uint8_t result = do_alu(aluop, get_reg8(opbyte0 & 0x7), get_reg8(REG_A));
if (aluop != 0x07) // CMP doesn't write back
{
set_reg8(opbyte0 & 0x7, result);
}
}
void tlcs870_device::do_ALUOP_g_n(const uint8_t opbyte0, const uint8_t opbyte1)
{
// (ALU OP) g,n
const int aluop = (opbyte1 & 0x7);
const uint8_t n = READ8();
const uint8_t result = do_alu(aluop, get_reg8(opbyte0 & 0x7), n);
if (aluop != 0x07) // CMP doesn't write back
{
set_reg8(opbyte0 & 0x7, result);
}
}
/**********************************************************************************************************************/
// (16-bit ALU handlers)
/**********************************************************************************************************************/
void tlcs870_device::do_ALUOP_WA_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
// (ALU OP) WA,gg
/*
1110 10gg 0011 0000 ADDC WA,gg
1110 10gg 0011 0001 ADD WA,gg
1110 10gg 0011 0010 SUBB WA,gg
1110 10gg 0011 0011 SUB WA,gg
1110 10gg 0011 0100 AND WA,gg
1110 10gg 0011 0101 XOR WA,gg
1110 10gg 0011 0110 OR WA,gg
1110 10gg 0011 0111 CMP WA,gg
*/
const int aluop = (opbyte1 & 0x7);
const uint16_t result = do_alu(aluop, get_reg16(REG_WA), get_reg16(opbyte0 & 0x3));
if (aluop != 0x07) // CMP doesn't write back
{
set_reg16(REG_WA, result);
}
}
void tlcs870_device::do_ALUOP_gg_mn(const uint8_t opbyte0, const uint8_t opbyte1)
{
// (ALU OP) gg,mn
const int aluop = (opbyte1 & 0x7);
const uint16_t mn = READ16();
const uint16_t result = do_alu(aluop, get_reg16(opbyte0 & 0x3), mn);
if (aluop != 0x07) // CMP doesn't write back
{
set_reg16(opbyte0 & 0x3, result);
}
}
/**********************************************************************************************************************/
// bit accesses
/**********************************************************************************************************************/
// ops using (pp).g
void tlcs870_device::do_SET_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
// SET (pp).g
const uint8_t bitpos = opbyte0 & 7;
const uint8_t bitused = 1 << bitpos;
const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
uint8_t val = RM8(addr);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val |= bitused;
WM8(addr, val);
}
void tlcs870_device::do_CLR_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
// CLR (pp).g
const uint8_t bitpos = opbyte0 & 7;
const uint8_t bitused = 1 << bitpos;
const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
uint8_t val = RM8(addr);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val &= ~bitused;
WM8(addr, val);
}
void tlcs870_device::do_CPL_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
// CPL (pp).g
const uint8_t bitpos = opbyte0 & 7;
const uint8_t bitused = 1 << bitpos;
const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
uint8_t val = RM8(addr);
uint8_t bit = val & bitused;
if (bit) // if the bit is set, clear the zero/jump flags and unset the bit
{
clear_ZF();
clear_JF();
val &= ~bitused;
}
else // if the bit isn't set, set the zero/jump flags and set the bit
{
set_ZF();
set_JF();
val |= bitused;
}
WM8(addr, val);
}
void tlcs870_device::do_LD_inppbit_CF(const uint8_t opbyte0, const uint8_t opbyte1)
{
// LD (pp).g,CF
const uint8_t bitpos = opbyte0 & 7;
const uint8_t bitused = 1 << bitpos;
const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
uint8_t val = RM8(addr);
if (is_CF()) // if carry flag is set, set the bit in val
{
val |= bitused;
}
else // if carry flag isn't set, clear the bit in val
{
val &= ~bitused;
}
// for this optype of operation ( LD *.b, CF ) the Jump Flag always ends up being 1
set_JF();
WM8(addr, val);
}
void tlcs870_device::do_LD_CF_inppbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
// LD CF,(pp).g aka TEST (pp).g
// 1110 1ggg 1001 111p
const uint8_t bitpos = opbyte0 & 7;
const uint8_t bitused = 1 << bitpos;
const uint16_t addr = get_reg16((opbyte1 & 1) + 2); // DE or HL
const uint8_t val = RM8(addr);
const uint8_t bit = val & bitused;
bit ? set_CF() : clear_CF();
// for this optype of operation ( LD CF, *.b ) the Jump Flag always ends up the inverse of the Carry Flag
bit ? clear_JF() : set_JF();
}
// ops using g.b
void tlcs870_device::do_SET_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
// SET g.b
// 1110 1ggg 0100 0bbb
uint8_t val = get_reg8(opbyte0 & 0x7);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val |= bitused;
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_CLR_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
// CLR g.b
// 1110 1ggg 0100 1bbb
uint8_t val = get_reg8(opbyte0 & 0x7);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val &= ~bitused;
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_CPL_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
// CPL g.b
// 1110 1ggg 1100 0bbb
uint8_t val = get_reg8(opbyte0 & 0x7);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
uint8_t bit = val & bitused;
if (bit) // if the bit is set, clear the zero/jump flags and unset the bit
{
clear_ZF();
clear_JF();
val &= ~bitused;
}
else // if the bit isn't set, set the zero/jump flags and set the bit
{
set_ZF();
set_JF();
val |= bitused;
}
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_LD_gbit_CF(const uint8_t opbyte0, const uint8_t opbyte1)
{
// LD g.b,CF
// m_op = LD; // Flags / Cycles 1--- / 2
//m_flagsaffected |= FLAG_J;
uint8_t val = get_reg8(opbyte0 & 0x7);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
if (is_CF()) // if carry flag is set, set the bit in val
{
val |= bitused;
}
else // if carry flag isn't set, clear the bit in val
{
val &= ~bitused;
}
// for this optype of operation ( LD *.b, CF ) the Jump Flag always ends up being 1
set_JF();
set_reg8(opbyte0 & 0x7, val);
}
void tlcs870_device::do_XOR_CF_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
// XOR CF,g.b
const uint8_t bitpos = opbyte1 & 0x7;
const uint8_t bitused = 1 << bitpos;
const uint8_t g = get_reg8(opbyte0 & 0x7);
const uint8_t bit = g & bitused;
if (is_CF())
{
if (bit)
{
clear_CF();
}
else
{
set_CF();
}
}
else
{
if (bit)
{
set_CF();
}
else
{
clear_CF();
}
}
// JF ends up being whatever the new value of CF is
if (is_CF())
set_JF();
else
clear_JF();
}
void tlcs870_device::do_LD_CF_gbit(const uint8_t opbyte0, const uint8_t opbyte1)
{
// LD CF,g.b aka TEST g.b
const uint8_t bitpos = opbyte1 & 0x7;
const uint8_t bitused = 1 << bitpos;
const uint8_t g = get_reg8(opbyte0 & 0x7);
const uint8_t bit = g & bitused;
bit ? set_CF() : clear_CF();
// for this optype of operation ( LD CF, *.b ) the Jump Flag always ends up the inverse of the Carry Flag
bit ? clear_JF() : set_JF();
}
/**********************************************************************************************************************/
// 16-bit
/**********************************************************************************************************************/
void tlcs870_device::do_MUL_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
// MUL ggH, ggL (odd syntax, basically MUL gg)
const uint8_t reg = opbyte0 & 0x3; // opbyte0 & 4 = invalid?
handle_mul(reg); // flag changes in handler
}
void tlcs870_device::do_DIV_gg_C(const uint8_t opbyte0, const uint8_t opbyte1)
{
// DIV gg,C
// (DIV BC,C is presumably an illegal / undefined result)
// (DIV WA,C is a redundant encoding)
const uint8_t reg = opbyte0 & 0x3; // opbyte0 & 4 = invalid?
handle_div(reg); // flag changes in handler
}
void tlcs870_device::do_POP_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
// POP gg
m_sp.d += 2;
const uint16_t val = RM16(m_sp.d - 1);
set_reg16(opbyte0 & 3, val);
// no flag changes
}
void tlcs870_device::do_PUSH_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
// PUSH gg
const uint16_t val = get_reg16(opbyte0 & 3);
WM16(m_sp.d - 1, val);
m_sp.d -= 2;
// no flag changes
}
void tlcs870_device::do_LD_SP_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
// LD SP,gg
m_sp.d = get_reg16(opbyte0 & 0x3);
set_JF(); // no other flag changes for this type of LD
}
void tlcs870_device::do_LD_gg_SP(const uint8_t opbyte0, const uint8_t opbyte1)
{
// LD gg,SP
set_reg16(opbyte0 & 0x3, m_sp.d);
set_JF(); // no other flag changes for this type of LD
}
void tlcs870_device::do_LD_rr_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
// LD rr,gg
const uint16_t gg = get_reg16(opbyte0 & 0x3);
set_reg16(opbyte1 & 0x3, gg);
set_JF(); // no other flag changes for this type of LD
}
void tlcs870_device::do_XCH_rr_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
// XCH rr,gg
const uint16_t gg = get_reg16(opbyte0 & 0x3);
const uint16_t rr = get_reg16(opbyte1 & 0x3);
set_reg16(opbyte1 & 0x3, gg);
set_reg16(opbyte0 & 0x3, rr);
// flags not done
}
void tlcs870_device::do_CALL_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
// CALL gg
const uint16_t val = get_reg16(opbyte0 & 3);
WM16(m_sp.d - 1, m_addr);
m_sp.d -= 2;
m_addr = val;
// no flag changes on call
}
void tlcs870_device::do_JP_gg(const uint8_t opbyte0, const uint8_t opbyte1)
{
// JP gg
const uint16_t val = get_reg16(opbyte0 & 3);
m_addr = val;
set_JF();
}

View File

@ -0,0 +1,548 @@
// license:BSD-3-Clause
// copyright-holders:David Haywood
/*************************************************************************************************************
Toshiba TLCS-870 Series MCUs
(src) prefix ops (e0 to e7 subtable)
(src) address depends on the first byte of the opcode
E0 (x)
E1 (PC+A)
E2 (DE)
E3 (HL)
E4 (HL+d)
E5 (HL+C)
E6 (HL+)
E7 (-HL)
note, in cases where the address is an immediate value, not a register (x) and (HL+d) the
immediate value is directly after the first byte of the opcode
*************************************************************************************************************/
#include "emu.h"
#include "tlcs870.h"
#include "tlcs870d.h"
#include "debugger.h"
// Main dispatch handlers for these
void tlcs870_device::do_e0_opcode(const uint8_t opbyte0)
{
const uint16_t srcaddr = get_addr((opbyte0 & 0x7), READ8());
do_e0_to_e7_opcode(opbyte0, srcaddr);
}
void tlcs870_device::do_e1_to_e3_opcode(const uint8_t opbyte0)
{
const uint16_t srcaddr = get_addr((opbyte0 & 0x7), 0);
do_e0_to_e7_opcode(opbyte0, srcaddr);
}
void tlcs870_device::do_e4_opcode(const uint8_t opbyte0)
{
const uint16_t srcaddr = get_addr((opbyte0 & 0x7), READ8());
do_e0_to_e7_opcode(opbyte0, srcaddr);
}
void tlcs870_device::do_e5_to_e7_opcode(const uint8_t opbyte0)
{
const uint16_t srcaddr = get_addr((opbyte0 & 0x7), 0);
do_e0_to_e7_opcode(opbyte0, srcaddr);
}
// e0 - e7 use this table
void tlcs870_device::do_e0_to_e7_opcode(uint8_t opbyte0, uint16_t srcaddr)
{
const uint8_t opbyte1 = READ8();
switch (opbyte1)
{
case 0x08:
do_ROLD_A_insrc(opbyte0, opbyte1, srcaddr); break;
case 0x09:
do_RORD_A_insrc(opbyte0, opbyte1, srcaddr); break;
case 0x14: case 0x15: case 0x16: case 0x17:
do_LD_rr_insrc(opbyte0, opbyte1, srcaddr); break;
case 0x20:
do_INC_insrc(opbyte0, opbyte1, srcaddr); break;
case 0x26:
do_LD_inx_insrc(opbyte0, opbyte1, srcaddr); break;
case 0x27:
do_LD_inHL_insrc(opbyte0, opbyte1, srcaddr); break;
case 0x28:
do_DEC_insrc(opbyte0, opbyte1, srcaddr); break;
case 0x2f:
do_MCMP_insrc_n(opbyte0, opbyte1, srcaddr); break;
case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47:
do_SET_insrcbit(opbyte0, opbyte1, srcaddr); break;
case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f:
do_CLR_insrcbit(opbyte0, opbyte1, srcaddr); break;
case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f:
do_LD_r_insrc(opbyte0, opbyte1, srcaddr); break;
case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67:
do_ALUOP_insrc_inHL(opbyte0, opbyte1, srcaddr); break;
case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77:
do_ALUOP_insrc_n(opbyte0, opbyte1, srcaddr); break;
case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f:
do_ALUOP_A_insrc(opbyte0, opbyte1, srcaddr); break;
case 0xa8: case 0xa9: case 0xaa: case 0xab: case 0xac: case 0xad: case 0xae: case 0xaf:
do_XCH_r_insrc(opbyte0, opbyte1, srcaddr); break;
case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7:
do_CPL_insrcbit(opbyte0, opbyte1, srcaddr); break;
case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf:
do_LD_insrcbit_CF(opbyte0, opbyte1, srcaddr); break;
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
do_XOR_CF_insrcbit(opbyte0, opbyte1, srcaddr); break;
case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
do_LD_CF_insrcbit(opbyte0, opbyte1, srcaddr); break;
case 0xfc:
do_CALL_insrc(opbyte0, opbyte1, srcaddr); break;
case 0xfe:
do_JP_insrc(opbyte0, opbyte1, srcaddr); break;
default:
do_e0_to_e7_oprand_illegal(opbyte0, opbyte1, srcaddr); break;
}
}
// Actual handlers
void tlcs870_device::do_e0_to_e7_oprand_illegal(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
logerror("illegal src prefix opcode %02x %02x (src addr %04x)\n", opbyte0, opbyte1, srcaddr);
}
/**********************************************************************************************************************/
// (16-bit)
/**********************************************************************************************************************/
void tlcs870_device::do_LD_rr_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// LD rr, (src)
const uint16_t val = RM16(srcaddr);
set_reg16(opbyte1 & 0x3, val);
set_JF();
}
/**********************************************************************************************************************/
// (8-bit)
/**********************************************************************************************************************/
void tlcs870_device::do_INC_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// INC (src)
uint8_t val = RM8(srcaddr);
val++;
if (val == 0)
{
set_ZF();
set_JF();
}
else
{
clear_ZF();
clear_JF();
}
WM8(srcaddr, val);
}
void tlcs870_device::do_DEC_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// DEC (src)
uint8_t val = RM8(srcaddr);
val--;
if (val == 0xff)
{
set_JF();
}
else
{
// do we clear?
clear_JF();
}
if (val == 0x00) // check
{
set_ZF();
}
else
{
set_ZF();
}
WM8(srcaddr, val);
}
void tlcs870_device::do_ROLD_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// ROLD A,(src)
// 12-bit left rotation using lower 4 bits of REG_A and content of (src)
const uint8_t val = RM8(srcaddr);
const uint8_t reg = get_reg8(REG_A);
uint8_t tempval = (val & 0x0f) << 4;
tempval |= reg & 0x0f;
const uint8_t tempa = (reg & 0xf0) | (val & 0xf0) >> 4;
set_reg8(REG_A, tempa);
WM8(srcaddr, tempval);
// TODO: flags
}
void tlcs870_device::do_RORD_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// RORD A,(src)
// 12-bit right rotation using lower 4 bits of REG_A and content of (src)
const uint8_t val = RM8(srcaddr);
const uint8_t reg = get_reg8(REG_A);
uint8_t tempval = (val & 0xf0) >> 4;
tempval |= ((reg & 0x0f) << 4);
const uint8_t tempa = (reg & 0xf0) | (val & 0x0f);
set_reg8(REG_A, tempa);
WM8(srcaddr, tempval);
// TODO: flags
}
void tlcs870_device::do_LD_inx_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// LD (x),(src)
// invalid if (src) is also (x) ? (not specified)
const uint16_t x = READ8(); // get address x
const uint8_t val = RM8(srcaddr);
WM8(x, val);
set_JF();
// z-flag is undefined, check real behavior
}
void tlcs870_device::do_LD_inHL_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// LD (HL),(src)
const uint8_t val = RM8(srcaddr);
const uint16_t dstaddr = get_reg16(REG_HL);
WM8(dstaddr, val);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
}
void tlcs870_device::do_LD_r_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// LD r, (src)
const uint8_t val = RM8(srcaddr);
set_reg8(opbyte1 & 0x7, val);
set_JF();
if (val == 0x00) set_ZF();
else clear_ZF();
}
void tlcs870_device::do_MCMP_insrc_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// MCMP (src), n
const uint8_t n = READ8();
const uint8_t val = RM8(srcaddr);
const uint8_t temp = n & val;
const uint8_t a = get_reg8(REG_A);
// ZF and JF set conditionally
if (a == temp)
{
// if n & val is equal to accumulator
set_ZF();
set_JF();
}
else
{
clear_ZF();
clear_JF();
}
// C gets set conditionally (like CMP?)
if (a < temp)
{
set_CF();
}
else
{
clear_CF();
}
// apparently H gets set conditionally too? (like CMP?)
}
void tlcs870_device::do_XCH_r_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// XCH r,(src)
const uint8_t val = RM8(srcaddr);
const uint8_t temp = get_reg8(opbyte1 & 0x7);
WM8(srcaddr, temp);
set_reg8(opbyte1 & 0x7, val);
set_JF();
if (val == 0)
{
set_ZF();
}
else
{
// do we clear?
clear_ZF();
}
}
/**********************************************************************************************************************/
// ALU Operations
/**********************************************************************************************************************/
void tlcs870_device::do_ALUOP_insrc_inHL(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// (ALU OP) (src), (HL)
const int aluop = (opbyte1 & 0x7);
const uint8_t val = RM8(srcaddr);
const uint16_t HL = get_reg16(REG_HL);
const uint8_t result = do_alu(aluop, val, RM8(HL));
if (aluop != 0x07) // CMP doesn't write back
{
WM8(srcaddr, result);
}
}
void tlcs870_device::do_ALUOP_insrc_n(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// (ALU OP) (src), n
const uint8_t n = READ8();
const int aluop = (opbyte1 & 0x7);
const uint8_t val = RM8(srcaddr);
const uint8_t result = do_alu(aluop, val, n);
if (aluop != 0x07) // CMP doesn't write back
{
WM8(srcaddr, result);
}
}
void tlcs870_device::do_ALUOP_A_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// (ALU OP) A, (src)
const int aluop = (opbyte1 & 0x7);
const uint8_t val = RM8(srcaddr);
const uint8_t result = do_alu(aluop, get_reg8(REG_A), val);
if (aluop != 0x07) // CMP doesn't write back
{
set_reg8(REG_A, result);
}
}
/**********************************************************************************************************************/
// jumps / calls
/**********************************************************************************************************************/
void tlcs870_device::do_CALL_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// CALL (src)
const uint16_t val = RM16(srcaddr);
WM16(m_sp.d - 1, m_addr);
m_sp.d -= 2;
m_addr = val;
// no flag changes on call
}
void tlcs870_device::do_JP_insrc(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// JP (src)
const uint16_t val = RM16(srcaddr);
m_addr = val;
set_JF();
}
/**********************************************************************************************************************/
// (8-bit) bit operations
/**********************************************************************************************************************/
void tlcs870_device::do_XOR_CF_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// XOR CF,(src).b
const uint8_t val = RM8(srcaddr);
const uint8_t bitpos = opbyte1 & 0x7;
int bitused = (1 << bitpos);
const uint8_t bit = val & bitused;
if (is_CF())
{
if (bit)
{
clear_CF();
}
else
{
set_CF();
}
}
else
{
if (bit)
{
set_CF();
}
else
{
clear_CF();
}
}
// JF ends up being whatever the new value of CF is
if (is_CF())
set_JF();
else
clear_JF();
}
void tlcs870_device::do_LD_insrcbit_CF(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// LD (src).b,CF
uint8_t val = RM8(srcaddr);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
if (is_CF()) // if carry flag is set, set the bit in val
{
val |= bitused;
}
else // if carry flag isn't set, clear the bit in val
{
val &= ~bitused;
}
// for this optype of operation ( LD *.b, CF ) the Jump Flag always ends up being 1
set_JF();
WM8(srcaddr, val);
}
void tlcs870_device::do_CPL_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// CPL (src).b
uint8_t val = RM8(srcaddr);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
const uint8_t bit = val & bitused;
if (bit) // if the bit is set, clear the zero/jump flags and unset the bit
{
clear_ZF();
clear_JF();
val &= ~bitused;
}
else // if the bit isn't set, set the zero/jump flags and set the bit
{
set_ZF();
set_JF();
val |= bitused;
}
WM8(srcaddr, val);
}
void tlcs870_device::do_LD_CF_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// LD CF,(src).b aka TEST (src).b
const uint8_t val = RM8(srcaddr);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
const uint8_t bit = val & bitused;
bit ? set_CF() : clear_CF();
// for this optype of operation ( LD CF, *.b ) the Jump Flag always ends up the inverse of the Carry Flag
bit ? clear_JF() : set_JF();
}
void tlcs870_device::do_SET_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// SET (src).b
uint8_t val = RM8(srcaddr);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val |= bitused;
WM8(srcaddr, val);
}
void tlcs870_device::do_CLR_insrcbit(const uint8_t opbyte0, const uint8_t opbyte1, const uint16_t srcaddr)
{
// CLR (src).b
uint8_t val = RM8(srcaddr);
const uint8_t bitpos = opbyte1 & 0x7;
const int bitused = (1 << bitpos);
if (val & bitused) // Zero flag gets set based on original value of bit?
{
clear_ZF();
clear_JF(); // 'Z' (so copy Z flag?)
}
else
{
set_ZF();
set_JF(); // 'Z'
}
val &= ~bitused;
WM8(srcaddr, val);
}

View File

@ -8,8 +8,6 @@
The TLCS-870/C appears to have a completely different encoding.
loosely baesd on the tlcs90 core by Luca Elia
*************************************************************************************************************/
#include "emu.h"
@ -1020,7 +1018,7 @@ void tlcs870_disassembler::decode_register_prefix(uint8_t b0)
break;
case 0x02:
// MUL ggG, ggL
// MUL ggH, ggL
m_op = MUL;
m_param1_type = REG_16BIT; // odd syntax
@ -1416,6 +1414,10 @@ void tlcs870_disassembler::decode_register_prefix(uint8_t b0)
case 0x97:
break;
case 0x98:
case 0x99:
break;
case 0x9a:
case 0x9b:
// LD (pp).g,CF
@ -1458,6 +1460,25 @@ void tlcs870_disassembler::decode_register_prefix(uint8_t b0)
case 0xa7:
break;
case 0xa8:
case 0xa9:
case 0xaa:
case 0xab:
case 0xac:
case 0xad:
case 0xae:
case 0xaf:
// XCH r,g
m_op = XCH;
//m_flagsaffected |= FLAG_J | FLAG_Z;
m_param1_type = REG_8BIT;
m_param1 = bx & 0x7;
m_param2_type = REG_8BIT;
m_param2 = b0 & 0x7;
break;
case 0xb0:
case 0xb1:
case 0xb2:

View File

@ -1558,7 +1558,6 @@ MACHINE_CONFIG_START(hng64_state::hng64)
hng64_network(config);
MCFG_DEVICE_ADD("iomcu", TMP87PH40AN, 8000000)
MCFG_DEVICE_DISABLE() // work in progress
MACHINE_CONFIG_END
@ -1566,9 +1565,18 @@ MACHINE_CONFIG_END
#define ROM_LOAD_HNG64_BIOS(bios,name,offset,length,hash) \
ROMX_LOAD(name, offset, length, hash, ROM_BIOS(bios))
// all BIOS roms are said to be from 'fighting' type PCB, it is unknown if the actual MIPS BIOS differs on the others, or only the MCU internal ROM
/* All main BIOS roms are said to be from 'fighting' type PCB, it is unknown if the actual MIPS BIOS differs on the others, but it appears unlikely.
The IO MCU was dumped from a TMP87PH40AN type chip taken from an unknown IO board type.
Some boards instead use a TMP87CH40N but in all cases they're stickered SNK-IOJ1.00A so the content is possibly the same on all types.
This needs further studying of the MCU code as it is known that the different IO boards return a different ident value.
*/
#define HNG64_BIOS \
ROM_REGION32_BE( 0x0100000, "user1", 0 ) /* 512k for R4300 BIOS code */ \
/* R4300 BIOS code (main CPU) */ \
ROM_REGION32_BE( 0x0100000, "user1", 0 ) \
ROM_SYSTEM_BIOS( 0, "japan", "Japan" ) \
ROM_LOAD_HNG64_BIOS( 0, "brom1.bin", 0x00000, 0x080000, CRC(a30dd3de) SHA1(3e2fd0a56214e6f5dcb93687e409af13d065ea30) ) \
ROM_SYSTEM_BIOS( 1, "us", "USA" ) \
@ -1577,12 +1585,14 @@ MACHINE_CONFIG_END
ROM_LOAD_HNG64_BIOS( 2, "bios_export.bin", 0x00000, 0x080000, CRC(bbf07ec6) SHA1(5656aa077f6a6d43953f15b5123eea102a9d5313) ) \
ROM_SYSTEM_BIOS( 3, "korea", "Korea" ) \
ROM_LOAD_HNG64_BIOS( 3, "bios_korea.bin", 0x00000, 0x080000, CRC(ac953e2e) SHA1(f502188ef252b7c9d04934c4b525730a116de48b) ) \
ROM_REGION( 0x0100000, "user2", 0 ) /* KL5C80 BIOS */ \
/* KL5C80 BIOS (network CPU) */ \
ROM_REGION( 0x0100000, "user2", 0 ) \
ROM_LOAD ( "from1.bin", 0x000000, 0x080000, CRC(6b933005) SHA1(e992747f46c48b66e5509fe0adf19c91250b00c7) ) \
/* FPGA (unknown) */ \
ROM_REGION( 0x0100000, "fpga", 0 ) /* FPGA data */ \
ROM_LOAD ( "rom1.bin", 0x000000, 0x01ff32, CRC(4a6832dc) SHA1(ae504f7733c2f40450157cd1d3b85bc83fac8569) ) \
/* TMP87PH40AN (I/O MCU) */ \
ROM_REGION( 0x10000, "iomcu", 0 ) /* "64Bit I/O Controller Ver 1.0 1997.06.29(C)SNK" internal ID string */ \
/* this was dumped from a TMP87PH40AN type chip. Some boards use a TMP87CH40N, in all cases they're stickered SNK-IOJ1.00A so likely the same content */ \
ROM_LOAD ( "tmp87ph40an.bin", 0x8000, 0x8000, CRC(b70df21f) SHA1(5b742e8a0bbf4c0ae4f4398d34c7058fb24acc92) )