mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
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:
parent
fedf58aa42
commit
88b1546f30
@ -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
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
951
src/devices/cpu/tlcs870/tlcs870_ops.cpp
Normal file
951
src/devices/cpu/tlcs870/tlcs870_ops.cpp
Normal 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
|
||||
}
|
127
src/devices/cpu/tlcs870/tlcs870_ops_dst.cpp
Normal file
127
src/devices/cpu/tlcs870/tlcs870_ops_dst.cpp
Normal 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);
|
||||
}
|
500
src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp
Normal file
500
src/devices/cpu/tlcs870/tlcs870_ops_helper.cpp
Normal 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));
|
||||
}
|
||||
|
760
src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp
Normal file
760
src/devices/cpu/tlcs870/tlcs870_ops_reg.cpp
Normal 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();
|
||||
}
|
548
src/devices/cpu/tlcs870/tlcs870_ops_src.cpp
Normal file
548
src/devices/cpu/tlcs870/tlcs870_ops_src.cpp
Normal 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);
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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) )
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user