summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sparc/mb86901.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sparc/mb86901.cpp')
-rw-r--r--src/devices/cpu/sparc/mb86901.cpp1564
1 files changed, 1091 insertions, 473 deletions
diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/mb86901.cpp
index fad89cf9610..76ef7ac56e4 100644
--- a/src/devices/cpu/sparc/mb86901.cpp
+++ b/src/devices/cpu/sparc/mb86901.cpp
@@ -41,8 +41,16 @@ const int mb86901_device::NWINDOWS = 7;
mb86901_device::mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, MB86901, tag, owner, clock)
- , m_program_config("program", ENDIANNESS_BIG, 32, 32)
{
+ m_default_config = address_space_config("program", ENDIANNESS_BIG, 32, 32);
+
+ char buf[32];
+ for (uint32_t i = 0; i < AS_COUNT; i++)
+ {
+ snprintf(buf, ARRAY_LENGTH(buf), "asi%d", i);
+ m_asi_names[i] = buf;
+ m_asi_config[i] = address_space_config(m_asi_names[i].c_str(), ENDIANNESS_BIG, 32, 32);
+ }
}
@@ -202,7 +210,11 @@ void mb86901_device::device_start()
m_alu_op3_assigned[OP3_UDIVCC] = true;
m_alu_op3_assigned[OP3_SDIVCC] = true;
#endif
- m_program = &space(AS_PROGRAM);
+ for (uint32_t i = 0; i < AS_COUNT; i++)
+ {
+ m_space[i] = &space(AS_START + i);
+ m_access_cache[i] = m_space[i]->cache<2, 0, ENDIANNESS_BIG>();
+ }
memset(m_ldst_op3_assigned, 0, 64 * sizeof(bool));
m_ldst_op3_assigned[OP3_LD] = true;
@@ -354,7 +366,6 @@ void mb86901_device::device_start()
save_item(NAME(m_ps));
save_item(NAME(m_et));
save_item(NAME(m_cwp));
- save_item(NAME(m_asi));
save_item(NAME(m_mae));
save_item(NAME(m_annul));
save_item(NAME(m_hold_bus));
@@ -394,7 +405,6 @@ void mb86901_device::device_reset()
m_bp_irl = 0;
m_irq_state = 0;
- m_asi = 0;
MAE = false;
HOLD_BUS = false;
m_annul = false;
@@ -409,6 +419,8 @@ void mb86901_device::device_reset()
Y = 0;
PSR = PSR_S_MASK | PSR_PS_MASK;
+ m_s = true;
+ m_fetch_space = 9;
for (int i = 0; i < 8; i++)
{
@@ -434,9 +446,13 @@ void mb86901_device::device_reset()
device_memory_interface::space_config_vector mb86901_device::memory_space_config() const
{
- return space_config_vector {
- std::make_pair(AS_PROGRAM, &m_program_config)
- };
+ space_config_vector config_vector;
+ config_vector.push_back(std::make_pair(AS_PROGRAM, &m_default_config));
+ for (uint32_t i = 0; i < 32; i++)
+ {
+ config_vector.push_back(std::make_pair(AS_START + i, &m_asi_config[i]));
+ }
+ return config_vector;
}
@@ -449,18 +465,18 @@ device_memory_interface::space_config_vector mb86901_device::memory_space_config
uint32_t mb86901_device::read_sized_word(uint8_t asi, uint32_t address, int size)
{
- m_asi = asi;
+ assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines.
if (size == 1)
{
- return m_program->read_byte(address) << ((3 - (address & 3)) * 8);
+ return m_access_cache[asi]->read_byte(address) << ((3 - (address & 3)) * 8);
}
else if (size == 2)
{
- return m_program->read_word(address) << ((2 - (address & 2)) * 8);
+ return m_access_cache[asi]->read_word(address) << ((2 - (address & 2)) * 8);
}
else
{
- return m_program->read_dword(address);
+ return m_access_cache[asi]->read_dword(address);
}
}
@@ -476,18 +492,18 @@ uint32_t mb86901_device::read_sized_word(uint8_t asi, uint32_t address, int size
void mb86901_device::write_sized_word(uint8_t asi, uint32_t address, uint32_t data, int size)
{
- m_asi = asi;
+ assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines.
if (size == 1)
{
- m_program->write_byte(address, data >> ((3 - (address & 3)) * 8));
+ m_access_cache[asi]->write_byte(address, data >> ((3 - (address & 3)) * 8));
}
else if (size == 2)
{
- m_program->write_word(address, data >> ((2 - (address & 2)) * 8));
+ m_access_cache[asi]->write_word(address, data >> ((2 - (address & 2)) * 8));
}
else
{
- m_program->write_dword(address, data);
+ m_access_cache[asi]->write_dword(address, data);
}
}
@@ -676,6 +692,9 @@ void mb86901_device::execute_add(uint32_t op)
PSR |= ((BIT31(rs1) && BIT31(operand2)) ||
(!BIT31(result) && (BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0;
}
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -724,19 +743,21 @@ void mb86901_device::execute_taddcc(uint32_t op)
{
m_trap = 1;
m_tag_overflow = true;
+ return;
}
- else
- {
- CLEAR_ICC;
- PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
- PSR |= (result == 0) ? PSR_Z_MASK : 0;
- PSR |= temp_v ? PSR_V_MASK : 0;
- PSR |= ((BIT31(rs1) && BIT31(operand2)) ||
- (!BIT31(result) && (BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0;
- if (RD != 0)
- RDREG = result;
- }
+ CLEAR_ICC;
+ PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
+ PSR |= (result == 0) ? PSR_Z_MASK : 0;
+ PSR |= temp_v ? PSR_V_MASK : 0;
+ PSR |= ((BIT31(rs1) && BIT31(operand2)) ||
+ (!BIT31(result) && (BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0;
+
+ if (RD != 0)
+ RDREG = result;
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -791,6 +812,9 @@ void mb86901_device::execute_sub(uint32_t op)
PSR |= ((!BIT31(rs1) && BIT31(operand2)) ||
(BIT31(result) && (!BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0;
}
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -840,19 +864,21 @@ void mb86901_device::execute_tsubcc(uint32_t op)
{
m_trap = 1;
m_tag_overflow = 1;
+ return;
}
- else
- {
- CLEAR_ICC;
- PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
- PSR |= (result == 0) ? PSR_Z_MASK : 0;
- PSR |= temp_v ? PSR_V_MASK : 0;
- PSR |= ((!BIT31(rs1) && BIT31(operand2)) ||
- (BIT31(result) && (!BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0;
- if (RD != 0)
- RDREG = result;
- }
+ CLEAR_ICC;
+ PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
+ PSR |= (result == 0) ? PSR_Z_MASK : 0;
+ PSR |= temp_v ? PSR_V_MASK : 0;
+ PSR |= ((!BIT31(rs1) && BIT31(operand2)) ||
+ (BIT31(result) && (!BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0;
+
+ if (RD != 0)
+ RDREG = result;
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -925,6 +951,9 @@ void mb86901_device::execute_logical(uint32_t op)
PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
PSR |= (result == 0) ? PSR_Z_MASK : 0;
}
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -954,6 +983,9 @@ void mb86901_device::execute_shift(uint32_t op)
RDREG = uint32_t(RS1REG) >> shift_count;
else if (SRA && RD != 0)
RDREG = int32_t(RS1REG) >> shift_count;
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -1003,6 +1035,9 @@ void mb86901_device::execute_mulscc(uint32_t op)
(!BIT31(operand1) && !BIT31(operand2) && BIT31(result))) ? PSR_V_MASK : 0;
PSR |= ((BIT31(operand1) && BIT31(operand2)) ||
(!BIT31(result) && (BIT31(operand1) || BIT31(operand2)))) ? PSR_C_MASK : 0;
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -1035,13 +1070,16 @@ void mb86901_device::execute_rdsr(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
+ return;
}
else if (m_illegal_instruction_asr[RS1])
{
m_trap = 1;
m_illegal_instruction = 1;
+ return;
}
- else if (RD != 0)
+
+ if (RD != 0)
{
if (RDASR)
{
@@ -1059,6 +1097,9 @@ void mb86901_device::execute_rdsr(uint32_t op)
else if (RDTBR)
RDREG = TBR;
}
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -1119,6 +1160,8 @@ void mb86901_device::execute_wrsr(uint32_t op)
if (WRASR && RD == 0)
{
Y = result;
+ PC = nPC;
+ nPC = nPC + 4;
}
else if (WRASR)
{
@@ -1126,15 +1169,19 @@ void mb86901_device::execute_wrsr(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
+ return;
}
else if (m_illegal_instruction_asr[RD])
{
m_trap = 1;
m_illegal_instruction = 1;
+ return;
}
else
{
// SPARCv8
+ PC = nPC;
+ nPC = nPC + 4;
}
}
else if (WRPSR)
@@ -1143,17 +1190,25 @@ void mb86901_device::execute_wrsr(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
+ return;
}
else if ((result & 31) >= NWINDOWS)
{
m_trap = 1;
m_illegal_instruction = 1;
+ return;
}
- else
- {
- PSR = result &~ PSR_ZERO_MASK;
- update_gpr_pointers();
- }
+
+ PSR = result &~ PSR_ZERO_MASK;
+ update_gpr_pointers();
+
+ m_et = PSR & PSR_ET_MASK;
+ m_pil = (PSR & PSR_PIL_MASK) >> PSR_PIL_SHIFT;
+ m_s = PSR & PSR_S_MASK;
+ m_fetch_space = m_s ? 9 : 8;
+
+ PC = nPC;
+ nPC = nPC + 4;
}
else if (WRWIM)
{
@@ -1161,11 +1216,12 @@ void mb86901_device::execute_wrsr(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
+ return;
}
- else
- {
- WIM = result & 0x7f;
- }
+
+ WIM = result & 0x7f;
+ PC = nPC;
+ nPC = nPC + 4;
}
else if (WRTBR)
{
@@ -1173,11 +1229,12 @@ void mb86901_device::execute_wrsr(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
+ return;
}
- else
- {
- TBR = result & 0xfffff000;
- }
+
+ TBR = result & 0xfffff000;
+ PC = nPC;
+ nPC = nPC + 4;
}
}
@@ -1227,7 +1284,7 @@ void mb86901_device::execute_rett(uint32_t op)
uint8_t new_cwp = ((PSR & PSR_CWP_MASK) + 1) % NWINDOWS;
uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
- if (PSR & PSR_ET_MASK)
+ if (m_et)
{
m_trap = 1;
if (IS_USER)
@@ -1238,6 +1295,7 @@ void mb86901_device::execute_rett(uint32_t op)
{
m_illegal_instruction = 1;
}
+ return;
}
else if (IS_USER)
{
@@ -1246,6 +1304,7 @@ void mb86901_device::execute_rett(uint32_t op)
m_tt = 3;
m_execute_mode = 0;
m_error_mode = 1;
+ return;
}
else if ((WIM & (1 << new_cwp)) != 0)
{
@@ -1254,6 +1313,7 @@ void mb86901_device::execute_rett(uint32_t op)
m_tt = 6;
m_execute_mode = 0;
m_error_mode = 1;
+ return;
}
else if (address & 3)
{
@@ -1262,20 +1322,28 @@ void mb86901_device::execute_rett(uint32_t op)
m_tt = 7;
m_execute_mode = 0;
m_error_mode = 1;
+ return;
}
- else
- {
- PSR |= PSR_ET_MASK;
- PC = nPC;
- nPC = address;
- PSR &= ~PSR_CWP_MASK;
- PSR |= new_cwp;
+ PSR |= PSR_ET_MASK;
+ m_et = true;
+ PC = nPC;
+ nPC = address;
- if (PSR & PSR_PS_MASK)
- PSR |= PSR_S_MASK;
- else
- PSR &= ~PSR_S_MASK;
+ PSR &= ~PSR_CWP_MASK;
+ PSR |= new_cwp;
+
+ if (PSR & PSR_PS_MASK)
+ {
+ PSR |= PSR_S_MASK;
+ m_s = true;
+ m_fetch_space = 9;
+ }
+ else
+ {
+ PSR &= ~PSR_S_MASK;
+ m_s = false;
+ m_fetch_space = 8;
}
update_gpr_pointers();
@@ -1331,14 +1399,13 @@ void mb86901_device::execute_saverestore(uint32_t op)
{
m_trap = 1;
m_window_overflow = 1;
+ return;
}
- else
- {
- result = rs1 + operand2;
- PSR &= ~PSR_CWP_MASK;
- PSR |= new_cwp;
- BREAK_PSR;
- }
+
+ result = rs1 + operand2;
+ PSR &= ~PSR_CWP_MASK;
+ PSR |= new_cwp;
+ //BREAK_PSR;
}
else if (RESTORE)
{
@@ -1347,20 +1414,22 @@ void mb86901_device::execute_saverestore(uint32_t op)
{
m_trap = 1;
m_window_underflow = 1;
+ return;
}
- else
- {
- result = rs1 + operand2;
- PSR &= ~PSR_CWP_MASK;
- PSR |= new_cwp;
- BREAK_PSR;
- }
+
+ result = rs1 + operand2;
+ PSR &= ~PSR_CWP_MASK;
+ PSR |= new_cwp;
+ //BREAK_PSR;
}
update_gpr_pointers();
- if (m_trap == 0 && RD != 0)
+ if (RD != 0)
RDREG = result;
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -1475,8 +1544,13 @@ void mb86901_device::execute_group2(uint32_t op)
case OP3_FPOP1:
case OP3_FPOP2:
- // Not yet implemented
- break;
+ if (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present)
+ {
+ //printf("fpop @ %08x: %08x\n", PC, op);
+ m_trap = 1;
+ m_fp_disabled = 1;
+ }
+ return;
case OP3_JMPL:
execute_jmpl(op);
@@ -1492,6 +1566,8 @@ void mb86901_device::execute_group2(uint32_t op)
case OP3_IFLUSH:
// Ignored
+ PC = nPC;
+ nPC = nPC + 4;
break;
case OP3_SAVE:
@@ -1516,15 +1592,17 @@ void mb86901_device::execute_group2(uint32_t op)
case OP3_CPOP1:
case OP3_CPOP2:
- break;
+ printf("fpop @ %08x: %08x\n", PC, op);
+ m_trap = 1;
+ m_cp_disabled = 1;
+ return;
#endif
default:
- {
+ printf("illegal instruction at %08x: %08x\n", PC, op);
m_trap = 1;
m_illegal_instruction = 1;
break;
- }
}
}
@@ -1676,188 +1754,186 @@ void mb86901_device::execute_store(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
+ return;
}
else if (USEIMM && (STDA || STA || STHA || STBA))
{
m_trap = 1;
m_illegal_instruction = 1;
+ return;
}
uint32_t address = 0;
uint8_t addr_space = 0;
- if (!m_trap)
+ if (STD || ST || STH || STB || STF || STDF || STFSR || STDFQ || STCSR || STC || STDC || STDCQ)
{
- if (STD || ST || STH || STB || STF || STDF || STFSR || STDFQ || STCSR || STC || STDC || STDCQ)
- {
- address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
- addr_space = (IS_USER ? 10 : 11);
- }
- else if (STDA || STA || STHA || STBA)
- {
- address = RS1REG + RS2REG;
- addr_space = ASI;
- }
- if ((STF || STDF || STFSR || STDFQ) && (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present))
- {
- m_trap = 1;
- m_fp_disabled = 1;
- }
- if ((STC || STDC || STCSR || STDCQ) && (!(PSR & PSR_EC_MASK) || !m_bp_cp_present))
- {
- m_trap = 1;
- m_cp_disabled = 1;
- }
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+ }
+ else if (STDA || STA || STHA || STBA)
+ {
+ address = RS1REG + RS2REG;
+ addr_space = ASI;
+ }
+ if ((STF || STDF || STFSR || STDFQ) && (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present))
+ {
+ m_trap = 1;
+ m_fp_disabled = 1;
+ return;
+ }
+ if ((STC || STDC || STCSR || STDCQ) && (!(PSR & PSR_EC_MASK) || !m_bp_cp_present))
+ {
+ m_trap = 1;
+ m_cp_disabled = 1;
+ return;
}
- if (!m_trap)
+ if ((STH || STHA) && ((address & 1) != 0))
{
- if ((STH || STHA) && ((address & 1) != 0))
- {
- m_trap = 1;
- m_mem_address_not_aligned = 1;
- }
- else if ((ST || STA || STF || STFSR || STC || STCSR) && ((address & 3) != 0))
- {
- m_trap = 1;
- m_mem_address_not_aligned = 1;
- }
- else if ((STD || STDA || STDF || STDFQ || STDC || STDCQ) && ((address & 7) != 0))
- {
- m_trap = 1;
- m_mem_address_not_aligned = 1;
- }
- else
- {
- if (STDFQ)
- {
- // assume no floating-point queue for now
- m_trap = 1;
- m_fp_exception = 1;
- m_ftt = m_fpu_sequence_err;
- }
- if (STDCQ)
- {
- // assume no coprocessor queue for now
- m_trap = 1;
- m_cp_exception = 1;
- // { possibly additional implementation-dependent actions }
- }
- if (STDF && ((RD & 1) != 0))
- {
- m_trap = 1;
- m_fp_exception = 1;
- m_ftt = 0xff;
- }
- }
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+ else if ((ST || STA || STF || STFSR || STC || STCSR) && ((address & 3) != 0))
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+ else if ((STD || STDA || STDF || STDFQ || STDC || STDCQ) && ((address & 7) != 0))
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ if (STDFQ)
+ {
+ // assume no floating-point queue for now
+ m_trap = 1;
+ m_fp_exception = 1;
+ m_ftt = m_fpu_sequence_err;
+ return;
+ }
+ if (STDCQ)
+ {
+ // assume no coprocessor queue for now
+ m_trap = 1;
+ m_cp_exception = 1;
+ // { possibly additional implementation-dependent actions }
+ return;
+ }
+ if (STDF && ((RD & 1) != 0))
+ {
+ m_trap = 1;
+ m_fp_exception = 1;
+ m_ftt = 0xff;
+ return;
}
uint32_t data0 = 0;
- if (!m_trap)
+ //uint8_t byte_mask;
+ if (STF)
{
- //uint8_t byte_mask;
- if (STF)
- {
- //byte_mask = 15;
- data0 = FREG(RD);
- }
- else if (STC)
- {
- //byte_mask = 15;
- data0 = 0;
- }
- else if (STDF)
- {
- //byte_mask = 15;
- data0 = FREG(RD & 0x1e);
- }
- else if (STDC)
- {
- //byte_mask = 15;
- data0 = 0;
- }
- else if (STD || STDA)
+ //byte_mask = 15;
+ data0 = FREG(RD);
+ }
+ else if (STC)
+ {
+ //byte_mask = 15;
+ data0 = 0;
+ }
+ else if (STDF)
+ {
+ //byte_mask = 15;
+ data0 = FREG(RD & 0x1e);
+ }
+ else if (STDC)
+ {
+ //byte_mask = 15;
+ data0 = 0;
+ }
+ else if (STD || STDA)
+ {
+ //byte_mask = 15;
+ data0 = REG(RD & 0x1e);
+ }
+ else if (STDFQ)
+ {
+ //byte_mask = 15;
+ data0 = 0;
+ }
+ else if (STDCQ)
+ {
+ //byte_mask = 15;
+ data0 = 0;
+ }
+ else if (STFSR)
+ {
+ // while ((FSR.qne = 1) and (trap = 0)) (
+ // wait for pending floating-point instructions to complete
+ // )
+ // next;
+ //byte_mask = 15;
+ data0 = FSR;
+ }
+ else if (STCSR)
+ {
+ // { implementation-dependent actions }
+ //byte_mask = 15;
+ data0 = 0;
+ }
+ else if (ST || STA)
+ {
+ //byte_mask = 15;
+ data0 = REG(RD);
+ }
+ else if (STH || STHA)
+ {
+ if ((address & 3) == 0)
{
- //byte_mask = 15;
- data0 = REG(RD & 0x1e);
+ //byte_mask = 12;
+ data0 = REG(RD) << 16;
}
- else if (STDFQ)
+ else if ((address & 3) == 2)
{
- //byte_mask = 15;
- data0 = 0;
+ //byte_mask = 3;
+ data0 = REG(RD);
}
- else if (STDCQ)
+ }
+ else if (STB || STBA)
+ {
+ if ((address & 3) == 0)
{
- //byte_mask = 15;
- data0 = 0;
+ //byte_mask = 8;
+ data0 = REG(RD) << 24;
}
- else if (STFSR)
+ else if ((address & 3) == 1)
{
- // while ((FSR.qne = 1) and (trap = 0)) (
- // wait for pending floating-point instructions to complete
- // )
- // next;
- //byte_mask = 15;
- data0 = FSR;
+ //byte_mask = 4;
+ data0 = REG(RD) << 16;
}
- else if (STCSR)
+ else if ((address & 3) == 2)
{
- // { implementation-dependent actions }
- //byte_mask = 15;
- data0 = 0;
+ //byte_mask = 2;
+ data0 = REG(RD) << 8;
}
- else if (ST || STA)
+ else if ((address & 3) == 3)
{
- //byte_mask = 15;
+ //byte_mask = 1;
data0 = REG(RD);
}
- else if (STH || STHA)
- {
- if ((address & 3) == 0)
- {
- //byte_mask = 12;
- data0 = REG(RD) << 16;
- }
- else if ((address & 3) == 2)
- {
- //byte_mask = 3;
- data0 = REG(RD);
- }
- }
- else if (STB || STBA)
- {
- if ((address & 3) == 0)
- {
- //byte_mask = 8;
- data0 = REG(RD) << 24;
- }
- else if ((address & 3) == 1)
- {
- //byte_mask = 4;
- data0 = REG(RD) << 16;
- }
- else if ((address & 3) == 2)
- {
- //byte_mask = 2;
- data0 = REG(RD) << 8;
- }
- else if ((address & 3) == 3)
- {
- //byte_mask = 1;
- data0 = REG(RD);
- }
- }
}
- if (!m_trap)
+ write_sized_word(addr_space, address, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 4 : ((STH || STHA) ? 2 : 1));
+ if (MAE)
{
- write_sized_word(addr_space, address, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 4 : ((STH || STHA) ? 2 : 1));
- if (MAE)
- {
- m_trap = 1;
- m_data_access_exception = 1;
- }
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
}
- if (!m_trap && (STD || STDA || STDF || STDC || STDFQ || STDCQ))
+
+ if (STD || STDA || STDF || STDC || STDFQ || STDCQ)
{
uint32_t data1 = 0;
if (STD || STDA)
@@ -1886,8 +1962,12 @@ void mb86901_device::execute_store(uint32_t op)
{
m_trap = 1;
m_data_access_exception = 1;
+ return;
}
}
+
+ PC = nPC;
+ nPC = nPC + 4;
}
//-------------------------------------------------
@@ -1998,140 +2078,688 @@ void mb86901_device::execute_load(uint32_t op)
uint32_t address = 0;
uint8_t addr_space = 0;
- if (LDD || LD || LDSH || LDUH || LDSB || LDUB || LDDF || LDF || LDFSR || LDDC || LDC || LDCSR)
- {
- address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
- addr_space = (IS_USER ? 10 : 11);
- }
- else if (LDDA || LDA || LDSHA || LDUHA || LDSBA || LDUBA)
+ switch (OP3)
{
- if (IS_USER)
+ case OP3_LDD:
{
- m_trap = 1;
- m_privileged_instruction = 1;
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+
+ if (address & 7)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ }
+
+ const uint32_t data = read_sized_word(addr_space, address, 4);
+
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RD != 0)
+ RDREG = data;
+
+ const uint32_t word1 = read_sized_word(addr_space, address + 4, 4);
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ REG(RD | 1) = word1;
+ break;
}
- else if (USEIMM)
+ case OP3_LD:
{
- m_trap = 1;
- m_illegal_instruction = 1;
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+
+ if (address & 3)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ const uint32_t data = read_sized_word(addr_space, address, 4);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RD != 0)
+ RDREG = data;
+ break;
}
- else
+ case OP3_LDSH:
{
- address = RS1REG + RS2REG;
- addr_space = ASI;
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+
+ if (address & 1)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ const uint32_t data = read_sized_word(addr_space, address, 2);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RD != 0)
+ {
+ if ((address & 3) == 0) RDREG = (int32_t)data >> 16;
+ else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 16;
+ }
+ break;
}
- }
+ case OP3_LDUH:
+ {
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
- if (!m_trap)
- {
- if ((LDF || LDDF || LDFSR) && (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0))
+ if (address & 1)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ const uint32_t data = read_sized_word(addr_space, address, 2);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RD != 0)
+ {
+ if ((address & 3) == 0) RDREG = data >> 16;
+ else if ((address & 3) == 2) RDREG = data & 0xffff;
+ }
+ break;
+ }
+ case OP3_LDSB:
{
- m_trap = 1;
- m_fp_disabled = 1;
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+
+ const uint32_t data = read_sized_word(addr_space, address, 1);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RD != 0)
+ {
+ if ((address & 3) == 0) RDREG = (int32_t)data >> 24;
+ else if ((address & 3) == 1) RDREG = ((int32_t)data << 8) >> 24;
+ else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 24;
+ else if ((address & 3) == 3) RDREG = ((int32_t)data << 24) >> 24;
+ }
+ break;
}
- else if ((LDC || LDDC || LDCSR) && (!(PSR & PSR_EC_MASK) || m_bp_cp_present == 0))
+ case OP3_LDUB:
{
- m_trap = 1;
- m_cp_disabled = 1;
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+
+ const uint32_t data = read_sized_word(addr_space, address, 1);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RD != 0)
+ {
+ if ((address & 3) == 0) RDREG = data >> 24;
+ else if ((address & 3) == 1) RDREG = (data >> 16) & 0xff;
+ else if ((address & 3) == 2) RDREG = (data >> 8) & 0xff;
+ else if ((address & 3) == 3) RDREG = data & 0xff;
+ }
+ break;
}
- else if (((LDD || LDDA || LDDF || LDDC) && ((address & 7) != 0)) ||
- ((LD || LDA || LDF || LDFSR || LDC || LDCSR) && ((address & 3) != 0)) ||
- ((LDSH || LDSHA || LDUH || LDUHA) && ((address & 1) != 0)))
+ case OP3_LDDFPR:
{
- m_trap = 1;
- m_mem_address_not_aligned = 1;
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+
+ if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0)
+ {
+ m_trap = 1;
+ m_fp_disabled = 1;
+ return;
+ }
+
+ if (address & 7)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ if (RD & 1)
+ {
+ m_trap = 1;
+ m_fp_exception = 1;
+ m_ftt = 0xff;
+ return;
+ }
+
+ if (m_fpu_sequence_err)
+ {
+ m_trap = 1;
+ m_fp_exception = 1;
+ m_ftt = m_fpu_sequence_err;
+ return;
+ }
+
+ const uint32_t data = read_sized_word(addr_space, address, 4);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ FREG(RD & 0x1e) = data;
+
+ const uint32_t word1 = read_sized_word(addr_space, address + 4, 4);
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ FREG(RD | 1) = word1;
+ break;
}
- else if (LDDF && ((RD & 1) != 0))
+ case OP3_LDFPR:
{
- m_trap = 1;
- m_fp_exception = 1;
- m_ftt = 0xff;
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+
+ if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0)
+ {
+ m_trap = 1;
+ m_fp_disabled = 1;
+ return;
+ }
+
+ if (address & 3)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ if (m_fpu_sequence_err)
+ {
+ m_trap = 1;
+ m_fp_exception = 1;
+ m_ftt = m_fpu_sequence_err;
+ return;
+ }
+
+ const uint32_t data = read_sized_word(addr_space, address, 4);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ FDREG = data;
+ break;
}
- else if ((LDF || LDDF || LDFSR) && m_fpu_sequence_err != 0)
+ case OP3_LDFSR:
{
- m_trap = 1;
- m_fp_exception = 1;
- m_ftt = m_fpu_sequence_err;
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+
+ if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0)
+ {
+ m_trap = 1;
+ m_fp_disabled = 1;
+ return;
+ }
+
+ if (address & 3)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ if (m_fpu_sequence_err)
+ {
+ m_trap = 1;
+ m_fp_exception = 1;
+ m_ftt = m_fpu_sequence_err;
+ return;
+ }
+
+ const uint32_t data = read_sized_word(addr_space, address, 4);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ FSR = data;
+ break;
}
- else if ((LDC || LDDC || LDCSR) && m_cp_sequence_err != 0)
+ case OP3_LDDCPR:
{
- m_trap = 1;
- m_cp_exception = 1;
- // possibly additional implementation-dependent actions
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+
+ if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present)
+ {
+ m_trap = 1;
+ m_cp_disabled = 1;
+ return;
+ }
+
+ if (address & 7)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ if (m_cp_sequence_err)
+ {
+ m_trap = 1;
+ m_cp_exception = 1;
+ // possibly additional implementation-dependent actions
+ return;
+ }
+
+ read_sized_word(addr_space, address, 4);
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ // implementation-dependent actions
+
+ read_sized_word(addr_space, address + 4, 4);
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ // implementation-dependent actions
+ break;
}
- }
+ case OP3_LDCPR:
+ {
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
- uint32_t word0(0);
- if (!m_trap)
- {
- uint32_t data = read_sized_word(addr_space, address, (LD || LDD || LDA || LDDA) ? 4 : ((LDUH || LDSH || LDUHA || LDSHA) ? 2 : 1));
+ if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present)
+ {
+ m_trap = 1;
+ m_cp_disabled = 1;
+ return;
+ }
+
+ if (address & 3)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ if (m_cp_sequence_err)
+ {
+ m_trap = 1;
+ m_cp_exception = 1;
+ // possibly additional implementation-dependent actions
+ return;
+ }
- if (m_mae)
+ read_sized_word(addr_space, address, 4);
+
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ // implementation-dependent actions
+ break;
+ }
+ case OP3_LDCSR:
{
- m_trap = 1;
- m_data_access_exception = 1;
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+
+ if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present)
+ {
+ m_trap = 1;
+ m_cp_disabled = 1;
+ return;
+ }
+
+ if (address & 3)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ if (m_cp_sequence_err)
+ {
+ m_trap = 1;
+ m_cp_exception = 1;
+ // possibly additional implementation-dependent actions
+ return;
+ }
+
+ read_sized_word(addr_space, address, 4);
+
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ // implementation-dependent actions
+ break;
}
- else
+ case OP3_LDDA:
{
- if (LDSB || LDSBA || LDUB || LDUBA)
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ return;
+ }
+ else if (USEIMM)
{
- uint8_t byte = 0;
- if ((address & 3) == 0) byte = (data >> 24) & 0xff;
- else if ((address & 3) == 1) byte = (data >> 16) & 0xff;
- else if ((address & 3) == 2) byte = (data >> 8) & 0xff;
- else if ((address & 3) == 3) byte = data & 0xff;
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ return;
+ }
+ else
+ {
+ address = RS1REG + RS2REG;
+ addr_space = ASI;
+ }
+
+ if (address & 7)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
- if (LDSB || LDSBA)
- word0 = (((int32_t)byte) << 24) >> 24;
- else
- word0 = byte;
+ const uint32_t data = read_sized_word(addr_space, address, 4);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
}
- else if (LDSH || LDSHA || LDUH || LDUHA)
+
+ if (RD != 0)
+ RDREG = data;
+
+ uint32_t word1 = read_sized_word(addr_space, address + 4, 4);
+ if (MAE)
{
- uint16_t halfword = 0;
- if ((address & 3) == 0) halfword = (data >> 16) & 0xffff;
- else if ((address & 3) == 2) halfword = data & 0xffff;
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
- if (LDSH || LDSHA)
- {
- word0 = (((int32_t)halfword) << 16) >> 16;
- }
- else
- {
- word0 = halfword;
- }
+ REG(RD | 1) = word1;
+ break;
+ }
+ case OP3_LDA:
+ {
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ return;
+ }
+ else if (USEIMM)
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ return;
}
else
{
- word0 = data;
+ address = RS1REG + RS2REG;
+ addr_space = ASI;
}
+
+ if (address & 3)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ const uint32_t data = read_sized_word(addr_space, address, 4);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RD != 0)
+ RDREG = data;
+ break;
}
- }
+ case OP3_LDSHA:
+ {
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ return;
+ }
+ else if (USEIMM)
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ return;
+ }
+ else
+ {
+ address = RS1REG + RS2REG;
+ addr_space = ASI;
+ }
- if (!m_trap)
- {
- if (RD == 0) { }
- else if (LD || LDA || LDSH || LDSHA || LDUHA || LDUH || LDSB || LDSBA || LDUB || LDUBA) RDREG = word0;
- else if (LDF) FDREG = word0;
- else if (LDC) { } // implementation-dependent actions
- else if (LDFSR) FSR = word0;
- else if (LDD || LDDA) REG(RD & 0x1e) = word0;
- else if (LDDF) FREG(RD & 0x1e) = word0;
- else if (LDDC) { } // implementation-dependent actions
- }
+ if (address & 1)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
- if (!m_trap && (LDD || LDDA || LDDF || LDDC))
- {
- uint32_t word1 = read_sized_word(addr_space, address + 4, 4);
- if (MAE)
+ const uint32_t data = read_sized_word(addr_space, address, 2);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RD != 0)
+ {
+ if ((address & 3) == 0) RDREG = (int32_t)data >> 16;
+ else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 16;
+ }
+ break;
+ }
+ case OP3_LDUHA:
{
- m_trap = 1;
- m_data_access_exception = 1;
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ return;
+ }
+ else if (USEIMM)
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ return;
+ }
+ else
+ {
+ address = RS1REG + RS2REG;
+ addr_space = ASI;
+ }
+
+ if (address & 1)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ return;
+ }
+
+ const uint32_t data = read_sized_word(addr_space, address, 2);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RD != 0)
+ {
+ if ((address & 3) == 0) RDREG = data >> 16;
+ else if ((address & 3) == 2) RDREG = data & 0xffff;
+ }
+ break;
+ }
+ case OP3_LDSBA:
+ {
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ return;
+ }
+ else if (USEIMM)
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ return;
+ }
+ else
+ {
+ address = RS1REG + RS2REG;
+ addr_space = ASI;
+ }
+
+ const uint32_t data = read_sized_word(addr_space, address, 1);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RD != 0)
+ {
+ if ((address & 3) == 0) RDREG = (int32_t)data >> 24;
+ else if ((address & 3) == 1) RDREG = ((int32_t)data << 8) >> 24;
+ else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 24;
+ else if ((address & 3) == 3) RDREG = ((int32_t)data << 24) >> 24;
+ }
+ break;
+ }
+ case OP3_LDUBA:
+ {
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ return;
+ }
+ else if (USEIMM)
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ return;
+ }
+ else
+ {
+ address = RS1REG + RS2REG;
+ addr_space = ASI;
+ }
+
+ const uint32_t data = read_sized_word(addr_space, address, 1);
+
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ if (RD != 0)
+ {
+ if ((address & 3) == 0) RDREG = data >> 24;
+ else if ((address & 3) == 1) RDREG = (data >> 16) & 0xff;
+ else if ((address & 3) == 2) RDREG = (data >> 8) & 0xff;
+ else if ((address & 3) == 3) RDREG = data & 0xff;
+ }
+ break;
}
- else if (LDD || LDDA) REG(RD | 1) = word1;
- else if (LDDF) FREG(RD | 1) = word1;
- else if (LDDC) { } // implementation-dependent actions
+ default:
+ break;
}
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -2214,91 +2842,91 @@ void mb86901_device::execute_ldstub(uint32_t op)
{
m_trap = 1;
m_privileged_instruction = 1;
+ return;
}
else if (USEIMM)
{
m_trap = 1;
m_illegal_instruction = 1;
+ return;
}
else
{
address = RS1REG + RS2REG;
addr_space = ASI;
+ return;
}
}
uint32_t data(0);
- if (!m_trap)
+ while (m_pb_block_ldst_byte || m_pb_block_ldst_word)
{
- while (m_pb_block_ldst_byte || m_pb_block_ldst_word)
- {
- // { wait for lock(s) to be lifted }
- // { an implementation actually need only block when another LDSTUB or SWAP
- // is pending on the same byte in memory as the one addressed by this LDSTUB }
- }
+ // { wait for lock(s) to be lifted }
+ // { an implementation actually need only block when another LDSTUB or SWAP
+ // is pending on the same byte in memory as the one addressed by this LDSTUB }
+ }
- m_pb_block_ldst_byte = 1;
+ m_pb_block_ldst_byte = 1;
- data = read_sized_word(addr_space, address, 1);
+ data = read_sized_word(addr_space, address, 1);
- if (MAE)
- {
- m_trap = 1;
- m_data_access_exception = 1;
- }
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
}
- if (!m_trap)
+ //uint8_t byte_mask;
+ if ((address & 3) == 0)
{
- //uint8_t byte_mask;
- if ((address & 3) == 0)
- {
- //byte_mask = 8;
- }
- else if ((address & 3) == 1)
- {
- //byte_mask = 4;
- }
- else if ((address & 3) == 2)
- {
- //byte_mask = 2;
- }
- else if ((address & 3) == 3)
- {
- //byte_mask = 1;
- }
- write_sized_word(addr_space, address, 0xffffffff, 1);
+ //byte_mask = 8;
+ }
+ else if ((address & 3) == 1)
+ {
+ //byte_mask = 4;
+ }
+ else if ((address & 3) == 2)
+ {
+ //byte_mask = 2;
+ }
+ else if ((address & 3) == 3)
+ {
+ //byte_mask = 1;
+ }
+ write_sized_word(addr_space, address, 0xffffffff, 1);
- m_pb_block_ldst_byte = 0;
+ m_pb_block_ldst_byte = 0;
- if (MAE)
- {
- m_trap = 1;
- m_data_access_exception = 1;
- }
- else
- {
- uint32_t word;
- if ((address & 3) == 0)
- {
- word = (data >> 24) & 0xff;
- }
- else if ((address & 3) == 1)
- {
- word = (data >> 16) & 0xff;
- }
- else if ((address & 3) == 2)
- {
- word = (data >> 8) & 0xff;
- }
- else // if ((address & 3) == 3)
- {
- word = data & 0xff;
- }
- if (RD != 0)
- RDREG = word;
- }
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ return;
+ }
+
+ uint32_t word;
+ if ((address & 3) == 0)
+ {
+ word = (data >> 24) & 0xff;
+ }
+ else if ((address & 3) == 1)
+ {
+ word = (data >> 16) & 0xff;
+ }
+ else if ((address & 3) == 2)
+ {
+ word = (data >> 8) & 0xff;
+ }
+ else // if ((address & 3) == 3)
+ {
+ word = data & 0xff;
}
+ if (RD != 0)
+ RDREG = word;
+
+ PC = nPC;
+ nPC = nPC + 4;
}
@@ -2373,6 +3001,12 @@ void mb86901_device::execute_group3(uint32_t op)
execute_swap(op);
break;
#endif
+
+ default:
+ printf("illegal instruction at %08x: %08x\n", PC, op);
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ break;
}
if (MAE || HOLD_BUS)
@@ -2548,7 +3182,7 @@ void mb86901_device::select_trap()
m_trap = 0;
return;
}
- else if (!(PSR & PSR_ET_MASK))
+ else if (!m_et)
{
m_execute_mode = 0;
m_error_mode = 1;
@@ -2712,6 +3346,7 @@ void mb86901_device::execute_trap()
if (!m_error_mode)
{
PSR &= ~PSR_ET_MASK;
+ m_et = false;
if (IS_USER)
PSR &= ~PSR_PS_MASK;
@@ -2719,6 +3354,8 @@ void mb86901_device::execute_trap()
PSR |= PSR_PS_MASK;
PSR |= PSR_S_MASK;
+ m_s = true;
+ m_fetch_space = 9;
int cwp = PSR & PSR_CWP_MASK;
int new_cwp = ((cwp + NWINDOWS) - 1) % NWINDOWS;
@@ -2756,17 +3393,41 @@ void mb86901_device::execute_trap()
//-------------------------------------------------
-// complete_instruction_execution - execute a
-// single fetched instruction that has been
-// checked for FP-disabled, CP-disabled, and
-// validity.
+// dispatch_instruction - executes a
+// single fetched instruction.
//-------------------------------------------------
-void mb86901_device::complete_instruction_execution(uint32_t op)
+/* The SPARC Instruction Manual: Version 8, page 159, "Appendix C - ISP Descriptions - C.6. Instruction Dispatch" (SPARCv8.pdf, pg. 156)
+
+illegal_IU_instr :- (
+ if ( ( (op == 00) and (op2 == 000) ) { UNIMP instruction }
+ or
+ ( ((op=11) or (op=10)) and (op3=unassigned) )
+ then 1 else 0
+
+if (illegal_IU_instr = 1) then (
+ trap <- 1
+ illegal_instruction <- 1
+);
+if ((FPop1 or FPop2 or FBfcc) and ((EF = 0) or (bp_FPU_present = 0))) then (
+ trap <- 1;
+ fp_disabled <- 1
+);
+if (CPop1 or CPop2 or CBccc) and ((EC = 0) or (bp_CP_present = 0))) then (
+ trap <- 1;
+ cp_disabled <- 1
+);
+next;
+if (trap = 0) then (
+ { code for specific instruction, defined below }
+);
+*/
+
+inline void mb86901_device::dispatch_instruction(uint32_t op)
{
- switch (OP)
+ switch (OP_NS)
{
- case OP_TYPE0: // Bicc, SETHI, FBfcc
+ case OP_TYPE0_NS: // Bicc, SETHI, FBfcc
switch (OP2)
{
case OP2_UNIMP: // unimp
@@ -2776,22 +3437,41 @@ void mb86901_device::complete_instruction_execution(uint32_t op)
execute_bicc(op);
break;
case OP2_SETHI: // sethi
- SET_RDREG(IMM22);
+ //SET_RDREG(IMM22);
+ *m_regs[RD] = op << 10;
+ m_r[0] = 0;
+ PC = nPC;
+ nPC = nPC + 4;
break;
case OP2_FBFCC: // branch on floating-point condition codes
- printf("fbfcc @ %x\n", PC);
+ if (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present)
+ {
+ //printf("fbfcc at %08x: %08x\n", PC, op);
+ m_trap = 1;
+ m_fp_disabled = 1;
+ return;
+ }
break;
#if SPARCV8
case OP2_CBCCC: // branch on coprocessor condition codes, SPARCv8
- break;
+ if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present)
+ {
+ printf("cbccc @ %08x: %08x\n", PC, op);
+ m_trap = 1;
+ m_cp_disabled = 1;
+ return;
+ }
+ return;
#endif
default:
- printf("unknown %08x @ %x\n", op, PC);
- break;
+ printf("illegal instruction at %08x: %08x\n", PC, op);
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ return;
}
break;
- case OP_CALL: // call
+ case OP_CALL_NS: // call
{
uint32_t pc = PC;
uint32_t callpc = PC + DISP30;
@@ -2802,77 +3482,16 @@ void mb86901_device::complete_instruction_execution(uint32_t op)
break;
}
- case OP_ALU:
+ case OP_ALU_NS:
execute_group2(op);
break;
- case OP_LDST:
+ case OP_LDST_NS:
execute_group3(op);
break;
- default:
- break;
}
}
-
-//-------------------------------------------------
-// dispatch_instruction - dispatch the previously
-// fetched instruction
-//-------------------------------------------------
-
-void mb86901_device::dispatch_instruction(uint32_t op)
-{
- /* The SPARC Instruction Manual: Version 8, page 159, "Appendix C - ISP Descriptions - C.6. Instruction Dispatch" (SPARCv8.pdf, pg. 156)
-
- illegal_IU_instr :- (
- if ( ( (op == 00) and (op2 == 000) ) { UNIMP instruction }
- or
- ( ((op=11) or (op=10)) and (op3=unassigned) )
- then 1 else 0
-
- if (illegal_IU_instr = 1) then (
- trap <- 1
- illegal_instruction <- 1
- );
- if ((FPop1 or FPop2 or FBfcc) and ((EF = 0) or (bp_FPU_present = 0))) then (
- trap <- 1;
- fp_disabled <- 1
- );
- if (CPop1 or CPop2 or CBccc) and ((EC = 0) or (bp_CP_present = 0))) then (
- trap <- 1;
- cp_disabled <- 1
- );
- next;
- if (trap = 0) then (
- { code for specific instruction, defined below }
- );
- */
- bool illegal_IU_instr = (OP == 0 && OP2 == 0) || ((OP == 3 && !m_ldst_op3_assigned[OP3]) || (OP == 2 && !m_alu_op3_assigned[OP3]));
-
- if (illegal_IU_instr)
- {
- printf("illegal instruction at %08x: %08x\n", PC, op);
- m_trap = 1;
- m_illegal_instruction = 1;
- }
- if (((OP == OP_ALU && (FPOP1 || FPOP2)) || (OP == OP_TYPE0 && OP2 == OP2_FBFCC)) && (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present))
- {
- m_trap = 1;
- m_fp_disabled = 1;
- }
- if (((OP == OP_ALU && (CPOP1 || CPOP2)) || (OP == OP_TYPE0 && OP2 == OP2_CBCCC)) && (!(PSR & PSR_EC_MASK) || !m_bp_cp_present))
- {
- m_trap = 1;
- m_cp_disabled = 1;
- }
-
- if (!m_trap)
- {
- complete_instruction_execution(op);
- }
-}
-
-
//-------------------------------------------------
// complete_fp_execution - completes execution
// of a floating-point operation
@@ -2949,7 +3568,7 @@ void mb86901_device::execute_step()
//printf("Entering reset mode\n");
return;
}
- else if ((PSR & PSR_ET_MASK) && (m_bp_irl == 15 || m_bp_irl > ((PSR & PSR_PIL_MASK) >> PSR_PIL_SHIFT)))
+ else if (m_et && (m_bp_irl == 15 || m_bp_irl > m_pil))
{
m_trap = 1;
m_interrupt_level = m_bp_irl;
@@ -2958,7 +3577,7 @@ void mb86901_device::execute_step()
if (m_trap)
{
execute_trap();
- BREAK_PSR;
+ //BREAK_PSR;
debugger_instruction_hook(PC);
}
@@ -2966,8 +3585,7 @@ void mb86901_device::execute_step()
{
// write-state-register delay not yet implemented
- uint32_t addr_space = (IS_USER ? 8 : 9);
- uint32_t op = read_sized_word(addr_space, PC, 4);
+ const uint32_t op = read_sized_word(m_fetch_space, PC, 4);
#if LOG_FCODES
//if (m_log_fcodes)
@@ -2992,11 +3610,11 @@ void mb86901_device::execute_step()
complete_fp_execution(op);
}
- if (m_trap == 0 && !(OP == OP_CALL || (OP == OP_TYPE0 && (OP2 == OP2_BICC || OP2 == OP2_FBFCC || OP2 == OP2_CBCCC)) || (OP == OP_ALU && (JMPL || TICC || RETT))))
- {
- PC = nPC;
- nPC = nPC + 4;
- }
+ //if (m_trap == 0 && !(OP == OP_CALL || (OP == OP_TYPE0 && (OP2 == OP2_BICC || OP2 == OP2_FBFCC || OP2 == OP2_CBCCC)) || (OP == OP_ALU && (JMPL || TICC || RETT))))
+ //{
+ //PC = nPC;
+ //nPC = nPC + 4;
+ //}
}
else
{
@@ -3081,7 +3699,7 @@ void mb86901_device::execute_run()
continue;
}
- BREAK_PSR;
+ //BREAK_PSR;
debugger_instruction_hook(PC);
if (m_reset_mode)