summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2021-11-23 23:46:12 +0100
committer hap <happppp@users.noreply.github.com>2021-11-23 23:46:32 +0100
commit4518f0eadeb4482ba01ab5add75d6eae921ce571 (patch)
tree1154fb8e0139f47270ad291f7a04067a05ae153d /src/devices
parent497b9a31262b453fd64503b72341c9bcd78df774 (diff)
sparc: added initial support for SPARClite [Ryan Holtz]
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/cpu/sparc/sparc.cpp687
-rw-r--r--src/devices/cpu/sparc/sparc.h119
-rw-r--r--src/devices/cpu/sparc/sparcdasm.cpp28
-rw-r--r--src/devices/cpu/sparc/sparcdasm.h8
-rw-r--r--src/devices/cpu/sparc/sparcdefs.h2
5 files changed, 792 insertions, 52 deletions
diff --git a/src/devices/cpu/sparc/sparc.cpp b/src/devices/cpu/sparc/sparc.cpp
index de53e0aa1ea..3312bd236b3 100644
--- a/src/devices/cpu/sparc/sparc.cpp
+++ b/src/devices/cpu/sparc/sparc.cpp
@@ -27,8 +27,32 @@
#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'")
const int sparc_base_device::NWINDOWS = 7;
@@ -36,6 +60,23 @@ const int sparc_base_device::NWINDOWS = 7;
#include "ss1fcode.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" } }
+};
+}
//-------------------------------------------------
// sparc_base_device - constructor
@@ -46,20 +87,29 @@ sparc_base_device::sparc_base_device(const machine_config &mconfig, device_type
, m_mmu(*this, finder_base::DUMMY_TAG)
{
m_debugger_config = address_space_config("debug", ENDIANNESS_BIG, 32, 32);
- for (int i = 0; i < 0x10; i++)
+
+ if (type != MB86930)
{
- m_asi_names[i] = util::string_format("asi%x", i);
- m_asi_config[i] = address_space_config(m_asi_names[i].c_str(), ENDIANNESS_BIG, 32, 32);
+ for (int i = 0; i < 0x10; i++)
+ {
+ m_asi_names[i] = util::string_format("asi%x", i);
+ m_asi_config[i] = address_space_config(m_asi_names[i].c_str(), ENDIANNESS_BIG, 32, 32);
+ }
}
}
//-------------------------------------------------
-// sparcv7_device - constructor
+// sparcv7_device - constructors
//-------------------------------------------------
sparcv7_device::sparcv7_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : sparc_base_device(mconfig, SPARCV7, tag, owner, 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)
{
}
@@ -69,8 +119,61 @@ sparcv7_device::sparcv7_device(const machine_config &mconfig, const char *tag, d
//-------------------------------------------------
sparcv8_device::sparcv8_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : sparc_base_device(mconfig, SPARCV8, tag, owner, clock)
+ : sparcv8_device(mconfig, SPARCV8, tag, owner, clock)
+{
+}
+
+
+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)
+ , m_cs_w(*this)
{
+ m_asi_names[0x00] = "debugger";
+ m_asi_names[0x01] = "system_control";
+ m_asi_names[0x02] = "icache_lock";
+ m_asi_names[0x03] = "dcache_lock";
+ m_asi_names[0x04] = "asi4";
+ m_asi_names[0x05] = "asi5";
+ m_asi_names[0x06] = "asi6";
+ m_asi_names[0x07] = "asi7";
+ m_asi_names[0x08] = "user_insn";
+ m_asi_names[0x09] = "super_insn";
+ m_asi_names[0x0a] = "user_data";
+ m_asi_names[0x0b] = "super_data";
+ m_asi_names[0x0c] = "icache_tag";
+ m_asi_names[0x0d] = "icache_data";
+ m_asi_names[0x0e] = "dcache_tag";
+ m_asi_names[0x0f] = "dcache_data";
+
+ m_asi_config[0x00] = address_space_config(m_asi_names[0x00].c_str(), ENDIANNESS_BIG, 32, 32);
+ m_asi_config[0x01] = address_space_config(m_asi_names[0x01].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::control_map), this));
+ m_asi_config[0x02] = address_space_config(m_asi_names[0x02].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_lock_map), this));
+ m_asi_config[0x03] = address_space_config(m_asi_names[0x03].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::dcache_lock_map), this));
+ m_asi_config[0x04] = address_space_config(m_asi_names[0x04].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<4>), this));
+ m_asi_config[0x05] = address_space_config(m_asi_names[0x05].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<5>), this));
+ m_asi_config[0x06] = address_space_config(m_asi_names[0x06].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<6>), this));
+ m_asi_config[0x07] = address_space_config(m_asi_names[0x07].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<7>), this));
+ m_asi_config[0x08] = address_space_config(m_asi_names[0x08].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<8>), this));
+ m_asi_config[0x09] = address_space_config(m_asi_names[0x09].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<9>), this));
+ m_asi_config[0x0a] = address_space_config(m_asi_names[0x0a].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<10>), this));
+ m_asi_config[0x0b] = address_space_config(m_asi_names[0x0b].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::mmu_map<11>), this));
+ m_asi_config[0x0c] = address_space_config(m_asi_names[0x0c].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_tag_map), this));
+ m_asi_config[0x0d] = address_space_config(m_asi_names[0x0d].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::icache_data_map), this));
+ m_asi_config[0x0e] = address_space_config(m_asi_names[0x0e].c_str(), ENDIANNESS_BIG, 32, 32, 0, address_map_constructor(FUNC(mb86930_device::dcache_tag_map), this));
+ m_asi_config[0x0f] = address_space_config(m_asi_names[0x0f].c_str(), 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); });
}
@@ -176,13 +279,13 @@ void sparc_base_device::device_start()
space(i).specific(m_asi[i]);
}
- memset(m_dbgregs, 0, 24 * sizeof(uint32_t));
+ 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;
@@ -199,7 +302,7 @@ void sparc_base_device::device_start()
m_alu_setcc[OP3_TSUBCCTV] = true;
m_alu_setcc[OP3_MULSCC] = true;
- 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;
@@ -247,7 +350,7 @@ void sparc_base_device::device_start()
m_alu_op3_assigned[OP3_SAVE] = true;
m_alu_op3_assigned[OP3_RESTORE] = true;
- 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;
@@ -315,7 +418,7 @@ void sparc_base_device::device_start()
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 < 120; 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));
@@ -401,35 +504,38 @@ void sparc_base_device::device_start()
void sparc_base_device::device_resolve_objects()
{
- m_mmu->set_host(this);
+ if (m_mmu.found())
+ m_mmu->set_host(this);
}
void sparc_base_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_fp_exception = 0;
- m_fp_exception_pending = 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_disabled = 0;
- m_cp_exception = 0;
m_cp_sequence_err = 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_bp_irl = 0;
m_irq_state = 0;
@@ -442,8 +548,8 @@ void sparc_base_device::device_reset()
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;
@@ -516,6 +622,424 @@ void sparcv8_device::device_reset()
m_division_by_zero = 0;
}
+
+//-------------------------------------------------
+// mb86930_device - initializers
+//-------------------------------------------------
+
+void mb86930_device::device_start()
+{
+ sparcv8_device::device_start();
+
+ m_alu_setcc[OP3_DIVSCC] = true;
+
+ m_alu_op3_assigned[OP3_DIVSCC] = true;
+ m_alu_op3_assigned[OP3_SCAN] = true;
+
+ 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));
+ save_item(NAME(m_same_page_waits[6]));
+ save_item(NAME(m_other_page_waits[6]));
+
+ std::fill_n(&m_arsr[0], 6, 0);
+ std::fill_n(&m_amr[0], 6, 0);
+
+ m_cs_r.resolve_all_safe(0);
+ m_cs_w.resolve_all_safe();
+}
+
+void mb86930_device::device_reset()
+{
+ sparcv8_device::device_reset();
+
+ m_spmr = 0;
+ m_spmr_mask = ~0ULL;
+ std::fill_n(&m_wssr[0], 3, 0);
+ m_last_masked_addr = 0ULL;
+
+ std::fill_n(&m_same_page_waits[0], 6, 0);
+ std::fill_n(&m_other_page_waits[0], 6, 0);
+
+ m_arsr[0] = (9 << 23);
+ m_amr[0] = (0x1f << 1);
+
+ update_addr_masks();
+}
+
+
+//-------------------------------------------------
+// mb86930_device - internal maps
+//-------------------------------------------------
+
+void mb86930_device::control_map(address_map &map)
+{
+ 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])
+ {
+ eat_cycles(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])
+ {
+ eat_cycles(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];
+ }
+}
+
+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 = 0;
+ 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);
+}
+
+
+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]);
+
+ const uint32_t wait_idx = (offset << 1);
+ const bool wait_en0 = BIT(m_wssr[offset], 21) && !BIT(m_wssr[offset], 20);
+ const bool wait_en1 = BIT(m_wssr[offset], 8) && !BIT(m_wssr[offset], 7);
+ m_other_page_waits[wait_idx] = wait_en0 ? (((m_wssr[offset] >> 27) & 0x1f) + 1) : 0;
+ m_same_page_waits[wait_idx] = wait_en0 ? (((m_wssr[offset] >> 22) & 0x1f) + 1) : 0;
+ m_other_page_waits[wait_idx + 1] = wait_en1 ? (((m_wssr[offset] >> 14) & 0x1f) + 1) : 0;
+ m_same_page_waits[wait_idx + 1] = wait_en1 ? (((m_wssr[offset] >> 9) & 0x1f) + 1) : 0;
+}
+
+
+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);
+}
+
+
//-------------------------------------------------
// device_post_load - update register pointers
// after loading a savestate
@@ -614,11 +1138,24 @@ void sparc_base_device::state_string_export(const device_state_entry &entry, std
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), 7);
+ auto dasm = std::make_unique<sparc_disassembler>(static_cast<sparc_disassembler::config const *>(this), sparc_disassembler::v7);
+ 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), sparc_disassembler::v8);
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);
+ m_asi_desc_adder(dasm.get());
+ return std::move(dasm);
+}
//**************************************************************************
// CORE EXECUTION LOOP
@@ -1361,6 +1898,12 @@ void sparc_base_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;
}
@@ -1786,12 +2329,24 @@ inline void sparc_base_device::execute_group2(uint32_t op)
//-------------------------------------------------
// update_extra_group2 - execute a group2
// instruction belonging to a newer SPARC version
-// than v7
+// than v7, or which can be overridden from v7
//-------------------------------------------------
bool sparcv7_device::execute_extra_group2(uint32_t op)
{
- return false;
+ switch (OP3)
+ {
+ case OP3_TADDCCTV:
+ execute_taddcc(op);
+ return true;
+
+ case OP3_TSUBCCTV:
+ execute_tsubcc(op);
+ return true;
+
+ default:
+ return false;
+ }
}
bool sparcv8_device::execute_extra_group2(uint32_t op)
@@ -1826,6 +2381,40 @@ bool sparcv8_device::execute_extra_group2(uint32_t op)
}
}
+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;
+
+ default:
+ return false;
+ }
+}
+
//-------------------------------------------------
// update_gpr_pointers - cache pointers to
// the registers in our current window
@@ -4527,11 +5116,17 @@ void sparcv8_device::execute_swap(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
{
@@ -4561,6 +5156,9 @@ void sparcv8_device::execute_swap(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
+ m_stashed_icount = m_icount;
+ m_icount = 0;
+ return;
}
}
if (!m_trap)
@@ -4572,6 +5170,9 @@ void sparcv8_device::execute_swap(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
+ m_stashed_icount = m_icount;
+ m_icount = 0;
+ return;
}
else
{
@@ -4579,6 +5180,9 @@ void sparcv8_device::execute_swap(uint32_t op)
RDREG = word;
}
}
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -4632,6 +5236,9 @@ void sparcv8_device::execute_mul(uint32_t op)
PSR |= BIT31(result) ? PSR_N_MASK : 0;
PSR |= (result == 0) ? PSR_Z_MASK : 0;
}
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -4692,6 +5299,9 @@ void sparcv8_device::execute_div(uint32_t op)
{
m_trap = 1;
m_division_by_zero = 1;
+ m_stashed_icount = m_icount;
+ m_icount = 0;
+ return;
}
else
{
@@ -4742,6 +5352,9 @@ void sparcv8_device::execute_div(uint32_t op)
PSR |= temp_v ? PSR_V_MASK : 0;
}
}
+
+ PC = nPC;
+ nPC = nPC + 4;
}
diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h
index acdc044a62c..8f071a8c72b 100644
--- a/src/devices/cpu/sparc/sparc.h
+++ b/src/devices/cpu/sparc/sparc.h
@@ -152,7 +152,7 @@ protected:
void log_fcodes();
#endif
- required_device<sparc_mmu_interface> m_mmu;
+ optional_device<sparc_mmu_interface> m_mmu;
// address spaces
std::string m_asi_names[0x10];
@@ -172,7 +172,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];
@@ -279,6 +279,9 @@ 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;
@@ -290,7 +293,12 @@ 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;
virtual void device_reset() override;
@@ -312,9 +320,116 @@ private:
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:
+ virtual void device_start() override;
+ virtual void device_reset() 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);
+ void icache_lock_map(address_map &map);
+ void dcache_lock_map(address_map &map);
+ template <uint8_t Asi> void mmu_map(address_map &map);
+ void icache_tag_map(address_map &map);
+ void icache_data_map(address_map &map);
+ void dcache_tag_map(address_map &map);
+ void dcache_data_map(address_map &map);
+
+ void update_addr_masks();
+
+ devcb_read32::array<6> m_cs_r;
+ devcb_write32::array<6> m_cs_w;
+
+ 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(SPARCV7, sparcv7_device)
DECLARE_DEVICE_TYPE(SPARCV8, sparcv8_device)
+DECLARE_DEVICE_TYPE(MB86930, mb86930_device)
enum
{
diff --git a/src/devices/cpu/sparc/sparcdasm.cpp b/src/devices/cpu/sparc/sparcdasm.cpp
index 1fcbcdfa7a8..b6a5a590b9c 100644
--- a/src/devices/cpu/sparc/sparcdasm.cpp
+++ b/src/devices/cpu/sparc/sparcdasm.cpp
@@ -176,6 +176,10 @@ 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[] = {
+ { 0x1d, { false, "divscc" } }, { 0x22, { 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" } },
@@ -610,24 +614,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 +642,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;
diff --git a/src/devices/cpu/sparc/sparcdasm.h b/src/devices/cpu/sparc/sparcdasm.h
index f6f0e7bc27d..91a22df173a 100644
--- a/src/devices/cpu/sparc/sparcdasm.h
+++ b/src/devices/cpu/sparc/sparcdasm.h
@@ -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];
diff --git a/src/devices/cpu/sparc/sparcdefs.h b/src/devices/cpu/sparc/sparcdefs.h
index f5eff0f55c9..d7e291cbcdd 100644
--- a/src/devices/cpu/sparc/sparcdefs.h
+++ b/src/devices/cpu/sparc/sparcdefs.h
@@ -200,10 +200,12 @@
#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
#define OP3_TSUBCC 33
+#define OP3_SCAN 34
#define OP3_TADDCCTV 34
#define OP3_TSUBCCTV 35
#define OP3_MULSCC 36