summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sparc')
-rw-r--r--src/devices/cpu/sparc/sparc.cpp (renamed from src/devices/cpu/sparc/mb86901.cpp)3281
-rw-r--r--src/devices/cpu/sparc/sparc.h245
-rw-r--r--src/devices/cpu/sparc/sparc_intf.h2
-rw-r--r--src/devices/cpu/sparc/sparcdasm.cpp126
-rw-r--r--src/devices/cpu/sparc/sparcdasm.h14
-rw-r--r--src/devices/cpu/sparc/sparcdefs.h129
-rw-r--r--src/devices/cpu/sparc/sparcv8ops.ipp293
-rw-r--r--src/devices/cpu/sparc/ss1fcode.ipp8
8 files changed, 2256 insertions, 1842 deletions
diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/sparc.cpp
index 809df3db8f3..9bdd1bfbad5 100644
--- a/src/devices/cpu/sparc/mb86901.cpp
+++ b/src/devices/cpu/sparc/sparc.cpp
@@ -2,11 +2,8 @@
// copyright-holders:Ryan Holtz
//================================================================
//
-// mb86901.cpp - Emulation for the Fujitsu MB86901 / LSI L64801
-// processors. Both chips are identical both
-// electrically and functionally, and implement
-// the integer instructions in a SPARC v7
-// compatible instruction set.
+// sparc.cpp - Emulation for the SPARCv7/v8 line of
+// processors.
//
// Notes:
// - The CPU core implementation has been simplified
@@ -16,10 +13,10 @@
// ever be.
//
// To-Do:
-// - Ops: FBFcc, LDF, STF
// - Test: SPARCv8 ops are untested
-// - FPU support
+// - Extended-precision FPU support
// - Coprocessor support
+// - Finish SPARClite peripherals
//
//================================================================
@@ -27,34 +24,145 @@
#include "sparc.h"
#include "sparcdefs.h"
-#include "debugger.h"
-
-
-DEFINE_DEVICE_TYPE(MB86901, mb86901_device, "mb86901", "Fujitsu MB86901")
-
-const int mb86901_device::NWINDOWS = 7;
+#include "softfloat3/source/include/softfloat.h"
+
+#define LOG_BIU_CTRL (1U << 1)
+#define LOG_LOCK_CTRL (1U << 2)
+#define LOG_LOCK_CTRL_SAVE (1U << 3)
+#define LOG_CACHE_STATUS (1U << 4)
+#define LOG_RESTORE_LOCK_CTRL (1U << 5)
+#define LOG_SYSTEM_CTRL (1U << 6)
+#define LOG_SAME_PAGE_MASK (1U << 7)
+#define LOG_ADDR_RANGE (1U << 8)
+#define LOG_ADDR_MASK (1U << 9)
+#define LOG_WAIT_STATE (1U << 10)
+#define LOG_TIMER (1U << 11)
+#define LOG_TIMER_PRELOAD (1U << 12)
+#define LOG_UNMAPPED (1U << 13)
+#define LOG_ICACHE_LOCK (1U << 14)
+#define LOG_ICACHE_TAG (1U << 15)
+#define LOG_ICACHE_DATA (1U << 16)
+#define LOG_DCACHE_LOCK (1U << 17)
+#define LOG_DCACHE_TAG (1U << 18)
+#define LOG_DCACHE_DATA (1U << 19)
+
+#define VERBOSE (0)
+#include "logmacro.h"
+
+DEFINE_DEVICE_TYPE(SPARCV7, sparcv7_device, "sparcv7", "Sun SPARC v7")
+DEFINE_DEVICE_TYPE(SPARCV8, sparcv8_device, "sparcv8", "Sun SPARC v8")
+DEFINE_DEVICE_TYPE(MB86930, mb86930_device, "mb86930", "Fujitsu MB86930 'SPARClite'")
#if LOG_FCODES
#include "ss1fcode.ipp"
#endif
-#if SPARCV8
-#include "sparcv8ops.ipp"
-#endif
+namespace
+{
+const sparc_disassembler::asi_desc_map::value_type mb86930_asi_desc[] =
+{
+ { 0x01, { nullptr, "Control Registers" } },
+ { 0x02, { nullptr, "Instruction Cache Lock" } },
+ { 0x03, { nullptr, "Data Cache Lock" } },
+ { 0x08, { nullptr, "User Instruction" } },
+ { 0x09, { nullptr, "Supervisor Instruction" } },
+ { 0x0a, { nullptr, "User Data" } },
+ { 0x0b, { nullptr, "Supervisor Data" } },
+ { 0x0c, { nullptr, "Instruction Cache Tag RAM" } },
+ { 0x0d, { nullptr, "Instruction Cache Data RAM" } },
+ { 0x0e, { nullptr, "Data Cache Tag RAM" } },
+ { 0x0f, { nullptr, "Data Cache Data RAM" } }
+};
+} // anonymous namespace
+
+const char *const sparc_base_device::DEFAULT_ASI_NAMES[16] =
+{
+ "asi0", "asi1", "asi2", "asi3", "asi4", "asi5", "asi6", "asi7",
+ "asi8", "asi9", "asi10", "asi11", "asi12", "asi13", "asi14", "asi15"
+};
//-------------------------------------------------
-// mb86901_device - constructor
+// sparc_base_device - constructor
//-------------------------------------------------
-mb86901_device::mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : cpu_device(mconfig, MB86901, tag, owner, clock)
+sparc_base_device::sparc_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : cpu_device(mconfig, type, tag, owner, clock)
, m_mmu(*this, finder_base::DUMMY_TAG)
{
- m_default_config = address_space_config("program", ENDIANNESS_BIG, 32, 32);
+ m_debugger_config = address_space_config("debug", ENDIANNESS_BIG, 32, 32);
+
+ if (type != MB86930)
+ {
+ for (int i = 0; i < 0x10; i++)
+ {
+ m_asi_config[i] = address_space_config(DEFAULT_ASI_NAMES[i], ENDIANNESS_BIG, 32, 32);
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// sparcv7_device - constructors
+//-------------------------------------------------
+
+sparcv7_device::sparcv7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sparcv7_device(mconfig, SPARCV7, tag, owner, clock)
+{
+}
+
+sparcv7_device::sparcv7_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : sparc_base_device(mconfig, type, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// sparcv8_device - constructor
+//-------------------------------------------------
+
+sparcv8_device::sparcv8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sparcv8_device(mconfig, SPARCV8, tag, owner, clock)
+{
}
-void mb86901_device::device_start()
+sparcv8_device::sparcv8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ : sparc_base_device(mconfig, type, tag, owner, clock)
+{
+}
+
+
+//-------------------------------------------------
+// mb86930_device - constructor
+//-------------------------------------------------
+
+mb86930_device::mb86930_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : sparcv8_device(mconfig, MB86930, tag, owner, clock)
+ , m_cs_r(*this, 0)
+ , m_cs_w(*this)
+{
+ m_asi_config[0x00] = address_space_config("debugger", ENDIANNESS_BIG, 32, 32);
+ m_asi_config[0x01] = address_space_config("system_control", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::control_map), this));
+ m_asi_config[0x02] = address_space_config("icache_lock", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_lock_map), this));
+ m_asi_config[0x03] = address_space_config("dcache_lock", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::dcache_lock_map), this));
+ m_asi_config[0x04] = address_space_config("asi4", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<4>), this));
+ m_asi_config[0x05] = address_space_config("asi5", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<5>), this));
+ m_asi_config[0x06] = address_space_config("asi6", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<6>), this));
+ m_asi_config[0x07] = address_space_config("asi7", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<7>), this));
+ m_asi_config[0x08] = address_space_config("user_insn", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<8>), this));
+ m_asi_config[0x09] = address_space_config("super_insn", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<9>), this));
+ m_asi_config[0x0a] = address_space_config("user_data", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<10>), this));
+ m_asi_config[0x0b] = address_space_config("super_data", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<11>), this));
+ m_asi_config[0x0c] = address_space_config("icache_tag", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_tag_map), this));
+ m_asi_config[0x0d] = address_space_config("icache_data", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_data_map), this));
+ m_asi_config[0x0e] = address_space_config("dcache_tag", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::dcache_tag_map), this));
+ m_asi_config[0x0f] = address_space_config("dcache_data", ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::dcache_data_map), this));
+
+ add_asi_desc([](sparc_disassembler *dasm) { dasm->add_asi_desc(mb86930_asi_desc); });
+}
+
+
+void sparc_base_device::device_start()
{
#if LOG_FCODES
m_ss1_fcode_table.clear();
@@ -138,8 +246,13 @@ void mb86901_device::device_start()
m_log_fcodes = false;
#endif
+ NWINDOWS = 7;
+ PSR = 0;
+ m_ver = 0;
+ m_impl = 0;
+
m_bp_reset_in = false;
- m_bp_fpu_present = false;
+ m_bp_fpu_present = true;
m_bp_cp_present = false;
m_pb_error = false;
m_pb_block_ldst_byte = false;
@@ -147,13 +260,22 @@ void mb86901_device::device_start()
m_bp_irl = 0;
m_irq_state = 0;
- memset(m_dbgregs, 0, 24 * sizeof(uint32_t));
+ for (int i = 0; i < 0x20; i++)
+ {
+ if (i > 0 && i < 0x10)
+ {
+ continue;
+ }
+ space(i).specific(m_asi[i]);
+ }
+
+ std::fill_n(m_dbgregs, std::size(m_dbgregs), 0);
- memset(m_illegal_instruction_asr, 0, 32 * sizeof(bool));
- memset(m_privileged_asr, 1, 32 * sizeof(bool));
+ std::fill_n(m_illegal_instruction_asr, std::size(m_illegal_instruction_asr), false);
+ std::fill_n(m_privileged_asr, std::size(m_privileged_asr), true);
m_privileged_asr[0] = false;
- memset(m_alu_setcc, 0, 64 * sizeof(bool));
+ std::fill_n(m_alu_setcc, std::size(m_alu_setcc), false);
m_alu_setcc[OP3_ADDCC] = true;
m_alu_setcc[OP3_ANDCC] = true;
m_alu_setcc[OP3_ORCC] = true;
@@ -169,14 +291,8 @@ void mb86901_device::device_start()
m_alu_setcc[OP3_TADDCCTV] = true;
m_alu_setcc[OP3_TSUBCCTV] = true;
m_alu_setcc[OP3_MULSCC] = true;
-#if SPARCV8
- m_alu_setcc[OP3_UMULCC] = true;
- m_alu_setcc[OP3_SMULCC] = true;
- m_alu_setcc[OP3_UDIVCC] = true;
- m_alu_setcc[OP3_SDIVCC] = true;
-#endif
- memset(m_alu_op3_assigned, 0, 64 * sizeof(bool));
+ std::fill_n(m_alu_op3_assigned, std::size(m_alu_op3_assigned), false);
m_alu_op3_assigned[OP3_ADD] = true;
m_alu_op3_assigned[OP3_AND] = true;
m_alu_op3_assigned[OP3_OR] = true;
@@ -223,18 +339,8 @@ void mb86901_device::device_start()
m_alu_op3_assigned[OP3_IFLUSH] = true;
m_alu_op3_assigned[OP3_SAVE] = true;
m_alu_op3_assigned[OP3_RESTORE] = true;
-#if SPARCV8
- m_alu_op3_assigned[OP3_UMUL] = true;
- m_alu_op3_assigned[OP3_SMUL] = true;
- m_alu_op3_assigned[OP3_UDIV] = true;
- m_alu_op3_assigned[OP3_SDIV] = true;
- m_alu_op3_assigned[OP3_UMULCC] = true;
- m_alu_op3_assigned[OP3_SMULCC] = true;
- m_alu_op3_assigned[OP3_UDIVCC] = true;
- m_alu_op3_assigned[OP3_SDIVCC] = true;
-#endif
- memset(m_ldst_op3_assigned, 0, 64 * sizeof(bool));
+ std::fill_n(m_ldst_op3_assigned, std::size(m_ldst_op3_assigned), false);
m_ldst_op3_assigned[OP3_LD] = true;
m_ldst_op3_assigned[OP3_LDUB] = true;
m_ldst_op3_assigned[OP3_LDUH] = true;
@@ -264,17 +370,6 @@ void mb86901_device::device_start()
m_ldst_op3_assigned[OP3_STFSR] = true;
m_ldst_op3_assigned[OP3_STDFQ] = true;
m_ldst_op3_assigned[OP3_STDFPR] = true;
-#if SPARCV8
- m_ldst_op3_assigned[OP3_SWAP] = true;
- m_ldst_op3_assigned[OP3_SWAPA] = true;
- m_ldst_op3_assigned[OP3_LDCPR] = true;
- m_ldst_op3_assigned[OP3_LDCSR] = true;
- m_ldst_op3_assigned[OP3_LDDCPR] = true;
- m_ldst_op3_assigned[OP3_STCPR] = true;
- m_ldst_op3_assigned[OP3_STCSR] = true;
- m_ldst_op3_assigned[OP3_STDCQ] = true;
- m_ldst_op3_assigned[OP3_STDCPR] = true;
-#endif
// register our state for the debugger
state_add(STATE_GENPC, "GENPC", m_pc).noshow();
@@ -289,31 +384,18 @@ void mb86901_device::device_start()
state_add(SPARC_ANNUL, "ANNUL", m_no_annul).formatstr("%01u");
state_add(SPARC_ICC, "icc", m_icc).formatstr("%4s");
state_add(SPARC_CWP, "CWP", m_cwp).formatstr("%2d");
- char regname[3] = "g0";
+
for (int i = 0; i < 8; i++)
- {
- regname[1] = 0x30 + i;
- state_add(SPARC_G0 + i, regname, m_r[i]).formatstr("%08X");
- }
- regname[0] = 'o';
+ state_add(SPARC_G0 + i, util::string_format("g%d", i).c_str(), m_r[i]).formatstr("%08X");
+
for (int i = 0; i < 8; i++)
- {
- regname[1] = 0x30 + i;
- state_add(SPARC_O0 + i, regname, m_dbgregs[i]).formatstr("%08X");
- }
+ state_add(SPARC_O0 + i, util::string_format("o%d", i).c_str(), m_dbgregs[i]).formatstr("%08X");
- regname[0] = 'l';
for (int i = 0; i < 8; i++)
- {
- regname[1] = 0x30 + i;
- state_add(SPARC_L0 + i, regname, m_dbgregs[8+i]).formatstr("%08X");
- }
- regname[0] = 'i';
+ state_add(SPARC_L0 + i, util::string_format("l%d", i).c_str(), m_dbgregs[8+i]).formatstr("%08X");
+
for (int i = 0; i < 8; i++)
- {
- regname[1] = 0x30 + i;
- state_add(SPARC_I0 + i, regname, m_dbgregs[16+i]).formatstr("%08X");
- }
+ state_add(SPARC_I0 + i, util::string_format("i%d", i).c_str(), m_dbgregs[16+i]).formatstr("%08X");
state_add(SPARC_EC, "EC", m_ec).formatstr("%1u");
state_add(SPARC_EF, "EF", m_ef).formatstr("%1u");
@@ -321,13 +403,13 @@ void mb86901_device::device_start()
state_add(SPARC_PIL, "PIL", m_pil).formatstr("%2d");
state_add(SPARC_S, "S", m_s).formatstr("%1u");
state_add(SPARC_PS, "PS", m_ps).formatstr("%1u");
+ state_add(SPARC_FSR, "FSR", m_fsr).formatstr("%08X");
- char rname[5];
- for (int i = 0; i < 120; i++)
- {
- sprintf(rname, "r%d", i);
- state_add(SPARC_R0 + i, rname, m_r[i]).formatstr("%08X");
- }
+ for (int i = 0; i < 32; i++)
+ state_add(SPARC_F0 + i, util::string_format("f%d", i).c_str(), m_fpr[i]);
+
+ for (int i = 0; i < 136; i++)
+ state_add(SPARC_R0 + i, util::string_format("r%d", i).c_str(), m_r[i]).formatstr("%08X");
save_item(NAME(m_r));
save_item(NAME(m_fpr));
@@ -355,17 +437,14 @@ void mb86901_device::device_start()
save_item(NAME(m_illegal_instruction));
save_item(NAME(m_mem_address_not_aligned));
save_item(NAME(m_fp_disabled));
- save_item(NAME(m_fp_exception));
save_item(NAME(m_cp_disabled));
+ save_item(NAME(m_fp_exception));
+ save_item(NAME(m_fp_exception_pending));
+ save_item(NAME(m_fpr_pending));
+ save_item(NAME(m_pending_fpr));
save_item(NAME(m_cp_exception));
- save_item(NAME(m_unimplemented_FLUSH));
- save_item(NAME(m_r_register_access_error));
- save_item(NAME(m_instruction_access_error));
save_item(NAME(m_instruction_access_exception));
- save_item(NAME(m_data_access_error));
- save_item(NAME(m_data_store_error));
save_item(NAME(m_data_access_exception));
- save_item(NAME(m_division_by_zero));
save_item(NAME(m_trap_instruction));
save_item(NAME(m_window_underflow));
save_item(NAME(m_window_overflow));
@@ -389,13 +468,12 @@ void mb86901_device::device_start()
save_item(NAME(m_alu_op3_assigned));
save_item(NAME(m_ldst_op3_assigned));
save_item(NAME(m_alu_setcc));
+ save_item(NAME(m_nwindows));
save_item(NAME(m_privileged_asr));
save_item(NAME(m_illegal_instruction_asr));
save_item(NAME(m_mae));
save_item(NAME(m_no_annul));
save_item(NAME(m_hold_bus));
- save_item(NAME(m_icount));
- save_item(NAME(m_stashed_icount));
save_item(NAME(m_insn_space));
save_item(NAME(m_data_space));
@@ -413,58 +491,67 @@ void mb86901_device::device_start()
}
-void mb86901_device::device_stop()
+void sparc_base_device::device_resolve_objects()
{
+ if (m_mmu.found())
+ m_mmu->set_host(this);
}
-void mb86901_device::device_resolve_objects()
+void sparc_base_device::device_reset()
{
- m_mmu->set_host(this);
-}
-
-void mb86901_device::device_reset()
-{
- m_trap = 0;
+ m_trap = false;
m_tt = 0;
m_ticc_trap_type = 0;
- m_privileged_instruction = 0;
- m_illegal_instruction = 0;
- m_mem_address_not_aligned = 0;
- m_fp_disabled = 0;
- m_cp_disabled = 0;
- m_instruction_access_exception = 0;
- m_trap_instruction = 0;
- m_window_underflow = 0;
- m_window_overflow = 0;
- m_tag_overflow = 0;
- m_reset_mode = 1;
- m_reset_trap = 0;
- m_execute_mode = 0;
- m_error_mode = 0;
+ m_interrupt_level = 0;
+ m_privileged_instruction = false;
+ m_illegal_instruction = false;
+ m_mem_address_not_aligned = false;
+ m_fp_disabled = false;
+ m_cp_disabled = false;
+ m_fp_exception = false;
+ m_fp_exception_pending = false;
+ m_fpr_pending = 0;
+ m_pending_fpr = std::size(m_fpr);
+ m_cp_exception = false;
+ m_instruction_access_exception = false;
+ m_data_access_exception = false;
+ m_trap_instruction = false;
+ m_window_underflow = false;
+ m_window_overflow = false;
+ m_tag_overflow = false;
+ m_reset_mode = true;
+ m_reset_trap = false;
+ m_execute_mode = false;
+ m_error_mode = false;
m_fpu_sequence_err = 0;
m_cp_sequence_err = 0;
m_bp_irl = 0;
m_irq_state = 0;
- m_stashed_icount = -1;
-
MAE = false;
HOLD_BUS = false;
m_no_annul = true;
PC = 0;
nPC = 4;
- memset(m_r, 0, sizeof(uint32_t) * 120);
- memset(m_fpr, 0, sizeof(uint32_t) * 32);
+ std::fill_n(m_r, std::size(m_r), 0);
+ std::fill_n(m_fpr, std::size(m_fpr), 0);
WIM = 0;
TBR = 0;
Y = 0;
- PSR = PSR_S_MASK | PSR_PS_MASK;
+ PSR = (PSR & PSR_ZERO_MASK) | (PSR_S_MASK | PSR_PS_MASK);
m_s = true;
+ m_ps = true;
m_data_space = 11;
+ m_pil = 0;
+ m_et = false;
+ m_icc = 0;
+ m_ec = false;
+ m_ef = false;
+ m_cwp = 0;
for (int i = 0; i < 8; i++)
{
@@ -481,59 +568,540 @@ void mb86901_device::device_reset()
#endif
}
+void sparcv8_device::device_start()
+{
+ sparc_base_device::device_start();
+
+ save_item(NAME(m_unimplemented_FLUSH));
+ save_item(NAME(m_r_register_access_error));
+ save_item(NAME(m_instruction_access_error));
+ save_item(NAME(m_data_access_error));
+ save_item(NAME(m_data_store_error));
+ save_item(NAME(m_division_by_zero));
+
+ m_alu_setcc[OP3_UMULCC] = true;
+ m_alu_setcc[OP3_SMULCC] = true;
+ m_alu_setcc[OP3_UDIVCC] = true;
+ m_alu_setcc[OP3_SDIVCC] = true;
+
+ m_alu_op3_assigned[OP3_UMUL] = true;
+ m_alu_op3_assigned[OP3_SMUL] = true;
+ m_alu_op3_assigned[OP3_UDIV] = true;
+ m_alu_op3_assigned[OP3_SDIV] = true;
+ m_alu_op3_assigned[OP3_UMULCC] = true;
+ m_alu_op3_assigned[OP3_SMULCC] = true;
+ m_alu_op3_assigned[OP3_UDIVCC] = true;
+ m_alu_op3_assigned[OP3_SDIVCC] = true;
+
+ m_ldst_op3_assigned[OP3_SWAP] = true;
+ m_ldst_op3_assigned[OP3_SWAPA] = true;
+ m_ldst_op3_assigned[OP3_LDCPR] = true;
+ m_ldst_op3_assigned[OP3_LDCSR] = true;
+ m_ldst_op3_assigned[OP3_LDDCPR] = true;
+ m_ldst_op3_assigned[OP3_STCPR] = true;
+ m_ldst_op3_assigned[OP3_STCSR] = true;
+ m_ldst_op3_assigned[OP3_STDCQ] = true;
+ m_ldst_op3_assigned[OP3_STDCPR] = true;
+}
+
+void sparcv8_device::device_reset()
+{
+ sparc_base_device::device_reset();
+
+ m_unimplemented_FLUSH = 0;
+ m_r_register_access_error = 0;
+ m_instruction_access_error = 0;
+ m_data_access_error = 0;
+ m_data_store_error = 0;
+ m_division_by_zero = 0;
+}
+
//-------------------------------------------------
-// device_post_load - update register pointers
-// after loading a savestate
+// mb86930_device - initializers
//-------------------------------------------------
-void mb86901_device::device_post_load()
+void mb86930_device::device_start()
{
- update_gpr_pointers();
+ sparcv8_device::device_start();
+
+ NWINDOWS = 8;
+ PSR |= 2 << PSR_VER_SHIFT;
+ m_ver = 2;
+
+ m_bp_cp_present = false;
+ m_bp_fpu_present = false;
+
+ m_alu_setcc[OP3_DIVSCC] = true;
+
+ m_alu_op3_assigned[OP3_DIVSCC] = true;
+ m_alu_op3_assigned[OP3_SCAN] = true;
+
+ save_item(NAME(m_ssctrl));
+ save_item(NAME(m_spmr));
+ save_item(NAME(m_spmr_mask));
+ save_item(NAME(m_arsr));
+ save_item(NAME(m_amr));
+ save_item(NAME(m_wssr));
+ save_item(NAME(m_last_masked_addr));
+
+ std::fill_n(&m_arsr[0], 6, 0);
+ std::fill_n(&m_amr[0], 6, 0);
+}
+
+void mb86930_device::device_reset()
+{
+ sparcv8_device::device_reset();
+
+ m_ssctrl = 0x08;
+ m_spmr = 0;
+ m_spmr_mask = ~0ULL;
+ m_last_masked_addr = 0ULL;
+
+ std::fill_n(&m_wssr[0], 3, 0);
+ m_wssr[0] = 0x1ffd << 6;
+
+ m_arsr[0] = (9 << 23);
+ m_amr[0] = (0x1f << 1);
+
+ update_addr_masks();
+ update_wait_states();
}
//-------------------------------------------------
-// memory_space_config - return the configuration
-// of the specified address space, or nullptr if
-// the space doesn't exist
+// mb86930_device - internal maps
//-------------------------------------------------
-device_memory_interface::space_config_vector mb86901_device::memory_space_config() const
+void mb86930_device::control_map(address_map &map)
{
- space_config_vector config_vector;
- config_vector.push_back(std::make_pair(AS_PROGRAM, &m_default_config));
- return config_vector;
+ map(0x00000000, 0x00000003).rw(FUNC(mb86930_device::biu_ctrl_r), FUNC(mb86930_device::biu_ctrl_w));
+ map(0x00000004, 0x00000007).rw(FUNC(mb86930_device::lock_ctrl_r), FUNC(mb86930_device::lock_ctrl_w));
+ map(0x00000008, 0x0000000b).rw(FUNC(mb86930_device::lock_ctrl_save_r), FUNC(mb86930_device::lock_ctrl_save_w));
+ map(0x0000000c, 0x0000000f).rw(FUNC(mb86930_device::cache_status_r), FUNC(mb86930_device::cache_status_w));
+ map(0x00000010, 0x00000013).rw(FUNC(mb86930_device::restore_lock_ctrl_r), FUNC(mb86930_device::restore_lock_ctrl_w));
+ map(0x00000080, 0x00000083).rw(FUNC(mb86930_device::system_support_ctrl_r), FUNC(mb86930_device::system_support_ctrl_w));
+ map(0x00000120, 0x00000123).rw(FUNC(mb86930_device::same_page_mask_r), FUNC(mb86930_device::same_page_mask_w));
+ map(0x00000124, 0x00000137).rw(FUNC(mb86930_device::addr_range_spec_r), FUNC(mb86930_device::addr_range_spec_w));
+ map(0x00000140, 0x00000157).rw(FUNC(mb86930_device::addr_mask_r), FUNC(mb86930_device::addr_mask_w));
+ map(0x00000160, 0x0000016b).rw(FUNC(mb86930_device::wait_specifier_r), FUNC(mb86930_device::wait_specifier_w));
+ map(0x00000174, 0x00000177).rw(FUNC(mb86930_device::timer_r), FUNC(mb86930_device::timer_w));
+ map(0x00000178, 0x0000017b).rw(FUNC(mb86930_device::timer_preload_r), FUNC(mb86930_device::timer_preload_w));
+}
+
+void mb86930_device::icache_lock_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(mb86930_device::icache_lock_r), FUNC(mb86930_device::icache_lock_w));
+}
+
+void mb86930_device::dcache_lock_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(mb86930_device::dcache_lock_r), FUNC(mb86930_device::dcache_lock_w));
+}
+
+void mb86930_device::icache_tag_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(mb86930_device::icache_tag_r), FUNC(mb86930_device::icache_tag_w));
+}
+
+void mb86930_device::icache_data_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(mb86930_device::icache_data_r), FUNC(mb86930_device::icache_data_w));
+}
+
+void mb86930_device::dcache_tag_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(mb86930_device::dcache_tag_r), FUNC(mb86930_device::dcache_tag_w));
+}
+
+void mb86930_device::dcache_data_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(mb86930_device::dcache_data_r), FUNC(mb86930_device::dcache_data_w));
+}
+
+
+//-------------------------------------------------
+// mb86930_device - cache control (TODO)
+//-------------------------------------------------
+
+uint32_t mb86930_device::icache_lock_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_ICACHE_LOCK, "%s: icache_lock_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::icache_lock_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_ICACHE_LOCK, "%s: icache_lock_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+uint32_t mb86930_device::dcache_lock_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_DCACHE_LOCK, "%s: dcache_lock_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::dcache_lock_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_DCACHE_LOCK, "%s: dcache_lock_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+uint32_t mb86930_device::icache_tag_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_ICACHE_TAG, "%s: icache_tag_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::icache_tag_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_ICACHE_TAG, "%s: icache_tag_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+uint32_t mb86930_device::icache_data_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_ICACHE_DATA, "%s: icache_data_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::icache_data_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_ICACHE_DATA, "%s: icache_data_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+uint32_t mb86930_device::dcache_tag_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_DCACHE_TAG, "%s: dcache_tag_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::dcache_tag_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_DCACHE_TAG, "%s: dcache_tag_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+uint32_t mb86930_device::dcache_data_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_DCACHE_DATA, "%s: dcache_data_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::dcache_data_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_DCACHE_DATA, "%s: dcache_data_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+//-------------------------------------------------
+// mb86930_device - MMU map and handlers
+//-------------------------------------------------
+
+template <uint8_t Asi>
+void mb86930_device::mmu_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(mb86930_device::mmu_r<Asi>), FUNC(mb86930_device::mmu_w<Asi>));
+}
+
+template <uint8_t Asi>
+uint32_t mb86930_device::mmu_r(offs_t offset, uint32_t mem_mask)
+{
+ const uint64_t full_addr = ((uint64_t)Asi << 30) | offset;
+
+ const uint64_t masked_addr = full_addr & m_spmr_mask;
+ const bool is_same_page = (masked_addr == m_last_masked_addr);
+ m_last_masked_addr = masked_addr;
+
+ for (int cs = 0; cs < 6; cs++)
+ {
+ if ((full_addr & m_full_masks[cs]) == m_full_ranges[cs])
+ {
+ m_icount -= is_same_page ? m_same_page_waits[cs] : m_other_page_waits[cs];
+ return m_cs_r[cs](offset, mem_mask);
+ }
+ }
+ LOGMASKED(LOG_UNMAPPED, "%s: mmu_r, unmapped access: ASI %d, address %08x & %08x\n", machine().describe_context(), Asi, offset << 2, mem_mask);
+ return 0;
+}
+
+template <uint8_t Asi> void mb86930_device::mmu_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ const uint64_t full_addr = ((uint64_t)Asi << 30) | offset;
+
+ const uint64_t masked_addr = full_addr & m_spmr_mask;
+ const bool is_same_page = (masked_addr == m_last_masked_addr);
+ m_last_masked_addr = masked_addr;
+
+ for (int cs = 0; cs < 6; cs++)
+ {
+ if ((full_addr & m_full_masks[cs]) == m_full_ranges[cs])
+ {
+ m_icount -= is_same_page ? m_same_page_waits[cs] : m_other_page_waits[cs];
+ m_cs_w[cs](offset, data, mem_mask);
+ return;
+ }
+ }
+ LOGMASKED(LOG_UNMAPPED, "%s: mmu_w, unmapped access: ASI %d, address %08x = %08x & %08x\n", machine().describe_context(), Asi, offset << 2, data, mem_mask);
+}
+
+
+//-------------------------------------------------
+// mb86930_device - system control handlers
+//-------------------------------------------------
+
+void mb86930_device::update_addr_masks()
+{
+ for (int i = 0; i < 6; i++)
+ {
+ m_full_masks[i] = ~(((uint64_t)m_amr[i] << 7) | 0xff);
+ m_full_ranges[i] = ((uint64_t)m_arsr[i] << 7) & m_full_masks[i];
+ }
+}
+
+void mb86930_device::update_wait_states()
+{
+ for (int i = 0; i < 6; i++)
+ {
+ const uint8_t shift = (i & 1) ? 19 : 6;
+ const bool enable = bool(BIT(m_wssr[i >> 1], shift + 2));
+ const bool single = bool(BIT(m_wssr[i >> 1], shift + 1));
+ //const bool override = bool(BIT(m_wssr[i >> 1], shift + 0));
+
+ if (BIT(m_ssctrl, 3) && !single && enable)
+ {
+ const uint8_t count1 = ((m_wssr[i >> 1] >> (shift + 8)) & 0x1f) + 1;
+ const uint8_t count2 = ((m_wssr[i >> 1] >> (shift + 3)) & 0x1f) + 1;
+ m_other_page_waits[i] = count1;
+ m_same_page_waits[i] = BIT(m_ssctrl, 5) ? count2 : count1;
+ }
+ else
+ {
+ m_other_page_waits[i] = 0;
+ m_same_page_waits[i] = 0;
+ }
+ }
+}
+
+uint32_t mb86930_device::biu_ctrl_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_BIU_CTRL, "%s: biu_ctrl_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::biu_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_BIU_CTRL, "%s: biu_ctrl_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+uint32_t mb86930_device::lock_ctrl_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_LOCK_CTRL, "%s: lock_ctrl_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::lock_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_LOCK_CTRL, "%s: lock_ctrl_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+uint32_t mb86930_device::lock_ctrl_save_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_LOCK_CTRL_SAVE, "%s: lock_ctrl_save_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::lock_ctrl_save_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_LOCK_CTRL_SAVE, "%s: lock_ctrl_save_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+uint32_t mb86930_device::cache_status_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_CACHE_STATUS, "%s: cache_status_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::cache_status_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_CACHE_STATUS, "%s: cache_status_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+uint32_t mb86930_device::restore_lock_ctrl_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_RESTORE_LOCK_CTRL, "%s: restore_lock_ctrl_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::restore_lock_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_RESTORE_LOCK_CTRL, "%s: restore_lock_ctrl_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+uint32_t mb86930_device::system_support_ctrl_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = m_ssctrl;
+ LOGMASKED(LOG_SYSTEM_CTRL, "%s: system_ctrl_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::system_support_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SYSTEM_CTRL, "%s: system_ctrl_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_ssctrl);
+ update_wait_states();
+}
+
+
+uint32_t mb86930_device::same_page_mask_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = m_spmr;
+ LOGMASKED(LOG_SAME_PAGE_MASK, "%s: same_page_mask_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::same_page_mask_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_SAME_PAGE_MASK, "%s: same_page_mask_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ COMBINE_DATA(&m_spmr);
+ m_spmr_mask = ~(((uint64_t)m_spmr << 7) | 0xff);
+}
+
+
+uint32_t mb86930_device::addr_range_spec_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = m_arsr[offset + 1];
+ LOGMASKED(LOG_ADDR_RANGE, "%s: addr_range_spec_r[%d]: %08x & %08x\n", machine().describe_context(), offset + 1, data, mem_mask);
+ return data;
+}
+
+void mb86930_device::addr_range_spec_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_ADDR_RANGE, "%s: addr_range_spec_w[%d]: %08x & %08x\n", machine().describe_context(), offset + 1, data, mem_mask);
+ COMBINE_DATA(&m_arsr[offset + 1]);
+ update_addr_masks();
+}
+
+
+uint32_t mb86930_device::addr_mask_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = m_amr[offset];
+ LOGMASKED(LOG_ADDR_MASK, "%s: addr_mask_r[%d]: %08x & %08x\n", machine().describe_context(), offset, data, mem_mask);
+ return data;
+}
+
+void mb86930_device::addr_mask_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_ADDR_MASK, "%s: addr_mask_w[%d]: %08x & %08x\n", machine().describe_context(), offset, data, mem_mask);
+ COMBINE_DATA(&m_amr[offset]);
+ update_addr_masks();
+}
+
+
+uint32_t mb86930_device::wait_specifier_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = m_wssr[offset];
+ LOGMASKED(LOG_WAIT_STATE, "%s: wait_state_r[%d]: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::wait_specifier_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_WAIT_STATE, "%s: wait_state_w[%d]: %08x & %08x\n", machine().describe_context(), offset, data, mem_mask);
+ COMBINE_DATA(&m_wssr[offset]);
+ update_wait_states();
+}
+
+
+uint32_t mb86930_device::timer_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_TIMER, "%s: timer_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::timer_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_TIMER, "%s: timer_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+}
+
+
+uint32_t mb86930_device::timer_preload_r(offs_t offset, uint32_t mem_mask)
+{
+ uint32_t data = 0;
+ LOGMASKED(LOG_TIMER_PRELOAD, "%s: timer_preload_r: %08x & %08x\n", machine().describe_context(), data, mem_mask);
+ return data;
+}
+
+void mb86930_device::timer_preload_w(offs_t offset, uint32_t data, uint32_t mem_mask)
+{
+ LOGMASKED(LOG_TIMER_PRELOAD, "%s: timer_preload_w: %08x & %08x\n", machine().describe_context(), data, mem_mask);
}
//-------------------------------------------------
-// read_sized_word - read a value from a given
-// address space and address, shifting the data
-// that is read into the appropriate location of
-// a 32-bit word in a big-endian system.
+// device_post_load - update register pointers
+// after loading a savestate
//-------------------------------------------------
-uint32_t mb86901_device::read_sized_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask)
+void sparc_base_device::device_post_load()
+{
+ update_gpr_pointers();
+}
+
+void mb86930_device::device_post_load()
{
- assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines.
- return m_mmu->read_asi(asi, address >> 2, mem_mask);
+ sparcv8_device::device_post_load();
+ update_addr_masks();
+ update_wait_states();
}
//-------------------------------------------------
-// write_sized_word - write a value to a given
-// address space and address, shifting the data
-// that is written into the least significant
-// bits as appropriate in order to write the
-// value to a memory system with separate data
-// size handlers
+// memory_space_config - return the configuration
+// of the specified address space, or nullptr if
+// the space doesn't exist
//-------------------------------------------------
-void mb86901_device::write_sized_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask)
+device_memory_interface::space_config_vector sparc_base_device::memory_space_config() const
{
- assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines.
- m_mmu->write_asi(asi, address >> 2, data, mem_mask);
+ space_config_vector config_vector;
+ config_vector.push_back(std::make_pair(0, &m_debugger_config));
+ for (int i = 0; i < 0x10; i++)
+ {
+ config_vector.push_back(std::make_pair(0x10 + i, &m_asi_config[i]));
+ }
+ return config_vector;
+}
+
+inline uint32_t sparc_base_device::read_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask)
+{
+ assert(asi < 0x10); // We do not currently support ASIs outside the range used by actual Sun machines.
+ return m_asi[asi | 0x10].read_dword(address, mem_mask);
+}
+
+inline void sparc_base_device::write_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask)
+{
+ assert(asi < 0x10); // We do not currently support ASIs outside the range used by actual Sun machines.
+ return m_asi[asi | 0x10].write_dword(address, data, mem_mask);
}
@@ -542,7 +1110,7 @@ void mb86901_device::write_sized_word(const uint8_t asi, const uint32_t address,
// for the debugger
//-------------------------------------------------
-void mb86901_device::state_string_export(const device_state_entry &entry, std::string &str) const
+void sparc_base_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
switch (entry.index())
{
@@ -592,13 +1160,29 @@ void mb86901_device::state_string_export(const device_state_entry &entry, std::s
// helper function
//-------------------------------------------------
-std::unique_ptr<util::disasm_interface> mb86901_device::create_disassembler()
+std::unique_ptr<util::disasm_interface> sparc_base_device::create_disassembler()
+{
+ auto dasm = std::make_unique<sparc_disassembler>(static_cast<sparc_disassembler::config const *>(this), sparc_disassembler::v7);
+ if (m_asi_desc_adder)
+ m_asi_desc_adder(dasm.get());
+ return std::move(dasm);
+}
+
+std::unique_ptr<util::disasm_interface> sparcv8_device::create_disassembler()
{
- auto dasm = std::make_unique<sparc_disassembler>(static_cast<sparc_disassembler::config const *>(this), 7);
- m_asi_desc_adder(dasm.get());
+ auto dasm = std::make_unique<sparc_disassembler>(static_cast<sparc_disassembler::config const *>(this), sparc_disassembler::v8);
+ if (m_asi_desc_adder)
+ m_asi_desc_adder(dasm.get());
return std::move(dasm);
}
+std::unique_ptr<util::disasm_interface> mb86930_device::create_disassembler()
+{
+ auto dasm = std::make_unique<sparc_disassembler>(static_cast<sparc_disassembler::config const *>(this), sparc_disassembler::sparclite);
+ if (m_asi_desc_adder)
+ m_asi_desc_adder(dasm.get());
+ return std::move(dasm);
+}
//**************************************************************************
// CORE EXECUTION LOOP
@@ -609,7 +1193,7 @@ std::unique_ptr<util::disasm_interface> mb86901_device::create_disassembler()
// cycles it takes for one instruction to execute
//-------------------------------------------------
-uint32_t mb86901_device::execute_min_cycles() const
+uint32_t sparc_base_device::execute_min_cycles() const noexcept
{
return 1;
}
@@ -620,29 +1204,18 @@ uint32_t mb86901_device::execute_min_cycles() const
// cycles it takes for one instruction to execute
//-------------------------------------------------
-uint32_t mb86901_device::execute_max_cycles() const
+uint32_t sparc_base_device::execute_max_cycles() const noexcept
{
return 4;
}
//-------------------------------------------------
-// execute_input_lines - return the number of
-// input/interrupt lines
-//-------------------------------------------------
-
-uint32_t mb86901_device::execute_input_lines() const
-{
- return 16;
-}
-
-
-//-------------------------------------------------
// execute_set_input - set the state of an input
// line during execution
//-------------------------------------------------
-void mb86901_device::execute_set_input(int inputnum, int state)
+void sparc_base_device::execute_set_input(int inputnum, int state)
{
switch (inputnum)
{
@@ -699,30 +1272,10 @@ void mb86901_device::execute_set_input(int inputnum, int state)
// execute_add - execute an add-type opcode
//-------------------------------------------------
-void mb86901_device::execute_add(uint32_t op)
+void sparc_base_device::execute_add(uint32_t op)
{
- /* The SPARC Instruction Manual: Version 8, page 173, "Appendix C - ISP Descriptions - Add Instructions" (SPARCv8.pdf, pg. 170)
-
- operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
-
- if (ADD or ADDcc) then
- result <- r[rs1] + operand2;
- else if (ADDX or ADDXcc) then
- result <= r[rs1] + operand2 + C;
- next;
+ // The SPARC Instruction Manual: Version 8, page 173, "Appendix C - ISP Descriptions - Add Instructions" (SPARCv8.pdf, pg. 170)
- if (rd != 0) then
- r[rd] <- result;
-
- if (ADDcc or ADDXcc) then (
- N <- result<31>;
- Z <- if (result = 0) then 1 else 0;
- V <- (r[rs1]<31> and operand2<31> and (not result<31>)) or
- ((not r[rs1]<31>) and (not operand2<31>) and result<31>);
- C <- (r[rs1]<31> and operand2<31>) or
- ((not result<31>) and (r[rs1]<31> or operand2<31>))
- );
- */
uint32_t rs1 = RS1REG;
uint32_t operand2 = USEIMM ? SIMM13 : RS2REG;
@@ -756,33 +1309,10 @@ void mb86901_device::execute_add(uint32_t op)
// opcode
//-------------------------------------------------
-void mb86901_device::execute_taddcc(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 173, "Appendix C - ISP Descriptions - Tagged Add Instructions" (SPARCv8.pdf, pg. 170)
-
- operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
-
- result <- r[rs1] + operand2;
- next;
-
- temp_V <- (r[rs1]<31> and operand2<31> and (not result<31>)) or
- ((not r[rs1]<31>) and (not operand2<31>) and result<31>) or
- (r[rs1]<1:0> != 0 or operand2<1:0> != 0);
- next;
-
- if (TADDccTV and (temp_V = 1)) then (
- trap <- 1;
- tag_overflow <- 1
- ) else (
- N <- result<31>;
- Z <- if (result = 0) then 1 else 0;
- V <- temp_V;
- C <- (r[rs1]<31> and operand2<31>) or
- ((not result<31>) and (r[rs1]<31> or operand2<31>));
- if (rd != 0) then
- r[rd] <- result;
- );
- */
+void sparc_base_device::execute_taddcc(uint32_t op)
+{
+ // The SPARC Instruction Manual: Version 8, page 173, "Appendix C - ISP Descriptions - Tagged Add Instructions" (SPARCv8.pdf, pg. 170)
+
uint32_t rs1 = RS1REG;
uint32_t operand2 = USEIMM ? SIMM13 : RS2REG;
@@ -796,8 +1326,6 @@ void mb86901_device::execute_taddcc(uint32_t op)
{
m_trap = 1;
m_tag_overflow = true;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -821,30 +1349,10 @@ void mb86901_device::execute_taddcc(uint32_t op)
// opcode
//-------------------------------------------------
-void mb86901_device::execute_sub(uint32_t op)
+void sparc_base_device::execute_sub(uint32_t op)
{
- /* The SPARC Instruction Manual: Version 8, page 174, "Appendix C - ISP Descriptions - Subtract Instructions" (SPARCv8.pdf, pg. 171)
-
- operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
-
- if (SUB or SUBcc) then
- result <- r[rs1] - operand2;
- else if (SUBX or SUBXcc) then
- result <= r[rs1] - operand2 - C;
- next;
+ // The SPARC Instruction Manual: Version 8, page 174, "Appendix C - ISP Descriptions - Subtract Instructions" (SPARCv8.pdf, pg. 171)
- if (rd != 0) then
- r[rd] <- result;
-
- if (SUBcc or SUBXcc) then (
- N <- result<31>;
- Z <- if (result = 0) then 1 else 0;
- V <- (r[rs1]<31> and (not operand2<31>) and (not result<31>)) or
- ((not r[rs1]<31>) and operand2<31> and result<31>);
- C <- ((not r[rs1]<31>) and operand2<31>) or
- (result<31> and ((not r[rs1]<31>) or operand2<31>))
- );
- */
uint32_t rs1 = RS1REG;
uint32_t operand2 = USEIMM ? SIMM13 : RS2REG;
@@ -878,33 +1386,9 @@ void mb86901_device::execute_sub(uint32_t op)
// opcode
//--------------------------------------------------
-void mb86901_device::execute_tsubcc(uint32_t op)
+void sparc_base_device::execute_tsubcc(uint32_t op)
{
- /* The SPARC Instruction Manual: Version 8, page 174, "Appendix C - ISP Descriptions - Tagged Subtract Instructions" (SPARCv8.pdf, pg. 171)
-
- operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
-
- result <- r[rs1] - operand2;
- next;
-
- temp_V <- (r[rs1]<31> and (not operand2<31>) and (not result<31>)) or
- ((not r[rs1]<31>) and operand2<31> and result<31>) or
- (r[rs1]<1:0> != 0 or operand2<1:0> != 0);
- next;
-
- if (TSUBccTV and (temp_V = 1)) then (
- trap <- 1;
- tag_overflow <- 1
- ) else (
- N <- result<31>;
- Z <- if (result = 0) then 1 else 0;
- V <- temp_V;
- C <- ((not r[rs1]<31>) and operand2<31>) or
- (result<31> and ((not r[rs1]<31>) or operand2<31>));
- if (rd != 0) then
- r[rd] <- result;
- );
- */
+ // The SPARC Instruction Manual: Version 8, page 174, "Appendix C - ISP Descriptions - Tagged Subtract Instructions" (SPARCv8.pdf, pg. 171)
uint32_t rs1 = RS1REG;
uint32_t operand2 = USEIMM ? SIMM13 : RS2REG;
@@ -919,8 +1403,6 @@ void mb86901_device::execute_tsubcc(uint32_t op)
{
m_trap = 1;
m_tag_overflow = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -939,30 +1421,10 @@ void mb86901_device::execute_tsubcc(uint32_t op)
}
-/* The SPARC Instruction Manual: Version 8, page 172, "Appendix C - ISP Descriptions - Logical Instructions" (SPARCv8.pdf, pg. 169)
-
-operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
-
-if ( AND or ANDcc) then result <- r[rs1] and operand2
-if (ANDN or ANDNcc) then result <- r[rs1] and not operand2
-if ( OR or ORcc) then result <- r[rs1] or operand2
-if ( ORN or ORNcc) then result <- r[rs1] or not operand2
-if ( XOR or XORcc) then result <- r[rs1] xor operand2
-if (XNOR or XNORcc) then result <- r[rs1] xor not operand2;
-next;
-
-if (rd != 0) then r[rd] <- result;
+// The SPARC Instruction Manual: Version 8, page 172, "Appendix C - ISP Descriptions - Logical Instructions" (SPARCv8.pdf, pg. 169)
-if (ANDcccc or ANDNcc or ORcc or ORNcc or XORcc or XNORcc) then (
- N <- result<31>;
- Z <- if (result = 0) then 1 else 0;
- V <- 0
- C <- 0
-);
-*/
-
-template <mb86901_device::set_cc SETCC>
-void mb86901_device::execute_and(const uint32_t op)
+template <sparc_base_device::set_cc SETCC>
+void sparc_base_device::execute_and(const uint32_t op)
{
const uint32_t result = RS1REG & (USEIMM ? SIMM13 : RS2REG);
if (RDBITS) RDREG = result;
@@ -979,8 +1441,8 @@ void mb86901_device::execute_and(const uint32_t op)
nPC = nPC + 4;
}
-template <mb86901_device::set_cc SETCC>
-void mb86901_device::execute_or(const uint32_t op)
+template <sparc_base_device::set_cc SETCC>
+void sparc_base_device::execute_or(const uint32_t op)
{
const uint32_t result = RS1REG | (USEIMM ? SIMM13 : RS2REG);
if (RDBITS) RDREG = result;
@@ -997,8 +1459,8 @@ void mb86901_device::execute_or(const uint32_t op)
nPC = nPC + 4;
}
-template <mb86901_device::set_cc SETCC>
-void mb86901_device::execute_xor(const uint32_t op)
+template <sparc_base_device::set_cc SETCC>
+void sparc_base_device::execute_xor(const uint32_t op)
{
const uint32_t result = RS1REG ^ (USEIMM ? SIMM13 : RS2REG);
if (RDBITS) RDREG = result;
@@ -1015,8 +1477,8 @@ void mb86901_device::execute_xor(const uint32_t op)
nPC = nPC + 4;
}
-template <mb86901_device::set_cc SETCC>
-void mb86901_device::execute_andn(const uint32_t op)
+template <sparc_base_device::set_cc SETCC>
+void sparc_base_device::execute_andn(const uint32_t op)
{
const uint32_t result = RS1REG & ~(USEIMM ? SIMM13 : RS2REG);
if (RDBITS) RDREG = result;
@@ -1033,8 +1495,8 @@ void mb86901_device::execute_andn(const uint32_t op)
nPC = nPC + 4;
}
-template <mb86901_device::set_cc SETCC>
-void mb86901_device::execute_orn(const uint32_t op)
+template <sparc_base_device::set_cc SETCC>
+void sparc_base_device::execute_orn(const uint32_t op)
{
const uint32_t result = RS1REG | ~(USEIMM ? SIMM13 : RS2REG);
if (RDBITS) RDREG = result;
@@ -1051,8 +1513,8 @@ void mb86901_device::execute_orn(const uint32_t op)
nPC = nPC + 4;
}
-template <mb86901_device::set_cc SETCC>
-void mb86901_device::execute_xnor(const uint32_t op)
+template <sparc_base_device::set_cc SETCC>
+void sparc_base_device::execute_xnor(const uint32_t op)
{
const uint32_t result = RS1REG ^ ~(USEIMM ? SIMM13 : RS2REG);
if (RDBITS) RDREG = result;
@@ -1074,19 +1536,10 @@ void mb86901_device::execute_xnor(const uint32_t op)
// sll/srl/sra
//-------------------------------------------------
-void mb86901_device::execute_shift(uint32_t op)
+void sparc_base_device::execute_shift(uint32_t op)
{
- /* The SPARC Instruction Manual: Version 8, page 172, "Appendix C - ISP Descriptions - Shift Instructions" (SPARCv8.pdf, pg. 169)
-
- shift_count := if (i = 0) then r[rs2]<4:0> else shcnt;
+ // The SPARC Instruction Manual: Version 8, page 172, "Appendix C - ISP Descriptions - Shift Instructions" (SPARCv8.pdf, pg. 169)
- if (SLL and (rd != 0) ) then
- r[rd] <- shift_left_logical(r[rs1], shift_count)
- else if (SRL and (rd != 0) ) then
- r[rd] <- shift_right_logical(r[rs1], shift_count)
- else if (SRA and (rd != 0) ) then
- r[rd] <- shift_right_arithmetic(r[rs1], shift_count)
- */
uint32_t shift_count = USEIMM ? (SIMM13 & 31) : (RS2REG & 31);
if (RDBITS)
@@ -1108,31 +1561,10 @@ void mb86901_device::execute_shift(uint32_t op)
// execute_mulscc - execute a multiply step opcode
//--------------------------------------------------
-void mb86901_device::execute_mulscc(uint32_t op)
+void sparc_base_device::execute_mulscc(uint32_t op)
{
- /* The SPARC Instruction Manual: Version 8, page 175, "Appendix C - ISP Descriptions - Multiply Step Instruction" (SPARCv8.pdf, pg. 172)
-
- operand1 := (N xor V) [] (r[rs1]<31:1>);
-
- operand2 := (
- if (Y<0> = 0) then 0
- else if (i = 0) then r[rs2] else sign_extend(simm13)
- );
+ // The SPARC Instruction Manual: Version 8, page 175, "Appendix C - ISP Descriptions - Multiply Step Instruction" (SPARCv8.pdf, pg. 172)
- result <- operand1 + operand2;
- Y <- r[rs1]<0> [] Y<31:1>;
- next;
-
- if (rd != 0) then (
- r[rd] <- result;
- )
- N <- result<31>;
- Z <- if (result = 0) then 1 else 0;
- V <- (operand1<31> and operand2<31> and (not result<31>)) or
- ((not operand1<31>) and (not operand2<31>) and result<31>);
- C <- (operand1<31> and operand2<31>) or
- ((not result<31>) and (operand1<31> or operand2<31>))
- */
uint32_t operand1 = ((ICC_N != ICC_V) ? 0x80000000 : 0) | (RS1REG >> 1);
uint32_t operand2 = (Y & 1) ? (USEIMM ? SIMM13 : RS2REG) : 0;
@@ -1161,40 +1593,28 @@ void mb86901_device::execute_mulscc(uint32_t op)
// opcode
//-------------------------------------------------
-void mb86901_device::execute_rdsr(uint32_t op)
+void sparc_base_device::execute_rdsr(uint32_t op)
{
- /* The SPARC Instruction Manual: Version 8, page 182, "Appendix C - ISP Descriptions - Read State Register Instructions" (SPARCv8.pdf, pg. 179)
+ // The SPARC Instruction Manual: Version 8, page 182, "Appendix C - ISP Descriptions - Read State Register Instructions" (SPARCv8.pdf, pg. 179)
- if ((RDPSR or RDWIM or RDBTR
- or (RDASR and (privileged_ASR(rs1) = 1))) and (S = 0)) then (
- trap <- 1;
- privileged_instruction <- 1;
- else if (illegal_instruction_ASR(rs1) = 1) then (
- trap <- 1;
- illegal_instruction <- 1
- else if (rd != 0) then (
- if (RDY) then r[rd] <- Y
- else if (RDASR) then r[rd] <- ASR[rs1]
- else if (RDPSR) then r[rd] <- PSR
- else if (RDWIM) then r[rd] <- WIM
- else if (RDTBR) then r[rd] <- TBR;
- );
- */
+ if (RDASR && RS1 == 15 && RD == 0)
+ {
+ // Store Barrier instruction - not implemented, as stores are always consistent in the context of MAME
+ PC = nPC;
+ nPC = nPC + 4;
+ return;
+ }
- if (((WRPSR || WRWIM || WRTBR) || (WRASR && m_privileged_asr[RS1])) && IS_USER)
+ if (((RDPSR || RDWIM || RDTBR) || (RDASR && m_privileged_asr[RS1])) && IS_USER)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (m_illegal_instruction_asr[RS1])
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1227,51 +1647,10 @@ void mb86901_device::execute_rdsr(uint32_t op)
// opcode
//-------------------------------------------------
-void mb86901_device::execute_wrsr(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 183, "Appendix C - ISP Descriptions - Write State Register Instructions" (SPARCv8.pdf, pg. 180)
-
- operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
- result := r[rs1] xor operand2;
-
- if (WRY) then (
- Y'''' <- result
- ) else if (WRASR) then (
- if ( (privileged_ASR(rd) = 1) and (S = 0) ) then (
- trap <- 1;
- privileged_instruction <- 1
- ) else if (illegal_instruction_ASR(rd) = 1) then (
- trap <- 1;
- illegal_instruction <- 1
- ) else (
- ASR[rd]'''' <- result
- )
- ) else if (WRPSR) then (
- if (S = 0) then (
- trap <- 1;
- privileged_instruction <- 1
- ) else if (result<4:0> >= NWINDOWS) then (
- trap <- 1;
- illegal_instruction <- 1
- ) else (
- PSR'''' <- result
- )
- ) else if (WRWIM) then (
- if (S = 0) then (
- trap <- 1;
- privileged_instruction <- 1
- ) else (
- WIM'''' <- result
- )
- ) else if (WRBTR) then (
- if (S = 0) then (
- trap <- 1;
- privileged_instruction <- 1
- ) else (
- WIM'''' <- result
- )
- );
- */
+void sparc_base_device::execute_wrsr(uint32_t op)
+{
+ // The SPARC Instruction Manual: Version 8, page 183, "Appendix C - ISP Descriptions - Write State Register Instructions" (SPARCv8.pdf, pg. 180)
+
uint32_t operand2 = USEIMM ? SIMM13 : RS2REG;
uint32_t result = RS1REG ^ operand2;
@@ -1288,16 +1667,12 @@ void mb86901_device::execute_wrsr(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (m_illegal_instruction_asr[RD])
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else
@@ -1313,20 +1688,16 @@ void mb86901_device::execute_wrsr(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if ((result & 31) >= NWINDOWS)
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- PSR = result &~ PSR_ZERO_MASK;
+ PSR = (PSR & PSR_ZERO_MASK) | (result & ~PSR_ZERO_MASK);
update_gpr_pointers();
m_et = PSR & PSR_ET_MASK;
@@ -1341,6 +1712,12 @@ void mb86901_device::execute_wrsr(uint32_t op)
m_data_space = 10;
}
+ if (m_et && (m_bp_irl == 15 || m_bp_irl > m_pil) && m_interrupt_level == 0)
+ {
+ m_trap = 1;
+ m_interrupt_level = m_bp_irl;
+ }
+
PC = nPC;
nPC = nPC + 4;
}
@@ -1350,8 +1727,6 @@ void mb86901_device::execute_wrsr(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1365,8 +1740,6 @@ void mb86901_device::execute_wrsr(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1382,43 +1755,9 @@ void mb86901_device::execute_wrsr(uint32_t op)
// opcode
//-------------------------------------------------
-void mb86901_device::execute_rett(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 181, "Appendix C - ISP Descriptions - Return from Trap Instructions" (SPARCv8.pdf, pg. 178)
-
- new_cwp <- (CWP + 1) modulo NWINDOWS;
- address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
- next;
- if (ET = 1) then (
- trap <- 1;
- if (S = 0) then privileged_instruction <- 1
- else if (S != 0) then illegal_instruction <- 1
- ) else if (S = 0) then (
- trap <- 1;
- privileged_instruction <- 1
- tt <- 00000011; { trap type for privileged_instruction }
- execute_mode <- 0;
- error_mode = 1
- ) else if ((WIM and (1 << new_cwp)) != 0) then (
- trap <- 1;
- window_underflow <- 1;
- tt <- 00000110; { trap type for window_underflow }
- execute_mode = 0;
- error_mode = 1
- ) else if (address<1:0> != 0) then (
- trap = 1;
- mem_address_not_aligned = 1;
- tt = 7; { trap type for mem_address_not_aligned }
- execute_mode = 0;
- error_mode = 1
- ) else (
- ET <- 1;
- PC <- nPC;
- nPC <- address;
- CWP <- new_cwp;
- S <- PS
- )
- */
+void sparc_base_device::execute_rett(uint32_t op)
+{
+ // The SPARC Instruction Manual: Version 8, page 181, "Appendix C - ISP Descriptions - Return from Trap Instructions" (SPARCv8.pdf, pg. 178)
uint8_t new_cwp = ((PSR & PSR_CWP_MASK) + 1) % NWINDOWS;
uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
@@ -1433,8 +1772,6 @@ void mb86901_device::execute_rett(uint32_t op)
{
m_illegal_instruction = 1;
}
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (IS_USER)
@@ -1444,8 +1781,6 @@ void mb86901_device::execute_rett(uint32_t op)
m_tt = 3;
m_execute_mode = 0;
m_error_mode = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if ((WIM & (1 << new_cwp)) != 0)
@@ -1455,8 +1790,6 @@ void mb86901_device::execute_rett(uint32_t op)
m_tt = 6;
m_execute_mode = 0;
m_error_mode = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (address & 3)
@@ -1466,8 +1799,6 @@ void mb86901_device::execute_rett(uint32_t op)
m_tt = 7;
m_execute_mode = 0;
m_error_mode = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1493,6 +1824,12 @@ void mb86901_device::execute_rett(uint32_t op)
}
update_gpr_pointers();
+
+ if (m_et && (m_bp_irl == 15 || m_bp_irl > m_pil) && m_interrupt_level == 0)
+ {
+ m_trap = 1;
+ m_interrupt_level = m_bp_irl;
+ }
}
@@ -1502,37 +1839,9 @@ void mb86901_device::execute_rett(uint32_t op)
// opcode
//-------------------------------------------------
-void mb86901_device::execute_saverestore(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 177, "Appendix C - ISP Descriptions - SAVE and RESTORE Instructions" (SPARCv8.pdf, pg. 174)
-
- operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
-
- if (SAVE) then (
- new_cwp <- (CWP - 1) modulo NWINDOWS;
- next;
- if ((WIM and (1 << new_cwp)) != 0) then (
- trap <- 1;
- window_overflow <- 1
- ) else (
- result <- r[rs1] + operand2; { operands from old window }
- CWP <- new_cwp
- )
- ) else if (RESTORE) then (
- new_cwp <- (CWP + 1) modulo NWINDOWS;
- next;
- if ((WIM and (1 << new_cwp)) != 0) then (
- trap <- 1;
- window_overflow <- 1
- ) else (
- result <- r[rs1] + operand2; { operands from old window }
- CWP <- new_cwp
- )
- );
- next;
- if ((trap = 0) and (rd != 0)) then
- r[rd] <- result { destination in new window }
- */
+void sparc_base_device::execute_saverestore(uint32_t op)
+{
+ // The SPARC Instruction Manual: Version 8, page 177, "Appendix C - ISP Descriptions - SAVE and RESTORE Instructions" (SPARCv8.pdf, pg. 174)
uint32_t rs1 = RS1REG;
uint32_t operand2 = USEIMM ? SIMM13 : RS2REG;
@@ -1545,8 +1854,6 @@ void mb86901_device::execute_saverestore(uint32_t op)
{
m_trap = 1;
m_window_overflow = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1561,8 +1868,6 @@ void mb86901_device::execute_saverestore(uint32_t op)
{
m_trap = 1;
m_window_underflow = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1585,21 +1890,9 @@ void mb86901_device::execute_saverestore(uint32_t op)
// execute_jmpl - execute a jump and link opcode
//-------------------------------------------------
-void mb86901_device::execute_jmpl(uint32_t op)
+void sparc_base_device::execute_jmpl(uint32_t op)
{
- /* The SPARC Instruction Manual: Version 8, page 180, "Appendix C - ISP Descriptions - SAVE and RESTORE Instructions" (SPARCv8.pdf, pg. 177)
-
- jump_address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
- next;
- if (jump_address<1:0> != 0) then (
- trap <- 1;
- mem_address_not_aligned <- 1
- ) else (
- if (rd != 0) then r[rd] <- PC;
- PC <- nPC;
- nPC <- jump_address
- )
- */
+ // The SPARC Instruction Manual: Version 8, page 180, "Appendix C - ISP Descriptions - SAVE and RESTORE Instructions" (SPARCv8.pdf, pg. 177)
uint32_t jump_address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
@@ -1607,8 +1900,6 @@ void mb86901_device::execute_jmpl(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
}
else
{
@@ -1625,7 +1916,7 @@ void mb86901_device::execute_jmpl(uint32_t op)
// mostly ALU ops
//-------------------------------------------------
-inline void mb86901_device::execute_group2(uint32_t op)
+inline void sparc_base_device::execute_group2(uint32_t op)
{
switch (OP3)
{
@@ -1718,11 +2009,8 @@ inline void mb86901_device::execute_group2(uint32_t op)
case OP3_FPOP2:
if (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present)
{
- //printf("fpop @ %08x: %08x\n", PC, op);
m_trap = 1;
m_fp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
}
complete_fp_execution(op);
return;
@@ -1750,49 +2038,108 @@ inline void mb86901_device::execute_group2(uint32_t op)
execute_saverestore(op);
break;
-#if SPARCV8
+ default:
+ if (!execute_extra_group2(op))
+ {
+ logerror("illegal instruction at %08x: %08x\n", PC, op);
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ }
+ break;
+ }
+}
+
+
+//-------------------------------------------------
+// update_extra_group2 - execute a group2
+// instruction belonging to a newer SPARC version
+// than v7, or which can be overridden from v7
+//-------------------------------------------------
+
+bool sparcv7_device::execute_extra_group2(uint32_t op)
+{
+ switch (OP3)
+ {
+ default:
+ return false;
+ }
+}
+
+bool sparcv8_device::execute_extra_group2(uint32_t op)
+{
+ switch (OP3)
+ {
case OP3_UMUL:
case OP3_SMUL:
case OP3_UMULCC:
case OP3_SMULCC:
execute_mul(op);
- break;
+ return true;
case OP3_UDIV:
case OP3_SDIV:
case OP3_UDIVCC:
case OP3_SDIVCC:
execute_div(op);
- break;
+ return true;
case OP3_CPOP1:
case OP3_CPOP2:
- logerror("fpop @ %08x: %08x\n", PC, op);
+ logerror("cpop @ %08x: %08x\n", PC, op);
m_trap = 1;
m_cp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
- return;
-#endif
+ return true;
default:
- logerror("illegal instruction at %08x: %08x\n", PC, op);
- m_trap = 1;
- m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
- break;
+ return false;
}
}
+void mb86930_device::execute_divscc(uint32_t op)
+{
+ fatalerror("Not yet supported: divscc at %08x\n", PC);
+ /*const bool n_flag = (PSR & PSR_N_MASK);
+ const bool v_flag = (PSR & PSR_V_MASK);
+ const bool true_sign = n_flag ^ v_flag;
+ const uint64_t dividend = ((uint64_t)m_y << 32) | RS1REG;
+ const uint32_t remainder = m_y << 1;
+ const uint32_t divisor = (USEIMM ? SIMM13 : RS2REG);*/
+}
+
+void mb86930_device::execute_scan(uint32_t op)
+{
+ fatalerror("Not yet supported: scan at %08x\n", PC);
+}
+
+bool mb86930_device::execute_extra_group2(uint32_t op)
+{
+ switch (OP3)
+ {
+ case OP3_DIVSCC:
+ execute_divscc(op);
+ return true;
+
+ case OP3_SCAN:
+ execute_scan(op);
+ return true;
+ case OP3_UMUL:
+ case OP3_SMUL:
+ case OP3_UMULCC:
+ case OP3_SMULCC:
+ return sparcv8_device::execute_extra_group2(op);
+
+ default:
+ return false;
+ }
+}
//-------------------------------------------------
// update_gpr_pointers - cache pointers to
// the registers in our current window
//-------------------------------------------------
-void mb86901_device::update_gpr_pointers()
+void sparc_base_device::update_gpr_pointers()
{
int cwp = PSR & PSR_CWP_MASK;
for (int i = 0; i < 8; i++)
@@ -1808,141 +2155,20 @@ void mb86901_device::update_gpr_pointers()
// execute_store - execute a store-type opcode
//-------------------------------------------------
-void mb86901_device::execute_store(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 165, "Appendix C - ISP Descriptions - Store Instructions" (SPARCv8.pdf, pg. 162)
-
- if ( (S = 0) and (STDA or STA or STHA or STBA or STDFQ or STDCQ) ) then (
- trap <- 1;
- privileged_instruction <- 1
- ) else if ((i = 1) and (STDA or STA or STHA or STBA)) then (
- trap <- 1;
- illegal_instruction <- 1
- );
- next;
- if (trap = 0) then (
- if (STD or ST or STH or STB or STF or STDF or STFSR or STDFQ or STCSR or STC or STDC or STDCQ) then (
- address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
- addr_space <- (if (S = 0) then 10 else 11)
- ) else if (STDA or STA or STHA or STBA) then (
- address <- r[rs1] + r[rs2];
- addr_space <- asi
- );
- if ((STF or STDF or STFSR or STDFQ) and
- ((EF = 0) or (bp_FPU_present = 0)) ) then (
- trap <- 1;
- fp_disabled <- 1;
- );
- if ((STC or STDC or STCSR or STDCQ) and
- ((EC = 0) or (bp_CP_present = 0)) ) then (
- trap <- 1;
- cp_disabled <- 1;
- )
- );
- next;
- if (trap = 0) then (
- if ((STH or STHA) and (address<0> != 0)) then (
- trap <- 1;
- mem_address_not_aligned <- 1
- ) else if ((ST or STA or STF or STFSR or STC or STCSR) and (address<1:0> != 0)) then (
- trap <- 1;
- mem_address_not_aligned <- 1
- ) else if ((STD or STDA or STDF or STDFQ or STDC or STDCQ) and (address<2:0> != 0)) then (
- trap <- 1;
- mem_address_not_aligned <- 1
- ) else (
- if (STDFQ and ((implementation has no floating-point queue) or (FSR.qne = 0))) then (
- trap <- 1;
- fp_exception <- 1;
- ftt <- sequence_error;
- );
- if (STDCQ and ((implementation has no coprocessor queue)) then (
- trap <- 1;
- cp_exception <- 1;
- { possibly additional implementation-dependent actions }
- );
- if (STDF and (rd<0> != 0)) then (
- trap <- 1;
- fp_exception <- 1;
- ftt <- invalid_fp_register;
- )
- )
- );
- next;
- if (trap = 0) then (
- if (STF) then ( byte_mask <- 1111; data0 <- f[rd] )
- else if (STC) then ( byte_mask <- 1111; data0 <- implementation_dependent_value )
- else if (STDF) then ( byte_mask <- 1111; data0 <- f[rd & 0x1e] )
- else if (STDC) then ( byte_mask <- 1111; data0 <- implementation_dependent_value )
- else if (STD or STDA) then ( byte_mask <- 1111; data0 <- r[rd & 0x1e] )
- else if (STDFQ) then ( byte_mask <- 1111; data0 <- implementation_dependent_value )
- else if (STDCQ) then ( byte_mask <- 1111; data0 <- implementation_dependent_value )
- else if (STFSR) then (
- while ((FSR.qne = 1) and (trap = 0)) (
- // wait for pending floating-point instructions to complete
- )
- next;
- byte_mask <- 1111; data0 <- FSR
- ) else if (STCSR) then (
- { implementation-dependent actions }
- byte_mask <- 1111; data0 <- CSR
- ) else if (ST or STA) then ( byte_mask <- 1111; data0 = r[rd] )
- else if (STH or STHA) then (
- if (address<1:0> = 0) then (
- byte_mask <- 1100; data0 <- shift_left_logical(r[rd], 16) )
- else if (address<1:0> = 2) then (
- byte_mask <- 0011; data0 <- r[rd] )
- ) else if (STB or STBA) then (
- if (address<1:0> = 0) then (
- byte_mask <- 1000; data0 <- shift_left_logical(r[rd], 24) )
- ) else if (address<1:0> = 1) then (
- byte_mask <- 0100; data0 <- shift_left_logical(r[rd], 16) )
- ) else if (address<1:0> = 2) then (
- byte_mask <- 0010; data0 <- shift_left_logical(r[rd], 8) )
- ) else if (address<1:0> = 3) then (
- byte_mask <- 0001; data0 <- r[rd] )
- )
- );
- );
- next;
- if (trap = 0) then (
- MAE <- memory_write(addr_space, address, byte_mask, data1);
- next;
- if (MAE = 1) then (
- trap <- 1;
- data_access_exception <- 1
- )
- );
- if ((trap = 0) and (STD or STDA or STDF or STDC or STDFQ or STDCQ)) then (
- if (STD or STDA) then ( data1 <- r[rd or 00001] )
- else if (STDF) then ( data1 <- f[rd or 00001] )
- else if (STDC) then ( data1 <- implementation_dependent_value }
- else if (STDFQ) then ( data1 <- implementation_dependent_value }
- else if (STDCQ) then ( data1 <- implementation_dependent_value }
- next;
- MAE <- memory_write(addr_space, address + 4, 1111, data1);
- next;
- if (MAE = 1) then ( { MAE = 1 only due to a "non-resumable machine-check error" }
- trap <- 1;
- data_access_exception <- 1
- )
- );
- */
+void sparc_base_device::execute_store(uint32_t op)
+{
+ // The SPARC Instruction Manual: Version 8, page 165, "Appendix C - ISP Descriptions - Store Instructions" (SPARCv8.pdf, pg. 162)
if (IS_USER && (STDA || STA || STHA || STBA || STDFQ || STDCQ))
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- else if (USEIMM && (STDA || STA || STHA || STBA))
+ else if ((USEIMM && (STDA || STA || STHA || STBA)) || ((STD || STDA) && (RD & 1)))
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1962,24 +2188,18 @@ void mb86901_device::execute_store(uint32_t op)
{
m_trap = 1;
m_fp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
if ((STC || STDC || STCSR || STDCQ) && (!(PSR & PSR_EC_MASK) || !m_bp_cp_present))
{
m_trap = 1;
m_cp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
if ((STH || STHA) && ((address & 1) != 0))
{
m_trap = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
m_mem_address_not_aligned = 1;
return;
}
@@ -1987,27 +2207,18 @@ void mb86901_device::execute_store(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if ((STD || STDA || STDF || STDFQ || STDC || STDCQ) && ((address & 7) != 0))
{
- m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
+ m_trap = 1;
return;
}
if (STDFQ)
{
// assume no floating-point queue for now
- m_trap = 1;
- m_fp_exception = 1;
- m_ftt = m_fpu_sequence_err;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
if (STDCQ)
@@ -2015,27 +2226,20 @@ void mb86901_device::execute_store(uint32_t op)
// assume no coprocessor queue for now
m_trap = 1;
m_cp_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
// { possibly additional implementation-dependent actions }
return;
}
- if (STDF && ((RD & 1) != 0))
- {
- m_trap = 1;
- m_fp_exception = 1;
- m_ftt = 0xff;
- m_stashed_icount = m_icount;
- m_icount = 0;
- return;
- }
uint32_t data0 = 0;
+ uint32_t data1 = 0;
//uint8_t byte_mask;
if (STF)
{
//byte_mask = 15;
- data0 = FREG(RD);
+ if (get_fpr32(data0, RD))
+ {
+ return;
+ }
}
else if (STC)
{
@@ -2045,7 +2249,14 @@ void mb86901_device::execute_store(uint32_t op)
else if (STDF)
{
//byte_mask = 15;
- data0 = FREG(RD & 0x1e);
+ if (get_fpr32(data0, RD & 0x1e))
+ {
+ return;
+ }
+ if (get_fpr32(data1, RD | 1))
+ {
+ return;
+ }
}
else if (STDC)
{
@@ -2056,16 +2267,19 @@ void mb86901_device::execute_store(uint32_t op)
{
//byte_mask = 15;
data0 = REG(RD & 0x1e);
+ data1 = REG(RD | 1);
}
else if (STDFQ)
{
//byte_mask = 15;
data0 = 0;
+ data1 = 0;
}
else if (STDCQ)
{
//byte_mask = 15;
data0 = 0;
+ data1 = 0;
}
else if (STFSR)
{
@@ -2126,47 +2340,21 @@ void mb86901_device::execute_store(uint32_t op)
static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 };
static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
- m_mmu->write_asi(addr_space, address >> 2, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 0xffffffff : ((STH || STHA) ? mask16[address & 2] : mask8[address & 3]));
+ write_word(addr_space, address, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 0xffffffff : ((STH || STHA) ? mask16[address & 2] : mask8[address & 3]));
if (MAE)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
if (STD || STDA || STDF || STDC || STDFQ || STDCQ)
{
- uint32_t data1 = 0;
- if (STD || STDA)
- {
- data1 = REG(RD | 1);
- }
- else if (STDF)
- {
- data1 = FREG(RD | 1);
- }
- else if (STDC)
- {
- data1 = 0;
- }
- else if (STDFQ)
- {
- data1 = 0;
- }
- else if (STDCQ)
- {
- data1 = 0;
- }
-
- m_mmu->write_asi(addr_space, (address + 4) >> 2, data1, 0xffffffff);
+ write_word(addr_space, address + 4, data1);
if (MAE)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
}
@@ -2175,139 +2363,43 @@ void mb86901_device::execute_store(uint32_t op)
nPC = nPC + 4;
}
-/* The SPARC Instruction Manual: Version 8, page 163, "Appendix C - ISP Descriptions - C.9. Instruction Defintions - Load Instructions" (SPARCv8.pdf, pg. 160)
-
-if (LDD or LD or LDSH or LDUH or LDSB or LDUB or LDDF or LDF or LDFSR or LDDC or LDC or LDCSR) then (
- address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
- addr_space <- (if (S = 0) then 10 else 11)
-) else if (LDDA or LDA or LDSHA or LDUHA or LDSBA or LDUBA) then (
- if (S = 0) then (
- trap <- 1;
- privileged_instruction <- 1
- ) else if (i = 1) then (
- trap <- 1;
- illegal_instruction <- 1
- ) else (
- address <- r[rs1] + r[rs2];
- addr_space <- asi
- )
-)
-next;
-if (trap = 0) then (
- if ( (LDF or LDDF or LDFSR) and ((EF = 0) or (bp_FPU_present = 0)) then (
- trap <- 1;
- fp_disabled <- 1
- ) else if ( (LDC or LDDC or LDCSR) and ((EC = 0) or (bp_CP_present = 0)) then (
- trap <- 1;
- cp_disabled <- 1
- ) else if ( ( (LDD or LDDA or LDDF or LDDC) and (address<2:0> != 0)) or
- ((LD or LDA or LDF or LDFSR or LDC or LDCSR) and (address<1:0> != 0)) or
- ((LDSH or LDSHA or LDUH or LDUHA) and address<0> != 0) ) then (
- trap <- 1;
- mem_address_not_aligned <- 1
- ) else if (LDDF and (rd<0> != 0)) then (
- trap <- 1;
- fp_exception <- 1;
- ftt <- invalid_fpr_register
- ) else if ((LDF or LDDF or LDFSR) and (an FPU sequence error is detected)) then (
- trap <- 1;
- fp_exception <- 1;
- ftt <- sequence_error
- ) else if ((LDC or LDDC or LDCSR) and (a CP sequence error is detected)) then (
- trap <- 1;
- cp_exception <- 1;
- { possibly additional implementation-dependent actions }
- )
-);
-next;
-if (trap = 0) then {
- (data, MAE) <- memory_read(addr_space, address);
- next;
- if (MAE = 1) then (
- trap <- 1;
- data_access_exception <- 1;
- ) else (
- if (LDSB or LDSBA or LDUB or LDUBA) then (
- if (address<1:0> = 0) then byte <- data<31:24>
- else if (address<1:0> = 1) then byte <- data<23:16>
- else if (address<1:0> = 2) then byte <- data<15: 8>
- else if (address<1:0> = 3) then byte <- data< 7: 0>
- next;
- if (LDSB or LDSBA) then
- word0 <- sign_extend_byte(byte)
- else
- word0 <- zero_extend_byte(byte)
- ) else if (LDSH or LDSHA or LDUH or LDUHA) then (
- if (address<1:0> = 0) then halfword <- data<31:16>
- else if (address<1:0> = 2) then halfword <- data<15: 0>
- next;
- if (LDSH or LDSHA) then
- word0 <- sign_extend_halfword(halfword)
- else
- word0 <- zero_extend_halfword(halfword)
- ) else
- word0 <- data
- )
-);
-next;
-if (trap = 0) then (
- if ( (rd != 0) and (LD or LDA or LDSH or LDSHA
- or LDUHA or LDUH or LDSB or LDSBA or LDUB or LDUBA) ) then
- r[rd] <- word0
- else if (LDF) then f[rd] <- word0
- else if (LDC) then { implementation-dependent actions }
- else if (LDFSR) then FSR <- word0
- else if (LDCSR) then CSR <- word0
- else if (LDD or LDDA) then r[rd and 11110] <- word0
- else if (LDDF) then f[rd and 11110] <- word0
- else if (LDDC) then { implementation-dependent actions }
-);
-next;
-if (((trap = 0) and (LDD or LDDA or LDDF or LDDC)) then (
- (word1, MAE) <- memory_read(addr_space, address + 4);
- next;
- if (MAE = 1) then ( { MAE = 1 only due to a "non-resumable machine-check error" }
- trap <- 1;
- data_access_exception <- 1 )
- else if (LDD or LDDA) then r[rd or 1] <- word1
- else if (LDDF) then f[rd or 1] <- word1
- else if (LDDC) then { implementation-dependent actions }
-);
-*/
-
-inline void mb86901_device::execute_ldd(uint32_t op)
+// The SPARC Instruction Manual: Version 8, page 163, "Appendix C - ISP Descriptions - C.9. Instruction Defintions - Load Instructions" (SPARCv8.pdf, pg. 160)
+
+inline void sparc_base_device::execute_ldd(uint32_t op)
{
+ if (RD & 1)
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ return;
+ }
+
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
if (address & 7)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
+ return;
}
- const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff);
+ const uint32_t data = read_word(m_data_space, address);
if (MAE)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
if (RDBITS)
RDREG = data;
- const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff);
+ const uint32_t word1 = read_word(m_data_space, address + 4);
if (MAE)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2317,7 +2409,7 @@ inline void mb86901_device::execute_ldd(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_ld(uint32_t op)
+inline void sparc_base_device::execute_ld(uint32_t op)
{
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
@@ -2325,19 +2417,15 @@ inline void mb86901_device::execute_ld(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff);
+ const uint32_t data = read_word(m_data_space, address);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2348,7 +2436,7 @@ inline void mb86901_device::execute_ld(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_ldsh(uint32_t op)
+inline void sparc_base_device::execute_ldsh(uint32_t op)
{
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
@@ -2356,20 +2444,16 @@ inline void mb86901_device::execute_ldsh(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 };
- const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]);
+ const uint32_t data = read_word(m_data_space, address, mask16[address & 2]);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2383,7 +2467,7 @@ inline void mb86901_device::execute_ldsh(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_lduh(uint32_t op)
+inline void sparc_base_device::execute_lduh(uint32_t op)
{
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
@@ -2391,20 +2475,16 @@ inline void mb86901_device::execute_lduh(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 };
- const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]);
+ const uint32_t data = read_word(m_data_space, address, mask16[address & 2]);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2418,19 +2498,17 @@ inline void mb86901_device::execute_lduh(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_ldsb(uint32_t op)
+inline void sparc_base_device::execute_ldsb(uint32_t op)
{
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
- const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[address & 3]);
+ const uint32_t data = read_word(m_data_space, address, mask8[address & 3]);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2446,20 +2524,18 @@ inline void mb86901_device::execute_ldsb(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_ldub(uint32_t op)
+inline void sparc_base_device::execute_ldub(uint32_t op)
{
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
const uint32_t byte_idx = address & 3;
- const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[byte_idx]);
+ const uint32_t data = read_word(m_data_space, address, mask8[byte_idx]);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2473,7 +2549,7 @@ inline void mb86901_device::execute_ldub(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_lddfpr(uint32_t op)
+inline void sparc_base_device::execute_lddfpr(uint32_t op)
{
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
@@ -2481,8 +2557,6 @@ inline void mb86901_device::execute_lddfpr(uint32_t op)
{
m_trap = 1;
m_fp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2490,61 +2564,44 @@ inline void mb86901_device::execute_lddfpr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- if (RD & 1)
+ const uint32_t data = read_word(m_data_space, address);
+
+ if (m_mae)
{
m_trap = 1;
- m_fp_exception = 1;
- m_ftt = 0xff;
- m_stashed_icount = m_icount;
- m_icount = 0;
+ m_data_access_exception = 1;
return;
}
- if (m_fpu_sequence_err)
+ if (m_pending_fpr == (RD & 0x1e))
{
- m_trap = 1;
- m_fp_exception = 1;
- m_ftt = m_fpu_sequence_err;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff);
-
- if (m_mae)
+ const uint32_t word1 = read_word(m_data_space, address + 4);
+ if (MAE)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- FREG(RD & 0x1e) = data;
-
- const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff);
- if (MAE)
+ if (m_pending_fpr == (RD | 1))
{
- m_trap = 1;
- m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
+ FREG(RD & 0x1e) = data;
FREG(RD | 1) = word1;
PC = nPC;
nPC = nPC + 4;
}
-inline void mb86901_device::execute_ldfpr(uint32_t op)
+inline void sparc_base_device::execute_ldfpr(uint32_t op)
{
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
@@ -2552,8 +2609,6 @@ inline void mb86901_device::execute_ldfpr(uint32_t op)
{
m_trap = 1;
m_fp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2561,29 +2616,20 @@ inline void mb86901_device::execute_ldfpr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- if (m_fpu_sequence_err)
+ const uint32_t data = read_word(m_data_space, address);
+
+ if (m_mae)
{
m_trap = 1;
- m_fp_exception = 1;
- m_ftt = m_fpu_sequence_err;
- m_stashed_icount = m_icount;
- m_icount = 0;
+ m_data_access_exception = 1;
return;
}
- const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff);
-
- if (m_mae)
+ if (m_pending_fpr == RD)
{
- m_trap = 1;
- m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2593,7 +2639,7 @@ inline void mb86901_device::execute_ldfpr(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_ldfsr(uint32_t op)
+inline void sparc_base_device::execute_ldfsr(uint32_t op)
{
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
@@ -2601,8 +2647,6 @@ inline void mb86901_device::execute_ldfsr(uint32_t op)
{
m_trap = 1;
m_fp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2610,39 +2654,33 @@ inline void mb86901_device::execute_ldfsr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- if (m_fpu_sequence_err)
- {
- m_trap = 1;
- m_fp_exception = 1;
- m_ftt = m_fpu_sequence_err;
- m_stashed_icount = m_icount;
- m_icount = 0;
- return;
- }
-
- const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff);
+ const uint32_t data = read_word(m_data_space, address);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- FSR = data;
+ FSR = (data & ~FSR_RESV_MASK) | FSR_VER;
+
+ switch (FSR & FSR_RD_MASK)
+ {
+ case FSR_RD_NEAR: softfloat_roundingMode = softfloat_round_near_even; break;
+ case FSR_RD_ZERO: softfloat_roundingMode = softfloat_round_minMag; break;
+ case FSR_RD_UP: softfloat_roundingMode = softfloat_round_max; break;
+ case FSR_RD_DOWN: softfloat_roundingMode = softfloat_round_min; break;
+ }
PC = nPC;
nPC = nPC + 4;
}
-inline void mb86901_device::execute_lddcpr(uint32_t op)
+inline void sparc_base_device::execute_lddcpr(uint32_t op)
{
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
@@ -2650,8 +2688,6 @@ inline void mb86901_device::execute_lddcpr(uint32_t op)
{
m_trap = 1;
m_cp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2659,8 +2695,6 @@ inline void mb86901_device::execute_lddcpr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2668,31 +2702,25 @@ inline void mb86901_device::execute_lddcpr(uint32_t op)
{
m_trap = 1;
m_cp_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
// possibly additional implementation-dependent actions
return;
}
- m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff);
+ read_word(m_data_space, address);
if (MAE)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
// implementation-dependent actions
- m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff);
+ read_word(m_data_space, address + 4);
if (MAE)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2702,7 +2730,7 @@ inline void mb86901_device::execute_lddcpr(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_ldcpr(uint32_t op)
+inline void sparc_base_device::execute_ldcpr(uint32_t op)
{
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
@@ -2710,8 +2738,6 @@ inline void mb86901_device::execute_ldcpr(uint32_t op)
{
m_trap = 1;
m_cp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2719,8 +2745,6 @@ inline void mb86901_device::execute_ldcpr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2728,20 +2752,16 @@ inline void mb86901_device::execute_ldcpr(uint32_t op)
{
m_trap = 1;
m_cp_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
// possibly additional implementation-dependent actions
return;
}
- m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff);
+ read_word(m_data_space, address);
if (MAE)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2751,7 +2771,7 @@ inline void mb86901_device::execute_ldcpr(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_ldcsr(uint32_t op)
+inline void sparc_base_device::execute_ldcsr(uint32_t op)
{
const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
@@ -2759,8 +2779,6 @@ inline void mb86901_device::execute_ldcsr(uint32_t op)
{
m_trap = 1;
m_cp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2768,8 +2786,6 @@ inline void mb86901_device::execute_ldcsr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2777,20 +2793,16 @@ inline void mb86901_device::execute_ldcsr(uint32_t op)
{
m_trap = 1;
m_cp_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
// possibly additional implementation-dependent actions
return;
}
- m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff);
+ read_word(m_data_space, address);
if (MAE)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2800,22 +2812,18 @@ inline void mb86901_device::execute_ldcsr(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_ldda(uint32_t op)
+inline void sparc_base_device::execute_ldda(uint32_t op)
{
if (IS_USER)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- else if (USEIMM)
+ else if (USEIMM || (RD & 1))
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2826,32 +2834,26 @@ inline void mb86901_device::execute_ldda(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- const uint32_t data = m_mmu->read_asi(addr_space, address >> 2, 0xffffffff);
+ const uint32_t data = read_word(addr_space, address);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
if (RDBITS)
RDREG = data;
- uint32_t word1 = m_mmu->read_asi(addr_space, (address + 4) >> 2, 0xffffffff);
+ uint32_t word1 = read_word(addr_space, address + 4);
if (MAE)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2861,22 +2863,18 @@ inline void mb86901_device::execute_ldda(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_lda(uint32_t op)
+inline void sparc_base_device::execute_lda(uint32_t op)
{
if (IS_USER)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (USEIMM)
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2886,19 +2884,15 @@ inline void mb86901_device::execute_lda(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- const uint32_t data = m_mmu->read_asi(ASI, address >> 2, 0xffffffff);
+ const uint32_t data = read_word(ASI, address);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2909,22 +2903,18 @@ inline void mb86901_device::execute_lda(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_ldsha(uint32_t op)
+inline void sparc_base_device::execute_ldsha(uint32_t op)
{
if (IS_USER)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (USEIMM)
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2934,20 +2924,16 @@ inline void mb86901_device::execute_ldsha(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 };
- const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]);
+ const uint32_t data = read_word(ASI, address, mask16[address & 2]);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2961,22 +2947,18 @@ inline void mb86901_device::execute_ldsha(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_lduha(uint32_t op)
+inline void sparc_base_device::execute_lduha(uint32_t op)
{
if (IS_USER)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (USEIMM)
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2985,20 +2967,16 @@ inline void mb86901_device::execute_lduha(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 };
- const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]);
+ const uint32_t data = read_word(ASI, address, mask16[address & 2]);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3012,35 +2990,29 @@ inline void mb86901_device::execute_lduha(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_ldsba(uint32_t op)
+inline void sparc_base_device::execute_ldsba(uint32_t op)
{
if (IS_USER)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (USEIMM)
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
const uint32_t address = RS1REG + RS2REG;
- const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]);
+ const uint32_t data = read_word(ASI, address, mask8[address & 3]);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3056,35 +3028,29 @@ inline void mb86901_device::execute_ldsba(uint32_t op)
nPC = nPC + 4;
}
-inline void mb86901_device::execute_lduba(uint32_t op)
+inline void sparc_base_device::execute_lduba(uint32_t op)
{
if (IS_USER)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (USEIMM)
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
const uint32_t address = RS1REG + RS2REG;
- const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]);
+ const uint32_t data = read_word(ASI, address, mask8[address & 3]);
if (m_mae)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3106,66 +3072,9 @@ inline void mb86901_device::execute_lduba(uint32_t op)
// instruction
//-------------------------------------------------
-void mb86901_device::execute_ldstub(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 169, "Appendix C - ISP Descriptions - Atomic Load-Store Unsigned Byte Instructions" (SPARCv8.pdf, pg. 166)
-
- if (LDSTUB) then (
- address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
- addr_space <- (if (S = 0) then 10 else 11)
- } else if (LDSTUBA) then (
- if (S = 0) then (
- trap <- 1;
- privileged_instruction <- 1
- ) else if (i = 1) then (
- trap <- 1;
- illegal_instruction <- 1
- ) else (
- address <- r[rs1] + r[rs2];
- addr_space <- asi
- )
- );
- next;
- if (trap = 0) then (
- while ( (pb_block_ldst_byte = 1) or (pb_block_ldst_word = 1) ) then (
- { wait for lock(s) to be lifted }
- { an implementation actually need only block when another LDSTUB or SWAP
- is pending on the same byte in memory as the one addressed by this LDSTUB }
- };
- next;
- pb_block_ldst_byte <- 1;
- next;
- (data, MAE) <- memory_read(addr_space, address);
- next;
- if (MAE = 1) then (
- trap <- 1;
- data_access_exception <- 1
- )
- )
- next;
- if (trap = 0) then (
- if (address<1:0> = 0) then ( byte_mask <- 1000 )
- else if (address<1:0> = 1) then ( byte_mask <- 0100 )
- else if (address<1:0> = 2) then ( byte_mask <- 0010 )
- else if (address<1:0> = 3) then ( byte_mask <- 0001 )
- ;
- next;
- MAE <- memory_write(addr_space, address, byte_mask, FFFFFFFF);
- next;
- pb_block_ldst_byte <- 0;
- if (MAE = 1) then ( { MAE = 1 only due to a "non-resumable machine-check error" }
- trap <- 1;
- data_access_exception <- 1
- ) else (
- if (address<1:0> = 0) then word <- zero_extend_byte(data<31:24>)
- else if (address<1:0> = 1) then word <- zero_extend_byte(data<23:24>)
- else if (address<1:0> = 2) then word <- zero_extend_byte(data<15: 8>)
- else if (address<1:0> = 3) then word <- zero_extend_byte(data< 7: 0>)
- next;
- if (rd != 0) then r[rd] <- word
- )
- );
- */
+void sparc_base_device::execute_ldstub(uint32_t op)
+{
+ // The SPARC Instruction Manual: Version 8, page 169, "Appendix C - ISP Descriptions - Atomic Load-Store Unsigned Byte Instructions" (SPARCv8.pdf, pg. 166)
uint32_t address = 0;
uint8_t addr_space = 0;
@@ -3180,49 +3089,41 @@ void mb86901_device::execute_ldstub(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (USEIMM)
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else
{
address = RS1REG + RS2REG;
addr_space = ASI;
- return;
}
}
- uint32_t data(0);
- while (m_pb_block_ldst_byte || m_pb_block_ldst_word)
- {
+ //while (m_pb_block_ldst_byte || m_pb_block_ldst_word)
+ //{
// { wait for lock(s) to be lifted }
// { an implementation actually need only block when another LDSTUB or SWAP
// is pending on the same byte in memory as the one addressed by this LDSTUB }
- }
+ //}
m_pb_block_ldst_byte = 1;
static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
- data = m_mmu->read_asi(addr_space, address >> 2, mask8[address & 3]);
+ uint32_t data = read_word(addr_space, address, mask8[address & 3]);
if (MAE)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
- m_mmu->write_asi(addr_space, address >> 2, 0xffffffff, mask8[address & 3]);
+ write_word(addr_space, address, 0xffffffff, mask8[address & 3]);
m_pb_block_ldst_byte = 0;
@@ -3230,8 +3131,6 @@ void mb86901_device::execute_ldstub(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3265,7 +3164,7 @@ void mb86901_device::execute_ldstub(uint32_t op)
// (load/store)
//-------------------------------------------------
-inline void mb86901_device::execute_group3(uint32_t op)
+inline void sparc_base_device::execute_group3(uint32_t op)
{
static const int ldst_cycles[64] = {
1, 1, 1, 2, 2, 2, 2, 3,
@@ -3359,26 +3258,119 @@ inline void mb86901_device::execute_group3(uint32_t op)
execute_ldstub(op);
break;
-#if SPARCV8
+ default:
+ if (!execute_extra_group3(op))
+ {
+ logerror("illegal instruction at %08x: %08x\n", PC, op);
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ }
+ break;
+ }
+
+ if (MAE)
+ m_icount--;
+ else
+ m_icount -= ldst_cycles[OP3];
+}
+
+
+//-------------------------------------------------
+// update_extra_group3 - execute a group3
+// instruction belonging to a newer SPARC version
+// than v7
+//-------------------------------------------------
+
+bool sparcv7_device::execute_extra_group3(uint32_t op)
+{
+ return false;
+}
+
+bool sparcv8_device::execute_extra_group3(uint32_t op)
+{
+ switch (OP3)
+ {
case OP3_SWAP:
case OP3_SWAPA:
execute_swap(op);
- break;
-#endif
+ return true;
default:
- logerror("illegal instruction at %08x: %08x\n", PC, op);
- m_trap = 1;
- m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
- break;
+ return false;
}
+}
- if (MAE /*|| HOLD_BUS*/)
- m_icount--;
+
+//-------------------------------------------------
+// evaluate_fp_condition - evaluate a given fp
+// condition code
+//-------------------------------------------------
+
+bool sparc_base_device::evaluate_fp_condition(uint32_t op)
+{
+ // COND & 8
+ // 0 8
+ // fbn fba
+ // fbne fbe
+ // fblg fbue
+ // fbul fbge
+ // fbl fbuge
+ // fbug fble
+ // fbg fbule
+ // fbu fbo
+
+ static const uint32_t EQ_BIT = (1 << (FSR_FCC_EQ >> FSR_FCC_SHIFT));
+ static const uint32_t LT_BIT = (1 << (FSR_FCC_LT >> FSR_FCC_SHIFT));
+ static const uint32_t GT_BIT = (1 << (FSR_FCC_GT >> FSR_FCC_SHIFT));
+ static const uint32_t UO_BIT = (1 << (FSR_FCC_UO >> FSR_FCC_SHIFT));
+ const uint32_t fcc_bit = 1 << ((m_fsr & FSR_FCC_MASK) >> FSR_FCC_SHIFT);
+
+ switch(COND)
+ {
+ case 0: return false;
+ case 1: return fcc_bit & (LT_BIT | GT_BIT | UO_BIT);
+ case 2: return fcc_bit & (LT_BIT | GT_BIT);
+ case 3: return fcc_bit & (LT_BIT | UO_BIT);
+ case 4: return fcc_bit & (LT_BIT);
+ case 5: return fcc_bit & (GT_BIT | UO_BIT);
+ case 6: return fcc_bit & (GT_BIT);
+ case 7: return fcc_bit & (UO_BIT);
+
+ case 8: return true;
+ case 9: return fcc_bit & (EQ_BIT);
+ case 10: return fcc_bit & (EQ_BIT | UO_BIT);
+ case 11: return fcc_bit & (EQ_BIT | GT_BIT);
+ case 12: return fcc_bit & (EQ_BIT | GT_BIT | UO_BIT);
+ case 13: return fcc_bit & (EQ_BIT | LT_BIT);
+ case 14: return fcc_bit & (EQ_BIT | LT_BIT | UO_BIT);
+ case 15: return fcc_bit & (EQ_BIT | LT_BIT | GT_BIT);
+ }
+
+ return false;
+}
+
+
+//-------------------------------------------------
+// execute_fbfcc - execute an fp branch opcode
+//-------------------------------------------------
+
+void sparc_base_device::execute_fbfcc(uint32_t op)
+{
+ bool branch_taken = evaluate_fp_condition(op);
+ uint32_t pc = PC;
+ PC = nPC;
+ if (branch_taken)
+ {
+ nPC = pc + DISP22;
+ if (COND == COND_BA && ANNUL)
+ m_no_annul = false;
+ }
else
- m_icount -= ldst_cycles[OP3];
+ {
+ nPC = nPC + 4;
+ if (ANNUL)
+ m_no_annul = false;
+ }
}
@@ -3387,7 +3379,7 @@ inline void mb86901_device::execute_group3(uint32_t op)
// condition code
//-------------------------------------------------
-bool mb86901_device::evaluate_condition(uint32_t op)
+bool sparc_base_device::evaluate_condition(uint32_t op)
{
// COND & 8
// 0 8
@@ -3429,39 +3421,9 @@ bool mb86901_device::evaluate_condition(uint32_t op)
// execute_bicc - execute a branch opcode
//-------------------------------------------------
-void mb86901_device::execute_bicc(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 178, "Appendix C - ISP Descriptions - Branch on Integer Condition Instructions" (SPARCv8.pdf, pg. 175)
-
- eval_icc := (
- if (BNE) then (if (Z = 0) then 1 else 0);
- if (BE) then (if (Z = 1) then 1 else 0);
- if (BG) then (if ((Z or (N xor V)) = 0) then 1 else 0);
- if (BLE) then (if ((Z or (N xor V)) = 1) then 1 else 0);
- if (BGE) then (if ((N xor V) = 0) then 1 else 0);
- if (BL) then (if ((N xor V) = 1) then 1 else 0);
- if (BGU) then (if ((C = 0) and (Z = 0)) then 1 else 0);
- if (BLEU) then (if ((C = 1) or (Z = 1)) then 1 else 0);
- if (BCC) then (if (C = 0) then 1 else 0);
- if (BCS) then (if (C = 1) then 1 else 0);
- if (BPOS) then (if (N = 0) then 1 else 0);
- if (BNEG) then (if (N = 1) then 1 else 0);
- if (BVC) then (if (V = 0) then 1 else 0);
- if (BVS) then (if (V = 1) then 1 else 0);
- if (BA) then 1;
- if (BN) then 0;
- )
- PC <- nPC;
- if (eval_icc = 1) then (
- nPC <- PC + sign_extend(disp22[]00);
- if (BA and (a = 1)) then
- annul <- 1 { only for annulling Branch-Always }
- ) else (
- nPC <- nPC + 4;
- if (a = 1) then
- annul <- 1 { only for annulling branches other than BA }
- )
- */
+void sparc_base_device::execute_bicc(uint32_t op)
+{
+ // The SPARC Instruction Manual: Version 8, page 178, "Appendix C - ISP Descriptions - Branch on Integer Condition Instructions" (SPARCv8.pdf, pg. 175)
bool branch_taken = evaluate_condition(op);
uint32_t pc = PC;
@@ -3485,42 +3447,9 @@ void mb86901_device::execute_bicc(uint32_t op)
// execute_ticc - execute a conditional trap
//-------------------------------------------------
-void mb86901_device::execute_ticc(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 182, "Appendix C - ISP Descriptions - Trap on Integer Condition Instructions" (SPARCv8.pdf, pg. 179)
-
- trap_eval_icc := (
- if (TNE) then (if (Z = 0) then 1 else 0);
- if (TE) then (if (Z = 1) then 1 else 0);
- if (TG) then (if ((Z or (N xor V)) = 0) then 1 else 0);
- if (TLE) then (if ((Z or (N xor V)) = 1) then 1 else 0);
- if (TGE) then (if ((N xor V) = 0) then 1 else 0);
- if (TL) then (if ((N xor V) = 1) then 1 else 0);
- if (TGU) then (if ((C = 0) and (Z = 0)) then 1 else 0);
- if (TLEU) then (if ((C = 1) or (Z = 1)) then 1 else 0);
- if (TCC) then (if (C = 0) then 1 else 0);
- if (TCS) then (if (C = 1) then 1 else 0);
- if (TPOS) then (if (N = 0) then 1 else 0);
- if (TNEG) then (if (N = 1) then 1 else 0);
- if (TVC) then (if (V = 0) then 1 else 0);
- if (TVS) then (if (V = 1) then 1 else 0);
- if (TA) then 1;
- if (TN) then 0;
- )
-
- trap_number := r[rs1] + (if (i = 0) then r[rs2] else sign_extend(software_trap#));
-
- if (Ticc) then (
- if (trap_eval_icc = 1) then (
- trap <- 1;
- trap_instruction <- 1;
- ticc_trap_type <- trap_number<6:0>
- ) else (
- PC <- nPC;
- nPC <- nPC + 4;
- )
- );
- */
+void sparc_base_device::execute_ticc(uint32_t op)
+{
+ // The SPARC Instruction Manual: Version 8, page 182, "Appendix C - ISP Descriptions - Trap on Integer Condition Instructions" (SPARCv8.pdf, pg. 179)
bool trap_eval_icc = evaluate_condition(op);
@@ -3533,8 +3462,6 @@ void mb86901_device::execute_ticc(uint32_t op)
m_trap = 1;
m_trap_instruction = 1;
m_ticc_trap_type = trap_number & 0x7f;
- m_stashed_icount = m_icount;
- m_icount = 0;
}
else
{
@@ -3551,7 +3478,7 @@ void mb86901_device::execute_ticc(uint32_t op)
// additional functions from taking them
//-------------------------------------------------
-void mb86901_device::select_trap()
+void sparc_base_device::select_trap()
{
if (!m_trap)
return;
@@ -3565,10 +3492,74 @@ void mb86901_device::select_trap()
{
m_execute_mode = 0;
m_error_mode = 1;
- m_stashed_icount = m_icount;
m_icount = 0;
}
- else if (m_data_store_error)
+ else
+ {
+ update_tt();
+ }
+
+ TBR = (TBR & 0xfffff000) | (m_tt << 4);
+ m_trap = 0;
+ m_instruction_access_exception = 0;
+ m_illegal_instruction = 0;
+ m_privileged_instruction = 0;
+ m_fp_disabled = 0;
+ m_fp_exception = 0;
+ m_cp_disabled = 0;
+ m_window_overflow = 0;
+ m_window_underflow = 0;
+ m_mem_address_not_aligned = 0;
+ m_cp_exception = 0;
+ m_data_access_exception = 0;
+ m_tag_overflow = 0;
+ m_trap_instruction = 0;
+ m_interrupt_level = 0;
+ m_mae = 0;
+}
+
+
+//-------------------------------------------------
+// update_tt - determine TT register contents
+// based on trap priority
+//-------------------------------------------------
+
+void sparcv7_device::update_tt()
+{
+ if (m_instruction_access_exception)
+ m_tt = 0x01;
+ else if (m_privileged_instruction)
+ m_tt = 0x03;
+ else if (m_illegal_instruction)
+ m_tt = 0x02;
+ else if (m_fp_disabled)
+ m_tt = 0x04;
+ else if (m_cp_disabled)
+ m_tt = 0x24;
+ else if (m_window_overflow)
+ m_tt = 0x05;
+ else if (m_window_underflow)
+ m_tt = 0x06;
+ else if (m_mem_address_not_aligned)
+ m_tt = 0x07;
+ else if (m_fp_exception)
+ m_tt = 0x08;
+ else if (m_cp_exception)
+ m_tt = 0x28;
+ else if (m_data_access_exception)
+ m_tt = 0x09;
+ else if (m_tag_overflow)
+ m_tt = 0x0a;
+ else if (m_trap_instruction)
+ m_tt = 0x80 | m_ticc_trap_type;
+ else if (m_interrupt_level > 0)
+ m_tt = 0x10 | m_interrupt_level;
+}
+
+
+void sparcv8_device::update_tt()
+{
+ if (m_data_store_error)
m_tt = 0x2b;
else if (m_instruction_access_error)
m_tt = 0x21;
@@ -3609,24 +3600,12 @@ void mb86901_device::select_trap()
else if (m_interrupt_level > 0)
m_tt = 0x10 | m_interrupt_level;
- TBR = (TBR & 0xfffff000) | (m_tt << 4);
- m_trap = 0;
- m_instruction_access_exception = 0;
- m_illegal_instruction = 0;
- m_privileged_instruction = 0;
- m_fp_disabled = 0;
- m_cp_disabled = 0;
- m_window_overflow = 0;
- m_window_underflow = 0;
- m_mem_address_not_aligned = 0;
- m_fp_exception = 0;
- m_cp_exception = 0;
- m_data_access_exception = 0;
- m_tag_overflow = 0;
+ m_unimplemented_FLUSH = 0;
+ m_r_register_access_error = 0;
+ m_instruction_access_error = 0;
+ m_data_access_error = 0;
+ m_data_store_error = 0;
m_division_by_zero = 0;
- m_trap_instruction = 0;
- m_interrupt_level = 0;
- m_mae = 0;
}
@@ -3636,86 +3615,9 @@ void mb86901_device::select_trap()
// instructions, if any.
//-------------------------------------------------
-void mb86901_device::execute_trap()
-{
- /* The SPARC Instruction Manual: Version 8, page 161, "Appendix C - C.8. Traps" (SPARCv8.pdf, pg. 158)
-
- select_trap; { see below }
- next;
-
- if (error_mode = 0) then (
- ET <- 0;
- PS <- S;
- CWP <- (CWP - 1) modulo NWINDOWS;
-
- next;
- if (annul = 0) then (
- r[17] <- PC;
- r[18] <- nPC;
- ) else { annul != 0) } (
- r[17] <- nPC;
- r[18] <- nPC + 4;
- annul <- 0;
- )
-
- next;
- S <- 1;
- if (reset_trap = 0) then (
- PC <- TBR;
- nPC <- TBR + 4;
- ) else { reset_trap = 1 } (
- PC <- 0;
- nPC <- 4;
- reset_trap <- 0;
- )
- );
-
- select_trap := (
- if (reset_trap = 1) then { ignore ET, and leave tt unchanged }
- else if (ET = 0) then (
- execute_mode <- 0;
- error_mode <- 1 )
- else if (data_store_error = 1) then tt <- 00101011
- else if (instruction_access_error = 1) then tt <- 00100001
- else if (r_register_access_error = 1) then tt <- 00100000
- else if (instruction_access_exception = 1) then tt <- 00000001
- else if (privileged_instruction = 1) then tt <- 00000011
- else if (illegal_instruction = 1) then tt <- 00000010
- else if (fp_disabled = 1) then tt <- 00000100
- else if (cp_disabled = 1) then tt <- 00100100
- else if (unimplemented_FLUSH = 1) then tt <- 00100101
- else if (window_overflow = 1) then tt <- 00000101
- else if (window_underflow = 1) then tt <- 00000110
- else if (mem_address_not_aligned = 1) then tt <- 00000111
- else if (fp_exception = 1) then tt <- 00001000
- else if (cp_exception = 1) then tt <- 00101000
- else if (data_access_error = 1) then tt <- 00101001
- else if (data_access_exception = 1) then tt <- 00001001
- else if (tag_overflow = 1) then tt <- 00001010
- else if (division_by_zero = 1) then tt <- 00101010
- else if (trap_instruction = 1) then tt <- 1[]ticc_trap_type
- else if (interrupt_level > 0) then tt <- 0001[]interrupt_level;
-
- next;
-
- trap <- 0;
- instruction_access_exception <- 0;
- illegal_instruction <- 0;
- privileged_instruction <- 0;
- fp_disabled <- 0;
- cp_disabled <- 0;
- window_overflow <- 0;
- window_underflow <- 0;
- mem_address_not_aligned <- 0;
- fp_exception <- 0;
- cp_exception <- 0;
- data_access_exception <- 0;
- tag_overflow <- 0;
- division_by_zero <- 0;
- trap_instruction <- 0;
- interrupt_level <- 0;
- );
- */
+void sparc_base_device::execute_trap()
+{
+ // The SPARC Instruction Manual: Version 8, page 161, "Appendix C - C.8. Traps" (SPARCv8.pdf, pg. 158)
if (!m_trap)
{
@@ -3778,33 +3680,9 @@ void mb86901_device::execute_trap()
// single fetched instruction.
//-------------------------------------------------
-/* The SPARC Instruction Manual: Version 8, page 159, "Appendix C - ISP Descriptions - C.6. Instruction Dispatch" (SPARCv8.pdf, pg. 156)
-
-illegal_IU_instr :- (
- if ( ( (op == 00) and (op2 == 000) ) { UNIMP instruction }
- or
- ( ((op=11) or (op=10)) and (op3=unassigned) )
- then 1 else 0
-
-if (illegal_IU_instr = 1) then (
- trap <- 1
- illegal_instruction <- 1
-);
-if ((FPop1 or FPop2 or FBfcc) and ((EF = 0) or (bp_FPU_present = 0))) then (
- trap <- 1;
- fp_disabled <- 1
-);
-if (CPop1 or CPop2 or CBccc) and ((EC = 0) or (bp_CP_present = 0))) then (
- trap <- 1;
- cp_disabled <- 1
-);
-next;
-if (trap = 0) then (
- { code for specific instruction, defined below }
-);
-*/
-
-inline void mb86901_device::dispatch_instruction(uint32_t op)
+// The SPARC Instruction Manual: Version 8, page 159, "Appendix C - ISP Descriptions - C.6. Instruction Dispatch" (SPARCv8.pdf, pg. 156)
+
+inline void sparc_base_device::dispatch_instruction(uint32_t op)
{
const uint8_t op_type = OP;
switch (op_type)
@@ -3818,44 +3696,28 @@ inline void mb86901_device::dispatch_instruction(uint32_t op)
case OP2_BICC: // branch on integer condition codes
execute_bicc(op);
break;
- case OP2_SETHI: // sethi
- //SET_RDREG(IMM22);
- *m_regs[RD] = op << 10;
- m_r[0] = 0;
+ case OP2_SETHI: // sethi or nop
+ if (RDBITS) RDREG = op << 10;
PC = nPC;
nPC = nPC + 4;
break;
case OP2_FBFCC: // branch on floating-point condition codes
if (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present)
{
- logerror("fbfcc at %08x: %08x\n", PC, op);
m_trap = 1;
m_fp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
+ execute_fbfcc(op);
break;
-#if SPARCV8
- case OP2_CBCCC: // branch on coprocessor condition codes, SPARCv8
- if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present)
+ default:
+ if (!dispatch_extra_instruction(op))
{
- logerror("cbccc @ %08x: %08x\n", PC, op);
+ logerror("illegal instruction at %08x: %08x\n", PC, op);
m_trap = 1;
- m_cp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
- return;
+ m_illegal_instruction = 1;
}
return;
-#endif
- default:
- logerror("illegal instruction at %08x: %08x\n", PC, op);
- m_trap = 1;
- m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
- return;
}
break;
@@ -3880,78 +3742,654 @@ inline void mb86901_device::dispatch_instruction(uint32_t op)
}
}
+bool sparcv7_device::dispatch_extra_instruction(uint32_t op)
+{
+ return false;
+}
+
+bool sparcv8_device::dispatch_extra_instruction(uint32_t op)
+{
+ const uint8_t op_type = OP;
+ switch (op_type)
+ {
+ case OP_TYPE0: // Bicc, SETHI, FBfcc
+ switch (OP2)
+ {
+ case OP2_CBCCC: // branch on coprocessor condition codes, SPARCv8
+ if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present)
+ {
+ logerror("cbccc @ %08x: %08x\n", PC, op);
+ m_trap = 1;
+ m_cp_disabled = 1;
+ return true;
+ }
+ return true;
+ default:
+ return false;
+ }
+ default:
+ return false;
+ }
+}
+
+void sparc_base_device::check_fdiv_zero_exception()
+{
+ m_fsr |= FSR_CEXC_DZC;
+ if (m_fsr & FSR_TEM_DZM)
+ {
+ m_fsr = (m_fsr & ~FSR_FTT_MASK) | FSR_FTT_IEEE;
+ m_fp_exception_pending = true;
+ return;
+ }
+ m_fsr |= FSR_AEXC_DZA;
+}
+
+bool sparc_base_device::check_fp_exceptions()
+{
+ if (softfloat_exceptionFlags & softfloat_flag_inexact)
+ m_fsr |= FSR_CEXC_NXC;
+ if (softfloat_exceptionFlags & softfloat_flag_underflow)
+ m_fsr |= FSR_CEXC_UFC;
+ if (softfloat_exceptionFlags & softfloat_flag_overflow)
+ m_fsr |= FSR_CEXC_OFC;
+ if (softfloat_exceptionFlags & softfloat_flag_invalid)
+ m_fsr |= FSR_CEXC_NVC;
+
+ // accrue disabled exceptions
+ const uint32_t cexc = m_fsr & FSR_CEXC_MASK;
+ const uint32_t tem = (m_fsr & FSR_TEM_MASK) >> FSR_TEM_SHIFT;
+ m_fsr |= (~tem & cexc) << FSR_AEXC_SHIFT;
+
+ // check if exception is enabled
+ if (tem & cexc)
+ {
+ m_fsr = (m_fsr & ~FSR_FTT_MASK) | FSR_FTT_IEEE;
+ m_fp_exception = 1;
+ return true;
+ }
+ return false;
+}
+
+bool sparc_base_device::get_fpr32(uint32_t &data, const uint32_t rd)
+{
+ if (m_pending_fpr == rd)
+ {
+ return true;
+ }
+ data = FREG(rd);
+ return false;
+}
+
+bool sparc_base_device::get_fpr64(uint64_t &data, const uint32_t rd)
+{
+ if (m_pending_fpr == rd || m_pending_fpr == (rd | 1))
+ {
+ return true;
+ }
+ data = (uint64_t)FREG(rd) << 32;
+ data |= FREG(rd | 1);
+ return false;
+}
+
+bool sparc_base_device::set_fpr32(const uint32_t rd, const uint32_t data)
+{
+ m_pending_fpr = rd;
+ if (softfloat_exceptionFlags && check_fp_exceptions())
+ {
+ m_fp_exception_pending = true;
+ m_fpr[rd] = 0;
+ return true;
+ }
+
+ m_fpr[rd] = data;
+ return false;
+}
+
+bool sparc_base_device::set_fpr64(const uint32_t rd, const uint64_t data)
+{
+ m_pending_fpr = rd;
+ if (softfloat_exceptionFlags && check_fp_exceptions())
+ {
+ m_fp_exception_pending = true;
+ m_fpr[rd] = 0;
+ m_fpr[rd + 1] = 0;
+ return true;
+ }
+
+ m_fpr[rd] = (uint32_t)(data >> 32);
+ m_fpr[rd + 1] = (uint32_t)data;
+ return false;
+}
+
//-------------------------------------------------
// complete_fp_execution - completes execution
// of a floating-point operation
//-------------------------------------------------
-void mb86901_device::complete_fp_execution(uint32_t /*op*/)
+void sparc_base_device::complete_fp_execution(uint32_t op)
{
+ softfloat_exceptionFlags = 0;
+
+ uint32_t rs1 = 0;
+ uint32_t rs2 = 0;
+ uint64_t rd1 = 0;
+ uint64_t rd2 = 0;
+
+ const uint32_t fpop = (op >> 5) & 0x1ff;
+ switch (fpop)
+ {
+ case FPOP_FMOVS:
+ if (RD == m_pending_fpr) return;
+ if (get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 4;
+ set_fpr32(RD, rs2);
+ break;
+ case FPOP_FNEGS:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 4;
+ const float32_t fs2 = float32_t{ rs2 };
+ set_fpr32(RD, f32_mul(fs2, i32_to_f32(-1)).v);
+ break;
+ }
+ case FPOP_FABSS:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 4;
+ const float32_t fs2 = float32_t{ rs2 };
+ if (f32_lt(fs2, float32_t{0}))
+ {
+ set_fpr32(RD, f32_mul(fs2, i32_to_f32(-1)).v);
+ }
+ else
+ {
+ set_fpr32(RD, rs2);
+ }
+ break;
+ }
+ case FPOP_FSQRTS:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 62;
+ const float32_t fs2 = float32_t{ rs2 };
+ set_fpr32(RD, f32_sqrt(fs2).v);
+ break;
+ }
+ case FPOP_FSQRTD:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr64(rd2, RS2_D)) return;
+ m_fpr_pending = 120;
+ const float64_t fs2 = float64_t{ rd2 };
+ set_fpr64(RD_D, f64_sqrt(fs2).v);
+ break;
+ }
+ case FPOP_FADDS:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr32(rs1, RS1) || get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 8;
+ const float32_t fs1 = float32_t{ rs1 };
+ const float32_t fs2 = float32_t{ rs2 };
+ set_fpr32(RD, f32_add(fs1, fs2).v);
+ break;
+ }
+ case FPOP_FADDD:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr64(rd1, RS1_D) || get_fpr64(rd2, RS2_D)) return;
+ m_fpr_pending = 8;
+ const float64_t fs1 = float64_t{ rd1 };
+ const float64_t fs2 = float64_t{ rd2 };
+ set_fpr64(RD_D, f64_add(fs1, fs2).v);
+ break;
+ }
+ case FPOP_FSUBS:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr32(rs1, RS1) || get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 8;
+ const float32_t fs1 = float32_t{ rs1 };
+ const float32_t fs2 = float32_t{ rs2 };
+ set_fpr32(RD, f32_sub(fs1, fs2).v);
+ break;
+ }
+ case FPOP_FSUBD:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr64(rd1, RS1_D) || get_fpr64(rd2, RS2_D)) return;
+ m_fpr_pending = 8;
+ const float64_t fs1 = float64_t{ rd1 };
+ const float64_t fs2 = float64_t{ rd2 };
+ set_fpr64(RD_D, f64_sub(fs1, fs2).v);
+ break;
+ }
+ case FPOP_FMULS:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr32(rs1, RS1) || get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 8;
+ const float32_t fs1 = float32_t{ rs1 };
+ const float32_t fs2 = float32_t{ rs2 };
+ set_fpr32(RD, f32_mul(fs1, fs2).v);
+ break;
+ }
+ case FPOP_FMULD:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr64(rd1, RS1_D) || get_fpr64(rd2, RS2_D)) return;
+ m_fpr_pending = 14;
+ const float64_t fs1 = float64_t{ rd1 };
+ const float64_t fs2 = float64_t{ rd2 };
+ set_fpr64(RD_D, f64_mul(fs1, fs2).v);
+ break;
+ }
+ case FPOP_FDIVS:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr32(rs1, RS1) || get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 40;
+ if (rs2 == 0)
+ {
+ check_fdiv_zero_exception();
+ m_pending_fpr = RD;
+ break;
+ }
+ const float32_t fs1 = float32_t{ rs1 };
+ const float32_t fs2 = float32_t{ rs2 };
+ set_fpr32(RD, f32_div(fs1, fs2).v);
+ break;
+ }
+ case FPOP_FDIVD:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr64(rd1, RS1_D) || get_fpr64(rd2, RS2_D)) return;
+ m_fpr_pending = 68;
+ if (rd2 == 0)
+ {
+ check_fdiv_zero_exception();
+ m_pending_fpr = RD;
+ break;
+ }
+ const float64_t fs1 = float64_t{ rd1 };
+ const float64_t fs2 = float64_t{ rd2 };
+ set_fpr64(RD_D, f64_div(fs1, fs2).v);
+ break;
+ }
+ case FPOP_FITOS:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 16;
+ set_fpr32(RD, i32_to_f32(int32_t(rs2)).v);
+ break;
+ }
+ case FPOP_FDTOS:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr64(rd2, RS2_D)) return;
+ m_fpr_pending = 8;
+ const float64_t fs2 = float64_t{ rd2 };
+ set_fpr32(RD, f64_to_f32(fs2).v);
+ break;
+ }
+ case FPOP_FITOD:
+ {
+ if (RD_D == m_pending_fpr) return;
+ if (get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 8;
+ set_fpr64(RD_D, i32_to_f64(int32_t(rs2)).v);
+ break;
+ }
+ case FPOP_FSTOD:
+ {
+ if (RD_D == m_pending_fpr) return;
+ if (get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 8;
+ const float32_t fs = float32_t{ rs2 };
+ set_fpr64(RD_D, f32_to_f64(fs).v);
+ break;
+ }
+ case FPOP_FSTOI:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 16; // Guessed based on FITOS
+ const float32_t fs2 = float32_t{ rs2 };
+ set_fpr32(RD, f32_to_i32(fs2, softfloat_roundingMode, true));
+ break;
+ }
+ case FPOP_FDTOI:
+ {
+ if (RD == m_pending_fpr) return;
+ if (get_fpr64(rd2, RS2_D)) return;
+ m_fpr_pending = 8; // Guessed based on FITOD
+ const float64_t fs2 = float64_t{ rd2 };
+ set_fpr32(RD, f64_to_i32(fs2, softfloat_roundingMode, true));
+ break;
+ }
+ case FPOP_FCMPS:
+ {
+ if (get_fpr32(rs1, RS1) || get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 4;
+ const float32_t fs1 = float32_t{ rs1 };
+ const float32_t fs2 = float32_t{ rs2 };
+ bool equal = f32_eq(fs1, fs2);
+ if (softfloat_exceptionFlags & softfloat_flag_invalid)
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_UO;
+ else if (equal)
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_EQ;
+ else if (f32_lt(fs1, fs2))
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_LT;
+ else
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_GT;
+ break;
+ }
+ case FPOP_FCMPD:
+ {
+ if (get_fpr64(rd1, RS1_D) || get_fpr64(rd2, RS2_D)) return;
+ m_fpr_pending = 4;
+ const float64_t fs1 = float64_t{ rd1 };
+ const float64_t fs2 = float64_t{ rd2 };
+ bool equal = f64_eq(fs1, fs2);
+ if (softfloat_exceptionFlags & softfloat_flag_invalid)
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_UO;
+ else if (equal)
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_EQ;
+ else if (f64_lt(fs1, fs2))
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_LT;
+ else
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_GT;
+ break;
+ }
+ case FPOP_FCMPES:
+ {
+ if (get_fpr32(rs1, RS1) || get_fpr32(rs2, RS2)) return;
+ m_fpr_pending = 4;
+ const float32_t fs1 = float32_t{ rs1 };
+ const float32_t fs2 = float32_t{ rs2 };
+ bool equal = f32_eq(fs1, fs2);
+ if (softfloat_exceptionFlags & softfloat_flag_invalid)
+ {
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_UO;
+ m_fsr |= FSR_CEXC_NVC;
+ if (m_fsr & FSR_TEM_NVM)
+ {
+ m_fsr = (m_fsr & ~FSR_FTT_MASK) | FSR_FTT_IEEE;
+ m_fp_exception = 1;
+ break;
+ }
+ m_fsr |= FSR_AEXC_NVA;
+ }
+ else if (equal)
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_EQ;
+ else if (f32_lt(fs1, fs2))
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_LT;
+ else
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_GT;
+ break;
+ }
+ case FPOP_FCMPED:
+ {
+ if (get_fpr64(rd1, RS1_D) || get_fpr64(rd2, RS2_D)) return;
+ m_fpr_pending = 4;
+ const float64_t fs1 = float64_t{ rd1 };
+ const float64_t fs2 = float64_t{ rd2 };
+ bool equal = f64_eq(fs1, fs2);
+ if (softfloat_exceptionFlags & softfloat_flag_invalid)
+ {
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_UO;
+ m_fsr |= FSR_CEXC_NVC;
+ if (m_fsr & FSR_TEM_NVM)
+ {
+ m_fsr = (m_fsr & ~FSR_FTT_MASK) | FSR_FTT_IEEE;
+ m_fp_exception = 1;
+ break;
+ }
+ m_fsr |= FSR_AEXC_NVA;
+ }
+ else if (equal)
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_EQ;
+ else if (f64_lt(fs1, fs2))
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_LT;
+ else
+ m_fsr = (m_fsr & ~FSR_FCC_MASK) | FSR_FCC_GT;
+ break;
+ }
+ case FPOP_FSQRTX:
+ case FPOP_FADDX:
+ case FPOP_FSUBX:
+ case FPOP_FMULX:
+ case FPOP_FDIVX:
+ case FPOP_FXTOI:
+ case FPOP_FXTOS:
+ case FPOP_FXTOD:
+ case FPOP_FITOX:
+ case FPOP_FSTOX:
+ case FPOP_FDTOX:
+ case FPOP_FCMPX:
+ case FPOP_FCMPEX:
+ default:
+ m_fsr = (m_fsr & ~FSR_FTT_MASK) | FSR_FTT_UNIMP;
+ m_fp_exception = 1;
+ break;
+ }
+
+ PC = nPC;
+ nPC = nPC + 4;
}
+
+//-------------------------------------------------
+// execute_swap - execute a swap instruction
+//-------------------------------------------------
+
+void sparcv8_device::execute_swap(uint32_t op)
+{
+ // The SPARC Instruction Manual: Version 8, page 169, "Appendix C - ISP Descriptions - Atomic Load-Store Unsigned Byte Instructions" (SPARCv8.pdf, pg. 166)
+
+ uint32_t address = 0;
+ uint8_t addr_space = 0;
+ if (SWAP)
+ {
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+ }
+ else if (SWAPA)
+ {
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ return;
+ }
+ else if (USEIMM)
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ return;
+ }
+ else
+ {
+ address = RS1REG + RS2REG;
+ addr_space = ASI;
+ }
+ }
+
+ if (address & 3)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ uint32_t word = 0;
+ uint32_t data = RDREG;
+
+ //while (m_pb_block_ldst_byte || m_pb_block_ldst_word)
+ //{
+ // { wait for lock(s) to be lifted }
+ // { an implementation actually need only block when another SWAP is pending on
+ // the same word in memory as the one addressed by this SWAP, or a LDSTUB is
+ // pending on any byte of the word in memory addressed by this SWAP }
+ //}
+
+ m_pb_block_ldst_word = 1;
+
+ word = read_word(addr_space, address);
+
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ write_word(addr_space, address, data);
+
+ m_pb_block_ldst_word = 0;
+
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RDBITS)
+ RDREG = word;
+
+ PC = nPC;
+ nPC = nPC + 4;
+}
+
+
+//-------------------------------------------------
+// execute_mul - execute a multiply opcode
+//-------------------------------------------------
+
+void sparcv8_device::execute_mul(uint32_t op)
+{
+ // The SPARC Instruction Manual: Version 8, page 175, "Appendix C - ISP Descriptions - Multiply Instructions" (SPARCv8.pdf, pg. 172)
+
+ uint32_t operand2 = (USEIMM ? SIMM13 : RS2REG);
+
+ uint32_t result = 0;
+ if (UMUL || UMULCC)
+ {
+ uint64_t dresult = mulu_32x32(RS1REG, operand2);
+ Y = (uint32_t)(dresult >> 32);
+ result = (uint32_t)dresult;
+ }
+ else if (SMUL || SMULCC)
+ {
+ int64_t dresult = mul_32x32(RS1REG, operand2);
+ Y = (uint32_t)(dresult >> 32);
+ result = (uint32_t)dresult;
+ }
+
+ if (RDBITS)
+ {
+ RDREG = result;
+ }
+ if (UMULCC || SMULCC)
+ {
+ CLEAR_ICC;
+ PSR |= BIT31(result) ? PSR_N_MASK : 0;
+ PSR |= (result == 0) ? PSR_Z_MASK : 0;
+ }
+
+ PC = nPC;
+ nPC = nPC + 4;
+}
+
+
+//-------------------------------------------------
+// execute_div - execute a divide opcode
+//-------------------------------------------------
+
+void sparcv8_device::execute_div(uint32_t op)
+{
+ // The SPARC Instruction Manual: Version 8, page 176, "Appendix C - ISP Descriptions - Multiply Instructions" (SPARCv8.pdf, pg. 173)
+
+ uint32_t operand2 = (USEIMM ? SIMM13 : RS2REG);
+
+ if (operand2 == 0)
+ {
+ m_trap = 1;
+ m_division_by_zero = 1;
+ return;
+ }
+ else
+ {
+ uint32_t result = 0;
+ bool temp_v = false;
+ int64_t temp_64bit = 0;
+ if (UDIV || UDIVCC)
+ {
+ temp_64bit = int64_t(uint64_t((uint64_t(Y) << 32) | uint64_t(RS1REG)) / operand2);
+
+ result = uint32_t(temp_64bit);
+
+ temp_v = ((temp_64bit & 0xffffffff00000000ULL) == 0) ? false : true;
+ }
+ else if (SDIV || SDIVCC)
+ {
+ temp_64bit = int64_t(int64_t((uint64_t(Y) << 32) | uint64_t(RS1REG)) / operand2);
+
+ result = uint32_t(temp_64bit);
+
+ uint64_t shifted = uint64_t(temp_64bit) >> 31;
+ temp_v = (shifted == 0 || shifted == 0x1ffffffffULL) ? false : true;
+ }
+
+ if (temp_v)
+ {
+ if (UDIV || UDIVCC)
+ {
+ result = 0xffffffff;
+ }
+ else if (SDIV || SDIVCC)
+ {
+ if (temp_64bit > 0)
+ result = 0x7fffffff;
+ else
+ result = 0x80000000;
+ }
+ }
+
+ if (RDBITS)
+ RDREG = result;
+
+ if (UDIVCC || SDIVCC)
+ {
+ CLEAR_ICC;
+ PSR |= BIT31(result) ? PSR_N_MASK : 0;
+ PSR |= (result == 0) ? PSR_Z_MASK : 0;
+ PSR |= temp_v ? PSR_V_MASK : 0;
+ }
+ }
+
+ PC = nPC;
+ nPC = nPC + 4;
+}
+
+
//-------------------------------------------------
// execute_step - perform one step in execute
// mode (versus error or reset modes)
//-------------------------------------------------
-inline void mb86901_device::execute_step()
-{
- /* The SPARC Instruction Manual: Version 8, page 156, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 153)
-
- if (bp_reset_in = 1) then (
- execute_mode <- 0;
- reset_mode <- 1;
- break { out of while (execute_mode = 1) loop }
- ) else if ((ET = 1) and ((bp_IRL = 15) or (bp_IRL > PIL))) then (
- trap <- 1;
- interrupt_level <- bp_IRL
- );
- next;
-
- if (trap = 1) then execute_trap; { See Section C.8 }
-
- if (execute_mode = 1) then ( { execute_trap may have set execute_mode to 0 }
-
- { the following code emulates the delayed nature of the write-state-register instructions.
- PSR <- PSR'; PSR' <- PSR''; PSR'' <- PSR'''; PSR''' <- PSR'''';
- ASR <- ASR'; ASR' <- ASR''; ASR'' <- ASR'''; ASR''' <- ASR'''';
- TBR <- TBR'; TBR' <- TBR''; TBR'' <- TBR'''; TBR''' <- TBR'''';
- WIM <- WIM'; WIM' <- WIM''; WIM'' <- WIM'''; WIM''' <- WIM'''';
- Y <- Y'; Y' <- Y''; Y'' <- Y'''; Y''' <- Y'''';
- next;
-
- addr_space := (if (S = 0) then 8 else 9);
- (instruction, MAE) <- memory_read(addr_space, PC);
- next;
-
- if ( (MAE = 1) and (annul = 0) ) then (
- trap <- 1;
- instruction_access_exception <- 1
- ) else (
- if (annul = 0) then (
- dispatch_instruction ; { See Section C.6 }
- next;
- if (FPop1 or FPop2) then (
- complete_fp_execution { See Section C.7 }
- )
- next;
- if ( (trap = 0) and
- not (CALL or RETT or JMPL or Bicc or FBfcc or CBccc or Ticc) ) then (
- PC <- nPC;
- nPC <- nPC + 4
- )
- ) else { annul != 0 } (
- annul <- 0;
- PC <- nPC;
- nPC <- nPC + 4
- )
- )
- )
- */
+inline void sparc_base_device::execute_step()
+{
+ // The SPARC Instruction Manual: Version 8, page 156, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 153)
// write-state-register delay not yet implemented
- const uint32_t op = m_mmu->fetch_insn(m_s, PC >> 2);
+ const uint32_t op = read_word(8 + (IS_SUPERVISOR ? 1 : 0), PC);
#if LOG_FCODES
//if (m_log_fcodes)
@@ -3966,11 +4404,25 @@ inline void mb86901_device::execute_step()
{
m_trap = 1;
m_instruction_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
dispatch_instruction(op);
+
+ if (m_fpr_pending)
+ {
+ m_fpr_pending--;
+ if (!m_fpr_pending)
+ {
+ m_pending_fpr = std::size(m_fpr);
+ if (m_fp_exception_pending)
+ {
+ m_fp_exception_pending = false;
+ m_trap = 1;
+ m_fp_exception = 1;
+ return;
+ }
+ }
+ }
}
else
{
@@ -3985,29 +4437,14 @@ inline void mb86901_device::execute_step()
// reset_step - step one cycle in reset mode
//-------------------------------------------------
-void mb86901_device::reset_step()
+void sparc_base_device::reset_step()
{
- /* The SPARC Instruction Manual: Version 8, page 156, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 153)
-
- while (reset_mode = 1) (
- if (bp_reset_in = 0) then (
- reset_mode <- 0;
- execute_mode <- 1;
- trap <- 1;
- reset_trap <- 1;
- )
- );
- */
+ // The SPARC Instruction Manual: Version 8, page 156, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 153)
- if (!m_bp_reset_in)
- {
- m_reset_mode = 0;
- m_execute_mode = 1;
- m_trap = 1;
- m_reset_trap = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
- }
+ m_reset_mode = 0;
+ m_execute_mode = 1;
+ m_trap = 1;
+ m_reset_trap = 1;
}
@@ -4015,31 +4452,16 @@ void mb86901_device::reset_step()
// error_step - step one cycle in error mode
//-------------------------------------------------
-void mb86901_device::error_step()
+void sparc_base_device::error_step()
{
- /* The SPARC Instruction Manual: Version 8, page 157, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 154)
-
- while (error_mode = 1) (
- if (bp_reset_in = 1) then (
- error_mode <- 0;
- reset_mode <- 1;
- pb_error <- 0
- )
- );
- */
+ // The SPARC Instruction Manual: Version 8, page 157, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 154)
- if (m_bp_reset_in)
- {
- m_error_mode = 0;
- m_reset_mode = 1;
- m_pb_error = 0;
- m_stashed_icount = m_icount;
- m_icount = 0;
- }
+ // waiting for SPARC_RESET
+ m_icount = 0;
}
-template <bool CHECK_DEBUG, mb86901_device::running_mode MODE>
-void mb86901_device::run_loop()
+template <bool CHECK_DEBUG, sparc_base_device::running_mode MODE>
+void sparc_base_device::run_loop()
{
do
{
@@ -4049,19 +4471,22 @@ void mb86901_device::run_loop()
continue;
}*/
- if (CHECK_DEBUG)
- debugger_instruction_hook(PC);
-
if (MODE == MODE_RESET)
{
+ if (CHECK_DEBUG)
+ debugger_wait_hook();
reset_step();
}
else if (MODE == MODE_ERROR)
{
+ if (CHECK_DEBUG)
+ debugger_wait_hook();
error_step();
}
else if (MODE == MODE_EXECUTE)
{
+ if (CHECK_DEBUG)
+ debugger_instruction_hook(PC);
execute_step();
}
@@ -4075,7 +4500,7 @@ void mb86901_device::run_loop()
}
}
--m_icount;
- } while (m_icount >= 0);
+ } while (m_icount > 0 && !m_trap);
}
//-------------------------------------------------
@@ -4083,16 +4508,20 @@ void mb86901_device::run_loop()
// opcodes
//-------------------------------------------------
-void mb86901_device::execute_run()
+void sparc_base_device::execute_run()
{
- bool debug = machine().debug_flags & DEBUG_FLAG_ENABLED;
+ const bool debug = debugger_enabled();
if (m_bp_reset_in)
{
+ if (m_error_mode)
+ {
+ m_pb_error = 0;
+ }
+
m_execute_mode = 0;
m_error_mode = 0;
m_reset_mode = 1;
- m_stashed_icount = m_icount;
m_icount = 0;
return;
}
@@ -4127,13 +4556,7 @@ void mb86901_device::execute_run()
else
run_loop<false, MODE_EXECUTE>();
}
-
- if (m_stashed_icount >= 0)
- {
- m_icount = m_stashed_icount;
- m_stashed_icount = -1;
- }
- } while (m_icount >= 0);
+ } while (m_icount > 0);
}
@@ -4142,7 +4565,7 @@ void mb86901_device::execute_run()
// disassembler
//-------------------------------------------------
-uint64_t mb86901_device::get_reg_r(unsigned index) const
+uint64_t sparc_base_device::get_reg_r(unsigned index) const
{
return REG(index & 31);
}
@@ -4153,7 +4576,7 @@ uint64_t mb86901_device::get_reg_r(unsigned index) const
// disassembler
//-------------------------------------------------
-uint64_t mb86901_device::get_translated_pc() const
+uint64_t sparc_base_device::get_translated_pc() const
{
// FIXME: how do we apply translation to the address so it's in the same space the disassembler sees?
return m_pc;
@@ -4165,7 +4588,7 @@ uint64_t mb86901_device::get_translated_pc() const
// disassembler
//-------------------------------------------------
-uint8_t mb86901_device::get_icc() const
+uint8_t sparc_base_device::get_icc() const
{
return (m_psr & PSR_ICC_MASK) >> PSR_ICC_SHIFT;
}
@@ -4176,7 +4599,7 @@ uint8_t mb86901_device::get_icc() const
// for disassembler
//-------------------------------------------------
-uint8_t mb86901_device::get_xcc() const
+uint8_t sparc_base_device::get_xcc() const
{
// not present before SPARCv9
return 0;
@@ -4188,7 +4611,7 @@ uint8_t mb86901_device::get_xcc() const
// for disassembler
//-------------------------------------------------
-uint8_t mb86901_device::get_fcc(unsigned index) const
+uint8_t sparc_base_device::get_fcc(unsigned index) const
{
// only one fcc instance before SPARCv9
return (m_fsr >> 10) & 3;
diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h
index 488a9f38dfa..f61ddb30e5e 100644
--- a/src/devices/cpu/sparc/sparc.h
+++ b/src/devices/cpu/sparc/sparc.h
@@ -12,31 +12,28 @@
#include "sparcdasm.h"
#include "sparc_intf.h"
-#define SPARCV8 (1)
#define LOG_FCODES (0)
#if LOG_FCODES
#include <map>
#endif
-class mb86901_device : public cpu_device, public sparc_mmu_host_interface, protected sparc_disassembler::config
+class sparc_base_device : public cpu_device, public sparc_mmu_host_interface, protected sparc_disassembler::config
{
public:
- mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ sparc_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
template <typename T> void set_mmu(T &&tag) { m_mmu.set_tag(std::forward<T>(tag)); }
// device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_stop() override;
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
virtual void device_post_load() override;
- virtual void device_resolve_objects() override;
+ virtual void device_resolve_objects() override ATTR_COLD;
// device_execute_interface overrides
- virtual uint32_t execute_min_cycles() const override;
- virtual uint32_t execute_max_cycles() const override;
- virtual uint32_t execute_input_lines() const override;
+ virtual uint32_t execute_min_cycles() const noexcept override;
+ virtual uint32_t execute_max_cycles() const noexcept override;
virtual void execute_run() override;
virtual void execute_set_input(int inputnum, int state) override;
@@ -75,11 +72,8 @@ protected:
void execute_rett(uint32_t op);
void execute_saverestore(uint32_t op);
void execute_jmpl(uint32_t op);
-#if SPARCV8
- void execute_mul(uint32_t op);
- void execute_div(uint32_t op);
-#endif
inline void execute_group2(uint32_t op);
+ virtual bool execute_extra_group2(uint32_t op) = 0;
inline void execute_ldd(uint32_t op);
inline void execute_ld(uint32_t op);
@@ -102,10 +96,8 @@ protected:
void execute_store(uint32_t op);
void execute_ldstub(uint32_t op);
-#if SPARCV8
- void execute_swap(uint32_t op);
-#endif
inline void execute_group3(uint32_t op);
+ virtual bool execute_extra_group3(uint32_t op) = 0;
enum set_cc
{
@@ -122,12 +114,23 @@ protected:
bool evaluate_condition(uint32_t op);
inline void execute_bicc(uint32_t op);
+ bool evaluate_fp_condition(uint32_t op);
+ inline void execute_fbfcc(uint32_t op);
void execute_ticc(uint32_t op);
void select_trap();
void execute_trap();
+ virtual void update_tt() = 0;
+
+ void check_fdiv_zero_exception();
+ bool check_fp_exceptions();
+ bool get_fpr32(uint32_t &data, const uint32_t rd);
+ bool get_fpr64(uint64_t &data, const uint32_t rd);
+ bool set_fpr32(const uint32_t rd, const uint32_t data);
+ bool set_fpr64(const uint32_t rd, const uint64_t data);
void complete_instruction_execution(uint32_t op);
inline void dispatch_instruction(uint32_t op);
+ virtual bool dispatch_extra_instruction(uint32_t op) = 0;
void complete_fp_execution(uint32_t /*op*/);
inline void execute_step();
@@ -148,14 +151,16 @@ protected:
void log_fcodes();
#endif
- required_device<sparc_mmu_interface> m_mmu;
+ optional_device<sparc_mmu_interface> m_mmu;
// address spaces
- address_space_config m_default_config;
+ address_space_config m_debugger_config;
+ address_space_config m_asi_config[0x10];
+ memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_asi[0x20];
// memory access
- uint32_t read_sized_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask);
- void write_sized_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask);
+ inline uint32_t read_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask = 0xffffffff);
+ inline void write_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask = 0xffffffff);
// helpers for the disassembler
virtual uint64_t get_reg_r(unsigned index) const override;
@@ -165,7 +170,7 @@ protected:
virtual uint8_t get_fcc(unsigned index) const override;
// general-purpose registers
- uint32_t m_r[120];
+ uint32_t m_r[136];
// FPU registers
uint32_t m_fpr[32];
@@ -198,17 +203,14 @@ protected:
bool m_illegal_instruction;
bool m_mem_address_not_aligned;
bool m_fp_disabled;
+ bool m_cp_disabled;
bool m_fp_exception;
- bool m_cp_disabled; // SPARCv8
- bool m_cp_exception; // SPARCv8
- bool m_unimplemented_FLUSH; // SPARCv8
- bool m_r_register_access_error; // SPARCv8
- bool m_instruction_access_error; // SPARCv8
+ bool m_fp_exception_pending;
+ uint32_t m_fpr_pending;
+ uint32_t m_pending_fpr;
+ bool m_cp_exception;
bool m_instruction_access_exception;
- bool m_data_access_error; // SPARCv8
- bool m_data_store_error; // SPARCv8
bool m_data_access_exception;
- bool m_division_by_zero; // SPARCv8
bool m_trap_instruction;
bool m_window_underflow;
bool m_window_overflow;
@@ -221,16 +223,16 @@ protected:
uint8_t m_cp_sequence_err;
// fields separated out from PSR (Processor State Register)
- uint8_t m_impl; // implementation (always 0 in MB86901)
- uint8_t m_ver; // version (always 0 in MB86901)
- uint8_t m_icc; // integer condition codes
+ uint8_t m_impl; // implementation (always 0 in SPARCv7)
+ uint8_t m_ver; // version (always 0 in SPARCv7)
+ uint8_t m_icc; // integer condition codes
bool m_ec; // enable coprocessor
bool m_ef; // enable FPU
- uint8_t m_pil; // processor interrupt level
+ uint8_t m_pil; // processor interrupt level
bool m_s; // supervisor mode
bool m_ps; // prior S state
bool m_et; // enable traps
- uint8_t m_cwp; // current window pointer
+ uint8_t m_cwp; // current window pointer
bool m_alu_op3_assigned[64];
bool m_ldst_op3_assigned[64];
@@ -238,6 +240,7 @@ protected:
// register windowing helpers
uint32_t* m_regs[32];
+ int m_nwindows;
// other internal states
bool m_privileged_asr[32];
@@ -246,7 +249,6 @@ protected:
bool m_no_annul;
bool m_hold_bus;
int m_icount;
- int m_stashed_icount;
int m_insn_space;
int m_data_space;
@@ -263,14 +265,171 @@ protected:
bool m_log_fcodes;
#endif
- // processor configuration
- static const int NWINDOWS;
-
std::function<void (sparc_disassembler *)> m_asi_desc_adder;
+ static const char *const DEFAULT_ASI_NAMES[16];
+};
+
+class sparcv7_device : public sparc_base_device
+{
+public:
+ sparcv7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ sparcv7_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual bool execute_extra_group2(uint32_t op) override;
+ virtual bool execute_extra_group3(uint32_t op) override;
+ virtual bool dispatch_extra_instruction(uint32_t op) override;
+ virtual void update_tt() override;
+};
+
+class sparcv8_device : public sparc_base_device
+{
+public:
+ sparcv8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+protected:
+ sparcv8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ virtual bool execute_extra_group2(uint32_t op) override;
+ virtual bool execute_extra_group3(uint32_t op) override;
+ virtual bool dispatch_extra_instruction(uint32_t op) override;
+ virtual void update_tt() override;
+
+private:
+ void execute_mul(uint32_t op);
+ void execute_div(uint32_t op);
+ void execute_swap(uint32_t op);
+
+ bool m_unimplemented_FLUSH;
+ bool m_r_register_access_error;
+ bool m_instruction_access_error;
+ bool m_data_access_error;
+ bool m_data_store_error;
+ bool m_division_by_zero;
+};
+
+class mb86930_device : public sparcv8_device
+{
+public:
+ mb86930_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ // device_disasm_interface overrides
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ auto cs0_read_cb() { return m_cs_r[0].bind(); }
+ auto cs0_write_cb() { return m_cs_w[0].bind(); }
+ auto cs1_read_cb() { return m_cs_r[1].bind(); }
+ auto cs1_write_cb() { return m_cs_w[1].bind(); }
+ auto cs2_read_cb() { return m_cs_r[2].bind(); }
+ auto cs2_write_cb() { return m_cs_w[2].bind(); }
+ auto cs3_read_cb() { return m_cs_r[3].bind(); }
+ auto cs3_write_cb() { return m_cs_w[3].bind(); }
+ auto cs4_read_cb() { return m_cs_r[4].bind(); }
+ auto cs4_write_cb() { return m_cs_w[4].bind(); }
+ auto cs5_read_cb() { return m_cs_r[5].bind(); }
+ auto cs5_write_cb() { return m_cs_w[5].bind(); }
+
+protected:
+ // device-level overrides
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+ virtual void device_post_load() override;
+
+ virtual bool execute_extra_group2(uint32_t op) override;
+
+ void execute_divscc(uint32_t op);
+ void execute_scan(uint32_t op);
+
+ uint32_t biu_ctrl_r(offs_t offset, uint32_t mem_mask);
+ void biu_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t lock_ctrl_r(offs_t offset, uint32_t mem_mask);
+ void lock_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t lock_ctrl_save_r(offs_t offset, uint32_t mem_mask);
+ void lock_ctrl_save_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t cache_status_r(offs_t offset, uint32_t mem_mask);
+ void cache_status_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t restore_lock_ctrl_r(offs_t offset, uint32_t mem_mask);
+ void restore_lock_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t system_support_ctrl_r(offs_t offset, uint32_t mem_mask);
+ void system_support_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t same_page_mask_r(offs_t offset, uint32_t mem_mask);
+ void same_page_mask_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t addr_range_spec_r(offs_t offset, uint32_t mem_mask);
+ void addr_range_spec_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t addr_mask_r(offs_t offset, uint32_t mem_mask);
+ void addr_mask_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t wait_specifier_r(offs_t offset, uint32_t mem_mask);
+ void wait_specifier_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t timer_r(offs_t offset, uint32_t mem_mask);
+ void timer_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t timer_preload_r(offs_t offset, uint32_t mem_mask);
+ void timer_preload_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ template <uint8_t Asi> uint32_t mmu_r(offs_t offset, uint32_t mem_mask);
+ template <uint8_t Asi> void mmu_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t icache_lock_r(offs_t offset, uint32_t mem_mask);
+ void icache_lock_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t dcache_lock_r(offs_t offset, uint32_t mem_mask);
+ void dcache_lock_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ uint32_t icache_tag_r(offs_t offset, uint32_t mem_mask);
+ void icache_tag_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+ uint32_t icache_data_r(offs_t offset, uint32_t mem_mask);
+ void icache_data_w(offs_t offset, uint32_t data, uint32_t mem_mask);
+
+ u32 dcache_tag_r(offs_t offset, u32 mem_mask);
+ void dcache_tag_w(offs_t offset, u32 data, u32 mem_mask);
+ u32 dcache_data_r(offs_t offset, u32 mem_mask);
+ void dcache_data_w(offs_t offset, u32 data, u32 mem_mask);
+
+ void control_map(address_map &map) ATTR_COLD;
+ void icache_lock_map(address_map &map) ATTR_COLD;
+ void dcache_lock_map(address_map &map) ATTR_COLD;
+ template <uint8_t Asi> void mmu_map(address_map &map) ATTR_COLD;
+ void icache_tag_map(address_map &map) ATTR_COLD;
+ void icache_data_map(address_map &map) ATTR_COLD;
+ void dcache_tag_map(address_map &map) ATTR_COLD;
+ void dcache_data_map(address_map &map) ATTR_COLD;
+
+ void update_addr_masks();
+ void update_wait_states();
+
+ devcb_read32::array<6> m_cs_r;
+ devcb_write32::array<6> m_cs_w;
+
+ u32 m_ssctrl;
+ u32 m_spmr;
+ u64 m_spmr_mask;
+ u32 m_arsr[6];
+ u32 m_amr[6];
+ u64 m_full_masks[6];
+ u64 m_full_ranges[6];
+ u64 m_last_masked_addr;
+ int m_same_page_waits[6];
+ int m_other_page_waits[6];
+
+ u32 m_wssr[3];
};
// device type definition
-DECLARE_DEVICE_TYPE(MB86901, mb86901_device)
+DECLARE_DEVICE_TYPE(SPARCV7, sparcv7_device)
+DECLARE_DEVICE_TYPE(SPARCV8, sparcv8_device)
+DECLARE_DEVICE_TYPE(MB86930, mb86930_device)
enum
{
@@ -297,6 +456,12 @@ enum
SPARC_S,
SPARC_PS,
+ SPARC_FSR,
+ SPARC_F0, SPARC_F1, SPARC_F2, SPARC_F3, SPARC_F4, SPARC_F5, SPARC_F6, SPARC_F7,
+ SPARC_F8, SPARC_F9, SPARC_F10, SPARC_F11, SPARC_F12, SPARC_F13, SPARC_F14, SPARC_F15,
+ SPARC_F16, SPARC_F17, SPARC_F18, SPARC_F19, SPARC_F20, SPARC_F21, SPARC_F22, SPARC_F23,
+ SPARC_F24, SPARC_F25, SPARC_F26, SPARC_F27, SPARC_F28, SPARC_F29, SPARC_F30, SPARC_F31,
+
SPARC_R0, SPARC_R1, SPARC_R2, SPARC_R3, SPARC_R4, SPARC_R5, SPARC_R6, SPARC_R7, SPARC_R8, SPARC_R9, SPARC_R10, SPARC_R11, SPARC_R12, SPARC_R13, SPARC_R14, SPARC_R15,
SPARC_R16, SPARC_R17, SPARC_R18, SPARC_R19, SPARC_R20, SPARC_R21, SPARC_R22, SPARC_R23, SPARC_R24, SPARC_R25, SPARC_R26, SPARC_R27, SPARC_R28, SPARC_R29, SPARC_R30, SPARC_R31,
SPARC_R32, SPARC_R33, SPARC_R34, SPARC_R35, SPARC_R36, SPARC_R37, SPARC_R38, SPARC_R39, SPARC_R40, SPARC_R41, SPARC_R42, SPARC_R43, SPARC_R44, SPARC_R45, SPARC_R46, SPARC_R47,
diff --git a/src/devices/cpu/sparc/sparc_intf.h b/src/devices/cpu/sparc/sparc_intf.h
index b1fad3ad9a9..f84219be8fd 100644
--- a/src/devices/cpu/sparc/sparc_intf.h
+++ b/src/devices/cpu/sparc/sparc_intf.h
@@ -23,8 +23,6 @@ class sparc_mmu_interface
public:
virtual ~sparc_mmu_interface() { }
virtual uint32_t fetch_insn(const bool supervisor, const uint32_t offset) = 0;
- virtual uint32_t read_asi(uint8_t asi, uint32_t offset, uint32_t mem_mask) = 0;
- virtual void write_asi(uint8_t asi, uint32_t offset, uint32_t data, uint32_t mem_mask) = 0;
virtual void set_host(sparc_mmu_host_interface *host) = 0;
};
diff --git a/src/devices/cpu/sparc/sparcdasm.cpp b/src/devices/cpu/sparc/sparcdasm.cpp
index 584b5ab427a..c0a42cb0b79 100644
--- a/src/devices/cpu/sparc/sparcdasm.cpp
+++ b/src/devices/cpu/sparc/sparcdasm.cpp
@@ -13,9 +13,9 @@
namespace {
- int32_t get_disp16(uint32_t op) { return DISP19; }
+ int32_t get_disp16(uint32_t op) { return DISP16; }
int32_t get_disp19(uint32_t op) { return DISP19; }
- int32_t get_disp22(uint32_t op) { return DISP19; }
+ int32_t get_disp22(uint32_t op) { return DISP22; }
const char *bicc_comment(const sparc_disassembler::config *conf, bool use_cc, offs_t pc, uint32_t op)
{
@@ -176,6 +176,13 @@ const sparc_disassembler::int_op_desc_map::value_type sparc_disassembler::V7_INT
{ 0x3d, { false, "restore" } }
};
+const sparc_disassembler::int_op_desc_map::value_type sparc_disassembler::SPARCLITE_INT_OP_DESC[] = {
+ { 0x0a, { false, "umul" } }, { 0x1a, { false, "umulcc" } },
+ { 0x0b, { false, "smul" } }, { 0x1b, { false, "smulcc" } },
+ { 0x1d, { false, "divscc" } },
+ { 0x2c, { false, "scan" } }
+};
+
const sparc_disassembler::int_op_desc_map::value_type sparc_disassembler::V8_INT_OP_DESC[] = {
{ 0x0a, { false, "umul" } }, { 0x1a, { false, "umulcc" } },
{ 0x0b, { false, "smul" } }, { 0x1b, { false, "smulcc" } },
@@ -570,7 +577,7 @@ const sparc_disassembler::vis_op_desc_map::value_type sparc_disassembler::VIS3B_
inline uint32_t sparc_disassembler::freg(uint32_t val, bool shift) const
{
- return (shift && (m_version >= 9)) ? ((val & 0x1e) | ((val << 5) & 0x20)) : val;
+ return (shift && (m_version >= v9)) ? ((val & 0x1e) | ((val << 5) & 0x20)) : val;
}
template <typename T> inline void sparc_disassembler::add_int_op_desc(const T &desc)
@@ -610,24 +617,24 @@ inline void sparc_disassembler::pad_op_field(std::ostream &stream, std::streampo
stream << ' ';
}
-sparc_disassembler::sparc_disassembler(const config *conf, unsigned version)
+sparc_disassembler::sparc_disassembler(const config *conf, sparc_version version)
: sparc_disassembler(conf, version, vis_none)
{
}
-sparc_disassembler::sparc_disassembler(const config *conf, unsigned version, vis_level vis)
+sparc_disassembler::sparc_disassembler(const config *conf, sparc_version version, vis_level vis)
: m_version(version)
, m_vis_level(vis)
, m_op_field_width(9)
, m_branch_desc{
EMPTY_BRANCH_DESC,
- (version >= 9) ? BPCC_DESC : EMPTY_BRANCH_DESC, // branch on integer condition codes with prediction, SPARCv9
- BICC_DESC, // branch on integer condition codes
- (version >= 9) ? BPR_DESC : EMPTY_BRANCH_DESC, // branch on integer register with prediction, SPARCv9
+ (version >= v9) ? BPCC_DESC : EMPTY_BRANCH_DESC, // branch on integer condition codes with prediction, SPARCv9
+ BICC_DESC, // branch on integer condition codes
+ (version >= v9) ? BPR_DESC : EMPTY_BRANCH_DESC, // branch on integer register with prediction, SPARCv9
EMPTY_BRANCH_DESC,
- (version >= 9) ? FBPFCC_DESC : EMPTY_BRANCH_DESC, // branch on floating-point condition codes with prediction, SPARCv9
- FBFCC_DESC, // branch on floating-point condition codes
- (version == 8) ? CBCCC_DESC : EMPTY_BRANCH_DESC // branch on coprocessor condition codes, SPARCv8
+ (version >= v9) ? FBPFCC_DESC : EMPTY_BRANCH_DESC, // branch on floating-point condition codes with prediction, SPARCv9
+ FBFCC_DESC, // branch on floating-point condition codes
+ (version == v8) ? CBCCC_DESC : EMPTY_BRANCH_DESC // branch on coprocessor condition codes, SPARCv8
}
, m_int_op_desc(std::begin(V7_INT_OP_DESC), std::end(V7_INT_OP_DESC))
, m_state_reg_desc()
@@ -638,12 +645,16 @@ sparc_disassembler::sparc_disassembler(const config *conf, unsigned version, vis
, m_prftch_desc()
, m_vis_op_desc()
{
- if (m_version >= 8)
+ if (m_version == sparclite)
+ {
+ add_int_op_desc(SPARCLITE_INT_OP_DESC);
+ }
+ else if (m_version >= v8)
{
add_int_op_desc(V8_INT_OP_DESC);
}
- if (m_version >= 9)
+ if (m_version >= v9)
{
m_op_field_width = 11;
@@ -676,13 +687,17 @@ sparc_disassembler::sparc_disassembler(const config *conf, unsigned version, vis
{
case vis_3b:
add_vis_op_desc(VIS3B_OP_DESC);
+ [[fallthrough]];
case vis_3:
add_fpop1_desc(VIS3_FPOP1_DESC);
add_vis_op_desc(VIS3_OP_DESC);
+ [[fallthrough]];
case vis_2p:
add_asi_desc(VIS2P_ASI_DESC);
+ [[fallthrough]];
case vis_2:
add_vis_op_desc(VIS2_OP_DESC);
+ [[fallthrough]];
case vis_1:
m_op_field_width = std::max(m_op_field_width, 12);
add_vis_op_desc(VIS1_OP_DESC);
@@ -717,6 +732,7 @@ sparc_disassembler::sparc_disassembler(const config *conf, unsigned version, vis
m_vis_op_desc.find(0x07c)->second.mnemonic = "ford";
m_vis_op_desc.find(0x07e)->second.mnemonic = "foned";
}
+ [[fallthrough]];
case vis_none:
break;
}
@@ -740,7 +756,7 @@ offs_t sparc_disassembler::dasm(std::ostream &stream, offs_t pc, uint32_t op) co
switch (OP2)
{
case 0:
- util::stream_format(stream, "%-*s0x%06x", m_op_field_width, (m_version >= 9) ? "illtrap" : "unimp", CONST22);
+ util::stream_format(stream, "%-*s0x%06x", m_op_field_width, (m_version >= v9) ? "illtrap" : "unimp", CONST22);
break;
case 4:
if (IMM22 == 0 && RD == 0)
@@ -754,7 +770,7 @@ offs_t sparc_disassembler::dasm(std::ostream &stream, offs_t pc, uint32_t op) co
return 4 | SUPPORTED;
case 1:
util::stream_format(stream, "%-*s%%pc%c0x%08x ! 0x%08x", m_op_field_width, "call", (DISP30 < 0) ? '-' : '+', std::abs(DISP30), pc + DISP30);
- return 4 | SUPPORTED;
+ return 4 | STEP_OVER | step_over_extra(1) | SUPPORTED;
case 2:
switch (OP3)
{
@@ -857,14 +873,14 @@ offs_t sparc_disassembler::dasm(std::ostream &stream, offs_t pc, uint32_t op) co
case 0x28:
return dasm_read_state_reg(stream, pc, op);
case 0x29:
- if (m_version <= 8)
+ if (m_version < v9)
{
util::stream_format(stream, "%-*s%%psr,%s", m_op_field_width, "rd", REG_NAMES[RD]);
return 4 | SUPPORTED;
}
break;
case 0x2a:
- if (m_version >= 9)
+ if (m_version >= v9)
{
if (V9_PRIV_REG_NAMES[RS1])
{
@@ -879,7 +895,7 @@ offs_t sparc_disassembler::dasm(std::ostream &stream, offs_t pc, uint32_t op) co
}
break;
case 0x2b:
- if (m_version >= 9)
+ if (m_version >= v9)
{
if (!USEIMM)
{
@@ -896,7 +912,7 @@ offs_t sparc_disassembler::dasm(std::ostream &stream, offs_t pc, uint32_t op) co
case 0x2c:
return dasm_move_cond(stream, pc, op);
case 0x2e:
- if ((m_version >= 9) && (RS1 == 0))
+ if ((m_version >= v9) && (RS1 == 0))
{
if (USEIMM) util::stream_format(stream, "%-*s%d,%s", m_op_field_width, "popc", SIMM13, REG_NAMES[RD]);
else util::stream_format(stream, "%-*s%s,%s", m_op_field_width, "popc", REG_NAMES[RS2], REG_NAMES[RD]);
@@ -908,7 +924,7 @@ offs_t sparc_disassembler::dasm(std::ostream &stream, offs_t pc, uint32_t op) co
case 0x30:
return dasm_write_state_reg(stream, pc, op);
case 0x31:
- if (m_version >= 9)
+ if (m_version >= v9)
{
switch (RD)
{
@@ -936,7 +952,7 @@ offs_t sparc_disassembler::dasm(std::ostream &stream, offs_t pc, uint32_t op) co
}
break;
case 0x32:
- if (m_version >= 9)
+ if (m_version >= v9)
{
if (V9_PRIV_REG_NAMES[RD])
{
@@ -963,7 +979,7 @@ offs_t sparc_disassembler::dasm(std::ostream &stream, offs_t pc, uint32_t op) co
}
break;
case 0x33:
- if (m_version <= 8)
+ if (m_version < v9)
{
if (RS1 == 0)
{
@@ -994,13 +1010,9 @@ offs_t sparc_disassembler::dasm(std::ostream &stream, offs_t pc, uint32_t op) co
case 0x3a:
return dasm_tcc(stream, pc, op);
case 0x3b:
- if (m_version >= 8)
- {
- util::stream_format(stream, "%-*s", m_op_field_width, "flush");
- dasm_address(stream, op);
- return 4 | SUPPORTED;
- }
- break;
+ util::stream_format(stream, "%-*s", m_op_field_width, m_version >= v8 ? "flush" : "iflush");
+ dasm_address(stream, op);
+ return 4 | SUPPORTED;
case 0x3c:
if (!USEIMM && (RS1 == RS2) && (RS2 == RD) && (RD == 0))
{
@@ -1016,12 +1028,12 @@ offs_t sparc_disassembler::dasm(std::ostream &stream, offs_t pc, uint32_t op) co
}
break;
case 0x3e:
- if ((m_version >= 9) & ((op & 0x7ffff) == 0))
+ if ((m_version >= v9) & ((op & 0x7ffff) == 0))
{
switch (RD)
{
- case 0: util::stream_format(stream, "done"); return 4 | SUPPORTED;
- case 1: util::stream_format(stream, "retry"); return 4 | SUPPORTED;
+ case 0: util::stream_format(stream, "done"); return 4 | STEP_OUT | SUPPORTED;
+ case 1: util::stream_format(stream, "retry"); return 4 | STEP_OUT | SUPPORTED;
}
}
break;
@@ -1072,7 +1084,7 @@ offs_t sparc_disassembler::dasm_invalid(std::ostream &stream, offs_t pc, uint32_
}
else if ((OP == 2) && ((OP3 == 0x36) || (OP3 == 0x37)))
{
- if (m_version >= 9)
+ if (m_version >= v9)
util::stream_format(stream, "IMPDEP%d impl-dep=%02x impl-dep=%05x", 1 + (OP3 & 1), RD, op & 0x7ffff);
else
util::stream_format(stream, "CPop%d opf=%03x rd=%d rs1=%d rs2=%d", 1 + (OP3 & 1), OPC, RD, RS1, RS2);
@@ -1101,13 +1113,16 @@ offs_t sparc_disassembler::dasm_branch(std::ostream &stream, offs_t pc, uint32_t
//const char * const comment(desc.get_comment ? desc.get_comment(m_config, desc.use_cc, pc, op) : nullptr);
//if (comment) util::stream_format(stream, " - %s", comment);
- return 4 | SUPPORTED;
+ if ((COND & 7) != 0)
+ return 4 | STEP_COND | step_over_extra(1) | SUPPORTED;
+ else
+ return 4 | SUPPORTED; // branch never or always
}
offs_t sparc_disassembler::dasm_shift(std::ostream &stream, offs_t pc, uint32_t op, const char *mnemonic, const char *mnemonicx, const char *mnemonicx0) const
{
- if ((m_version >= 9) && USEEXT)
+ if ((m_version >= v9) && USEEXT)
{
if (USEIMM)
util::stream_format(stream, "%-*s%s,%d,%s", m_op_field_width, mnemonicx, REG_NAMES[RS1], SHCNT64, REG_NAMES[RD]);
@@ -1137,9 +1152,9 @@ offs_t sparc_disassembler::dasm_read_state_reg(std::ostream &stream, offs_t pc,
util::stream_format(stream, "%-*s%%y,%s", m_op_field_width, "rd", REG_NAMES[RD]);
return 4 | SUPPORTED;
}
- else if ((m_version == 8) || ((m_version >= 9) && !USEIMM))
+ else if ((m_version == v8) || (m_version == sparclite) || ((m_version >= v9) && !USEIMM))
{
- if (!USEIMM && (RS1 == 15) && (RD == 0))
+ if (!USEIMM && (RS1 == 15) && (RD == 0) && (m_version != sparclite))
{
util::stream_format(stream, "stbar");
return 4 | SUPPORTED;
@@ -1157,7 +1172,7 @@ offs_t sparc_disassembler::dasm_read_state_reg(std::ostream &stream, offs_t pc,
}
}
}
- else if ((m_version >= 9) && USEIMM && (RS1 == 15) && (RD == 0))
+ else if ((m_version >= v9) && USEIMM && (RS1 == 15) && (RD == 0))
{
util::stream_format(stream, "%-*s", m_op_field_width, "membar");
uint32_t mask(MMASK | (CMASK << 4));
@@ -1197,9 +1212,9 @@ offs_t sparc_disassembler::dasm_write_state_reg(std::ostream &stream, offs_t pc,
}
return 4 | SUPPORTED;
}
- else if (m_version >= 8)
+ else if (m_version >= v8)
{
- if ((m_version >= 9) && USEIMM && (RS1 == 0) && (RD == 15))
+ if ((m_version >= v9) && USEIMM && (RS1 == 0) && (RD == 15))
{
util::stream_format(stream, "%-*s%d", m_op_field_width, "sir", SIMM13);
return 4 | SUPPORTED;
@@ -1246,7 +1261,7 @@ offs_t sparc_disassembler::dasm_write_state_reg(std::ostream &stream, offs_t pc,
offs_t sparc_disassembler::dasm_move_cond(std::ostream &stream, offs_t pc, uint32_t op) const
{
- if ((m_version < 9) || !MOVCC_CC_NAMES[MOVCC]) return dasm_invalid(stream, pc, op);
+ if ((m_version < v9) || !MOVCC_CC_NAMES[MOVCC]) return dasm_invalid(stream, pc, op);
const std::streampos start_position(stream.tellp());
util::stream_format(stream, "mov%s", MOVCC_COND_NAMES[MOVCOND | ((MOVCC << 2) & 16)]);
@@ -1261,7 +1276,7 @@ offs_t sparc_disassembler::dasm_move_cond(std::ostream &stream, offs_t pc, uint3
offs_t sparc_disassembler::dasm_move_reg_cond(std::ostream &stream, offs_t pc, uint32_t op) const
{
- if ((m_version < 9) || !MOVE_INT_COND_MNEMONICS[RCOND]) return dasm_invalid(stream, pc, op);
+ if ((m_version < v9) || !MOVE_INT_COND_MNEMONICS[RCOND]) return dasm_invalid(stream, pc, op);
if (USEIMM)
util::stream_format(stream, "%-*s%s,%d,%s", m_op_field_width, MOVE_INT_COND_MNEMONICS[RCOND], REG_NAMES[RS1], SIMM10, REG_NAMES[RD]);
@@ -1288,7 +1303,7 @@ offs_t sparc_disassembler::dasm_fpop1(std::ostream &stream, offs_t pc, uint32_t
offs_t sparc_disassembler::dasm_fpop2(std::ostream &stream, offs_t pc, uint32_t op) const
{
// Move Floating-Point Register on Condition
- if ((m_version >= 9) && (((op >> 18) & 1) == 0) && MOVCC_CC_NAMES[OPFCC])
+ if ((m_version >= v9) && (((op >> 18) & 1) == 0) && MOVCC_CC_NAMES[OPFCC])
{
const char *mnemonic;
bool shift;
@@ -1312,7 +1327,7 @@ offs_t sparc_disassembler::dasm_fpop2(std::ostream &stream, offs_t pc, uint32_t
const auto it(m_fpop2_desc.find(OPF));
if (it != m_fpop2_desc.end())
{
- if (m_version >= 9)
+ if (m_version >= v9)
{
if (it->second.int_rs1)
{
@@ -1391,6 +1406,7 @@ offs_t sparc_disassembler::dasm_jmpl(std::ostream &stream, offs_t pc, uint32_t o
if (USEIMM && (RD == 0) && ((RS1 == 15) || (RS1 == 31)) && (SIMM13 == 8))
{
util::stream_format(stream, (RS1 == 31) ? "ret" : "retl");
+ return 4 | STEP_OUT | step_over_extra(1) | SUPPORTED;
}
else
{
@@ -1398,16 +1414,19 @@ offs_t sparc_disassembler::dasm_jmpl(std::ostream &stream, offs_t pc, uint32_t o
dasm_address(stream, op);
if ((RD != 0) && (RD != 15))
util::stream_format(stream, ",%s", REG_NAMES[RD]);
+ if (RD != 0)
+ return 4 | STEP_OVER | step_over_extra(1) | SUPPORTED;
+ else
+ return 4 | SUPPORTED;
}
- return 4 | SUPPORTED;
}
offs_t sparc_disassembler::dasm_return(std::ostream &stream, offs_t pc, uint32_t op) const
{
- util::stream_format(stream, "%-*s", m_op_field_width, (m_version >= 9) ? "return" : "rett");
+ util::stream_format(stream, "%-*s", m_op_field_width, (m_version >= v9) ? "return" : "rett");
dasm_address(stream, op);
- return 4 | SUPPORTED;
+ return 4 | STEP_OUT | step_over_extra(1) | SUPPORTED;
}
@@ -1419,7 +1438,7 @@ offs_t sparc_disassembler::dasm_tcc(std::ostream &stream, offs_t pc, uint32_t op
};
static const char *const cc_names[4] = { "%icc", nullptr, "%xcc", nullptr };
const char *const mnemonic(tcc_names[COND]);
- if (m_version >= 9)
+ if (m_version >= v9)
{
const char *const cc(cc_names[TCCCC]);
if (!cc) return dasm_invalid(stream, pc, op);
@@ -1440,13 +1459,13 @@ offs_t sparc_disassembler::dasm_tcc(std::ostream &stream, offs_t pc, uint32_t op
else if (RS2 == 0) util::stream_format(stream, "%s", REG_NAMES[RS1]);
else util::stream_format(stream, "%s,%s", REG_NAMES[RS1], REG_NAMES[RS2]);
}
- return 4 | SUPPORTED;
+ return 4 | STEP_OVER | SUPPORTED;
}
offs_t sparc_disassembler::dasm_ldst(std::ostream &stream, offs_t pc, uint32_t op) const
{
- if (m_version >= 9)
+ if (m_version >= v9)
{
switch (OP3)
{
@@ -1463,6 +1482,7 @@ offs_t sparc_disassembler::dasm_ldst(std::ostream &stream, offs_t pc, uint32_t o
util::stream_format(stream, "%-*s[", m_op_field_width, "ldx");
dasm_address(stream, op);
util::stream_format(stream, "],%%efsr");
+ return 4 | SUPPORTED;
}
break;
case 0x25: // Store floating-point state register
@@ -1529,8 +1549,8 @@ offs_t sparc_disassembler::dasm_ldst(std::ostream &stream, offs_t pc, uint32_t o
dasm_address(stream, op);
stream << ']';
return 4 | SUPPORTED;
- case 0x26: // Store Floating-point deferred-trap Queue
- case 0x36: // Store Coprocessor deferred-trap Queue
+ case 0x26: // Store Double Floating-point deferred-trap Queue
+ case 0x36: // Store Double Coprocessor deferred-trap Queue
util::stream_format(stream, "%-*s%%%cq,[", m_op_field_width, "std", (OP3 == 0x36) ? 'c' : 'f');
dasm_address(stream, op);
stream << ']';
@@ -1542,7 +1562,7 @@ offs_t sparc_disassembler::dasm_ldst(std::ostream &stream, offs_t pc, uint32_t o
if (it == m_ldst_desc.end())
return dasm_invalid(stream, pc, op);
- if (it->second.alternate && USEIMM && (m_version < 9))
+ if (it->second.alternate && USEIMM && (m_version < v9))
return dasm_invalid(stream, pc, op);
if (it->second.g0_synth && (RD == 0))
diff --git a/src/devices/cpu/sparc/sparcdasm.h b/src/devices/cpu/sparc/sparcdasm.h
index f6f0e7bc27d..b92a2c283a3 100644
--- a/src/devices/cpu/sparc/sparcdasm.h
+++ b/src/devices/cpu/sparc/sparcdasm.h
@@ -4,8 +4,8 @@
SPARC disassembler
*/
-#ifndef MAME_DEVICES_CPU_SPARC_SPARC_DASM_H
-#define MAME_DEVICES_CPU_SPARC_SPARC_DASM_H
+#ifndef MAME_CPU_SPARC_SPARCDASM_H
+#define MAME_CPU_SPARC_SPARCDASM_H
#pragma once
@@ -26,6 +26,7 @@ public:
virtual uint8_t get_fcc(unsigned index) const = 0; // ?><=
};
+ enum sparc_version { v7, v8, sparclite, v9 };
enum vis_level { vis_none, vis_1, vis_2, vis_2p, vis_3, vis_3b };
struct asi_desc
@@ -55,8 +56,8 @@ public:
};
typedef std::map<uint8_t, prftch_desc> prftch_desc_map;
- sparc_disassembler(const config *conf, unsigned version);
- sparc_disassembler(const config *conf, unsigned version, vis_level vis);
+ sparc_disassembler(const config *conf, sparc_version version);
+ sparc_disassembler(const config *conf, sparc_version version, vis_level vis);
template <typename T> void add_state_reg_desc(const T &desc)
{
@@ -215,6 +216,7 @@ private:
static const branch_desc CBCCC_DESC;
static const int_op_desc_map::value_type V7_INT_OP_DESC[];
static const int_op_desc_map::value_type V8_INT_OP_DESC[];
+ static const int_op_desc_map::value_type SPARCLITE_INT_OP_DESC[];
static const int_op_desc_map::value_type V9_INT_OP_DESC[];
static const state_reg_desc_map::value_type V9_STATE_REG_DESC[];
static const char * const MOVCC_CC_NAMES[8];
@@ -239,7 +241,7 @@ private:
static const vis_op_desc_map::value_type VIS3B_OP_DESC[];
//const config *m_config;
- unsigned m_version;
+ sparc_version m_version;
vis_level m_vis_level;
int m_op_field_width;
branch_desc m_branch_desc[8];
@@ -253,4 +255,4 @@ private:
vis_op_desc_map m_vis_op_desc;
};
-#endif // MAME_DEVICES_CPU_SPARC_SPARC_DASM_H
+#endif // MAME_CPU_SPARC_SPARCDASM_H
diff --git a/src/devices/cpu/sparc/sparcdefs.h b/src/devices/cpu/sparc/sparcdefs.h
index f023da44679..19784b173a7 100644
--- a/src/devices/cpu/sparc/sparcdefs.h
+++ b/src/devices/cpu/sparc/sparcdefs.h
@@ -2,15 +2,15 @@
// copyright-holders:Ryan Holtz
//================================================================
//
-// mb86901defs.h - Helpful #defines for emulating the MB86901
-// series of SPARC processor.
+// sparcdefs.h - Helpful #defines for emulating the MB86901
+// series of SPARC processor.
//
//================================================================
-#pragma once
+#ifndef MAME_CPU_SPARC_SPARCDEFS_H
+#define MAME_CPU_SPARC_SPARCDEFS_H
-#ifndef __MB86901_DEFS_H__
-#define __MB86901_DEFS_H__
+#pragma once
#define PSR_CWP_MASK 0x0000001f
#define PSR_ET_SHIFT 5
@@ -85,6 +85,8 @@
#define WIM m_wim
#define TBR m_tbr
+#define NWINDOWS m_nwindows
+
#define OP_NS (op & 0xc0000000)
#define OP (op >> 30)
@@ -95,17 +97,17 @@
#define OPFLOW ((op >> 5) & 0x3f)
#define DISP30 (int32_t(op << 2))
-#define DISP22 (int32_t(op << 10) >> 8)
-#define DISP19 (int32_t(op << 13) >> 11)
-#define DISP16 (int32_t(((op << 10) & 0xc0000000) | ((op << 16) & 0x3fff0000)) >> 14)
+#define DISP22 util::sext(op << 2, 24)
+#define DISP19 util::sext(op << 2, 21)
+#define DISP16 util::sext((op & 0x300000) >> 4 | (op & 0x3fff) << 2, 18)
#define IMM22 (op << 10)
#define CONST22 (op & 0x3fffff)
-#define SIMM13 (int32_t(op << 19) >> 19)
-#define SIMM11 (int32_t(op << 21) >> 21)
-#define SIMM10 (int32_t(op << 22) >> 22)
-#define SIMM8 (int32_t(op << 24) >> 24)
+#define SIMM13 util::sext(op, 13)
+#define SIMM11 util::sext(op, 11)
+#define SIMM10 util::sext(op, 10)
+#define SIMM8 util::sext(op, 8)
#define IMM7 (op & 0x7f)
-#define SIMM7 (int32_t(op << 25) >> 25)
+#define SIMM7 util::sext(op, 7)
#define SHCNT32 (op & 31)
#define SHCNT64 (op & 63)
#define IAMODE (op & 0x7)
@@ -127,9 +129,12 @@
#define CMASK ((op >> 4) & 7)
#define RD ((op >> 25) & 31)
+#define RD_D ((op >> 25) & 30)
#define RDBITS (op & 0x3e000000)
#define RS1 ((op >> 14) & 31)
+#define RS1_D ((op >> 14) & 30)
#define RS2 (op & 31)
+#define RS2_D (op & 30)
#define FREG(x) m_fpr[(x)]
#define FDREG m_fpr[RD]
@@ -139,7 +144,7 @@
#define RDREG *m_regs[RD]
#define RS1REG *m_regs[RS1]
#define RS2REG *m_regs[RS2]
-#define SET_RDREG(x) do { if(RD) { RDREG = (x); } } while (0)
+#define SET_RDREG(x) do { if(RDBITS) { RDREG = (x); } } while (0)
#define ADDRESS (USEIMM ? (RS1REG + SIMM13) : (RS1REG + RS2REG))
#define PC m_pc
@@ -197,6 +202,7 @@
#define OP3_UMULCC 26
#define OP3_SMULCC 27
#define OP3_SUBXCC 28
+#define OP3_DIVSCC 29
#define OP3_UDIVCC 30
#define OP3_SDIVCC 31
#define OP3_TADDCC 32
@@ -211,6 +217,7 @@
#define OP3_RDPSR 41
#define OP3_RDWIM 42
#define OP3_RDTBR 43
+#define OP3_SCAN 44
#define OP3_WRASR 48
#define OP3_WRPSR 49
#define OP3_WRWIM 50
@@ -386,4 +393,96 @@
#define SDIV (OP3 == OP3_SDIV)
#define SDIVCC (OP3 == OP3_SDIVCC)
-#endif // __MB86901_DEFS_H__
+#define FSR_CEXC_MASK 0x0000001f
+#define FSR_CEXC_NXC 0x00000001
+#define FSR_CEXC_DZC 0x00000002
+#define FSR_CEXC_UFC 0x00000004
+#define FSR_CEXC_OFC 0x00000008
+#define FSR_CEXC_NVC 0x00000010
+
+#define FSR_AEXC_SHIFT 5
+#define FSR_AEXC_MASK 0x000003e0
+#define FSR_AEXC_NXA 0x00000020
+#define FSR_AEXC_DZA 0x00000040
+#define FSR_AEXC_UFA 0x00000080
+#define FSR_AEXC_OFA 0x00000100
+#define FSR_AEXC_NVA 0x00000200
+
+#define FSR_FCC_SHIFT 10
+#define FSR_FCC_MASK 0x00000c00
+#define FSR_FCC_EQ 0x00000000
+#define FSR_FCC_LT 0x00000400
+#define FSR_FCC_GT 0x00000800
+#define FSR_FCC_UO 0x00000c00
+
+#define FSR_QNE 0x00002000
+
+#define FSR_FTT_MASK 0x0001c000
+#define FSR_FTT_NONE 0x00000000
+#define FSR_FTT_IEEE 0x00004000
+#define FSR_FTT_UNFIN 0x00008000
+#define FSR_FTT_UNIMP 0x0000c000
+#define FSR_FTT_SEQ 0x00010000
+
+#define FSR_VER 0x00020000
+
+#define FSR_NS 0x00400000
+
+#define FSR_TEM_SHIFT 23
+#define FSR_TEM_MASK 0x0f800000
+#define FSR_TEM_NXM 0x00800000
+#define FSR_TEM_DZM 0x01000000
+#define FSR_TEM_UFM 0x02000000
+#define FSR_TEM_OFM 0x04000000
+#define FSR_TEM_NVM 0x08000000
+
+#define FSR_RD_SHIFT 30
+#define FSR_RD_MASK 0xc0000000
+#define FSR_RD_NEAR 0x00000000
+#define FSR_RD_ZERO 0x40000000
+#define FSR_RD_UP 0x80000000
+#define FSR_RD_DOWN 0xc0000000
+
+#define FSR_RESV_MASK 0x30301000
+
+// FPop1
+#define FPOP_FMOVS 0x001
+#define FPOP_FNEGS 0x005
+#define FPOP_FABSS 0x009
+#define FPOP_FSQRTS 0x029
+#define FPOP_FSQRTD 0x02a
+#define FPOP_FSQRTX 0x02b
+#define FPOP_FADDS 0x041
+#define FPOP_FADDD 0x042
+#define FPOP_FADDX 0x043
+#define FPOP_FSUBS 0x045
+#define FPOP_FSUBD 0x046
+#define FPOP_FSUBX 0x047
+#define FPOP_FMULS 0x049
+#define FPOP_FMULD 0x04a
+#define FPOP_FMULX 0x04b
+#define FPOP_FDIVS 0x04d
+#define FPOP_FDIVD 0x04e
+#define FPOP_FDIVX 0x04f
+#define FPOP_FITOS 0x0c4
+#define FPOP_FDTOS 0x0c6
+#define FPOP_FXTOS 0x0c7
+#define FPOP_FITOD 0x0c8
+#define FPOP_FSTOD 0x0c9
+#define FPOP_FXTOD 0x0cb
+#define FPOP_FITOX 0x0cc
+#define FPOP_FSTOX 0x0cd
+#define FPOP_FDTOX 0x0ce
+#define FPOP_FSTOI 0x0d1
+#define FPOP_FDTOI 0x0d2
+#define FPOP_FXTOI 0x0d3
+
+// FPop2
+#define FPOP_FCMPS 0x051
+#define FPOP_FCMPD 0x052
+#define FPOP_FCMPX 0x053
+#define FPOP_FCMPES 0x055
+#define FPOP_FCMPED 0x056
+#define FPOP_FCMPEX 0x057
+
+#endif // MAME_CPU_SPARC_SPARCDEFS_H
diff --git a/src/devices/cpu/sparc/sparcv8ops.ipp b/src/devices/cpu/sparc/sparcv8ops.ipp
deleted file mode 100644
index b2611d694f2..00000000000
--- a/src/devices/cpu/sparc/sparcv8ops.ipp
+++ /dev/null
@@ -1,293 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-//================================================================
-//
-// sparcv8ops.ipp - Emulation for SPARCv8-class instructions
-//
-//================================================================
-
-
-//-------------------------------------------------
-// execute_swap - execute a swap instruction
-//-------------------------------------------------
-
-void mb86901_device::execute_swap(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 169, "Appendix C - ISP Descriptions - Atomic Load-Store Unsigned Byte Instructions" (SPARCv8.pdf, pg. 166)
-
- if (SWAP) then (
- address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
- addr_space <- (if (S = 0) then 10 else 11)
- ) else if (SWAPA) then (
- if (S = 0) then (
- trap <- 1;
- privileged_instruction <- 1
- ) else if (i = 1) then (
- trap <- 1;
- illegal_instruction <- 1
- ) else (
- address <- r[rs1] + r[rs1];
- addr_space <- asi
- )
- );
- next;
- if (trap = 0) then (
- temp <- r[rd];
- while ( (pb_block_ldst_byte = 1) or (pb_block_ldst_word = 1) ) (
- { wait for lock(s) to be lifted }
- { an implementation actually need only block when another SWAP is pending on
- the same word in memory as the one addressed by this SWAP, or a LDSTUB is
- pending on any byte of the word in memory addressed by this SWAP }
- );
- next;
- pb_block_ldst_word <- 1;
- next;
- (word, MAE) <- memory_read(addr_space, address);
- next;
- if (MAE = 1) then (
- trap <- 1;
- data_access_exception = 1
- )
- next;
- if (trap = 0) then (
- MAE <- memory_write(addr_space, address, 1111, temp);
- next;
- pb_block_ldst_word <- 0;
- if (MAE = 1) then ( { MAE = 1 only due to a "non-resumable machine-check error" }
- trap <- 1;
- data_access_exception <- 1
- ) else (
- if (rd != 0) then r[rd] <- word
- )
- );
- */
-
- uint32_t address = 0;
- uint8_t addr_space = 0;
- if (SWAP)
- {
- address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
- addr_space = (IS_USER ? 10 : 11);
- }
- else if (SWAPA)
- {
- if (IS_USER)
- {
- m_trap = 1;
- m_privileged_instruction = 1;
- }
- else if (USEIMM)
- {
- m_trap = 1;
- m_illegal_instruction = 1;
- }
- else
- {
- address = RS1REG + RS2REG;
- addr_space = ASI;
- }
- }
-
- uint32_t word = 0;
- uint32_t temp = 0;
- if (!m_trap)
- {
- temp = RDREG;
- while (m_pb_block_ldst_byte || m_pb_block_ldst_word)
- {
- // { wait for lock(s) to be lifted }
- // { an implementation actually need only block when another SWAP is pending on
- // the same word in memory as the one addressed by this SWAP, or a LDSTUB is
- // pending on any byte of the word in memory addressed by this SWAP }
- }
-
- m_pb_block_ldst_word = 1;
-
- word = read_sized_word(addr_space, address, 4);
-
- if (MAE)
- {
- m_trap = 1;
- m_data_access_exception = 1;
- }
- }
- if (!m_trap)
- {
- write_sized_word(addr_space, address, temp, 4);
-
- m_pb_block_ldst_word = 0;
- if (MAE)
- {
- m_trap = 1;
- m_data_access_exception = 1;
- }
- else
- {
- if (RD != 0)
- RDREG = word;
- }
- }
-}
-
-
-//-------------------------------------------------
-// execute_mul - execute a multiply opcode
-//-------------------------------------------------
-
-void mb86901_device::execute_mul(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 175, "Appendix C - ISP Descriptions - Multiply Instructions" (SPARCv8.pdf, pg. 172)
-
- operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
-
- if (UMUL or UMULScc) then (Y, result) <- multiply_unsigned(r[rs1], operand2)
- else if (SMUL or SMULcc) then (Y, result) <- multiply_signed(r[rs1], operand2)
- next;
- if (rd != 0) then (
- r[rd] <- result;
- )
- if (UMULcc or SMULcc) then (
- N <- result<31>;
- Z <- if (result = 0) then 1 else 0;
- V <- 0
- C <- 0
- );
- */
-
- uint32_t operand2 = (USEIMM ? SIMM13 : RS2REG);
-
- uint32_t result = 0;
- if (UMUL || UMULCC)
- {
- uint64_t dresult = (uint64_t)RS1REG * (uint64_t)operand2;
- Y = (uint32_t)(dresult >> 32);
- result = (uint32_t)dresult;
- }
- else if (SMUL || SMULCC)
- {
- int64_t dresult = (int64_t)(int32_t)RS1REG * (int64_t)(int32_t)operand2;
- Y = (uint32_t)(dresult >> 32);
- result = (uint32_t)dresult;
- }
-
- if (RD != 0)
- {
- RDREG = result;
- }
- if (UMULCC || SMULCC)
- {
- CLEAR_ICC;
- PSR |= BIT31(result) ? PSR_N_MASK : 0;
- PSR |= (result == 0) ? PSR_Z_MASK : 0;
- }
-}
-
-
-//-------------------------------------------------
-// execute_div - execute a divide opcode
-//-------------------------------------------------
-
-void mb86901_device::execute_div(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 176, "Appendix C - ISP Descriptions - Multiply Instructions" (SPARCv8.pdf, pg. 173)
-
- operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
-
- next;
- if (operand2 = 0) then (
- trap <- 1;
- division_by_zero <- 1
- ) else (
- if (UDIV or UDIVcc) then (
- temp_64bit <- divide_unsigned(Y[]r[rs1], operand2);
- next;
- result <- temp_64bit<31:0>;
- temp_V <- if (temp_64bit<63:32> = 0) then 0 else 1;
- ) else if (SDIV or SDIVcc) then (
- temp_64bit <- divide_signed(Y[]r[rs1], operand2);
- next;
- result <- temp_64bit<31:0>;
- temp_V <- if (temp_64bit<63:31> = 0) or
- (temp_64bit<63:31> = (2^33 - 1)) ) then 0 else 1;
- ) ;
- next;
-
- if (temp_V) then (
- { result overflowed 32 bits; return largest appropriate integer }
- if (UDIV or UDIVcc) then result <- 2^32 - 1;
- else if (SDIV or SDIVcc) then (
- if (temp_64bit > 0) then result <- 2^31 - 1;
- else result <- -2^31
- )
- );
- next;
-
- if (rd != 0) then (
- r[rd] <- result
- ) ;
- if (UDIVcc or SDIVcc) then (
- N <- result<31>;
- Z <- if (result = 0) then 1 else 0;
- V <- temp_V;
- C <- 0
- )
- );
- */
-
- uint32_t operand2 = (USEIMM ? SIMM13 : RS2REG);
-
- if (operand2 == 0)
- {
- m_trap = 1;
- m_division_by_zero = 1;
- }
- else
- {
- uint32_t result = 0;
- bool temp_v = false;
- int64_t temp_64bit = 0;
- if (UDIV || UDIVCC)
- {
- temp_64bit = int64_t(uint64_t((uint64_t(Y) << 32) | uint64_t(RS1REG)) / operand2);
-
- result = uint32_t(temp_64bit);
-
- temp_v = ((temp_64bit & 0xffffffff00000000) == 0) ? false : true;
- }
- else if (SDIV || SDIVCC)
- {
- temp_64bit = int64_t(int64_t((uint64_t(Y) << 32) | uint64_t(RS1REG)) / operand2);
-
- result = uint32_t(temp_64bit);
-
- uint64_t shifted = uint64_t(temp_64bit) >> 31;
- temp_v = (shifted == 0 || shifted == 0x1ffffffff) ? false : true;
- }
-
- if (temp_v)
- {
- if (UDIV || UDIVCC)
- {
- result = 0xffffffff;
- }
- else if (SDIV || SDIVCC)
- {
- if (temp_64bit > 0)
- result = 0x7fffffff;
- else
- result = 0x80000000;
- }
- }
-
- if (RD != 0)
- RDREG = result;
-
- if (UDIVCC || SDIVCC)
- {
- CLEAR_ICC;
- PSR |= BIT31(result) ? PSR_N_MASK : 0;
- PSR |= (result == 0) ? PSR_Z_MASK : 0;
- PSR |= temp_v ? PSR_V_MASK : 0;
- }
- }
-}
diff --git a/src/devices/cpu/sparc/ss1fcode.ipp b/src/devices/cpu/sparc/ss1fcode.ipp
index d9457742340..35b2cd7cd72 100644
--- a/src/devices/cpu/sparc/ss1fcode.ipp
+++ b/src/devices/cpu/sparc/ss1fcode.ipp
@@ -7,7 +7,7 @@
//
//================================================================
-void mb86901_device::log_fcodes()
+void sparc_base_device::log_fcodes()
{
if (PC != 0xffef0000 && PC != m_ss1_next_entry_point)
return;
@@ -23,7 +23,7 @@ void mb86901_device::log_fcodes()
if (false)//opcode == 0x6304)
{
m_log_fcodes = true;
- //machine().debugger().debug_break();
+ //machine().debug_break();
}
else if (!m_log_fcodes)
{
@@ -57,7 +57,7 @@ void mb86901_device::log_fcodes()
}
}
-void mb86901_device::indent()
+void sparc_base_device::indent()
{
uint32_t program_depth = (0xffeff000 - (REG(6) - 4)) / 4;
@@ -71,7 +71,7 @@ void mb86901_device::indent()
}
}
-void mb86901_device::disassemble_ss1_fcode(uint32_t r5, uint32_t opcode, uint32_t handler_base, uint32_t entry_point, uint32_t stack)
+void sparc_base_device::disassemble_ss1_fcode(uint32_t r5, uint32_t opcode, uint32_t handler_base, uint32_t entry_point, uint32_t stack)
{
std::string opdesc = m_ss1_fcode_table[opcode];
if (opdesc.length() == 0)