summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Ryan Holtz <ryan.holtz@arrowheadgs.com>2018-09-21 18:24:28 +0200
committer Ryan Holtz <ryan.holtz@arrowheadgs.com>2018-09-21 18:24:35 +0200
commit45c4749b25adeefb65331f6b6673c69bad555570 (patch)
treed019d4cbcdaf0e0d5f9ac27de143f661bf565a49
parent99936288c49f1021420935c5136fd031d9b833a0 (diff)
-sun4, sparc: Optimized the SPARC core and the sun4 driver. [Ryan Holtz]
-rw-r--r--src/devices/bus/sbus/bwtwo.cpp17
-rw-r--r--src/devices/cpu/sparc/mb86901.cpp1564
-rw-r--r--src/devices/cpu/sparc/sparc.h30
-rw-r--r--src/devices/cpu/sparc/sparcdefs.h9
-rw-r--r--src/mame/drivers/sun4.cpp1148
5 files changed, 1772 insertions, 996 deletions
diff --git a/src/devices/bus/sbus/bwtwo.cpp b/src/devices/bus/sbus/bwtwo.cpp
index a5e78323aab..ab9fd194a88 100644
--- a/src/devices/bus/sbus/bwtwo.cpp
+++ b/src/devices/bus/sbus/bwtwo.cpp
@@ -70,14 +70,19 @@ uint32_t sbus_bwtwo_device::screen_update(screen_device &screen, bitmap_rgb32 &b
for (int y = 0; y < 900; y++)
{
uint32_t *scanline = &bitmap.pix32(y);
+ uint8_t *line = vram + y * (1152/8);
for (int x = 0; x < 1152/8; x++)
{
- const uint8_t pixels = vram[(y * (1152/8)) + (BYTE4_XOR_BE(x))];
-
- for (int bit = 7; bit >= 0; bit--)
- {
- *scanline++ = palette[BIT(pixels, bit)];
- }
+ const uint8_t pixels = line[BYTE4_XOR_BE(x)];
+
+ *scanline++ = palette[BIT(pixels, 7)];
+ *scanline++ = palette[BIT(pixels, 6)];
+ *scanline++ = palette[BIT(pixels, 5)];
+ *scanline++ = palette[BIT(pixels, 4)];
+ *scanline++ = palette[BIT(pixels, 3)];
+ *scanline++ = palette[BIT(pixels, 2)];
+ *scanline++ = palette[BIT(pixels, 1)];
+ *scanline++ = palette[BIT(pixels, 0)];
}
}
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)
diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h
index 9c97b86bdef..41264b6ed2b 100644
--- a/src/devices/cpu/sparc/sparc.h
+++ b/src/devices/cpu/sparc/sparc.h
@@ -27,6 +27,19 @@ class mb86901_device : public cpu_device, protected sparc_disassembler::config
public:
mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ enum
+ {
+ AS_COUNT = 32,
+
+ AS_START = 128,
+ AS_END = AS_START + (AS_COUNT - 1)
+ };
+
+ template <typename T> void set_asi_addrmap(int asi, T &&obj)
+ {
+ set_addrmap(asi + AS_START, std::forward<T>(obj));
+ }
+
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
@@ -48,7 +61,7 @@ public:
// device_state_interface overrides
virtual void state_string_export(const device_state_entry &entry, std::string &str) const override;
- uint8_t get_asi() { return m_asi; }
+ uint8_t get_asi() { return 0; }
uint32_t pc() { return m_pc; }
void set_mae() { m_mae = 1; }
@@ -96,7 +109,7 @@ protected:
void execute_trap();
void complete_instruction_execution(uint32_t op);
- void dispatch_instruction(uint32_t op);
+ inline void dispatch_instruction(uint32_t op);
void complete_fp_execution(uint32_t /*op*/);
void execute_step();
@@ -110,7 +123,10 @@ protected:
#endif
// address spaces
- const address_space_config m_program_config;
+ std::string m_asi_names[AS_COUNT];
+ address_space_config m_asi_config[AS_COUNT];
+ memory_access_cache<2, 0, ENDIANNESS_BIG> *m_access_cache[AS_COUNT];
+ address_space_config m_default_config;
// memory access
uint32_t read_sized_word(uint8_t asi, uint32_t address, int size);
@@ -197,9 +213,6 @@ protected:
// register windowing helpers
uint32_t* m_regs[32];
- // addressing helpers
- uint8_t m_asi;
-
// other internal states
bool m_privileged_asr[32];
bool m_illegal_instruction_asr[32];
@@ -207,12 +220,13 @@ protected:
bool m_annul;
bool m_hold_bus;
int m_icount;
+ int m_fetch_space;
// debugger helpers
uint32_t m_dbgregs[24];
// address spaces
- address_space *m_program;
+ address_space *m_space[32];
#if LOG_FCODES
uint32_t m_ss1_next_pc;
@@ -288,4 +302,4 @@ enum
SPARC_RESET
};
-#endif // MAME_CPU_SPARC_SPARC_H
+#endif // MAME_CPU_SPARC_SPARC_H \ No newline at end of file
diff --git a/src/devices/cpu/sparc/sparcdefs.h b/src/devices/cpu/sparc/sparcdefs.h
index b3ebb95d589..952702022eb 100644
--- a/src/devices/cpu/sparc/sparcdefs.h
+++ b/src/devices/cpu/sparc/sparcdefs.h
@@ -81,7 +81,9 @@
#define WIM m_wim
#define TBR m_tbr
-#define OP (op >> 30) // gangnam style
+#define OP_NS (op & 0xc0000000)
+
+#define OP (op >> 30)
#define OP2 ((op >> 22) & 7)
#define OP3 ((op >> 19) & 63)
#define OPF ((op >> 5) & 0x1ff)
@@ -153,6 +155,11 @@
#define OP_ALU 2
#define OP_LDST 3
+#define OP_TYPE0_NS (OP_TYPE0 << 30)
+#define OP_CALL_NS (OP_CALL << 30)
+#define OP_ALU_NS (OP_ALU << 30)
+#define OP_LDST_NS (OP_LDST << 30)
+
#define OP2_UNIMP 0
#define OP2_BICC 2
#define OP2_SETHI 4
diff --git a/src/mame/drivers/sun4.cpp b/src/mame/drivers/sun4.cpp
index 2be69f71d95..45666d9e4ad 100644
--- a/src/mame/drivers/sun4.cpp
+++ b/src/mame/drivers/sun4.cpp
@@ -583,6 +583,36 @@ private:
static const device_timer_id TIMER_1 = 1;
static const device_timer_id TIMER_RESET = 2;
+ enum insn_data_mode
+ {
+ USER_INSN,
+ SUPER_INSN,
+ USER_DATA,
+ SUPER_DATA
+ };
+
+ DECLARE_READ32_MEMBER( sun4_cache_flush_r );
+ DECLARE_WRITE32_MEMBER( sun4_cache_flush_w );
+ DECLARE_READ32_MEMBER( sun4_system_r );
+ DECLARE_WRITE32_MEMBER( sun4_system_w );
+ DECLARE_READ32_MEMBER( sun4_segment_map_r );
+ DECLARE_WRITE32_MEMBER( sun4_segment_map_w );
+ DECLARE_READ32_MEMBER( sun4_page_map_r );
+ DECLARE_WRITE32_MEMBER( sun4_page_map_w );
+ template <insn_data_mode MODE> DECLARE_READ32_MEMBER( sun4_insn_data_r );
+ DECLARE_WRITE32_MEMBER( sun4_insn_data_w );
+
+ DECLARE_READ32_MEMBER( sun4c_cache_flush_r );
+ DECLARE_WRITE32_MEMBER( sun4c_cache_flush_w );
+ DECLARE_READ32_MEMBER( sun4c_system_r );
+ DECLARE_WRITE32_MEMBER( sun4c_system_w );
+ DECLARE_READ32_MEMBER( sun4c_segment_map_r );
+ DECLARE_WRITE32_MEMBER( sun4c_segment_map_w );
+ DECLARE_READ32_MEMBER( sun4c_page_map_r );
+ DECLARE_WRITE32_MEMBER( sun4c_page_map_w );
+ template <insn_data_mode MODE> DECLARE_READ32_MEMBER( sun4c_insn_data_r );
+ template <insn_data_mode MODE> DECLARE_WRITE32_MEMBER( sun4c_insn_data_w );
+
DECLARE_READ32_MEMBER( sun4_mmu_r );
DECLARE_WRITE32_MEMBER( sun4_mmu_w );
DECLARE_READ32_MEMBER( sun4c_mmu_r );
@@ -618,8 +648,23 @@ private:
void ncr53c90a(device_t *device);
- void sun4_mem(address_map &map);
- void sun4c_mem(address_map &map);
+ void sun4_system_map(address_map &map);
+ void sun4_segment_map(address_map &map);
+ void sun4_page_map(address_map &map);
+ void sun4_insn_map(address_map &map);
+ void sun4_supervisor_insn_map(address_map &map);
+ void sun4_data_map(address_map &map);
+ void sun4_supervisor_data_map(address_map &map);
+
+ void sun4c_system_map(address_map &map);
+ void sun4c_segment_map(address_map &map);
+ void sun4c_page_map(address_map &map);
+ void sun4c_insn_map(address_map &map);
+ void sun4c_supervisor_insn_map(address_map &map);
+ void sun4c_data_map(address_map &map);
+ void sun4c_supervisor_data_map(address_map &map);
+ void sun4c_cache_flush_map(address_map &map);
+
void type0space_map(address_map &map);
void type1space_map(address_map &map);
void type1space_sbus_map(address_map &map);
@@ -647,12 +692,15 @@ private:
optional_device<sbus_device> m_sbus;
optional_device<address_map_bank_device> m_type0space;
optional_device<address_map_bank_device> m_type1space;
+ memory_access_cache<2, 0, ENDIANNESS_BIG> *m_type1_cache;
required_device<ram_device> m_ram;
required_memory_region m_rom;
uint32_t *m_rom_ptr;
uint32_t m_context;
+ uint32_t m_context_masked;
uint8_t m_system_enable;
+ bool m_fetch_bootrom;
uint8_t m_auxio;
uint32_t m_buserr[4];
uint32_t m_counter[4];
@@ -663,9 +711,46 @@ private:
int m_scsi_irq;
int m_fdc_irq;
+ struct page_entry_t
+ {
+ uint32_t valid;
+ uint32_t writable;
+ uint32_t supervisor;
+ uint32_t uncached;
+ uint32_t accessed;
+ uint32_t modified;
+ uint32_t page;
+ uint8_t type;
+ uint8_t pad[3];
+
+ template <sun4_arch ARCH_4C>
+ uint32_t to_uint()
+ {
+ return valid | writable | supervisor | uncached | (type << 26) | accessed | modified | (ARCH_4C ? (page >> 10) : (page >> 11));
+ }
+
+ template <sun4_arch ARCH_4C>
+ void merge_uint(uint32_t data, uint32_t mem_mask)
+ {
+ const uint32_t new_value = (to_uint<ARCH_4C>() & ~mem_mask) | (data & mem_mask);
+ valid = new_value & PM_VALID;
+ writable = new_value & PM_WRITEMASK;
+ supervisor = new_value & PM_SYSMASK;
+ uncached = new_value & PM_CACHE;
+ type = (new_value & PM_TYPEMASK) >> 26;
+ accessed = new_value & PM_ACCESSED;
+ modified = new_value & PM_MODIFIED;
+ page = ARCH_4C ? ((new_value & 0xffff) << 10) : ((new_value & 0x7ffff) << 11);
+ }
+ };
+
uint32_t *m_ram_ptr;
uint8_t m_segmap[16][4096];
- uint32_t m_pagemap[16384];
+ uint8_t *m_curr_segmap;
+ uint32_t m_segmap_masked[16][4096];
+ uint32_t *m_curr_segmap_masked;
+ page_entry_t m_pagemap[16384];
+ bool m_page_valid[16384];
uint32_t m_cachetags[0x4000];
uint32_t m_cachedata[0x4000];
uint32_t m_ram_size;
@@ -680,11 +765,6 @@ private:
emu_timer *m_c0_timer, *m_c1_timer;
emu_timer *m_reset_timer;
- uint32_t read_insn_data(uint8_t asi, address_space &space, uint32_t offset, uint32_t mem_mask);
- void write_insn_data(uint8_t asi, address_space &space, uint32_t offset, uint32_t data, uint32_t mem_mask);
- uint32_t read_insn_data_4c(uint8_t asi, address_space &space, uint32_t offset, uint32_t mem_mask);
- void write_insn_data_4c(uint8_t asi, address_space &space, uint32_t offset, uint32_t data, uint32_t mem_mask);
-
void dma_check_interrupts();
void dma_transfer();
void dma_transfer_write();
@@ -696,25 +776,226 @@ private:
void fcodes_command(int ref, const std::vector<std::string> &params);
};
-uint32_t sun4_state::read_insn_data_4c(uint8_t asi, address_space &space, uint32_t offset, uint32_t mem_mask)
+READ32_MEMBER( sun4_state::sun4c_cache_flush_r )
+{
+ // Do nothing for now
+ return 0;
+}
+
+WRITE32_MEMBER( sun4_state::sun4c_cache_flush_w )
+{
+ // Do nothing for now
+}
+
+READ32_MEMBER( sun4_state::sun4c_system_r )
+{
+ //logerror("%s: system_space_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask);
+ switch (offset >> 26)
+ {
+ case 3: // context reg
+ if (mem_mask == 0x00ff0000) return m_context<<16;
+ return m_context<<24;
+
+ case 4: // system enable reg
+ return m_system_enable<<24;
+
+ case 6: // bus error register
+ {
+ //printf("sun4c: read buserror %08x, PC=%x (mask %08x)\n", 0x60000000 | (offset << 2), m_maincpu->pc(), mem_mask);
+ const uint32_t retval = m_buserr[offset & 0xf];
+ m_buserr[offset & 0xf] = 0; // clear on reading
+ return retval;
+ }
+
+ case 8: // (d-)cache tags
+ //logerror("sun4: read dcache tags @ %x, PC = %x\n", offset, m_maincpu->pc());
+ return m_cachetags[(offset>>3)&0x3fff];
+
+ case 9: // (d-)cache data
+ //logerror("sun4c: read dcache data @ %x, PC = %x\n", offset, m_maincpu->pc());
+ return m_cachedata[offset&0x3fff];
+
+ case 0xf: // UART bypass
+ //printf("read UART bypass @ %x mask %08x\n", offset<<2, mem_mask);
+ switch (offset & 3)
+ {
+ case 0: if (mem_mask == 0xff000000) return m_scc2->cb_r(space, offset)<<24; else return m_scc2->db_r(space, offset)<<8; break;
+ case 1: if (mem_mask == 0xff000000) return m_scc2->ca_r(space, offset)<<24; else return m_scc2->da_r(space, offset)<<8; break;
+ }
+ return 0xffffffff;
+
+ case 0: // IDPROM - TODO: SPARCstation-1 does not have an ID prom and a timeout should occur.
+ default:
+ logerror("sun4c: ASI 2 space unhandled read @ %x (PC=%x)\n", offset<<2, m_maincpu->pc());
+ return 0;
+ }
+}
+
+WRITE32_MEMBER( sun4_state::sun4c_system_w )
+{
+ //logerror("%s: system_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
+ switch (offset >> 26)
+ {
+ case 3: // context reg
+ //printf("%08x to context, mask %08x, offset %x\n", data, mem_mask, offset);
+ m_context = data>>24;
+ m_context_masked = m_context & m_ctx_mask;
+ m_curr_segmap = m_segmap[m_context_masked];
+ m_curr_segmap_masked = m_segmap_masked[m_context_masked];
+ return;
+
+ case 4: // system enable reg
+ {
+ const uint8_t old_enable = m_system_enable;
+ m_system_enable = data>>24;
+ m_fetch_bootrom = !(m_system_enable & ENA_NOTBOOT);
+
+ if (m_system_enable & ENA_RESET)
+ {
+ m_reset_timer->adjust(attotime::from_usec(1));
+ m_maincpu->set_input_line(SPARC_RESET, ASSERT_LINE);
+ logerror("%s: Asserting reset line\n", machine().describe_context());
+ }
+ //printf("%08x to system enable, mask %08x\n", data, mem_mask);
+ if (m_system_enable & ENA_RESET)
+ {
+ m_system_enable = 0;
+ m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ }
+
+ if ((old_enable ^ m_system_enable) & ENA_NOTBOOT)
+ {
+ //printf("%c", (m_system_enable & ENA_NOTBOOT) ? 'A' : 'B');
+ /*if (m_system_enable & ENA_NOTBOOT)
+ {
+ m_maincpu->space(mb86901_device::AS_START + 9).install_readwrite_handler(0x00000000, 0xffffffff, 0, 0, 0
+ , read32_delegate(FUNC(sun4_state::sun4c_insn_data_r<SUPER_INSN>), this)
+ , write32_delegate(FUNC(sun4_state::sun4c_insn_data_w<SUPER_INSN>), this));
+ m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x00000000, 0xffffffff, 0, 0, 0
+ , read32_delegate(FUNC(sun4_state::sun4c_insn_data_r<SUPER_INSN>), this)
+ , write32_delegate(FUNC(sun4_state::sun4c_insn_data_w<SUPER_INSN>), this));
+ }
+ else
+ {
+ m_maincpu->space(mb86901_device::AS_START + 9).install_rom(0x00000000, 0x7ffff, 0xfff80000, m_rom_ptr);
+ m_maincpu->space(AS_PROGRAM).install_rom(0x00000000, 0x7ffff, 0xfff80000, m_rom_ptr);
+ }*/
+ }
+ return;
+ }
+
+ case 6: // bus error
+ logerror("%08x to bus error @ %x, mask %08x\n", data, offset, mem_mask);
+ m_buserr[offset & 0xf] = data;
+ return;
+
+ case 8: // cache tags
+ //logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_maincpu->pc());
+ m_cachetags[(offset>>3)&0x3fff] = data & 0x03f8fffc;
+ return;
+
+ case 9: // cache data
+ //logerror("sun4c: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc());
+ m_cachedata[offset&0x3fff] = data;
+ return;
+
+ case 0xf: // UART bypass
+ //printf("%08x to UART bypass @ %x, mask %08x\n", data, offset<<2, mem_mask);
+ switch (offset & 3)
+ {
+ case 0: if (mem_mask == 0xff000000) m_scc2->cb_w(space, offset, data>>24); else m_scc2->db_w(space, offset, data>>8); break;
+ case 1: if (mem_mask == 0xff000000) m_scc2->ca_w(space, offset, data>>24); else { m_scc2->da_w(space, offset, data>>8); printf("%c", data>>8); } break;
+ }
+ return;
+
+ case 0: // IDPROM
+ default:
+ logerror("sun4c: ASI 2 space unhandled write %x @ %x (mask %08x, PC=%x, shift %x)\n", data, offset<<2, mem_mask, m_maincpu->pc(), offset>>26);
+ return;
+ }
+}
+
+READ32_MEMBER( sun4_state::sun4c_segment_map_r )
+{
+ //logerror("%s: segment_map_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask);
+ //printf("sun4: read segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", offset << 2, m_context_masked, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
+ if (mem_mask == 0xffff0000)
+ return m_curr_segmap[(offset>>16) & 0xfff]<<16;
+ else if (mem_mask == 0xff000000)
+ return m_curr_segmap[(offset>>16) & 0xfff]<<24;
+ else
+ logerror("sun4: read segment map w/ unknown mask %08x\n", mem_mask);
+ return 0;
+}
+
+WRITE32_MEMBER( sun4_state::sun4c_segment_map_w )
{
+ logerror("segment_map_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
+ uint8_t segdata = 0;
+ //printf("segment write, mask %08x, PC=%x\n", mem_mask, m_maincpu->pc());
+ if (mem_mask == 0xffff0000) segdata = (data >> 16) & 0xff;
+ else if (mem_mask == 0xff000000) segdata = (data >> 24) & 0xff;
+ else logerror("sun4c: writing segment map with unknown mask %08x, PC=%x\n", mem_mask, m_maincpu->pc());
+
+ //printf("sun4c: %08x to segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", segdata, offset << 2, m_context_masked, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
+ const uint32_t seg = (offset>>16) & 0xfff;
+ m_curr_segmap[seg] = segdata;
+ m_curr_segmap_masked[seg] = (segdata & m_pmeg_mask) << 6;
+}
+
+READ32_MEMBER( sun4_state::sun4c_page_map_r )
+{
+ //logerror("%s: page_map_r: %08x & %08x\n", machine().describe_context(), offset << 2, mem_mask);
+ const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 10) & 0x3f);
+ //printf("sun4: read page map @ %x (entry %d, seg %d, PMEG %d, mem_mask %08x, PC=%x)\n", offset << 2, page, (offset >> 16) & 0xfff, m_curr_segmap_masked[(offset >> 16) & 0xfff] >> 6, mem_mask, m_maincpu->pc());
+ return m_pagemap[page].to_uint<SUN4C>();
+}
+
+WRITE32_MEMBER( sun4_state::sun4c_page_map_w )
+{
+ //logerror("%s: page_map_w: %08x = %08x & %08x\n", machine().describe_context(), offset << 2, data, mem_mask);
+ const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 10) & 0x3f);
+ //printf("sun4c: %08x to page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", data, offset << 2, page, mem_mask, m_maincpu->pc());
+ m_pagemap[page].merge_uint<SUN4C>(data, mem_mask);
+ m_page_valid[page] = m_pagemap[page].valid;
+}
+
+template <sun4_state::insn_data_mode MODE>
+READ32_MEMBER( sun4_state::sun4c_insn_data_r )
+{
+ // supervisor program fetches in boot state are special
+ if (m_fetch_bootrom && MODE == SUPER_INSN)
+ {
+ return m_rom_ptr[offset & 0x1ffff];
+ }
+
// it's translation time
- uint8_t pmeg = m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask;
- uint32_t entry = (pmeg << 6) + ((offset >> 10) & 0x3f);
+ const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff];
+ const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f);
- if (m_pagemap[entry] & PM_VALID)
+ if (m_page_valid[entry_index])
{
- m_pagemap[entry] |= PM_ACCESSED;
+ page_entry_t &entry = m_pagemap[entry_index];
+ entry.accessed = PM_ACCESSED;
- uint32_t tmp = (m_pagemap[entry] & 0xffff) << 10;
- tmp |= (offset & 0x3ff);
+ const uint32_t tmp = entry.page | (offset & 0x3ff);
- //printf("sun4: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, (m_pagemap[entry]>>26) & 3, m_pagemap[entry], m_maincpu->pc());
+ //printf("sun4: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint<SUN4C>(), m_maincpu->pc());
- switch ((m_pagemap[entry] >> 26) & 3)
+ switch (entry.type)
{
case 0: // type 0 space
- return m_type0space->read32(space, tmp, mem_mask);
+ //return m_type0space->read32(space, tmp, mem_mask);
+ if (tmp < 0x1000000>>2)
+ {
+ return m_ram_ptr[tmp];
+ }
+ else if (tmp >= 0x4000000>>2 && tmp < 0x10000000>>2)
+ {
+ timeout_r(space, tmp, mem_mask);
+ }
+ return ~0;
case 1: // type 1 space
// magic EPROM bypass
@@ -737,7 +1018,7 @@ uint32_t sun4_state::read_insn_data_4c(uint8_t asi, address_space &space, uint32
{
if (!machine().side_effects_disabled())
{
- logerror("sun4c: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry, m_pagemap[entry], offset <<2, m_maincpu->pc());
+ logerror("sun4c: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint<SUN4C>(), offset <<2, m_maincpu->pc());
m_maincpu->set_mae();
m_buserr[0] |= 0x80; // invalid PTE
m_buserr[0] &= ~0x8000; // read
@@ -762,15 +1043,17 @@ uint32_t sun4_state::read_insn_data_4c(uint8_t asi, address_space &space, uint32
}
}
-void sun4_state::write_insn_data_4c(uint8_t asi, address_space &space, uint32_t offset, uint32_t data, uint32_t mem_mask)
+template <sun4_state::insn_data_mode MODE>
+WRITE32_MEMBER( sun4_state::sun4c_insn_data_w )
{
// it's translation time
- uint8_t pmeg = m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask;
- uint32_t entry = (pmeg << 6) + ((offset >> 10) & 0x3f);
+ const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff];
+ const uint32_t entry_index = pmeg | ((offset >> 10) & 0x3f);
- if (m_pagemap[entry] & PM_VALID)
+ if (m_page_valid[entry_index])
{
- if ((!(m_pagemap[entry] & PM_WRITEMASK)) || ((m_pagemap[entry] & PM_SYSMASK) && !(asi & 1)))
+ page_entry_t &entry = m_pagemap[entry_index];
+ if ((!entry.writable) || (entry.supervisor && MODE != SUPER_DATA && MODE != SUPER_INSN))
{
logerror("sun4c: write protect MMU error (PC=%x)\n", m_maincpu->pc());
m_buserr[0] |= 0x8040; // write, protection error
@@ -779,23 +1062,32 @@ void sun4_state::write_insn_data_4c(uint8_t asi, address_space &space, uint32_t
return;
}
- m_pagemap[entry] |= (PM_ACCESSED | PM_MODIFIED);
+ entry.accessed = PM_ACCESSED;
+ entry.modified = PM_MODIFIED;
- uint32_t tmp = (m_pagemap[entry] & 0xffff) << 10;
- tmp |= (offset & 0x3ff);
+ const uint32_t tmp = entry.page | (offset & 0x3ff);
- //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, ASI %d, PC=%x\n", offset<<2, tmp<<2, (m_pagemap[entry]>>26) & 3, m_pagemap[entry], asi, m_maincpu->pc());
+ //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, ASI %d, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint<ARCH_4C>(), asi, m_maincpu->pc());
- switch ((m_pagemap[entry] >> 26) & 3)
+ switch (entry.type)
{
case 0: // type 0
- m_type0space->write32(space, tmp, data, mem_mask);
+ //m_type0space->write32(space, tmp, data, mem_mask);
+ if (tmp < 0x1000000>>2)
+ {
+ COMBINE_DATA((m_ram_ptr + tmp));
+ }
+ else if (tmp >= 0x4000000>>2 && tmp < 0x10000000>>2)
+ {
+ timeout_w(space, tmp, data, mem_mask);
+ }
return;
case 1: // type 1
//printf("write device space @ %x\n", tmp<<1);
m_type1space->write32(space, tmp, data, mem_mask);
return;
+
default:
logerror("sun4c: access to memory type not defined\n");
m_maincpu->set_mae();
@@ -806,7 +1098,7 @@ void sun4_state::write_insn_data_4c(uint8_t asi, address_space &space, uint32_t
}
else
{
- logerror("sun4c: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry, m_pagemap[entry], data, offset <<2, m_maincpu->pc());
+ logerror("sun4c: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint<SUN4C>(), data, offset <<2, m_maincpu->pc());
m_maincpu->set_mae();
m_buserr[0] |= 0x8080; // write cycle, invalid PTE
m_buserr[1] = offset<<2;
@@ -829,221 +1121,181 @@ void sun4_state::write_insn_data_4c(uint8_t asi, address_space &space, uint32_t
}
-READ32_MEMBER( sun4_state::sun4c_mmu_r )
+// -----------------------------------------------------------------
+
+READ32_MEMBER( sun4_state::sun4_system_r )
{
- uint8_t asi = m_maincpu->get_asi();
- int page;
- uint32_t retval = 0;
+ switch (offset >> 26)
+ {
+ case 3: // context reg
+ if (mem_mask == 0x00ff0000) return m_context<<16;
+ return m_context<<24;
- // make debugger fetches emulate supervisor program for best compatibility with boot PROM execution
- if (machine().side_effects_disabled()) asi = 9;
+ case 4: // system enable reg
+ return m_system_enable<<24;
- // supervisor program fetches in boot state are special
- if ((!(m_system_enable & ENA_NOTBOOT)) && (asi == 9))
- {
- return m_rom_ptr[offset & 0x1ffff];
- }
+ case 6: // bus error register
+ //printf("sun4: read buserror, PC=%x (mask %08x)\n", m_maincpu->pc(), mem_mask);
+ return 0;
- switch (asi)
- {
- case 2: // system space
- switch (offset >> 26)
- {
- case 3: // context reg
- if (mem_mask == 0x00ff0000) return m_context<<16;
- return m_context<<24;
-
- case 4: // system enable reg
- return m_system_enable<<24;
-
- case 6: // bus error register
- //printf("sun4c: read buserror %08x, PC=%x (mask %08x)\n", 0x60000000 | (offset << 2), m_maincpu->pc(), mem_mask);
- retval = m_buserr[offset & 0xf];
- m_buserr[offset & 0xf] = 0; // clear on reading
- return retval;
-
- case 8: // (d-)cache tags
- //logerror("sun4: read dcache tags @ %x, PC = %x\n", offset, m_maincpu->pc());
- return m_cachetags[(offset>>3)&0x3fff];
-
- case 9: // (d-)cache data
- //logerror("sun4c: read dcache data @ %x, PC = %x\n", offset, m_maincpu->pc());
- return m_cachedata[offset&0x3fff];
-
- case 0xf: // UART bypass
- //printf("read UART bypass @ %x mask %08x\n", offset<<2, mem_mask);
- switch (offset & 3)
- {
- case 0: if (mem_mask == 0xff000000) return m_scc2->cb_r(space, offset)<<24; else return m_scc2->db_r(space, offset)<<8; break;
- case 1: if (mem_mask == 0xff000000) return m_scc2->ca_r(space, offset)<<24; else return m_scc2->da_r(space, offset)<<8; break;
- }
- return 0xffffffff;
+ case 8: // (d-)cache tags
+ //logerror("sun4: read dcache tags @ %x, PC = %x\n", offset, m_maincpu->pc());
+ return m_cachetags[offset&0xfff];
- case 0: // IDPROM - TODO: SPARCstation-1 does not have an ID prom and a timeout should occur.
- default:
- logerror("sun4c: ASI 2 space unhandled read @ %x (PC=%x)\n", offset<<2, m_maincpu->pc());
- return 0;
- }
- break;
- case 3: // segment map
- //printf("sun4: read segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", offset << 2, m_context & m_ctx_mask, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
- if (mem_mask == 0xffff0000)
- {
- return m_segmap[m_context & m_ctx_mask][(offset>>16) & 0xfff]<<16;
- }
- else if (mem_mask == 0xff000000)
- {
- return m_segmap[m_context & m_ctx_mask][(offset>>16) & 0xfff]<<24;
- }
- else
- {
- // printf("sun4: read segment map w/unk mask %08x\n", mem_mask);
- }
- return 0x0;
-
- case 4: // page map
- page = (m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask) << 6;
- page += (offset >> 10) & 0x3f;
- //printf("sun4: read page map @ %x (entry %d, seg %d, PMEG %d, mem_mask %08x, PC=%x)\n", offset << 2, page, (offset >> 16) & 0xfff, m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask, mem_mask, m_maincpu->pc());
- return m_pagemap[page];
-
- case 8:
- case 9:
- case 10:
- case 11:
- return read_insn_data_4c(asi, space, offset, mem_mask);
-
- default:
- if (!machine().side_effects_disabled()) logerror("sun4c: ASI %d unhandled read @ %x (PC=%x)\n", asi, offset<<2, m_maincpu->pc());
- return 0;
- }
+ case 9: // (d-)cache data
+ logerror("sun4: read dcache data @ %x, PC = %x\n", offset, m_maincpu->pc());
+ return 0xffffffff;
- logerror("sun4c: read asi %d byte offset %x, PC = %x\n", asi, offset << 2, m_maincpu->pc());
+ case 0xf: // UART bypass
+ //printf("read UART bypass @ %x mask %08x (PC=%x)\n", offset<<2, mem_mask, m_maincpu->pc());
+ switch (offset & 3)
+ {
+ case 0: if (mem_mask == 0xff000000) return m_scc2->cb_r(space, offset)<<24; else return m_scc2->db_r(space, offset)<<8; break;
+ case 1: if (mem_mask == 0xff000000) return m_scc2->ca_r(space, offset)<<24; else return m_scc2->da_r(space, offset)<<8; break;
+ }
+ return 0xffffffff;
- return 0;
+ case 0:
+ default:
+ logerror("sun4: ASI 2 space unhandled read @ %x (PC=%x)\n", offset<<2, m_maincpu->pc());
+ return 0;
+ }
}
-WRITE32_MEMBER( sun4_state::sun4c_mmu_w )
+WRITE32_MEMBER( sun4_state::sun4_system_w )
{
- uint8_t asi = m_maincpu->get_asi();
- int page;
-
- //printf("sun4: write %08x to %08x (ASI %d, mem_mask %08x, PC %x)\n", data, offset, asi, mem_mask, m_maincpu->pc());
-
- switch (asi)
+ switch (offset >> 26)
{
- case 2:
- switch (offset >> 26)
- {
- case 3: // context reg
- //printf("%08x to context, mask %08x, offset %x\n", data, mem_mask, offset);
- m_context = data>>24;
- return;
+ case 3: // context reg
+ //printf("%08x to context, mask %08x, offset %x\n", data, mem_mask, offset);
+ m_context = data>>24;
+ return;
- case 4: // system enable reg
- m_system_enable = data>>24;
+ case 4: // system enable reg
+ m_system_enable = data>>24;
- if (m_system_enable & ENA_RESET)
- {
- m_reset_timer->adjust(attotime::from_usec(1));
- m_maincpu->set_input_line(SPARC_RESET, ASSERT_LINE);
- logerror("%s: Asserting reset line\n", machine().describe_context());
- }
- //printf("%08x to system enable, mask %08x\n", data, mem_mask);
- if (m_system_enable & ENA_RESET)
+ if (m_system_enable & ENA_RESET)
+ {
+ m_reset_timer->adjust(attotime::from_usec(1));
+ m_maincpu->set_input_line(SPARC_RESET, ASSERT_LINE);
+ logerror("%s: Asserting reset line\n", machine().describe_context());
+ }
+ //printf("%08x to system enable, mask %08x\n", data, mem_mask);
+ if (m_system_enable & ENA_RESET)
+ {
+ m_system_enable = 0;
+ m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
+ m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ }
+ return;
+
+ case 7: // diag reg
+ m_diag = data >> 24;
+ #if 1
+ printf("sun4: CPU LEDs to %02x (PC=%x) => ", ((data>>24) & 0xff) ^ 0xff, m_maincpu->pc());
+ for (int i = 0; i < 8; i++)
+ {
+ if (m_diag & (1<<i))
{
- m_system_enable = 0;
- m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
- m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
+ printf(".");
}
- return;
-
- case 6: // bus error
- logerror("%08x to bus error @ %x, mask %08x\n", data, offset, mem_mask);
- m_buserr[offset & 0xf] = data;
- return;
-
- case 8: // cache tags
- //logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_maincpu->pc());
- m_cachetags[(offset>>3)&0x3fff] = data & 0x03f8fffc;
- return;
-
- case 9: // cache data
- //logerror("sun4c: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc());
- m_cachedata[offset&0x3fff] = data;
- return;
-
- case 0xf: // UART bypass
- //printf("%08x to UART bypass @ %x, mask %08x\n", data, offset<<2, mem_mask);
- switch (offset & 3)
+ else
{
- case 0: if (mem_mask == 0xff000000) m_scc2->cb_w(space, offset, data>>24); else m_scc2->db_w(space, offset, data>>8); break;
- case 1: if (mem_mask == 0xff000000) m_scc2->ca_w(space, offset, data>>24); else { m_scc2->da_w(space, offset, data>>8); printf("%c", data>>8); } break;
+ printf("*");
}
- return;
+ }
+ printf("\n");
+ #endif
+ return;
- case 0: // IDPROM
- default:
- logerror("sun4c: ASI 2 space unhandled write %x @ %x (mask %08x, PC=%x, shift %x)\n", data, offset<<2, mem_mask, m_maincpu->pc(), offset>>26);
- return;
- }
- break;
- case 3: // segment map
- {
- uint8_t segdata = 0;
- //printf("segment write, mask %08x, PC=%x\n", mem_mask, m_maincpu->pc());
- if (mem_mask == 0xffff0000) segdata = (data >> 16) & 0xff;
- else if (mem_mask == 0xff000000) segdata = (data >> 24) & 0xff;
- else logerror("sun4c: writing segment map with unknown mask %08x, PC=%x\n", mem_mask, m_maincpu->pc());
-
- //printf("sun4c: %08x to segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", segdata, offset << 2, m_context, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
- m_segmap[m_context & m_ctx_mask][(offset>>16) & 0xfff] = segdata; // only 7 bits of the segment are necessary
- }
- return;
+ case 8: // cache tags
+ //logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_maincpu->pc());
+ m_cachetags[offset&0xfff] = data;
+ return;
- case 4: // page map
- page = (m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask) << 6; // get the PMEG
- page += (offset >> 10) & 0x3f; // add the offset
- //printf("sun4c: %08x to page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", data, offset << 2, page, mem_mask, m_maincpu->pc());
- COMBINE_DATA(&m_pagemap[page]);
- m_pagemap[page] &= 0xff00ffff; // these 8 bits are cleared when written and tested as such
- return;
+ case 9: // cache data
+ logerror("sun4: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc());
+ return;
- case 8:
- case 9:
- case 10:
- case 11:
- write_insn_data_4c(asi, space, offset, data, mem_mask);
- return;
+ case 0xf: // UART bypass
+ //printf("%08x to UART bypass @ %x, mask %08x\n", data, offset<<2, mem_mask);
+ switch (offset & 3)
+ {
+ case 0: if (mem_mask == 0xff000000) m_scc2->cb_w(space, offset, data>>24); else m_scc2->db_w(space, offset, data>>8); break;
+ case 1: if (mem_mask == 0xff000000) m_scc2->ca_w(space, offset, data>>24); else { m_scc2->da_w(space, offset, data>>8); printf("%c", data>>8); } break;
+ }
+ return;
- case 12: // Flush Cache (Segment)
- case 13: // Flush Cache (Page)
- case 14: // Flush Cache (Context)
- // Ignored
- return;
+ case 0: // IDPROM
+ default:
+ logerror("sun4: ASI 2 space unhandled write %x @ %x (mask %08x, PC=%x)\n", data, offset<<2, mem_mask, m_maincpu->pc());
+ return;
}
+}
- logerror("sun4c: %08x to asi %d byte offset %x, PC = %x, mask = %08x\n", data, asi, offset << 2, m_maincpu->pc(), mem_mask);
+READ32_MEMBER( sun4_state::sun4_segment_map_r )
+{
+ //printf("sun4: read segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", offset << 2, m_context, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
+ if (mem_mask == 0xffff0000)
+ return m_curr_segmap[(offset>>16) & 0xfff]<<16;
+ else if (mem_mask == 0xff000000)
+ return m_curr_segmap[(offset>>16) & 0xfff]<<24;
+ else
+ logerror("sun4: read segment map w/ unknown mask %08x\n", mem_mask);
+ return 0x0;
}
-// -----------------------------------------------------------------
+WRITE32_MEMBER( sun4_state::sun4_segment_map_w )
+{
+ uint8_t segdata = 0;
+ //printf("segment write, mask %08x, PC=%x\n", mem_mask, m_maincpu->pc());
+ if (mem_mask == 0xffff0000) segdata = (data >> 16) & 0xff;
+ else if (mem_mask == 0xff000000) segdata = (data >> 24) & 0xff;
+ else logerror("sun4: writing segment map with unknown mask %08x, PC=%x\n", mem_mask, m_maincpu->pc());
+
+ //printf("sun4: %08x to segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", segdata, offset << 2, m_context, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
+ m_curr_segmap[(offset>>16) & 0xfff] = segdata;
+ m_curr_segmap_masked[(offset>>16) & 0xfff] = segdata << 5;
+}
-uint32_t sun4_state::read_insn_data(uint8_t asi, address_space &space, uint32_t offset, uint32_t mem_mask)
+READ32_MEMBER( sun4_state::sun4_page_map_r )
{
+ uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 11) & 0x1f);
+ //printf("sun4: read page map @ %x (entry %d, seg %d, PMEG %d, mem_mask %08x, PC=%x)\n", offset << 2, page, (offset >> 16) & 0xfff, m_segmap[m_context][(offset >> 16) & 0xfff] & m_pmeg_mask, mem_mask, m_maincpu->pc());
+ return m_pagemap[page].to_uint<SUN4>();
+}
+
+WRITE32_MEMBER( sun4_state::sun4_page_map_w )
+{
+ const uint32_t page = m_curr_segmap_masked[(offset >> 16) & 0xfff] | ((offset >> 11) & 0x1f);
+ //printf("sun4: %08x to page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", data, offset << 2, page, mem_mask, m_maincpu->pc());
+ m_pagemap[page].merge_uint<SUN4>(data, mem_mask);
+ m_page_valid[page] = m_pagemap[page].valid;
+}
+
+template <sun4_state::insn_data_mode MODE>
+READ32_MEMBER( sun4_state::sun4_insn_data_r )
+{
+ // supervisor program fetches in boot state are special
+ if (m_fetch_bootrom && MODE == SUPER_INSN)
+ {
+ return m_rom_ptr[offset & 0x1ffff];
+ }
+
// it's translation time
- uint8_t pmeg = m_segmap[m_context][(offset >> 16) & 0xfff];
- uint32_t entry = (pmeg << 5) + ((offset >> 11) & 0x1f);
+ const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff];
+ const uint32_t entry_index = pmeg | ((offset >> 11) & 0x1f);
- if (m_pagemap[entry] & PM_VALID)
+ if (m_page_valid[entry_index])
{
- m_pagemap[entry] |= PM_ACCESSED;
+ page_entry_t &entry = m_pagemap[entry_index];
+ entry.accessed = PM_ACCESSED;
- uint32_t tmp = (m_pagemap[entry] & 0x7ffff) << 11;
- tmp |= (offset & 0x7ff);
+ const uint32_t tmp = entry.page | (offset & 0x7ff);
- //printf("sun4: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, (m_pagemap[entry]>>26) & 3, m_pagemap[entry], m_maincpu->pc());
+ //printf("sun4: read translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint<SUN4>(), m_maincpu->pc());
- switch ((m_pagemap[entry] >> 26) & 3)
+ switch (entry.type)
{
case 0: // type 0 space
return m_type0space->read32(space, tmp, mem_mask);
@@ -1066,7 +1318,7 @@ uint32_t sun4_state::read_insn_data(uint8_t asi, address_space &space, uint32_t
{
if (!machine().side_effects_disabled())
{
- logerror("sun4: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry, m_pagemap[entry], offset <<2, m_maincpu->pc());
+ logerror("sun4: INVALID PTE entry %d %08x accessed! vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint<SUN4>(), offset <<2, m_maincpu->pc());
m_maincpu->set_mae();
m_buserr[0] |= 0x80; // invalid PTE
m_buserr[0] &= ~0x8000; // read
@@ -1091,22 +1343,22 @@ uint32_t sun4_state::read_insn_data(uint8_t asi, address_space &space, uint32_t
}
}
-void sun4_state::write_insn_data(uint8_t asi, address_space &space, uint32_t offset, uint32_t data, uint32_t mem_mask)
+WRITE32_MEMBER( sun4_state::sun4_insn_data_w )
{
// it's translation time
- uint8_t pmeg = m_segmap[m_context][(offset >> 16) & 0xfff];
- uint32_t entry = (pmeg << 5) + ((offset >> 11) & 0x1f);
+ const uint32_t pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff];
+ const uint32_t entry_index = pmeg | ((offset >> 11) & 0x1f);
- if (m_pagemap[entry] & PM_VALID)
+ if (m_page_valid[entry_index])
{
- m_pagemap[entry] |= PM_ACCESSED;
+ page_entry_t &entry = m_pagemap[entry_index];
+ entry.accessed = PM_ACCESSED;
- uint32_t tmp = (m_pagemap[entry] & 0x7ffff) << 11;
- tmp |= (offset & 0x7ff);
+ uint32_t tmp = entry.page | (offset & 0x7ff);
- //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, (m_pagemap[entry]>>26) & 3, m_pagemap[entry], m_maincpu->pc());
+ //printf("sun4: write translated vaddr %08x to phys %08x type %d, PTE %08x, PC=%x\n", offset<<2, tmp<<2, entry.type, entry.to_uint<SUN4>(), m_maincpu->pc());
- switch ((m_pagemap[entry] >> 26) & 3)
+ switch (entry.type)
{
case 0: // type 0
m_type0space->write32(space, tmp, data, mem_mask);
@@ -1124,220 +1376,15 @@ void sun4_state::write_insn_data(uint8_t asi, address_space &space, uint32_t off
}
else
{
- logerror("sun4: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry, m_pagemap[entry], data, offset <<2, m_maincpu->pc());
+ logerror("sun4: INVALID PTE entry %d %08x accessed! data=%08x vaddr=%x PC=%x\n", entry_index, m_pagemap[entry_index].to_uint<SUN4>(), data, offset <<2, m_maincpu->pc());
//m_maincpu->trap(SPARC_DATA_ACCESS_EXCEPTION);
//m_buserr[0] = 0x8; // invalid PTE
//m_buserr[1] = offset<<2;
}
}
-READ32_MEMBER( sun4_state::sun4_mmu_r )
-{
- uint8_t asi = m_maincpu->get_asi();
- int page;
-
- // make debugger fetches emulate supervisor program for best compatibility with boot PROM execution
- if (machine().side_effects_disabled()) asi = 9;
-
- // supervisor program fetches in boot state are special
- if ((!(m_system_enable & ENA_NOTBOOT)) && (asi == 9))
- {
- return m_rom_ptr[offset & 0x1ffff];
- }
-
- switch (asi)
- {
- case 2: // system space
- switch (offset >> 26)
- {
- case 3: // context reg
- if (mem_mask == 0x00ff0000) return m_context<<16;
- return m_context<<24;
-
- case 4: // system enable reg
- return m_system_enable<<24;
-
- case 6: // bus error register
- //printf("sun4: read buserror, PC=%x (mask %08x)\n", m_maincpu->pc(), mem_mask);
- return 0;
-
- case 8: // (d-)cache tags
- //logerror("sun4: read dcache tags @ %x, PC = %x\n", offset, m_maincpu->pc());
- return m_cachetags[offset&0xfff];
-
- case 9: // (d-)cache data
- logerror("sun4: read dcache data @ %x, PC = %x\n", offset, m_maincpu->pc());
- return 0xffffffff;
-
- case 0xf: // UART bypass
- //printf("read UART bypass @ %x mask %08x (PC=%x)\n", offset<<2, mem_mask, m_maincpu->pc());
- switch (offset & 3)
- {
- case 0: if (mem_mask == 0xff000000) return m_scc2->cb_r(space, offset)<<24; else return m_scc2->db_r(space, offset)<<8; break;
- case 1: if (mem_mask == 0xff000000) return m_scc2->ca_r(space, offset)<<24; else return m_scc2->da_r(space, offset)<<8; break;
- }
- return 0xffffffff;
-
- case 0:
- default:
- logerror("sun4: ASI 2 space unhandled read @ %x (PC=%x)\n", offset<<2, m_maincpu->pc());
- return 0;
- }
- break;
- case 3: // segment map
- //printf("sun4: read segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", offset << 2, m_context & m_ctx_mask, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
- if (mem_mask == 0xffff0000)
- {
- return m_segmap[m_context][(offset>>16) & 0xfff]<<16;
- }
- else if (mem_mask == 0xff000000)
- {
- return m_segmap[m_context][(offset>>16) & 0xfff]<<24;
- }
- else
- {
- // printf("sun4: read segment map w/unk mask %08x\n", mem_mask);
- }
- return 0x0;
-
- case 4: // page map
- page = (m_segmap[m_context][(offset >> 16) & 0xfff]) << 5;
- page += (offset >> 11) & 0x1f;
- //printf("sun4: read page map @ %x (entry %d, seg %d, PMEG %d, mem_mask %08x, PC=%x)\n", offset << 2, page, (offset >> 16) & 0xfff, m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff] & m_pmeg_mask, mem_mask, m_maincpu->pc());
- return m_pagemap[page];
-
- case 6: // region map used in 4/4xx, I don't know anything about this
- return 0;
-
- case 8:
- case 9:
- case 10:
- case 11:
- return read_insn_data(asi, space, offset, mem_mask);
-
- default:
- if (!machine().side_effects_disabled()) logerror("sun4: ASI %d unhandled read @ %x (PC=%x)\n", asi, offset<<2, m_maincpu->pc());
- return 0;
- }
-
- logerror("sun4: read asi %d byte offset %x, PC = %x\n", asi, offset << 2, m_maincpu->pc());
-
- return 0;
-}
-
-WRITE32_MEMBER( sun4_state::sun4_mmu_w )
-{
- uint8_t asi = m_maincpu->get_asi();
- int page;
-
- //printf("sun4: write %08x to %08x (ASI %d, mem_mask %08x, PC %x)\n", data, offset, asi, mem_mask, m_maincpu->pc());
-
- switch (asi)
- {
- case 2:
- switch (offset >> 26)
- {
- case 3: // context reg
- //printf("%08x to context, mask %08x, offset %x\n", data, mem_mask, offset);
- m_context = data>>24;
- return;
-
- case 4: // system enable reg
- m_system_enable = data>>24;
-
- if (m_system_enable & ENA_RESET)
- {
- m_reset_timer->adjust(attotime::from_usec(1));
- m_maincpu->set_input_line(SPARC_RESET, ASSERT_LINE);
- logerror("%s: Asserting reset line\n", machine().describe_context());
- }
- //printf("%08x to system enable, mask %08x\n", data, mem_mask);
- if (m_system_enable & ENA_RESET)
- {
- m_system_enable = 0;
- m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
- m_maincpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
- }
- return;
-
- case 7: // diag reg
- m_diag = data >> 24;
- #if 1
- printf("sun4: CPU LEDs to %02x (PC=%x) => ", ((data>>24) & 0xff) ^ 0xff, m_maincpu->pc());
- for (int i = 0; i < 8; i++)
- {
- if (m_diag & (1<<i))
- {
- printf(".");
- }
- else
- {
- printf("*");
- }
- }
- printf("\n");
- #endif
- return;
-
- case 8: // cache tags
- //logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_maincpu->pc());
- m_cachetags[offset&0xfff] = data;
- return;
-
- case 9: // cache data
- logerror("sun4: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc());
- return;
-
- case 0xf: // UART bypass
- //printf("%08x to UART bypass @ %x, mask %08x\n", data, offset<<2, mem_mask);
- switch (offset & 3)
- {
- case 0: if (mem_mask == 0xff000000) m_scc2->cb_w(space, offset, data>>24); else m_scc2->db_w(space, offset, data>>8); break;
- case 1: if (mem_mask == 0xff000000) m_scc2->ca_w(space, offset, data>>24); else { m_scc2->da_w(space, offset, data>>8); printf("%c", data>>8); } break;
- }
- return;
-
- case 0: // IDPROM
- default:
- logerror("sun4: ASI 2 space unhandled write %x @ %x (mask %08x, PC=%x)\n", data, offset<<2, mem_mask, m_maincpu->pc());
- return;
- }
- break;
- case 3: // segment map
- {
- uint8_t segdata = 0;
- //printf("segment write, mask %08x, PC=%x\n", mem_mask, m_maincpu->pc());
- if (mem_mask == 0xffff0000) segdata = (data >> 16) & 0xff;
- else if (mem_mask == 0xff000000) segdata = (data >> 24) & 0xff;
- else logerror("sun4: writing segment map with unknown mask %08x, PC=%x\n", mem_mask, m_maincpu->pc());
-
- //printf("sun4: %08x to segment map @ %x (ctx %d entry %d, mem_mask %08x, PC=%x)\n", segdata, offset << 2, m_context, (offset>>16) & 0xfff, mem_mask, m_maincpu->pc());
- m_segmap[m_context][(offset>>16) & 0xfff] = segdata;
- }
- return;
-
- case 4: // page map
- page = (m_segmap[m_context][(offset >> 16) & 0xfff]) << 5; // get the PMEG
- page += (offset >> 11) & 0x1f; // add the offset
- //printf("sun4: %08x to page map @ %x (entry %d, mem_mask %08x, PC=%x)\n", data, offset << 2, page, mem_mask, m_maincpu->pc());
- COMBINE_DATA(&m_pagemap[page]);
- m_pagemap[page] &= 0xff07ffff; // these bits are cleared when written and tested as such
- return;
-
- case 6: // region map, used in 4/4xx
- return;
-
- case 8:
- case 9:
- case 10:
- case 11:
- write_insn_data(asi, space, offset, data, mem_mask);
- break;
-
- }
-
- printf("sun4: %08x to asi %d byte offset %x, PC = %x, mask = %08x\n", data, asi, offset << 2, m_maincpu->pc(), mem_mask);
-}
+// make debugger fetches emulate supervisor program for best compatibility with boot PROM execution
+//if (machine().side_effects_disabled()) asi = 9;
void sun4_state::l2p_command(int ref, const std::vector<std::string> &params)
{
@@ -1349,30 +1396,31 @@ void sun4_state::l2p_command(int ref, const std::vector<std::string> &params)
offset = addr >> 2;
uint8_t pmeg = 0;
- uint32_t entry = 0, tmp = 0;
+ uint32_t entry_index = 0, tmp = 0;
+ uint32_t entry_value = 0;
if (m_arch == ARCH_SUN4)
{
- pmeg = m_segmap[m_context][(offset >> 16) & 0xfff];
- entry = (pmeg << 5) + ((offset >> 11) & 0x1f);
- tmp = (m_pagemap[entry] & 0x7ffff) << 11;
- tmp |= (offset & 0x7ff);
+ pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff];
+ entry_index = pmeg | ((offset >> 11) & 0x1f);
+ tmp = m_pagemap[entry_index].page | (offset & 0x7ff);
+ entry_value = m_pagemap[entry_index].to_uint<SUN4>();
}
else if (m_arch == ARCH_SUN4C)
{
- pmeg = m_segmap[m_context & m_ctx_mask][(offset >> 16) & 0xfff];
- entry = (pmeg << 6) + ((offset >> 10) & 0x3f);
- tmp = (m_pagemap[entry] & 0xffff) << 10;
- tmp |= (offset & 0x3ff);
+ pmeg = m_curr_segmap_masked[(offset >> 16) & 0xfff];
+ entry_index = pmeg | ((offset >> 10) & 0x3f);
+ tmp = m_pagemap[entry_index].page | (offset & 0x3ff);
+ entry_value = m_pagemap[entry_index].to_uint<SUN4C>();
}
- if (m_pagemap[entry] & PM_VALID)
+ if (m_page_valid[entry_index])
{
- machine().debugger().console().printf("logical %08x => phys %08x, type %d (pmeg %d, entry %d PTE %08x)\n", addr, tmp << 2, (m_pagemap[entry] >> 26) & 3, pmeg, entry, m_pagemap[entry]);
+ machine().debugger().console().printf("logical %08x => phys %08x, type %d (pmeg %d, entry %d PTE %08x)\n", addr, tmp << 2, m_pagemap[entry_index].type, pmeg, entry_index, entry_value);
}
else
{
- machine().debugger().console().printf("logical %08x points to an invalid PTE! (pmeg %d, entry %d PTE %08x)\n", addr, tmp << 2, pmeg, entry, m_pagemap[entry]);
+ machine().debugger().console().printf("logical %08x points to an invalid PTE! (pmeg %d, entry %d PTE %08x)\n", addr, tmp << 2, pmeg, entry_index, entry_value);
}
}
@@ -1397,14 +1445,114 @@ void sun4_state::fcodes_command(int ref, const std::vector<std::string> &params)
#endif
}
-void sun4_state::sun4_mem(address_map &map)
+void sun4_state::sun4_system_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_system_r), FUNC(sun4_state::sun4_system_w));
+}
+
+void sun4_state::sun4_segment_map(address_map &map)
{
- map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_mmu_r), FUNC(sun4_state::sun4_mmu_w));
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_segment_map_r), FUNC(sun4_state::sun4_segment_map_w));
}
-void sun4_state::sun4c_mem(address_map &map)
+void sun4_state::sun4_page_map(address_map &map)
{
- map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_mmu_r), FUNC(sun4_state::sun4c_mmu_w));
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_page_map_r), FUNC(sun4_state::sun4_page_map_w));
+}
+
+void sun4_state::sun4_supervisor_insn_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_insn_data_r<SUPER_INSN>), FUNC(sun4_state::sun4_insn_data_w));
+}
+
+void sun4_state::sun4_supervisor_data_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_insn_data_r<SUPER_DATA>), FUNC(sun4_state::sun4_insn_data_w));
+}
+
+void sun4_state::sun4_insn_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_insn_data_r<USER_INSN>), FUNC(sun4_state::sun4_insn_data_w));
+}
+
+void sun4_state::sun4_data_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4_insn_data_r<USER_DATA>), FUNC(sun4_state::sun4_insn_data_w));
+}
+
+void sun4_state::sun4c_system_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_system_r), FUNC(sun4_state::sun4c_system_w));
+}
+
+void sun4_state::sun4c_segment_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_segment_map_r), FUNC(sun4_state::sun4c_segment_map_w));
+}
+
+void sun4_state::sun4c_page_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_page_map_r), FUNC(sun4_state::sun4c_page_map_w));
+}
+
+void sun4_state::sun4c_supervisor_insn_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r<SUPER_INSN>), FUNC(sun4_state::sun4c_insn_data_w<SUPER_INSN>));
+}
+
+void sun4_state::sun4c_supervisor_data_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r<SUPER_DATA>), FUNC(sun4_state::sun4c_insn_data_w<SUPER_DATA>));
+}
+
+void sun4_state::sun4c_insn_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r<USER_INSN>), FUNC(sun4_state::sun4c_insn_data_w<USER_INSN>));
+}
+
+void sun4_state::sun4c_data_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_insn_data_r<USER_DATA>), FUNC(sun4_state::sun4c_insn_data_w<USER_DATA>));
+}
+
+void sun4_state::sun4c_cache_flush_map(address_map &map)
+{
+ map(0x00000000, 0xffffffff).rw(FUNC(sun4_state::sun4c_cache_flush_r), FUNC(sun4_state::sun4c_cache_flush_w));
+}
+
+void sun4_state::type0space_map(address_map &map)
+{
+ map.unmap_value_high();
+ map(0x00000000, 0x00ffffff).rw(FUNC(sun4_state::ram_r), FUNC(sun4_state::ram_w));
+ map(0x04000000, 0x0fffffff).rw(FUNC(sun4_state::timeout_r), FUNC(sun4_state::timeout_w));
+}
+
+void sun4_state::type1space_map(address_map &map)
+{
+ map(0x00000000, 0x0000000f).rw(m_scc1, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00);
+ map(0x01000000, 0x0100000f).rw(m_scc2, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00);
+ map(0x02000000, 0x020007ff).rw(m_timekpr, FUNC(timekeeper_device::read), FUNC(timekeeper_device::write));
+ map(0x03000000, 0x0300000f).rw(FUNC(sun4_state::timer_r), FUNC(sun4_state::timer_w)).mirror(0xfffff0);
+ map(0x05000000, 0x05000003).rw(FUNC(sun4_state::irq_r), FUNC(sun4_state::irq_w));
+ map(0x06000000, 0x0607ffff).rom().region("user1", 0);
+ map(0x07200000, 0x07200003).rw(FUNC(sun4_state::fdc_r), FUNC(sun4_state::fdc_w));
+ map(0x07400003, 0x07400003).rw(FUNC(sun4_state::auxio_r), FUNC(sun4_state::auxio_w));
+ map(0x08000000, 0x08000003).r(FUNC(sun4_state::ss1_sl0_id)); // slot 0 contains SCSI/DMA/Ethernet
+ map(0x08400000, 0x0840000f).rw(FUNC(sun4_state::dma_r), FUNC(sun4_state::dma_w));
+ map(0x08800000, 0x0880002f).m(m_scsi, FUNC(ncr53c90a_device::map)).umask32(0xff000000);
+ map(0x08c00000, 0x08c00003).rw(m_lance, FUNC(am79c90_device::regs_r), FUNC(am79c90_device::regs_w));
+}
+
+void sun4_state::type1space_sbus_map(address_map &map)
+{
+ type1space_map(map);
+ map(0x0a000000, 0x0fffffff).rw(m_sbus, FUNC(sbus_device::read), FUNC(sbus_device::write));
+}
+
+void sun4_state::type1space_s4_map(address_map &map)
+{
+ map(0x00000000, 0x0000000f).rw(m_scc1, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00);
+ map(0x01000000, 0x0100000f).rw(m_scc2, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00);
}
/* Input ports */
@@ -1414,7 +1562,11 @@ INPUT_PORTS_END
void sun4_state::machine_reset()
{
m_context = 0;
+ m_context_masked = 0;
+ m_curr_segmap = m_segmap[0];
+ m_curr_segmap_masked = m_segmap_masked[0];
m_system_enable = 0;
+ m_fetch_bootrom = true;
m_auxio = 0xc0;
m_irq_reg = 0;
m_scc1_int = m_scc2_int = 0;
@@ -1435,6 +1587,12 @@ void sun4_state::machine_start()
m_ram_size = m_ram->size();
m_ram_size_words = m_ram_size >> 2;
+ //m_maincpu->space(mb86901_device::AS_START + 9).install_rom(0x00000, 0x7ffff, 0xfff80000, m_rom_ptr);
+ //m_maincpu->space(AS_PROGRAM).install_rom(0x00000, 0x7ffff, 0xfff80000, m_rom_ptr);
+ //memory_space().install_ram(start << 8, (start << 8) | 0x00ffU, m_memory);
+
+ m_type1_cache = m_type1space->space(0).cache<2, 0, ENDIANNESS_BIG>(); // Not currently used - unsure how to make it work
+
if (machine().debug_flags & DEBUG_FLAG_ENABLED)
{
using namespace std::placeholders;
@@ -1472,11 +1630,7 @@ WRITE32_MEMBER( sun4_state::timeout_w )
READ32_MEMBER( sun4_state::ram_r )
{
- //printf("ram_r: @ %08x (mask %08x)\n", offset<<2, mem_mask);
-
- if (offset < m_ram_size_words) return m_ram_ptr[offset];
-
- return 0xffffffff;
+ return m_ram_ptr[offset];
}
WRITE32_MEMBER( sun4_state::ram_w )
@@ -1538,45 +1692,7 @@ WRITE32_MEMBER( sun4_state::ram_w )
//if ((offset<<2) == 0xfb2000) printf("write %08x to %08x, mask %08x, PC=%x\n", data, offset<<2, mem_mask, m_maincpu->pc());
- if (offset < m_ram_size_words)
- {
- COMBINE_DATA(&m_ram_ptr[offset]);
- return;
- }
-}
-
-void sun4_state::type0space_map(address_map &map)
-{
- map(0x00000000, 0x03ffffff).rw(FUNC(sun4_state::ram_r), FUNC(sun4_state::ram_w));
- map(0x04000000, 0x0fffffff).rw(FUNC(sun4_state::timeout_r), FUNC(sun4_state::timeout_w));
-}
-
-void sun4_state::type1space_map(address_map &map)
-{
- map(0x00000000, 0x0000000f).rw(m_scc1, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00);
- map(0x01000000, 0x0100000f).rw(m_scc2, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00);
- map(0x02000000, 0x020007ff).rw(m_timekpr, FUNC(timekeeper_device::read), FUNC(timekeeper_device::write));
- map(0x03000000, 0x0300000f).rw(FUNC(sun4_state::timer_r), FUNC(sun4_state::timer_w)).mirror(0xfffff0);
- map(0x05000000, 0x05000003).rw(FUNC(sun4_state::irq_r), FUNC(sun4_state::irq_w));
- map(0x06000000, 0x0607ffff).rom().region("user1", 0);
- map(0x07200000, 0x07200003).rw(FUNC(sun4_state::fdc_r), FUNC(sun4_state::fdc_w));
- map(0x07400003, 0x07400003).rw(FUNC(sun4_state::auxio_r), FUNC(sun4_state::auxio_w));
- map(0x08000000, 0x08000003).r(FUNC(sun4_state::ss1_sl0_id)); // slot 0 contains SCSI/DMA/Ethernet
- map(0x08400000, 0x0840000f).rw(FUNC(sun4_state::dma_r), FUNC(sun4_state::dma_w));
- map(0x08800000, 0x0880002f).m(m_scsi, FUNC(ncr53c90a_device::map)).umask32(0xff000000);
- map(0x08c00000, 0x08c00003).rw(m_lance, FUNC(am79c90_device::regs_r), FUNC(am79c90_device::regs_w));
-}
-
-void sun4_state::type1space_sbus_map(address_map &map)
-{
- type1space_map(map);
- map(0x0a000000, 0x0fffffff).rw(m_sbus, FUNC(sbus_device::read), FUNC(sbus_device::write));
-}
-
-void sun4_state::type1space_s4_map(address_map &map)
-{
- map(0x00000000, 0x0000000f).rw(m_scc1, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00);
- map(0x01000000, 0x0100000f).rw(m_scc2, FUNC(z80scc_device::ba_cd_inv_r), FUNC(z80scc_device::ba_cd_inv_w)).umask32(0xff00ff00);
+ COMBINE_DATA(&m_ram_ptr[offset]);
}
READ8_MEMBER( sun4_state::fdc_r )
@@ -1618,13 +1734,13 @@ WRITE8_MEMBER( sun4_state::fdc_w )
READ8_MEMBER( sun4_state::auxio_r )
{
- logerror("%s: auxio_r: %02x\n", machine().describe_context(), m_auxio);
+ //logerror("%s: auxio_r: %02x\n", machine().describe_context(), m_auxio);
return m_auxio;
}
WRITE8_MEMBER( sun4_state::auxio_w )
{
- logerror("%s: auxio_w: %02x, drive_sel:%d tc:%d eject:%d LED:%d\n", machine().describe_context(), data, BIT(data, 3), BIT(data, 2), BIT(data, 1), BIT(data, 0));
+ //logerror("%s: auxio_w: %02x, drive_sel:%d tc:%d eject:%d LED:%d\n", machine().describe_context(), data, BIT(data, 3), BIT(data, 2), BIT(data, 1), BIT(data, 0));
m_auxio = (m_auxio & 0xf0) | (data & 0x0f);
if (!(m_auxio & AUXIO_DRIVE_SEL))
{
@@ -1648,7 +1764,7 @@ WRITE8_MEMBER( sun4_state::irq_w )
m_irq_reg = data;
const uint8_t changed = old_irq ^ data;
- logerror("%02x to IRQ, %02x changed\n", data, changed);
+ //logerror("%02x to IRQ, %02x changed\n", data, changed);
if (!changed)
return;
@@ -1836,7 +1952,7 @@ void sun4_state::dma_transfer_write()
{
//logerror("DMAing from device to RAM\n");
- address_space &space = m_maincpu->space(AS_PROGRAM);
+ address_space &space = m_maincpu->space(mb86901_device::AS_START+9);
uint8_t pack_cnt = (m_dma[DMA_CTRL] & DMA_PACK_CNT) >> DMA_PACK_CNT_SHIFT;
while (m_dma[DMA_CTRL] & DMA_REQ_PEND)
@@ -1855,11 +1971,11 @@ void sun4_state::dma_transfer_write()
//logerror("Writing pack register %08x to %08x\n", m_dma_pack_register, m_dma[DMA_ADDR]);
if (m_arch == ARCH_SUN4C)
{
- write_insn_data_4c(11, space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0);
+ sun4c_insn_data_w<SUPER_DATA>(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0);
}
else
{
- write_insn_data(11, space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0);
+ sun4c_insn_data_w<SUPER_DATA>(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, ~0);
}
pack_cnt = 0;
@@ -1876,7 +1992,7 @@ void sun4_state::dma_transfer_read()
{
//logerror("DMAing from RAM to device\n");
- address_space &space = m_maincpu->space(AS_PROGRAM);
+ address_space &space = m_maincpu->space(mb86901_device::AS_START+9);
bool word_cached = false;
uint32_t current_word = 0;
@@ -1886,11 +2002,11 @@ void sun4_state::dma_transfer_read()
{
if (m_arch == ARCH_SUN4C)
{
- current_word = read_insn_data_4c(11, space, m_dma[DMA_ADDR] >> 2, ~0);
+ current_word = sun4c_insn_data_r<SUPER_DATA>(space, m_dma[DMA_ADDR] >> 2, ~0);
}
else
{
- current_word = read_insn_data(11, space, m_dma[DMA_ADDR] >> 2, ~0);
+ current_word = sun4c_insn_data_r<SUPER_DATA>(space, m_dma[DMA_ADDR] >> 2, ~0);
}
word_cached = true;
//logerror("Current word: %08x\n", current_word);
@@ -1972,7 +2088,7 @@ WRITE32_MEMBER( sun4_state::dma_w )
const uint32_t bit_index = (3 - i) * 8;
//const uint32_t value = m_dma_pack_register & (0xff << bit_index);
//logerror("dma_w: draining %02x to RAM address %08x & %08x\n", value >> bit_index, m_dma[DMA_ADDR], 0xff << (24 - bit_index));
- write_insn_data_4c(11, space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index);
+ sun4c_insn_data_w<SUPER_DATA>(space, m_dma[DMA_ADDR] >> 2, m_dma_pack_register, 0xff << bit_index);
m_dma[DMA_ADDR]++;
}
m_dma_pack_register = 0;
@@ -2041,17 +2157,17 @@ WRITE_LINE_MEMBER( sun4_state::fdc_irq )
READ32_MEMBER( sun4_state::lance_dma_r )
{
if (m_arch == ARCH_SUN4)
- return read_insn_data(11, m_maincpu->space(AS_PROGRAM), offset, mem_mask);
+ return sun4_insn_data_r<SUPER_DATA>(space, offset, mem_mask);
else
- return read_insn_data_4c(11, m_maincpu->space(AS_PROGRAM), offset, mem_mask);
+ return sun4c_insn_data_r<SUPER_DATA>(space, offset, mem_mask);
}
WRITE32_MEMBER( sun4_state::lance_dma_w )
{
if (m_arch == ARCH_SUN4)
- write_insn_data(11, m_maincpu->space(AS_PROGRAM), offset, data, mem_mask);
+ sun4_insn_data_w(space, offset, data, mem_mask);
else
- write_insn_data_4c(11, m_maincpu->space(AS_PROGRAM), offset, data, mem_mask);
+ sun4c_insn_data_w<SUPER_DATA>(space, offset, data, mem_mask);
}
WRITE32_MEMBER( sun4_state::buserr_w )
@@ -2099,8 +2215,14 @@ void sun4_state::ncr53c90a(device_t *device)
MACHINE_CONFIG_START(sun4_state::sun4)
/* basic machine hardware */
MCFG_DEVICE_ADD(m_maincpu, MB86901, 16670000)
- MCFG_DEVICE_ADDRESS_MAP(AS_PROGRAM, sun4_mem)
MCFG_SPARC_ADD_ASI_DESC(sun4_asi_desc)
+ m_maincpu->set_asi_addrmap(2, &sun4_state::sun4_system_map);
+ m_maincpu->set_asi_addrmap(3, &sun4_state::sun4_segment_map);
+ m_maincpu->set_asi_addrmap(4, &sun4_state::sun4_page_map);
+ m_maincpu->set_asi_addrmap(8, &sun4_state::sun4_insn_map);
+ m_maincpu->set_asi_addrmap(9, &sun4_state::sun4_supervisor_insn_map);
+ m_maincpu->set_asi_addrmap(10, &sun4_state::sun4_data_map);
+ m_maincpu->set_asi_addrmap(11, &sun4_state::sun4_supervisor_data_map);
RAM(config, RAM_TAG).set_default_size("16M").set_default_value(0x00);
@@ -2163,8 +2285,18 @@ MACHINE_CONFIG_END
MACHINE_CONFIG_START(sun4_state::sun4c)
/* basic machine hardware */
MCFG_DEVICE_ADD(m_maincpu, MB86901, 16670000)
- MCFG_DEVICE_ADDRESS_MAP(AS_PROGRAM, sun4c_mem)
MCFG_SPARC_ADD_ASI_DESC(sun4c_asi_desc)
+ m_maincpu->set_addrmap(0, &sun4_state::sun4c_supervisor_insn_map);
+ m_maincpu->set_asi_addrmap(2, &sun4_state::sun4c_system_map);
+ m_maincpu->set_asi_addrmap(3, &sun4_state::sun4c_segment_map);
+ m_maincpu->set_asi_addrmap(4, &sun4_state::sun4c_page_map);
+ m_maincpu->set_asi_addrmap(8, &sun4_state::sun4c_insn_map);
+ m_maincpu->set_asi_addrmap(9, &sun4_state::sun4c_supervisor_insn_map);
+ m_maincpu->set_asi_addrmap(10, &sun4_state::sun4c_data_map);
+ m_maincpu->set_asi_addrmap(11, &sun4_state::sun4c_supervisor_data_map);
+ m_maincpu->set_asi_addrmap(12, &sun4_state::sun4c_cache_flush_map);
+ m_maincpu->set_asi_addrmap(13, &sun4_state::sun4c_cache_flush_map);
+ m_maincpu->set_asi_addrmap(14, &sun4_state::sun4c_cache_flush_map);
RAM(config, RAM_TAG).set_default_size("16M").set_default_value(0x00);
@@ -2526,4 +2658,4 @@ COMP( 1990, sun4_75, sun4_300, 0, sun4c, sun4, sun4_state, init_ss2,
// sun4m (using the SPARC "reference MMU", probably will go to a separate driver)
COMP( 1992, sun_s10, sun4_300, 0, sun4c, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation 10 (Sun S10)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
-COMP( 1994, sun_s20, sun4_300, 0, sun4c, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation 20", MACHINE_NOT_WORKING | MACHINE_NO_SOUND )
+COMP( 1994, sun_s20, sun4_300, 0, sun4c, sun4, sun4_state, init_sun4c, "Sun Microsystems", "SPARCstation 20", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) \ No newline at end of file