diff options
Diffstat (limited to 'src/devices/cpu/saturn/saturn.cpp')
-rw-r--r-- | src/devices/cpu/saturn/saturn.cpp | 410 |
1 files changed, 410 insertions, 0 deletions
diff --git a/src/devices/cpu/saturn/saturn.cpp b/src/devices/cpu/saturn/saturn.cpp new file mode 100644 index 00000000000..1d94a3a9ceb --- /dev/null +++ b/src/devices/cpu/saturn/saturn.cpp @@ -0,0 +1,410 @@ +// license:BSD-3-Clause +// copyright-holders:Peter Trauner,Antoine Mine +/***************************************************************************** + * + * saturn.c + * portable saturn emulator interface + * (hp calculators) + * + * + *****************************************************************************/ + +#include "emu.h" +#include "debugger.h" + +#include "saturn.h" + +#define R0 0 +#define R1 1 +#define R2 2 +#define R3 3 +#define R4 4 +#define A 5 +#define B 6 +#define C 7 +#define D 8 +#define I 9 // invalid + + +#define VERBOSE 0 + +#define LOG(x) do { if (VERBOSE) logerror x; } while (0) + + +// Hardware status bits +#define XM 1 // external Modules missing +#define SB 2 // Sticky bit +#define SR 4 // Service Request +#define MP 8 // Module Pulled + + + +const device_type SATURN = &device_creator<saturn_device>; + + +saturn_device::saturn_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : cpu_device(mconfig, SATURN, "HP Saturn", tag, owner, clock, "saturn_cpu", __FILE__) + , m_program_config("program", ENDIANNESS_LITTLE, 8, 20, 0) + , m_out_func(*this) + , m_in_func(*this) + , m_reset_func(*this) + , m_config_func(*this) + , m_unconfig_func(*this) + , m_id_func(*this) + , m_crc_func(*this) + , m_rsi_func(*this) +{ +} + + +offs_t saturn_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) +{ + extern CPU_DISASSEMBLE( saturn ); + return CPU_DISASSEMBLE_NAME(saturn)(this, buffer, pc, oprom, opram, options); +} + + +/*************************************************************** + * include the opcode macros, functions and tables + ***************************************************************/ + +#include "satops.inc" +#include "sattable.inc" + +/***************************************************************************** + * + * Saturn CPU interface functions + * + *****************************************************************************/ + +void saturn_device::device_start() +{ + m_program = &space(AS_PROGRAM); + m_direct = &m_program->direct(); + + m_out_func.resolve_safe(); + m_in_func.resolve_safe(0); + m_reset_func.resolve_safe(); + m_config_func.resolve_safe(); + m_unconfig_func.resolve_safe(); + m_id_func.resolve_safe(0); + m_crc_func.resolve_safe(); + m_rsi_func.resolve_safe(); + + memset(m_reg, 0, sizeof(m_reg)); + memset(m_d, 0, sizeof(m_d)); + m_pc = 0; + m_oldpc = 0; + memset(m_rstk, 0, sizeof(m_rstk)); + m_out = 0; + m_carry = 0; + m_decimal = 0; + m_st = 0; + m_hst = 0; + m_nmi_state = 0; + m_irq_state = 0; + m_irq_enable = 0; + m_in_irq = 0; + m_pending_irq = 0; + m_sleeping = 0; + m_p = 0; + + save_item(NAME(m_reg[R0])); + save_item(NAME(m_reg[R1])); + save_item(NAME(m_reg[R2])); + save_item(NAME(m_reg[R3])); + save_item(NAME(m_reg[R4])); + save_item(NAME(m_reg[A])); + save_item(NAME(m_reg[B])); + save_item(NAME(m_reg[C])); + save_item(NAME(m_reg[D])); + save_item(NAME(m_d)); + save_item(NAME(m_pc)); + save_item(NAME(m_oldpc)); + save_item(NAME(m_rstk)); + save_item(NAME(m_out)); + save_item(NAME(m_carry)); + save_item(NAME(m_st)); + save_item(NAME(m_hst)); + save_item(NAME(m_nmi_state)); + save_item(NAME(m_irq_state)); + save_item(NAME(m_irq_enable)); + save_item(NAME(m_in_irq)); + save_item(NAME(m_pending_irq)); + save_item(NAME(m_sleeping)); + + // TODO: Register state + state_add( SATURN_PC, "PC", m_pc ).formatstr("%5X"); + state_add( SATURN_D0, "D0", m_d[0] ).formatstr("%5X"); + state_add( SATURN_D1, "D1", m_d[1] ).formatstr("%5X"); + state_add( SATURN_A, "A", m_debugger_temp ).formatstr("%19s"); + state_add( SATURN_B, "B", m_debugger_temp ).formatstr("%19s"); + state_add( SATURN_C, "C", m_debugger_temp ).formatstr("%19s"); + state_add( SATURN_D, "D", m_debugger_temp ).formatstr("%19s"); + state_add( SATURN_R0, "R0", m_debugger_temp ).formatstr("%19s"); + state_add( SATURN_R1, "R1", m_debugger_temp ).formatstr("%19s"); + state_add( SATURN_R2, "R2", m_debugger_temp ).formatstr("%19s"); + state_add( SATURN_R3, "R3", m_debugger_temp ).formatstr("%19s"); + state_add( SATURN_R4, "R4", m_debugger_temp ).formatstr("%19s"); + state_add( SATURN_P, "P", m_p).formatstr("%1X"); + state_add( SATURN_OUT, "OUTP", m_out).formatstr("%3X"); + state_add( SATURN_CARRY, "Carry", m_carry).formatstr("%1X"); + state_add( SATURN_ST, "ST", m_st).formatstr("%4X"); + state_add( SATURN_HST, "HST", m_hst).formatstr("%1X"); + state_add( SATURN_RSTK0, "RSTK0", m_rstk[0]).formatstr("%5X"); + state_add( SATURN_RSTK1, "RSTK1", m_rstk[1]).formatstr("%5X"); + state_add( SATURN_RSTK2, "RSTK2", m_rstk[2]).formatstr("%5X"); + state_add( SATURN_RSTK3, "RSTK3", m_rstk[3]).formatstr("%5X"); + state_add( SATURN_RSTK4, "RSTK4", m_rstk[4]).formatstr("%5X"); + state_add( SATURN_RSTK5, "RSTK5", m_rstk[5]).formatstr("%5X"); + state_add( SATURN_RSTK6, "RSTK6", m_rstk[6]).formatstr("%5X"); + state_add( SATURN_RSTK7, "RSTK7", m_rstk[7]).formatstr("%5X"); + state_add( SATURN_IRQ_STATE, "IRQ", m_debugger_temp).formatstr("%4s"); + state_add( SATURN_SLEEPING, "sleep", m_sleeping).formatstr("%1X"); + + state_add( STATE_GENPC, "GENPC", m_pc ).noshow(); + state_add( STATE_GENFLAGS, "GENFLAGS", m_debugger_temp).formatstr("%2s").noshow(); + + m_icountptr = &m_icount; +} + +void saturn_device::state_string_export(const device_state_entry &entry, std::string &str) +{ +#define Reg64Data(s) s[15],s[14],s[13],s[12],s[11],s[10],s[9],s[8],s[7],s[6],s[5],s[4],s[3],s[2],s[1],s[0] +#define Reg64Format "%x %x%x%x%x%x%x%x %x%x%x %x%x%x%x%x" + + switch (entry.index()) + { + case SATURN_A: + strprintf(str, Reg64Format, Reg64Data(m_reg[A]) ); + break; + + case SATURN_B: + strprintf(str, Reg64Format, Reg64Data(m_reg[B]) ); + break; + + case SATURN_C: + strprintf(str, Reg64Format, Reg64Data(m_reg[C]) ); + break; + + case SATURN_D: + strprintf(str, Reg64Format, Reg64Data(m_reg[D]) ); + break; + + case SATURN_R0: + strprintf(str, Reg64Format, Reg64Data(m_reg[R0]) ); + break; + + case SATURN_R1: + strprintf(str, Reg64Format, Reg64Data(m_reg[R1]) ); + break; + + case SATURN_R2: + strprintf(str, Reg64Format, Reg64Data(m_reg[R2]) ); + break; + + case SATURN_R3: + strprintf(str, Reg64Format, Reg64Data(m_reg[R3]) ); + break; + + case SATURN_R4: + strprintf(str, Reg64Format, Reg64Data(m_reg[R4]) ); + break; + + case SATURN_IRQ_STATE: + strprintf(str, "%c%c%c%i", m_in_irq?'S':'.', m_irq_enable?'e':'.', m_pending_irq?'p':'.', m_irq_state ); + break; + + case STATE_GENFLAGS: + strprintf(str, "%c%c", m_decimal?'D':'.', m_carry ? 'C':'.' ); + break; + } +} + + +void saturn_device::state_import(const device_state_entry &entry) +{ + switch (entry.index()) + { + case SATURN_A: + IntReg64(m_reg[A], m_debugger_temp); + break; + + case SATURN_B: + IntReg64(m_reg[B], m_debugger_temp); + break; + + case SATURN_C: + IntReg64(m_reg[C], m_debugger_temp); + break; + + case SATURN_D: + IntReg64(m_reg[D], m_debugger_temp); + break; + + case SATURN_R0: + IntReg64(m_reg[R0], m_debugger_temp); + break; + + case SATURN_R1: + IntReg64(m_reg[R1], m_debugger_temp); + break; + + case SATURN_R2: + IntReg64(m_reg[R2], m_debugger_temp); + break; + + case SATURN_R3: + IntReg64(m_reg[R3], m_debugger_temp); + break; + + case SATURN_R4: + IntReg64(m_reg[R4], m_debugger_temp); + break; + } +} + +void saturn_device::state_export(const device_state_entry &entry) +{ + switch (entry.index()) + { + case SATURN_A: + m_debugger_temp = Reg64Int(m_reg[A]); + break; + + case SATURN_B: + m_debugger_temp = Reg64Int(m_reg[B]); + break; + + case SATURN_C: + m_debugger_temp = Reg64Int(m_reg[C]); + break; + + case SATURN_D: + m_debugger_temp = Reg64Int(m_reg[D]); + break; + + case SATURN_R0: + m_debugger_temp = Reg64Int(m_reg[R0]); + break; + + case SATURN_R1: + m_debugger_temp = Reg64Int(m_reg[R1]); + break; + + case SATURN_R2: + m_debugger_temp = Reg64Int(m_reg[R2]); + break; + + case SATURN_R3: + m_debugger_temp = Reg64Int(m_reg[R3]); + break; + + case SATURN_R4: + m_debugger_temp = Reg64Int(m_reg[R4]); + break; + } +} + + +void saturn_device::device_reset() +{ + m_pc=0; + m_sleeping = 0; + m_irq_enable = 0; + m_in_irq = 0; +} + + +void saturn_device::saturn_take_irq() +{ + m_in_irq = 1; /* reset by software, using RTI */ + m_pending_irq = 0; + m_icount -= 7; + saturn_push(m_pc); + m_pc=IRQ_ADDRESS; + + LOG(("Saturn '%s' takes IRQ ($%04x)\n", tag(), m_pc)); + + standard_irq_callback(SATURN_IRQ_LINE); +} + +void saturn_device::execute_run() +{ + do + { + m_oldpc = m_pc; + + debugger_instruction_hook(this, m_pc); + + if ( m_sleeping ) + { + /* advance time when sleeping */ + m_icount -= 100; + } + else + { + /* takes irq */ + if ( m_pending_irq && (!m_in_irq) ) + saturn_take_irq(); + + /* execute one instruction */ + saturn_instruction(); + } + + } while (m_icount > 0); +} + + +void saturn_device::execute_set_input(int inputnum, int state) +{ + switch (inputnum) + { + case SATURN_NMI_LINE: + if ( state == m_nmi_state ) return; + m_nmi_state = state; + if ( state != CLEAR_LINE ) + { + LOG(( "SATURN '%s' set_nmi_line(ASSERT)\n", tag())); + m_pending_irq = 1; + } + break; + + case SATURN_IRQ_LINE: + if ( state == m_irq_state ) return; + m_irq_state = state; + if ( state != CLEAR_LINE && m_irq_enable ) + { + LOG(( "SATURN '%s' set_irq_line(ASSERT)\n", tag())); + m_pending_irq = 1; + } + break; + + case SATURN_WAKEUP_LINE: + if (m_sleeping && state==1) + { + LOG(( "SATURN '%s' set_wakeup_line(ASSERT)\n", tag())); + standard_irq_callback(SATURN_WAKEUP_LINE); + m_sleeping = 0; + } + break; + } +} + + +void saturn_device::IntReg64(Saturn64 r, INT64 d) +{ + int i; + for (i=0; i<16; i++) + r[i] = (d >> (4*i)) & 0xf; +} + + +INT64 saturn_device::Reg64Int(Saturn64 r) +{ + INT64 x = 0; + int i; + for (i=0; i<16; i++) + x |= (INT64) r[i] << (4*i); + return x; +} |