mirror of
https://github.com/holub/mame
synced 2025-04-24 01:11:11 +03:00
sparc: added initial support for SPARClite [Ryan Holtz]
This commit is contained in:
parent
497b9a3126
commit
4518f0eade
@ -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,11 +119,64 @@ 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); });
|
||||
}
|
||||
|
||||
|
||||
void sparc_base_device::device_start()
|
||||
{
|
||||
#if LOG_FCODES
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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];
|
||||
@ -278,6 +278,9 @@ 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;
|
||||
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user