summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sparc/sparc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sparc/sparc.cpp')
-rw-r--r--src/devices/cpu/sparc/sparc.cpp509
1 files changed, 149 insertions, 360 deletions
diff --git a/src/devices/cpu/sparc/sparc.cpp b/src/devices/cpu/sparc/sparc.cpp
index 68c711c9833..8717d56e22e 100644
--- a/src/devices/cpu/sparc/sparc.cpp
+++ b/src/devices/cpu/sparc/sparc.cpp
@@ -17,8 +17,6 @@
// - Extended-precision FPU support
// - Coprocessor support
// - Finish SPARClite peripherals
-// - SPARClite m_wssr[0] should be 0x7ff40 at reset (32 wait cycles for CS0),
-// but that is problematic for Saitek Renaissance + Sparc module
//
//================================================================
@@ -26,29 +24,27 @@
#include "sparc.h"
#include "sparcdefs.h"
-#include "debugger.h"
-
#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_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 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"
@@ -57,16 +53,14 @@ 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;
-
#if LOG_FCODES
#include "ss1fcode.ipp"
#endif
namespace
{
-const sparc_disassembler::asi_desc_map::value_type mb86930_asi_desc[] = {
-
+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" } },
@@ -79,7 +73,13 @@ const sparc_disassembler::asi_desc_map::value_type mb86930_asi_desc[] = {
{ 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"
+};
//-------------------------------------------------
// sparc_base_device - constructor
@@ -95,8 +95,7 @@ sparc_base_device::sparc_base_device(const machine_config &mconfig, device_type
{
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);
+ m_asi_config[i] = address_space_config(DEFAULT_ASI_NAMES[i], ENDIANNESS_BIG, 32, 32);
}
}
}
@@ -139,42 +138,25 @@ sparcv8_device::sparcv8_device(const machine_config &mconfig, device_type type,
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_r(*this, 0)
, 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));
+ 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); });
}
@@ -264,6 +246,11 @@ void sparc_base_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 = true;
m_bp_cp_present = false;
@@ -481,13 +468,12 @@ void sparc_base_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));
@@ -543,8 +529,6 @@ void sparc_base_device::device_reset()
m_bp_irl = 0;
m_irq_state = 0;
- m_stashed_icount = -1;
-
MAE = false;
HOLD_BUS = false;
m_no_annul = true;
@@ -558,9 +542,16 @@ void sparc_base_device::device_reset()
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++)
{
@@ -634,6 +625,13 @@ void mb86930_device::device_start()
{
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;
@@ -649,9 +647,6 @@ void mb86930_device::device_start()
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()
@@ -661,9 +656,11 @@ void mb86930_device::device_reset()
m_ssctrl = 0x08;
m_spmr = 0;
m_spmr_mask = ~0ULL;
- std::fill_n(&m_wssr[0], 3, 0);
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);
@@ -1166,21 +1163,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), sparc_disassembler::v7);
- m_asi_desc_adder(dasm.get());
+ 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), sparc_disassembler::v8);
- m_asi_desc_adder(dasm.get());
+ 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);
- m_asi_desc_adder(dasm.get());
+ if (m_asi_desc_adder)
+ m_asi_desc_adder(dasm.get());
return std::move(dasm);
}
@@ -1337,8 +1337,6 @@ void sparc_base_device::execute_taddcc(uint32_t op)
{
m_trap = 1;
m_tag_overflow = true;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1416,8 +1414,6 @@ void sparc_base_device::execute_tsubcc(uint32_t op)
{
m_trap = 1;
m_tag_overflow = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1612,20 +1608,24 @@ 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)
+ 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 (((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;
}
@@ -1678,16 +1678,12 @@ void sparc_base_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
@@ -1703,20 +1699,16 @@ void sparc_base_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;
@@ -1746,8 +1738,6 @@ void sparc_base_device::execute_wrsr(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1761,8 +1751,6 @@ void sparc_base_device::execute_wrsr(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1795,8 +1783,6 @@ void sparc_base_device::execute_rett(uint32_t op)
{
m_illegal_instruction = 1;
}
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (IS_USER)
@@ -1806,8 +1792,6 @@ void sparc_base_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)
@@ -1817,8 +1801,6 @@ void sparc_base_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)
@@ -1828,8 +1810,6 @@ void sparc_base_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;
}
@@ -1855,6 +1835,12 @@ void sparc_base_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;
+ }
}
@@ -1879,8 +1865,6 @@ void sparc_base_device::execute_saverestore(uint32_t op)
{
m_trap = 1;
m_window_overflow = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1895,8 +1879,6 @@ void sparc_base_device::execute_saverestore(uint32_t op)
{
m_trap = 1;
m_window_underflow = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -1929,8 +1911,6 @@ void sparc_base_device::execute_jmpl(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
}
else
{
@@ -2042,8 +2022,6 @@ inline void sparc_base_device::execute_group2(uint32_t op)
{
m_trap = 1;
m_fp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
}
complete_fp_execution(op);
return;
@@ -2077,8 +2055,6 @@ inline void sparc_base_device::execute_group2(uint32_t op)
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;
}
@@ -2095,14 +2071,6 @@ bool sparcv7_device::execute_extra_group2(uint32_t op)
{
switch (OP3)
{
- case OP3_TADDCCTV:
- execute_taddcc(op);
- return true;
-
- case OP3_TSUBCCTV:
- execute_tsubcc(op);
- return true;
-
default:
return false;
}
@@ -2131,8 +2099,6 @@ bool sparcv8_device::execute_extra_group2(uint32_t op)
logerror("cpop @ %08x: %08x\n", PC, op);
m_trap = 1;
m_cp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return true;
default:
@@ -2168,6 +2134,12 @@ bool mb86930_device::execute_extra_group2(uint32_t op)
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;
}
@@ -2202,16 +2174,12 @@ void sparc_base_device::execute_store(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
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;
}
@@ -2231,24 +2199,18 @@ void sparc_base_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;
}
@@ -2256,16 +2218,12 @@ void sparc_base_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_mem_address_not_aligned = 1;
m_trap = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2279,8 +2237,6 @@ void sparc_base_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;
}
@@ -2400,8 +2356,6 @@ void sparc_base_device::execute_store(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2412,8 +2366,6 @@ void sparc_base_device::execute_store(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
}
@@ -2430,8 +2382,6 @@ inline void sparc_base_device::execute_ldd(uint32_t op)
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2441,8 +2391,7 @@ inline void sparc_base_device::execute_ldd(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 = read_word(m_data_space, address);
@@ -2451,8 +2400,6 @@ inline void sparc_base_device::execute_ldd(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2464,8 +2411,6 @@ inline void sparc_base_device::execute_ldd(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2483,8 +2428,6 @@ inline void sparc_base_device::execute_ld(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2494,8 +2437,6 @@ inline void sparc_base_device::execute_ld(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2514,8 +2455,6 @@ inline void sparc_base_device::execute_ldsh(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2526,8 +2465,6 @@ inline void sparc_base_device::execute_ldsh(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2549,8 +2486,6 @@ inline void sparc_base_device::execute_lduh(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2561,8 +2496,6 @@ inline void sparc_base_device::execute_lduh(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2587,8 +2520,6 @@ inline void sparc_base_device::execute_ldsb(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2616,8 +2547,6 @@ inline void sparc_base_device::execute_ldub(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2639,8 +2568,6 @@ inline void sparc_base_device::execute_lddfpr(uint32_t op)
{
m_trap = 1;
m_fp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2648,8 +2575,6 @@ inline void sparc_base_device::execute_lddfpr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2659,8 +2584,6 @@ inline void sparc_base_device::execute_lddfpr(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2674,8 +2597,6 @@ inline void sparc_base_device::execute_lddfpr(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2699,8 +2620,6 @@ inline void sparc_base_device::execute_ldfpr(uint32_t op)
{
m_trap = 1;
m_fp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2708,8 +2627,6 @@ inline void sparc_base_device::execute_ldfpr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2719,8 +2636,6 @@ inline void sparc_base_device::execute_ldfpr(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2743,8 +2658,6 @@ inline void sparc_base_device::execute_ldfsr(uint32_t op)
{
m_trap = 1;
m_fp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2752,8 +2665,6 @@ inline void sparc_base_device::execute_ldfsr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2763,8 +2674,6 @@ inline void sparc_base_device::execute_ldfsr(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2790,8 +2699,6 @@ inline void sparc_base_device::execute_lddcpr(uint32_t op)
{
m_trap = 1;
m_cp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2799,8 +2706,6 @@ inline void sparc_base_device::execute_lddcpr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2808,8 +2713,6 @@ inline void sparc_base_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;
}
@@ -2819,8 +2722,6 @@ inline void sparc_base_device::execute_lddcpr(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2831,8 +2732,6 @@ inline void sparc_base_device::execute_lddcpr(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2850,8 +2749,6 @@ inline void sparc_base_device::execute_ldcpr(uint32_t op)
{
m_trap = 1;
m_cp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2859,8 +2756,6 @@ inline void sparc_base_device::execute_ldcpr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2868,8 +2763,6 @@ inline void sparc_base_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;
}
@@ -2880,8 +2773,6 @@ inline void sparc_base_device::execute_ldcpr(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2899,8 +2790,6 @@ inline void sparc_base_device::execute_ldcsr(uint32_t op)
{
m_trap = 1;
m_cp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2908,8 +2797,6 @@ inline void sparc_base_device::execute_ldcsr(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2917,8 +2804,6 @@ inline void sparc_base_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;
}
@@ -2929,8 +2814,6 @@ inline void sparc_base_device::execute_ldcsr(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2946,16 +2829,12 @@ inline void sparc_base_device::execute_ldda(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
else if (USEIMM || (RD & 1))
{
m_trap = 1;
m_illegal_instruction = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2966,8 +2845,6 @@ inline void sparc_base_device::execute_ldda(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2977,8 +2854,6 @@ inline void sparc_base_device::execute_ldda(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -2990,8 +2865,6 @@ inline void sparc_base_device::execute_ldda(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3007,16 +2880,12 @@ inline void sparc_base_device::execute_lda(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;
}
@@ -3026,8 +2895,6 @@ inline void sparc_base_device::execute_lda(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3037,8 +2904,6 @@ inline void sparc_base_device::execute_lda(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3055,16 +2920,12 @@ inline void sparc_base_device::execute_ldsha(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;
}
@@ -3074,8 +2935,6 @@ inline void sparc_base_device::execute_ldsha(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3086,8 +2945,6 @@ inline void sparc_base_device::execute_ldsha(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3107,16 +2964,12 @@ inline void sparc_base_device::execute_lduha(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;
}
@@ -3125,8 +2978,6 @@ inline void sparc_base_device::execute_lduha(uint32_t op)
{
m_trap = 1;
m_mem_address_not_aligned = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3137,8 +2988,6 @@ inline void sparc_base_device::execute_lduha(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3158,16 +3007,12 @@ inline void sparc_base_device::execute_ldsba(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;
}
@@ -3179,8 +3024,6 @@ inline void sparc_base_device::execute_ldsba(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3202,16 +3045,12 @@ inline void sparc_base_device::execute_lduba(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;
}
@@ -3223,8 +3062,6 @@ inline void sparc_base_device::execute_lduba(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3263,27 +3100,21 @@ void sparc_base_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)
//{
// { wait for lock(s) to be lifted }
@@ -3294,14 +3125,12 @@ void sparc_base_device::execute_ldstub(uint32_t op)
m_pb_block_ldst_byte = 1;
static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff };
- data = read_word(addr_space, address, 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;
}
@@ -3313,8 +3142,6 @@ void sparc_base_device::execute_ldstub(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
@@ -3448,8 +3275,6 @@ inline void sparc_base_device::execute_group3(uint32_t op)
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;
}
@@ -3648,8 +3473,6 @@ void sparc_base_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
{
@@ -3680,7 +3503,6 @@ void sparc_base_device::select_trap()
{
m_execute_mode = 0;
m_error_mode = 1;
- m_stashed_icount = m_icount;
m_icount = 0;
}
else
@@ -3885,9 +3707,8 @@ inline void sparc_base_device::dispatch_instruction(uint32_t op)
case OP2_BICC: // branch on integer condition codes
execute_bicc(op);
break;
- case OP2_SETHI: // sethi
- *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;
@@ -3896,8 +3717,6 @@ inline void sparc_base_device::dispatch_instruction(uint32_t op)
{
m_trap = 1;
m_fp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
execute_fbfcc(op);
@@ -3908,8 +3727,6 @@ inline void sparc_base_device::dispatch_instruction(uint32_t op)
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;
}
@@ -3955,8 +3772,6 @@ bool sparcv8_device::dispatch_extra_instruction(uint32_t op)
logerror("cbccc @ %08x: %08x\n", PC, op);
m_trap = 1;
m_cp_disabled = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return true;
}
return true;
@@ -4400,16 +4215,12 @@ 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
@@ -4419,52 +4230,49 @@ void sparcv8_device::execute_swap(uint32_t op)
}
}
- uint32_t word = 0;
- uint32_t temp = 0;
- if (!m_trap)
+ if (address & 3)
{
- 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_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
- m_pb_block_ldst_word = 1;
+ uint32_t word = 0;
+ uint32_t data = RDREG;
- word = read_word(addr_space, address);
+ //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 }
+ //}
- if (MAE)
- {
- m_trap = 1;
- m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
- return;
- }
- }
- if (!m_trap)
+ m_pb_block_ldst_word = 1;
+
+ word = read_word(addr_space, address);
+
+ if (MAE)
{
- write_word(addr_space, address, temp);
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
- m_pb_block_ldst_word = 0;
- if (MAE)
- {
- m_trap = 1;
- m_data_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
- return;
- }
- else
- {
- if (RDBITS)
- RDREG = word;
- }
+ 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;
}
@@ -4524,8 +4332,6 @@ 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
@@ -4609,8 +4415,6 @@ inline void sparc_base_device::execute_step()
{
m_trap = 1;
m_instruction_access_exception = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
return;
}
dispatch_instruction(op);
@@ -4624,10 +4428,8 @@ inline void sparc_base_device::execute_step()
if (m_fp_exception_pending)
{
m_fp_exception_pending = false;
- m_fp_exception = 1;
m_trap = 1;
- m_stashed_icount = m_icount;
- m_icount = 0;
+ m_fp_exception = 1;
return;
}
}
@@ -4650,15 +4452,10 @@ 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)
- 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;
}
@@ -4670,14 +4467,8 @@ 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)
- 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, sparc_base_device::running_mode MODE>
@@ -4717,7 +4508,7 @@ void sparc_base_device::run_loop()
}
}
--m_icount;
- } while (m_icount >= 0);
+ } while (m_icount > 0 && !m_trap);
}
//-------------------------------------------------
@@ -4731,10 +4522,14 @@ void sparc_base_device::execute_run()
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;
}
@@ -4769,13 +4564,7 @@ void sparc_base_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);
}