summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/romp/romp.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/romp/romp.h')
-rw-r--r--src/devices/cpu/romp/romp.h306
1 files changed, 306 insertions, 0 deletions
diff --git a/src/devices/cpu/romp/romp.h b/src/devices/cpu/romp/romp.h
new file mode 100644
index 00000000000..9528a15078c
--- /dev/null
+++ b/src/devices/cpu/romp/romp.h
@@ -0,0 +1,306 @@
+// license:BSD-3-Clause
+// copyright-holders:Patrick Mackinlay
+
+#ifndef MAME_CPU_ROMP_ROMP_H
+#define MAME_CPU_ROMP_ROMP_H
+
+#pragma once
+
+#include "rsc.h"
+
+class romp_device : public cpu_device
+{
+public:
+ romp_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+ template <typename T> void set_mmu(T &&tag) { m_mmu.set_tag(std::forward<T>(tag)); }
+ template <typename T> void set_iou(T &&tag) { m_iou.set_tag(std::forward<T>(tag)); }
+
+ void clk_w(int state);
+
+protected:
+ enum registers : unsigned
+ {
+ ROMP_SCR = 0,
+ ROMP_GPR = 16,
+ };
+
+ enum scr : unsigned
+ {
+ COUS = 6, // counter source
+ COU = 7, // counter
+ TS = 8, // timer status
+ ECR = 9, // exception control (advanced/enhanced only)
+ MQ = 10, // multiplier quotient
+ MPCS = 11, // machine/program check status
+ IRB = 12, // interrupt request buffer
+ IAR = 13, // instruction address register
+ ICS = 14, // interrupt control status
+ CS = 15, // condition status
+ };
+
+ enum ts_mask : u32
+ {
+ TS_E = 0x0000'0040, // enable
+ TS_I = 0x0000'0020, // interrupt status
+ TS_O = 0x0000'0010, // overflow
+ TS_P = 0x0000'0007, // timer interrupt priority
+ };
+ enum mpcs_mask : u32
+ {
+ // reserved
+ PCS_DAE = 0x0000'0002, // data address exception
+ PCS_IAE = 0x0000'0004, // instruction address exception
+ PCS_IOC = 0x0000'0008, // illegal operation code
+ PCS_PIE = 0x0000'0010, // privileged instruction exception
+ PCS_PT = 0x0000'0020, // program trap
+ PCS_PCU = 0x0000'0040, // program check with unknown origin
+ PCS_PCK = 0x0000'0080, // program check with known origin
+ // reserved
+ MCS_IOT = 0x0000'0200, // i/o trap
+ MCS_PCT = 0x0000'0400, // processor channel timeout
+ MCS_DT = 0x0000'0800, // data timeout
+ MCS_IT = 0x0000'1000, // instruction timeout
+ MCS_PC = 0x0000'2000, // parity check
+ // reserved
+ MCS_PCC = 0x0000'8000, // processor channel check
+
+ MCS_ALL = 0x0000'be00,
+ PCS_ALL = 0x0000'00fe,
+ };
+
+ enum irb_mask : u16
+ {
+ // reserved
+ IRB_L6 = 0x0200, // interrupt request level 6
+ IRB_L5 = 0x0400, // interrupt request level 5
+ IRB_L4 = 0x0800, // interrupt request level 4
+ IRB_L3 = 0x1000, // interrupt request level 3
+ IRB_L2 = 0x2000, // interrupt request level 2
+ IRB_L1 = 0x4000, // interrupt request level 1
+ IRB_L0 = 0x8000, // interrupt request level 0
+
+ IRB_ALL = 0xfe00,
+ };
+ enum ics_mask : u32
+ {
+ ICS_PP = 0x0000'0007, // processor priority
+ // reserved
+ ICS_RS = 0x0000'0070, // register set number
+ ICS_CS = 0x0000'0080, // check stop mask
+ ICS_IM = 0x0000'0100, // interrupt mask
+ ICS_TM = 0x0000'0200, // translate mode
+ ICS_US = 0x0000'0400, // unprivileged state
+ ICS_MP = 0x0000'0800, // memory protect
+ ICS_PE = 0x0000'1000, // parity error retry interrupt enable
+ ICS_UA = 0x0000'2000, // unaligned access interrupt enable (advanced/enhanced only)
+ };
+ enum cs_mask : u32
+ {
+ CS_T = 0x0000'0001, // test bit
+ CS_O = 0x0000'0002, // overflow
+ CS_C = 0x0000'0008, // carry
+ CS_G = 0x0000'0010, // greater than
+ CS_E = 0x0000'0020, // equal
+ CS_L = 0x0000'0040, // less than
+ CS_Z = 0x0000'0080, // permanent zero
+ };
+
+ // device_t overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_execute_interface overrides
+ virtual u32 execute_min_cycles() const noexcept override { return 1; }
+ virtual u32 execute_max_cycles() const noexcept override { return 40; }
+ virtual void execute_run() override;
+ virtual void execute_set_input(int inputnum, int state) override;
+
+ // device_memory_interface overrides
+ virtual space_config_vector memory_space_config() const override;
+ virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override;
+
+ // device_state_interface overrides
+ virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+private:
+ // insruction decode helpers
+ u32 r3_0(unsigned reg) const { return reg ? m_gpr[reg] : 0; }
+ s32 ji(u16 op) const { return s32(s8(op)) << 1; }
+ u32 ba(u16 hi, u16 lo) const { return ((u32(hi) << 16) | lo) & 0x00ff'fffeU; }
+ s32 bi(u16 hi, u16 lo) const { return s32((u32(hi) << 16 | lo) << 12) >> 11; }
+
+ void flags_log(u32 const op1);
+ void flags_add(u32 const op1, u32 const op2);
+ void flags_sub(u32 const op1, u32 const op2);
+
+ void set_scr(unsigned scr, u32 data);
+
+ void interrupt_check();
+ void machine_check(u32 mcs);
+ void program_check(u32 pcs);
+ void interrupt_enter(unsigned vector, u32 iar, u16 svc = 0);
+
+ using rsc_mode = rsc_bus_interface::rsc_mode;
+
+ void fetch(u32 address, std::function<void(u16)> f)
+ {
+ u16 data = 0;
+
+ if (m_mmu->fetch(address, data, rsc_mode((m_scr[ICS] >> 9) & 7)))
+ f(data);
+ else
+ program_check(PCS_PCK | PCS_IAE);
+ }
+
+ template <typename T> void load(u32 address, std::function<void(T)> f, bool mask = true)
+ {
+ rsc_mode const mode = mask ? rsc_mode((m_scr[ICS] >> 9) & 7) : rsc_mode::RSC_N;
+
+ T data = 0;
+
+ switch (address >> 28)
+ {
+ default:
+ if (m_mmu->mem_load(address, data, mode))
+ f(data);
+ else
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+
+ case 15:
+ switch (address >> 24)
+ {
+ case 0xf0:
+ if (m_iou->pio_load(address, data, mode))
+ f(data);
+ else
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+ case 0xf4:
+ if (m_iou->mem_load(address, data, mode))
+ f(data);
+ else
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+
+ case 0xfc: // mc68881 assist mode
+ case 0xfd: // mc68881 non-assist mode
+ case 0xfe: // afpa dma
+ case 0xff: // fpa
+ default: // reserved
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+ }
+ break;
+ }
+ }
+
+ template <typename T> void store(u32 address, T data, bool mask = true)
+ {
+ rsc_mode const mode = mask ? rsc_mode((m_scr[ICS] >> 9) & 7) : rsc_mode::RSC_N;
+
+ switch (address >> 28)
+ {
+ default:
+ if (!m_mmu->mem_store(address, data, mode))
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+
+ case 15:
+ switch (address >> 24)
+ {
+ case 0xf0:
+ if (!m_iou->pio_store(address, data, mode))
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+ case 0xf4:
+ if (!m_iou->mem_store(address, data, mode))
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+
+ case 0xfc: // mc68881 assist mode
+ case 0xfd: // mc68881 non-assist mode
+ case 0xfe: // afpa dma
+ case 0xff: // fpa
+ default: // reserved
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+ }
+ break;
+ }
+ }
+
+ template <typename T> void modify(u32 address, std::function<T(T)> f, bool mask = true)
+ {
+ rsc_mode const mode = mask ? rsc_mode((m_scr[ICS] >> 9) & 7) : rsc_mode::RSC_N;
+
+ switch (address >> 28)
+ {
+ default:
+ if (!m_mmu->mem_modify(address, f, mode))
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+
+ case 15:
+ switch (address >> 24)
+ {
+ case 0xf0:
+ if (!m_iou->pio_modify(address, f, mode))
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+ case 0xf4:
+ if (!m_iou->mem_modify(address, f, mode))
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+
+ case 0xfc: // mc68881 assist mode
+ case 0xfd: // mc68881 non-assist mode
+ case 0xfe: // afpa dma
+ case 0xff: // fpa
+ default: // reserved
+ program_check(PCS_PCK | PCS_DAE);
+ break;
+ }
+ break;
+ }
+ }
+
+ // address spaces
+ address_space_config const m_mem_config;
+
+ required_device<rsc_cpu_interface> m_mmu;
+ required_device<rsc_bus_interface> m_iou;
+
+ // mame state
+ int m_icount;
+
+ // core registers
+ u32 m_scr[16];
+ u32 m_gpr[16];
+
+ // input line state
+ u8 m_reqi;
+ bool m_trap;
+
+ // internal state
+ enum branch_state : unsigned
+ {
+ DEFAULT = 0,
+ BRANCH = 1, // branch subject instruction active
+ DELAY = 2, // delayed branch instruction active
+ EXCEPTION = 3,
+ WAIT = 4,
+ }
+ m_branch_state;
+ u32 m_branch_source;
+ u32 m_branch_target;
+ bool m_defer_int;
+};
+
+DECLARE_DEVICE_TYPE(ROMP, romp_device)
+
+#endif // MAME_CPU_ROMP_ROMP_H