summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/lh5801/lh5801.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/lh5801/lh5801.c')
-rw-r--r--src/devices/cpu/lh5801/lh5801.c254
1 files changed, 254 insertions, 0 deletions
diff --git a/src/devices/cpu/lh5801/lh5801.c b/src/devices/cpu/lh5801/lh5801.c
new file mode 100644
index 00000000000..0287e0d0859
--- /dev/null
+++ b/src/devices/cpu/lh5801/lh5801.c
@@ -0,0 +1,254 @@
+// license:BSD-3-Clause
+// copyright-holders:Peter Trauner
+/*****************************************************************************
+ *
+ *
+ * 02/2011 (Sandro Ronco)
+ * - Added IO_SPACE and updated all access in ME1 memory for use it.
+ * - Implemented interrupts.
+ * - Fixed the flags in the ROL/ROR/SHL/SHR opcodes.
+ * - Fixed decimal add/sub opcodes.
+ *
+ * based on info found on an artikel for the tandy trs80 pc2
+ * and on "PC1500 Technical reference manual"
+ *
+ *****************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+
+#include "lh5801.h"
+
+#define VERBOSE 0
+
+#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+
+enum
+{
+ LH5801_T=1,
+ LH5801_P,
+ LH5801_S,
+ LH5801_U,
+ LH5801_X,
+ LH5801_Y,
+ LH5801_A,
+
+ LH5801_TM,
+ LH5801_IN,
+ LH5801_BF,
+ LH5801_PU,
+ LH5801_PV,
+ LH5801_DP,
+ LH5801_IRQ_STATE
+};
+
+
+#define P m_p.w.l
+#define S m_s.w.l
+#define U m_u.w.l
+#define UL m_u.b.l
+#define UH m_u.b.h
+#define X m_x.w.l
+#define XL m_x.b.l
+#define XH m_x.b.h
+#define Y m_y.w.l
+#define YL m_y.b.l
+#define YH m_y.b.h
+
+#define C 0x01
+#define IE 0x02
+#define Z 0x04
+#define V 0x08
+#define H 0x10
+
+
+const device_type LH5801 = &device_creator<lh5801_cpu_device>;
+
+
+lh5801_cpu_device::lh5801_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, LH5801, "LH5801", tag, owner, clock, "lh5801", __FILE__)
+ , m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0)
+ , m_io_config("io", ENDIANNESS_LITTLE, 8, 16, 0)
+ , m_in_func(*this)
+{
+}
+
+
+/***************************************************************
+ * include the opcode macros, functions and tables
+ ***************************************************************/
+#include "5801tbl.inc"
+
+void lh5801_cpu_device::device_start()
+{
+ m_program = &space(AS_PROGRAM);
+ m_io = &space(AS_IO);
+ m_direct = &m_program->direct();
+
+ m_in_func.resolve_safe(0);
+
+ m_s.w.l = 0;
+ m_p.w.l = 0;
+ m_u.w.l = 0;
+ m_x.w.l = 0;
+ m_y.w.l = 0;
+ m_tm = 0;
+ m_t = 0;
+ m_a = 0;
+ m_bf = 0;
+ m_dp = 0;
+ m_pu = 0;
+ m_pv = 0;
+ m_oldpc = 0;
+ m_irq_state = 0;
+ memset(m_ir_flipflop, 0, sizeof(m_ir_flipflop));
+ memset(m_lines_status, 0, sizeof(m_lines_status));
+ m_idle = 0;
+
+ save_item(NAME(m_s.w.l));
+ save_item(NAME(m_p.w.l));
+ save_item(NAME(m_u.w.l));
+ save_item(NAME(m_x.w.l));
+ save_item(NAME(m_y.w.l));
+ save_item(NAME(m_tm));
+ save_item(NAME(m_t));
+ save_item(NAME(m_a));
+ save_item(NAME(m_bf));
+ save_item(NAME(m_dp));
+ save_item(NAME(m_pu));
+ save_item(NAME(m_pv));
+ save_item(NAME(m_oldpc));
+ save_item(NAME(m_irq_state));
+ save_item(NAME(m_ir_flipflop));
+ save_item(NAME(m_lines_status));
+ save_item(NAME(m_idle));
+
+ state_add( LH5801_P, "P", m_p.w.l ).formatstr("%04X");
+ state_add( LH5801_S, "S", m_s.w.l ).formatstr("%04X");
+ state_add( LH5801_U, "U", m_u.w.l ).formatstr("%04X");
+ state_add( LH5801_X, "X", m_x.w.l ).formatstr("%04X");
+ state_add( LH5801_Y, "Y", m_y.w.l ).formatstr("%04X");
+ state_add( LH5801_T, "T", m_t ).formatstr("%02X");
+ state_add( LH5801_A, "A", m_a ).formatstr("%02X");
+ state_add( LH5801_TM, "TM", m_tm ).formatstr("%03X");
+ state_add( LH5801_PV, "PV", m_pv ).formatstr("%04X");
+ state_add( LH5801_PU, "PU", m_pu ).formatstr("%04X");
+ state_add( LH5801_BF, "BF", m_bf ).formatstr("%04X");
+ state_add( LH5801_DP, "DP", m_dp ).formatstr("%04X");
+
+ state_add(STATE_GENPC, "GENPC", m_p.w.l).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_t).noshow().formatstr("%8s");
+
+ m_icountptr = &m_icount;
+}
+
+void lh5801_cpu_device::state_string_export(const device_state_entry &entry, std::string &str)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ strprintf(str, "%c%c%c%c%c%c%c%c",
+ m_t&0x80?'1':'0',
+ m_t&0x40?'1':'0',
+ m_t&0x20?'1':'0',
+ m_t&0x10?'H':'.',
+ m_t&0x08?'V':'.',
+ m_t&0x04?'Z':'.',
+ m_t&0x02?'I':'.',
+ m_t&0x01?'C':'.');
+ break;
+ }
+}
+
+void lh5801_cpu_device::device_reset()
+{
+ P = (m_program->read_byte(0xfffe)<<8) | m_program->read_byte(0xffff);
+
+ m_idle=0;
+
+ memset(m_ir_flipflop, 0, sizeof(m_ir_flipflop));
+ memset(m_lines_status, 0, sizeof(m_lines_status));
+}
+
+
+void lh5801_cpu_device::check_irq()
+{
+ if (m_ir_flipflop[0])
+ {
+ //NMI interrupt
+ m_ir_flipflop[0] = 0;
+ lh5801_push(m_t);
+ m_t&=~IE;
+ lh5801_push_word(P);
+ P = (m_program->read_byte(0xfffc)<<8) | m_program->read_byte(0xfffd);
+ }
+ else if (m_ir_flipflop[1] && (m_t & IE))
+ {
+ //counter interrupt (counter not yet implemented)
+ m_ir_flipflop[1] = 0;
+ lh5801_push(m_t);
+ m_t&=~IE;
+ lh5801_push_word(P);
+ P = (m_program->read_byte(0xfffa)<<8) | m_program->read_byte(0xfffb);
+ }
+ else if (m_ir_flipflop[2] && (m_t & IE))
+ {
+ //MI interrupt
+ m_ir_flipflop[2] = 0;
+ lh5801_push(m_t);
+ m_t&=~IE;
+ lh5801_push_word(P);
+ P = (m_program->read_byte(0xfff8)<<8) | m_program->read_byte(0xfff9);
+ }
+}
+
+
+void lh5801_cpu_device::execute_run()
+{
+ do
+ {
+ check_irq();
+
+ if (m_idle)
+ m_icount = 0;
+ else
+ {
+ m_oldpc = P;
+
+ debugger_instruction_hook(this, P);
+ lh5801_instruction();
+ }
+
+ } while (m_icount > 0);
+}
+
+void lh5801_cpu_device::execute_set_input(int irqline, int state)
+{
+ switch( irqline)
+ {
+ case LH5801_LINE_MI:
+ if (m_lines_status[0] == CLEAR_LINE && state == ASSERT_LINE)
+ {
+ m_idle = 0;
+ m_ir_flipflop[2] = 1;
+ }
+
+ m_lines_status[0] = state;
+ break;
+ case INPUT_LINE_NMI:
+ if (m_lines_status[1] == CLEAR_LINE && state == ASSERT_LINE)
+ {
+ m_idle = 0;
+ m_ir_flipflop[0] = 1;
+ }
+
+ m_lines_status[1] = state;
+ break;
+ }
+}
+
+offs_t lh5801_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( lh5801 );
+ return CPU_DISASSEMBLE_NAME(lh5801)(this, buffer, pc, oprom, opram, options);
+}