summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author therealmogminer@gmail.com <therealmogminer@gmail.com>2016-06-19 17:49:28 +0200
committer therealmogminer@gmail.com <therealmogminer@gmail.com>2016-06-19 17:49:28 +0200
commitad030cc4f49180466ae0d702958b8e243ffdc041 (patch)
tree38e163365a4b0480cbbee299aad6ae1384641dc5 /src
parent1905f52ac827e90fa887e954a597b0233fccb5b3 (diff)
Checkpoint
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/sparc/mb86901.cpp216
-rw-r--r--src/devices/cpu/sparc/sparc.h36
-rw-r--r--src/devices/cpu/sparc/sparcdefs.h34
-rw-r--r--src/devices/machine/8530scc.cpp162
-rw-r--r--src/devices/machine/8530scc.h3
-rw-r--r--src/mame/drivers/sun4.cpp334
6 files changed, 561 insertions, 224 deletions
diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/mb86901.cpp
index 82bde76b7c2..382aa865522 100644
--- a/src/devices/cpu/sparc/mb86901.cpp
+++ b/src/devices/cpu/sparc/mb86901.cpp
@@ -165,6 +165,12 @@ void mb86901_device::device_stop()
void mb86901_device::device_reset()
{
+ m_queued_tt = 0;
+ m_queued_priority = 0;
+ m_asi = 0;
+ MAE = false;
+ HOLD_BUS = false;
+
PC = 0;
nPC = 4;
memset(m_r, 0, sizeof(UINT32) * 120);
@@ -699,7 +705,7 @@ bool mb86901_device::execute_group2(UINT32 op)
bool v = ((arg1 & 0x80000000) == (arg2 & 0x80000000) && (arg2 & 0x80000000) != (result & 0x80000000)) || ((arg1 & 3) != 0) || ((arg2 & 3) != 0);
if (v)
{
- queue_trap(sparc_tag_overflow);
+ trap(SPARC_TAG_OVERFLOW);
}
else
{
@@ -716,7 +722,7 @@ bool mb86901_device::execute_group2(UINT32 op)
bool v = ((arg1 & 0x80000000) == (arg2 & 0x80000000) && (arg2 & 0x80000000) != (result & 0x80000000)) || ((arg1 & 3) != 0) || ((arg2 & 3) != 0);
if (v)
{
- queue_trap(sparc_tag_overflow);
+ trap(SPARC_TAG_OVERFLOW);
}
else
{
@@ -795,7 +801,7 @@ bool mb86901_device::execute_group2(UINT32 op)
case 41: // rd psr
if (IS_USER)
{
- queue_trap(sparc_privileged_instruction);
+ trap(SPARC_PRIVILEGED_INSTRUCTION);
}
else
{
@@ -805,7 +811,7 @@ bool mb86901_device::execute_group2(UINT32 op)
case 42: // rd wim
if (IS_USER)
{
- queue_trap(sparc_privileged_instruction);
+ trap(SPARC_PRIVILEGED_INSTRUCTION);
}
else
{
@@ -815,7 +821,7 @@ bool mb86901_device::execute_group2(UINT32 op)
case 43: // rd tbr
if (IS_USER)
{
- queue_trap(sparc_privileged_instruction);
+ trap(SPARC_PRIVILEGED_INSTRUCTION);
}
else
{
@@ -837,14 +843,14 @@ bool mb86901_device::execute_group2(UINT32 op)
case 49: // wr psr
if (IS_USER)
{
- queue_trap(sparc_privileged_instruction);
+ trap(SPARC_PRIVILEGED_INSTRUCTION);
}
else
{
UINT32 new_psr = (arg1 ^ arg2) & ~PSR_ZERO_MASK;
if ((new_psr & PSR_CWP_MASK) >= WINDOW_COUNT)
{
- queue_trap(sparc_illegal_instruction);
+ trap(SPARC_ILLEGAL_INSTRUCTION);
}
else
{
@@ -856,7 +862,7 @@ bool mb86901_device::execute_group2(UINT32 op)
case 50: // wr wim
if (IS_USER)
{
- queue_trap(sparc_privileged_instruction);
+ trap(SPARC_PRIVILEGED_INSTRUCTION);
}
else
{
@@ -866,7 +872,7 @@ bool mb86901_device::execute_group2(UINT32 op)
case 51: // wr tbr
if (IS_USER)
{
- queue_trap(sparc_privileged_instruction);
+ trap(SPARC_PRIVILEGED_INSTRUCTION);
}
else
{
@@ -876,13 +882,13 @@ bool mb86901_device::execute_group2(UINT32 op)
case 52: // FPop1
if (FPU_DISABLED)
{
- queue_trap(sparc_floating_point_disabled);
+ trap(SPARC_FLOATING_POINT_DISABLED);
}
break;
case 53: // FPop2
if (FPU_DISABLED)
{
- queue_trap(sparc_floating_point_disabled);
+ trap(SPARC_FLOATING_POINT_DISABLED);
}
break;
case 56: // jmpl
@@ -891,7 +897,7 @@ bool mb86901_device::execute_group2(UINT32 op)
m_icount--;
if (addr & 3)
{
- queue_trap(sparc_mem_address_not_aligned);
+ trap(SPARC_MEM_ADDRESS_NOT_ALIGNED);
}
else
{
@@ -909,11 +915,11 @@ bool mb86901_device::execute_group2(UINT32 op)
{
if (IS_USER)
{
- queue_trap(sparc_privileged_instruction);
+ trap(SPARC_PRIVILEGED_INSTRUCTION);
}
else
{
- queue_trap(sparc_illegal_instruction);
+ trap(SPARC_ILLEGAL_INSTRUCTION);
}
break;
}
@@ -921,17 +927,17 @@ bool mb86901_device::execute_group2(UINT32 op)
{
if (IS_USER)
{
- queue_trap(sparc_reset, sparc_privileged_instruction);
+ trap(SPARC_RESET, SPARC_PRIVILEGED_INSTRUCTION);
break;
}
else if (m_wim & (1 << new_cwp))
{
- queue_trap(sparc_reset, sparc_window_underflow);
+ trap(SPARC_RESET, SPARC_WINDOW_UNDERFLOW);
break;
}
else if (ADDRESS & 3)
{
- queue_trap(sparc_reset, sparc_mem_address_not_aligned);
+ trap(SPARC_RESET, SPARC_MEM_ADDRESS_NOT_ALIGNED);
break;
}
}
@@ -963,7 +969,7 @@ bool mb86901_device::execute_group2(UINT32 op)
UINT8 new_cwp = ((m_cwp + WINDOW_COUNT) - 1) % WINDOW_COUNT;
if (m_wim & (1 << new_cwp))
{
- queue_trap(sparc_window_overflow);
+ trap(SPARC_WINDOW_OVERFLOW);
}
else
{
@@ -976,7 +982,7 @@ bool mb86901_device::execute_group2(UINT32 op)
UINT8 new_cwp = (m_cwp + 1) % WINDOW_COUNT;
if (m_wim & (1 << new_cwp))
{
- queue_trap(sparc_window_overflow);
+ trap(SPARC_WINDOW_UNDERFLOW);
}
else
{
@@ -985,7 +991,7 @@ bool mb86901_device::execute_group2(UINT32 op)
break;
}
default:
- queue_trap(sparc_illegal_instruction);
+ trap(SPARC_ILLEGAL_INSTRUCTION);
break;
}
@@ -1014,17 +1020,17 @@ bool mb86901_device::check_main_traps(UINT32 op, bool privileged, UINT32 alignme
bool trap_queued = false;
if (privileged && !m_s)
{
- queue_trap(sparc_privileged_instruction);
+ trap(SPARC_PRIVILEGED_INSTRUCTION);
trap_queued = true;
}
if (alignment & ADDRESS)
{
- queue_trap(sparc_mem_address_not_aligned);
+ trap(SPARC_MEM_ADDRESS_NOT_ALIGNED);
trap_queued = true;
}
if ((registeralign & RD) || (noimmediate && USEIMM))
{
- queue_trap(sparc_illegal_instruction);
+ trap(SPARC_ILLEGAL_INSTRUCTION);
trap_queued = true;
}
return trap_queued;
@@ -1051,21 +1057,44 @@ void mb86901_device::execute_group3(UINT32 op)
switch (OP3)
{
case 0: // ld
+ {
check_main_traps(op, false, 3, 0, false);
- SET_RDREG(read_word(m_data_asi, ADDRESS));
+ UINT32 result = read_word(m_data_asi, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
break;
+ }
case 1: // ldub
- SET_RDREG(read_byte(m_data_asi, ADDRESS));
+ {
+ UINT32 result = read_byte(m_data_asi, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
break;
+ }
case 2: // lduh
+ {
check_main_traps(op, false, 1, 0, false);
- SET_RDREG(read_half(m_data_asi, ADDRESS));
+ UINT32 result = read_half(m_data_asi, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
break;
+ }
case 3: // ldd
+ {
check_main_traps(op, false, 7, 1, false);
- SET_RDREG(read_word(m_data_asi, ADDRESS));
- REG(RD+1) = read_word(m_data_asi, ADDRESS+4);
+ UINT32 result = read_word(m_data_asi, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
+ result = read_word(m_data_asi, ADDRESS+4);
+ if (MAE || HOLD_BUS)
+ break;
+ REG(RD+1) = result;
break;
+ }
case 4: // st
check_main_traps(op, false, 3, 0, false);
write_word(m_data_asi, ADDRESS, RDREG);
@@ -1080,38 +1109,78 @@ void mb86901_device::execute_group3(UINT32 op)
case 7: // std
check_main_traps(op, false, 7, 1, false);
write_word(m_data_asi, ADDRESS, RDREG);
+ if (MAE || HOLD_BUS)
+ break;
write_word(m_data_asi, ADDRESS, REG(RD+1));
break;
case 9: // ldsb
- SET_RDREG(read_signed_byte(m_data_asi, ADDRESS));
+ {
+ UINT32 result = read_signed_byte(m_data_asi, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
break;
+ }
case 10: // lsdh
+ {
check_main_traps(op, false, 1, 0, false);
- SET_RDREG(read_signed_half(m_data_asi, ADDRESS));
+ UINT32 result = read_signed_half(m_data_asi, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
break;
+ }
case 13: // ldstub
- SET_RDREG(read_byte(m_data_asi, ADDRESS));
+ {
+ UINT32 result = read_byte(m_data_asi, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
write_byte(m_data_asi, ADDRESS, 0xff);
break;
+ }
case 15: // swap, SPARCv8
break;
case 16: // lda
+ {
check_main_traps(op, true, 3, 0, true);
- SET_RDREG(read_word(ASI, ADDRESS));
+ UINT32 result = read_word(ASI, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
break;
+ }
case 17: // lduba
+ {
check_main_traps(op, true, 0, 0, true);
- SET_RDREG(read_byte(ASI, ADDRESS));
+ UINT32 result = read_byte(ASI, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
break;
+ }
case 18: // lduha
+ {
check_main_traps(op, true, 1, 0, true);
- SET_RDREG(read_half(ASI, ADDRESS));
+ UINT32 result = read_half(ASI, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
break;
+ }
case 19: // ldda
+ {
check_main_traps(op, true, 7, 1, true);
- SET_RDREG(read_word(ASI, ADDRESS));
- REG(RD+1) = read_word(ASI, ADDRESS+4);
+ UINT32 result = read_word(ASI, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
+ result = read_word(ASI, ADDRESS+4);
+ if (MAE || HOLD_BUS)
+ break;
+ REG(RD+1) = result;
break;
+ }
case 20: // sta
check_main_traps(op, true, 3, 0, true);
write_word(ASI, ADDRESS, RDREG);
@@ -1127,36 +1196,67 @@ void mb86901_device::execute_group3(UINT32 op)
case 23: // stda
check_main_traps(op, true, 7, 1, true);
write_word(ASI, ADDRESS, RDREG);
+ if (MAE || HOLD_BUS)
+ break;
write_word(ASI, ADDRESS+4, REG(RD+1));
break;
case 25: // ldsba
+ {
check_main_traps(op, true, 0, 0, true);
- SET_RDREG(read_signed_byte(ASI, ADDRESS));
+ UINT32 result = read_signed_byte(ASI, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
break;
+ }
case 26: // ldsha
+ {
check_main_traps(op, true, 1, 0, true);
- SET_RDREG(read_signed_half(ASI, ADDRESS));
+ UINT32 result = read_signed_half(ASI, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
break;
+ }
case 29: // ldstuba
+ {
check_main_traps(op, true, 0, 0, true);
- SET_RDREG(read_byte(ASI, ADDRESS));
+ UINT32 result = read_byte(ASI, ADDRESS);
+ if (MAE || HOLD_BUS)
+ break;
+ SET_RDREG(result);
write_byte(ASI, ADDRESS, 0xff);
break;
+ }
case 31: // swapa, SPARCv8
break;
case 32: // ld fpr
+ if (FPU_DISABLED)
+ trap(SPARC_FLOATING_POINT_DISABLED);
break;
case 33: // ld fsr
+ if (FPU_DISABLED)
+ trap(SPARC_FLOATING_POINT_DISABLED);
break;
case 35: // ldd fpr
+ if (FPU_DISABLED)
+ trap(SPARC_FLOATING_POINT_DISABLED);
break;
case 36: // st fpr
+ if (FPU_DISABLED)
+ trap(SPARC_FLOATING_POINT_DISABLED);
break;
case 37: // st fsr
+ if (FPU_DISABLED)
+ trap(SPARC_FLOATING_POINT_DISABLED);
break;
case 38: // std fq, SPARCv8
+ if (FPU_DISABLED)
+ trap(SPARC_FLOATING_POINT_DISABLED);
break;
case 39: // std fpr
+ if (FPU_DISABLED)
+ trap(SPARC_FLOATING_POINT_DISABLED);
break;
case 40: // ld cpr, SPARCv8
break;
@@ -1174,7 +1274,10 @@ void mb86901_device::execute_group3(UINT32 op)
break;
}
- m_icount -= ldst_cycles[OP3];
+ if (MAE || HOLD_BUS)
+ m_icount--;
+ else
+ m_icount -= ldst_cycles[OP3];
}
@@ -1253,7 +1356,7 @@ bool mb86901_device::execute_ticc(UINT32 op)
{
UINT32 arg2 = USEIMM ? SIMM7 : RS2REG;
UINT8 tt = 128 + ((RS1REG + arg2) & 0x7f);
- queue_trap(sparc_trap_instruction, tt);
+ trap(SPARC_TRAP_INSTRUCTION, tt);
m_icount -= 3;
return false;
}
@@ -1263,24 +1366,32 @@ bool mb86901_device::execute_ticc(UINT32 op)
//-------------------------------------------------
-// queue_trap - flag an incoming trap of a given
+// trap - flag an incoming trap of a given
// type
//-------------------------------------------------
-void mb86901_device::queue_trap(UINT8 type, UINT8 tt_override)
+void mb86901_device::trap(UINT8 type, UINT8 tt_override)
{
- if (type == sparc_reset)
+ if (type == SPARC_RESET)
{
m_queued_priority = m_trap_priorities[0];
m_queued_tt = tt_override;
}
else
{
- if (type == sparc_trap_instruction)
+ if (type == SPARC_TRAP_INSTRUCTION)
{
type = tt_override;
}
+ if (type >= SPARC_INT1 && type <= SPARC_INT14)
+ {
+ if (!ET)
+ return;
+ int irl = (type - SPARC_INT1) + 1;
+ if (irl <= PIL)
+ return;
+ }
if (m_trap_priorities[type] < m_queued_priority)
{
m_queued_priority = m_trap_priorities[type];
@@ -1302,6 +1413,7 @@ bool mb86901_device::invoke_queued_traps()
if (m_queued_priority > 0)
{
m_queued_priority = 0;
+ m_queued_tt = 0;
m_et = false;
m_ps = m_s;
@@ -1336,8 +1448,20 @@ void mb86901_device::execute_run()
while (m_icount > 0)
{
+ bool trap_was_queued = invoke_queued_traps();
+ if (trap_was_queued)
+ {
+ m_icount -= 4;
+ continue;
+ }
+
debugger_instruction_hook(this, m_pc);
+ if (HOLD_BUS)
+ {
+ m_icount--;
+ continue;
+ }
UINT32 op = GET_OPCODE;
bool update_npc = true;
@@ -1390,7 +1514,7 @@ void mb86901_device::execute_run()
REG(0) = 0;
bool trap_taken = invoke_queued_traps();
- if (!trap_taken && update_npc)
+ if (!trap_taken && update_npc && !HOLD_BUS)
{
PC = nPC;
nPC = PC + 4;
diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h
index 0c23bdbe29c..324d46137a9 100644
--- a/src/devices/cpu/sparc/sparc.h
+++ b/src/devices/cpu/sparc/sparc.h
@@ -9,6 +9,34 @@
#ifndef __SPARC_H__
#define __SPARC_H__
+#define SPARC_RESET 0
+#define SPARC_INSTRUCTION_ACCESS_EXCEPTION 1
+#define SPARC_ILLEGAL_INSTRUCTION 2
+#define SPARC_PRIVILEGED_INSTRUCTION 3
+#define SPARC_FLOATING_POINT_DISABLED 4
+#define SPARC_WINDOW_OVERFLOW 5
+#define SPARC_WINDOW_UNDERFLOW 6
+#define SPARC_MEM_ADDRESS_NOT_ALIGNED 7
+#define SPARC_FLOATING_POINT_EXCEPTION 8
+#define SPARC_DATA_ACCESS_EXCEPTION 9
+#define SPARC_TAG_OVERFLOW 10
+#define SPARC_INT1 17
+#define SPARC_INT2 18
+#define SPARC_INT3 19
+#define SPARC_INT4 20
+#define SPARC_INT5 21
+#define SPARC_INT6 22
+#define SPARC_INT7 23
+#define SPARC_INT8 24
+#define SPARC_INT9 25
+#define SPARC_INT10 26
+#define SPARC_INT11 27
+#define SPARC_INT12 28
+#define SPARC_INT13 29
+#define SPARC_INT14 30
+#define SPARC_INT15 31
+#define SPARC_TRAP_INSTRUCTION 128
+
class mb86901_device : public cpu_device
{
public:
@@ -40,8 +68,12 @@ public:
UINT8 get_asi() { return m_asi; }
UINT32 pc() { return m_pc; }
+ void trap(UINT8 type, UINT8 tt_override = 0);
+ void set_mae() { m_mae = true; }
+ void hold_bus() { m_hold_bus = true; }
+ void release_bus() { m_hold_bus = false; }
+
protected:
- void queue_trap(UINT8 type, UINT8 tt_override = 0);
bool invoke_queued_traps();
bool check_main_traps(UINT32 op, bool privileged, UINT32 alignment, UINT8 registeralign, bool noimmediate);
@@ -103,6 +135,8 @@ protected:
UINT8 m_trap_priorities[256];
UINT8 m_queued_tt;
UINT8 m_queued_priority;
+ bool m_mae;
+ bool m_hold_bus;
int m_icount;
// debugger helpers
diff --git a/src/devices/cpu/sparc/sparcdefs.h b/src/devices/cpu/sparc/sparcdefs.h
index dbc50fd4e00..185845c1d4f 100644
--- a/src/devices/cpu/sparc/sparcdefs.h
+++ b/src/devices/cpu/sparc/sparcdefs.h
@@ -114,35 +114,9 @@
#define Y m_y
-enum sparc_trap_type
-{
- sparc_reset = 0,
- sparc_instruction_access_exception = 1,
- sparc_illegal_instruction = 2,
- sparc_privileged_instruction = 3,
- sparc_floating_point_disabled = 4,
- sparc_window_overflow = 5,
- sparc_window_underflow = 6,
- sparc_mem_address_not_aligned = 7,
- sparc_floating_point_exception = 8,
- sparc_data_access_exception = 9,
- sparc_tag_overflow = 10,
- sparc_int1 = 17,
- sparc_int2 = 18,
- sparc_int3 = 19,
- sparc_int4 = 20,
- sparc_int5 = 21,
- sparc_int6 = 22,
- sparc_int7 = 23,
- sparc_int8 = 24,
- sparc_int9 = 25,
- sparc_int10 = 26,
- sparc_int11 = 27,
- sparc_int12 = 28,
- sparc_int13 = 29,
- sparc_int14 = 30,
- sparc_int15 = 31,
- sparc_trap_instruction = 128
-};
+#define ET m_et
+#define PIL m_pil
+#define MAE m_mae
+#define HOLD_BUS m_hold_bus
#endif // __MB86901_DEFS_H__ \ No newline at end of file
diff --git a/src/devices/machine/8530scc.cpp b/src/devices/machine/8530scc.cpp
index c618fd57004..25484798b36 100644
--- a/src/devices/machine/8530scc.cpp
+++ b/src/devices/machine/8530scc.cpp
@@ -447,7 +447,7 @@ void scc8530_t::set_reg_a(int reg, UINT8 data)
/*-------------------------------------------------
- scc8530_set_reg_a
+ scc8530_set_reg_b
-------------------------------------------------*/
void scc8530_t::set_reg_b(int reg, UINT8 data)
@@ -457,46 +457,41 @@ void scc8530_t::set_reg_b(int reg, UINT8 data)
-/*-------------------------------------------------
- scc8530_r
--------------------------------------------------*/
+//-------------------------------------------------
+// reg_r - read handler, trampolines into normal
+// getter
+//-------------------------------------------------
-READ8_MEMBER( scc8530_t::reg_r)
+READ8_MEMBER(scc8530_t::reg_r)
{
- UINT8 result = 0;
+ return read_reg(offset & 3);
+}
- offset %= 4;
+
+//-------------------------------------------------
+// read_reg - reads either the control or data
+// port for either SCC channel.
+//-------------------------------------------------
+
+UINT8 scc8530_t::read_reg(int offset)
+{
switch(offset)
{
- case 0:
- /* Channel B (Printer Port) Control */
- if (mode == 1)
- mode = 0;
- else
- reg = 0;
-
- result = getbreg();
- break;
+ case 0: /* Channel B (Printer Port) Control */
+ case 1: /* Channel A (Modem Port) Control */
- case 1:
- /* Channel A (Modem Port) Control */
if (mode == 1)
mode = 0;
else
reg = 0;
- result = getareg();
- break;
-
- case 2:
- /* Channel B (Printer Port) Data */
- result = channel[1].rxData;
+ result = (offset == 0) ? getbreg(); : getareg()
break;
- case 3:
- /* Channel A (Modem Port) Data */
- result = channel[0].rxData;
+ case 2: /* Channel B (Printer Port) Data */
+ case 3:/* Channel A (Modem Port) Data */
+ result = channel[offset == 2 ? 1 : 0].rxData;
break;
}
return result;
@@ -504,116 +499,85 @@ READ8_MEMBER( scc8530_t::reg_r)
-/*-------------------------------------------------
- scc8530_w
--------------------------------------------------*/
+//-------------------------------------------------
+// reg_w - write handler, trampolines into normal
+// setter
+//-------------------------------------------------
WRITE8_MEMBER( scc8530_t::reg_w )
{
- Chan *pChan;
+ write_reg(offset & 3, data);
+}
+
- offset &= 3;
+
+//-------------------------------------------------
+// write_reg - writes either the control or data
+// port for either SCC channel.
+//-------------------------------------------------
+
+void scc8530_t::write_reg(int offset, UINT8 data)
+{
+ offset & 3;
// printf(" mode %d data %x offset %d \n", mode, data, offset);
+ Chan *pChan;
switch(offset)
{
- case 0:
- /* Channel B (Printer Port) Control */
- if (mode == 0)
- {
- if((data & 0xf0) == 0) // not a reset command
- {
- mode = 1;
- reg = data & 0x0f;
-// putbreg(data & 0xf0);
- }
- else if (data == 0x10)
- {
- pChan = &channel[1];
- // clear ext. interrupts
- pChan->extIRQPending = 0;
- pChan->baudIRQPending = 0;
- updateirqs();
- }
- }
- else
- {
- mode = 0;
- putreg(1, data);
- }
- break;
-
- case 1:
- /* Channel A (Modem Port) Control */
+ case 0: /* Channel B (Printer Port) Control */
+ case 1: /* Channel A (Modem Port) Control */
+ {
+ int chan = ((offset == 2) ? 1 : 0);
if (mode == 0)
{
if((data & 0xf0) == 0) // not a reset command
{
mode = 1;
reg = data & 0x0f;
-// putareg(data & 0xf0);
+// putbreg(data & 0xf0);
}
else if (data == 0x10)
{
- pChan = &channel[0];
// clear ext. interrupts
- pChan->extIRQPending = 0;
- pChan->baudIRQPending = 0;
+ channel[chan].extIRQPending = 0;
+ channel[chan].baudIRQPending = 0;
updateirqs();
}
}
else
{
mode = 0;
- putreg(0, data);
+ putreg(chan, data);
}
break;
+ }
- case 2:
- /* Channel B (Printer Port) Data */
- pChan = &channel[1];
-
- if (pChan->txEnable)
- {
- pChan->txData = data;
- // local loopback?
- if (pChan->reg_val[14] & 0x10)
- {
- pChan->rxData = data;
- pChan->reg_val[0] |= 0x01; // Rx character available
- }
- pChan->reg_val[1] |= 0x01; // All sent
- pChan->reg_val[0] |= 0x04; // Tx empty
- pChan->txUnderrun = 1;
- pChan->txIRQPending = 1;
- updateirqs();
- }
- break;
-
- case 3:
- /* Channel A (Modem Port) Data */
- pChan = &channel[0];
-
- if (pChan->txEnable)
+ case 2: /* Channel B (Printer Port) Data */
+ case 3: /* Channel A (Modem Port) Data */
+ {
+ int chan = ((offset == 2) ? 1 : 0);
+ if (channel[chan].txEnable)
{
- pChan->txData = data;
+ channel[chan].txData = data;
// local loopback?
- if (pChan->reg_val[14] & 0x10)
+ if (channel[chan].reg_val[14] & 0x10)
{
- pChan->rxData = data;
- pChan->reg_val[0] |= 0x01; // Rx character available
+ channel[chan].rxData = data;
+ channel[chan].reg_val[0] |= 0x01; // Rx character available
}
- pChan->reg_val[1] |= 0x01; // All sent
- pChan->reg_val[0] |= 0x04; // Tx empty
- pChan->txUnderrun = 1;
- pChan->txIRQPending = 1;
+ channel[chan].reg_val[1] |= 0x01; // All sent
+ channel[chan].reg_val[0] |= 0x04; // Tx empty
+ channel[chan].txUnderrun = 1;
+ channel[chan].txIRQPending = 1;
updateirqs();
}
break;
+ }
}
}
+
/*
AppleTalk check:
diff --git a/src/devices/machine/8530scc.h b/src/devices/machine/8530scc.h
index 2e6e703ceb8..b711f7cdabe 100644
--- a/src/devices/machine/8530scc.h
+++ b/src/devices/machine/8530scc.h
@@ -43,6 +43,9 @@ public:
DECLARE_READ8_MEMBER(reg_r);
DECLARE_WRITE8_MEMBER(reg_w);
+ void write_reg(int offset, UINT8 data);
+ UINT8 read_reg(int offset);
+
protected:
virtual void device_start() override;
virtual void device_reset() override;
diff --git a/src/mame/drivers/sun4.cpp b/src/mame/drivers/sun4.cpp
index e89fa616231..ceae4a5e568 100644
--- a/src/mame/drivers/sun4.cpp
+++ b/src/mame/drivers/sun4.cpp
@@ -387,6 +387,8 @@
#include "emu.h"
#include "cpu/sparc/sparc.h"
+#include "machine/z80scc.h"
+#include "bus/rs232/rs232.h"
#define ENA_NOTBOOT 0x80
#define ENA_SDVMA 0x20
@@ -394,6 +396,22 @@
#define ENA_RESET 0x04
#define ENA_DIAG 0x01
+#define SCC1_TAG "kbdmouse"
+#define SCC2_TAG "uart"
+#define RS232A_TAG "rs232a"
+#define RS232B_TAG "rs232b"
+
+#define ASI_SYSTEM_SPACE 2
+#define ASI_SEGMENT_MAP 3
+#define ASI_PAGE_MAP 4
+#define ASI_USER_INSN 8
+#define ASI_SUPER_INSN 9
+#define ASI_USER_DATA 10
+#define ASI_SUPER_DATA 11
+#define ASI_FLUSH_SEGMENT 12
+#define ASI_FLUSH_PAGE 13
+#define ASI_FLUSH_CONTEXT 14
+
class sun4_state : public driver_device
{
public:
@@ -401,7 +419,10 @@ public:
: driver_device(mconfig, type, tag)
, m_maincpu(*this, "maincpu")
, m_rom(*this, "user1")
+ , m_kbdmouse(*this, SCC1_TAG)
+ , m_uart(*this, SCC2_TAG)
, m_rom_ptr(nullptr)
+ , m_context(0)
, m_system_enable(0)
{
}
@@ -416,39 +437,172 @@ protected:
required_device<mb86901_device> m_maincpu;
required_memory_region m_rom;
+ required_device<z80scc_device> m_kbdmouse;
+ required_device<z80scc_device> m_uart;
+
+ UINT32 read_supervisor_data(UINT32 vaddr, UINT32 mem_mask);
+ void write_supervisor_data(UINT32 vaddr, UINT32 data, UINT32 mem_mask);
+
UINT32 *m_rom_ptr;
UINT32 m_context;
+ UINT16 m_segmap[8][4096];
+ UINT32 m_pagemap[8192];
UINT32 m_system_enable;
};
+#define SEGMENT(vaddr) m_segmap[m_context & 7][((vaddr) >> 18) & 0xfff]
+#define PAGE(vaddr) m_pagemap[((m_segmap[m_context & 7][((vaddr) >> 18) & 0xfff] & 0x7f) << 6) | (((vaddr) >> 12) & 0x3f)]
+#define PADDR(vaddr) (((PAGE(vaddr) << 12) & 0x0ffff000) | ((vaddr) & 0xfff))
+
+UINT32 sun4_state::read_supervisor_data(UINT32 vaddr, UINT32 mem_mask)
+{
+ UINT32 page = PAGE(vaddr);
+ bool v = (page & 0x80000000) ? true : false;
+ bool w = (page & 0x40000000) ? true : false;
+ bool s = (page & 0x20000000) ? true : false;
+ bool x = (page & 0x10000000) ? true : false;
+ int t = (page & 0x0c000000) >> 26;
+ bool a = (page & 0x02000000) ? true : false;
+ bool m = (page & 0x01000000) ? true : false;
+ char mode[4] = { 'M', 'S', '0', '1' };
+
+ logerror("supervisor data read: vaddr %08x, paddr %08x, context %d, segment entry %02x, page entry %08x, %c%c%c%c%c%c%c\n", vaddr, PADDR(vaddr), m_context, SEGMENT(vaddr), PAGE(vaddr)
+ , v ? 'V' : 'v', w ? 'W' : 'w', s ? 'S' : 's', x ? 'X' : 'x', mode[t], a ? 'A' : 'a', m ? 'M' : 'm');
+ return 0;
+}
+
+void sun4_state::write_supervisor_data(UINT32 vaddr, UINT32 data, UINT32 mem_mask)
+{
+ UINT32 page = PAGE(vaddr);
+ bool v = (page & 0x80000000) ? true : false;
+ bool w = (page & 0x40000000) ? true : false;
+ bool s = (page & 0x20000000) ? true : false;
+ bool x = (page & 0x10000000) ? true : false;
+ int t = (page & 0x0c000000) >> 26;
+ bool a = (page & 0x02000000) ? true : false;
+ bool m = (page & 0x01000000) ? true : false;
+ char mode[4] = { 'M', 'S', '0', '1' };
+
+ logerror("supervisor data write: vaddr %08x, paddr %08x, data %08x, mem_mask %08x, context %d, segment entry %02x, page entry %08x, %c%c%c%c%c%c%c\n", vaddr, PADDR(vaddr), data, mem_mask,
+ m_context, SEGMENT(vaddr), PAGE(vaddr), v ? 'V' : 'v', w ? 'W' : 'w', s ? 'S' : 's', x ? 'X' : 'x', mode[t], a ? 'A' : 'a', m ? 'M' : 'm');
+}
+
READ32_MEMBER( sun4_state::sun4_mmu_r )
{
UINT8 asi = m_maincpu->get_asi();
- if (asi == 2 && !space.debugger_access())
+ if (!space.debugger_access())
{
- switch (offset >> 26)
+ switch(asi)
{
- case 3: // context reg
- return m_context;
-
- case 4: // system enable reg
- return m_system_enable;
-
- case 6: // bus error register
- return 0;
-
- case 8: // (d-)cache tags
- logerror("sun4: read dcache tags @ %x, PC = %x\n", offset, m_maincpu->pc());
- return 0xffffffff;
+ case ASI_SYSTEM_SPACE:
+ switch (offset >> 26)
+ {
+ case 3: // context reg
+ logerror("sun4: read context register %08x (& %08x) asi 2, offset %x, PC = %x\n", m_context << 24, mem_mask, offset << 2, m_maincpu->pc());
+ return m_context << 24;
+
+ case 4: // system enable reg
+ logerror("sun4: read system enable register %08x (& %08x) asi 2, offset %x, PC = %x\n", m_system_enable << 24, mem_mask, offset << 2, m_maincpu->pc());
+ return m_system_enable << 24;
+
+ case 8: // (d-)cache tags
+ logerror("sun4: read dcache tags %08x (& %08x) asi 2, offset %x, PC = %x\n", 0xffffffff, mem_mask, offset << 2, m_maincpu->pc());
+ return 0xffffffff;
+
+ case 9: // (d-)cache data
+ logerror("sun4: read dcache data %08x (& %08x) asi 2, offset %x, PC = %x\n", 0xffffffff, mem_mask, offset << 2, m_maincpu->pc());
+ return 0xffffffff;
+
+ case 15: // Type 1 space passthrough
+ switch ((offset >> 22) & 15)
+ {
+ case 0: // keyboard/mouse
+ switch (offset & 1)
+ {
+ case 0:
+ {
+ UINT32 ret = 0;
+ if (mem_mask & 0xffff0000)
+ ret |= m_kbdmouse->cb_r(space, 0) << 24;
+ if (mem_mask & 0x0000ffff)
+ ret |= m_kbdmouse->db_r(space, 0) << 8;
+ return ret;
+ }
+ case 1:
+ {
+ UINT32 ret = 0;
+ if (mem_mask & 0xffff0000)
+ ret |= m_kbdmouse->ca_r(space, 0) << 24;
+ if (mem_mask & 0x0000ffff)
+ ret |= m_kbdmouse->da_r(space, 0) << 8;
+ return ret;
+ }
+ }
+ break;
+ case 1: // serial ports
+ switch (offset & 1)
+ {
+ case 0:
+ {
+ UINT32 ret = 0;
+ if (mem_mask & 0xffff0000)
+ ret |= m_uart->cb_r(space, 0) << 24;
+ if (mem_mask & 0x0000ffff)
+ ret |= m_uart->db_r(space, 0) << 8;
+ return ret;
+ }
+ case 1:
+ {
+ UINT32 ret = 0;
+ if (mem_mask & 0xffff0000)
+ ret |= m_uart->ca_r(space, 0) << 24;
+ if (mem_mask & 0x0000ffff)
+ ret |= m_uart->da_r(space, 0) << 8;
+ return ret;
+ }
+ }
+ break;
+
+ default:
+ logerror("sun4: read unknown type 1 space at address %x (& %08x) asi 2, offset %x, PC = %x\n", offset << 2, mem_mask, offset << 2, m_maincpu->pc());
+ }
+ break;
+
+ case 0: // IDPROM - TODO: SPARCstation-1 does not have an ID prom and a timeout should occur.
+ default:
+ logerror("sun4: read unknown register (& %08x) asi 2, offset %x, PC = %x\n", mem_mask, offset << 2, m_maincpu->pc());
+ return 0;
+ }
+ break;
+
+ case ASI_SEGMENT_MAP:
+ {
+ logerror("sun4: read m_segmap[%d][(%08x >> 18) & 0xfff = %03x] = %08x << 24 & %08x\n", m_context & 7, offset << 2, (offset >> 16) & 0xfff, SEGMENT(offset << 2), mem_mask);
+ UINT32 result = SEGMENT(offset << 2);
+ while (!(mem_mask & 1))
+ {
+ mem_mask >>= 1;
+ result <<= 1;
+ }
+ return result;
+ }
+
+ case ASI_PAGE_MAP: // page map
+ {
+ logerror("sun4: read m_pagemap[(m_segmap[%d][(%08x >> 18) & 0xfff = %03x] = %08x << 6) | ((%08x >> 12) & 0x3f)]] = %08x & %08x\n", m_context & 7, offset << 2, (offset >> 16) & 0xfff, SEGMENT(offset << 2), offset << 2, PAGE(offset << 2), mem_mask);
+ return PAGE(offset << 2);
+ }
+
+ case ASI_SUPER_INSN: // supervisor instruction space
+ return m_rom_ptr[offset & 0x1ffff]; // wrong, but works for now
+
+ case ASI_SUPER_DATA:
+ return read_supervisor_data(offset << 2, mem_mask);
- case 9: // (d-)cache data
- logerror("sun4: read dcache data @ %x, PC = %x\n", offset, m_maincpu->pc());
- return 0xffffffff;
-
- case 0: // IDPROM - TODO: SPARCstation-1 does not have an ID prom and a timeout should occur.
default:
- return 0;
+ logerror("sun4: read (& %08x) asi %d byte offset %x, PC = %x\n", mem_mask, asi, offset << 2, m_maincpu->pc());
+ break;
}
}
@@ -456,10 +610,6 @@ READ32_MEMBER( sun4_state::sun4_mmu_r )
{
return m_rom_ptr[offset & 0x1ffff];
}
- else if (asi < 8 || asi > 11)
- {
- logerror("sun4: read asi %d byte offset %x, PC = %x\n", asi, offset << 2, m_maincpu->pc());
- }
return 0;
}
@@ -468,34 +618,107 @@ WRITE32_MEMBER( sun4_state::sun4_mmu_w )
{
UINT8 asi = m_maincpu->get_asi();
- if (asi == 2)
+ switch (asi)
{
- switch (offset >> 26)
+ case 2:
+ switch (offset >> 26)
+ {
+ case 3: // context reg
+ logerror("sun4: %08x (& %08x) asi 2 to context register, offset %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
+ m_context = (UINT8)(data >> 24) & 7;
+ return;
+
+ case 4: // system enable reg
+ logerror("sun4: write %08x (& %08x) asi 2 to system enable register, offset %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
+ m_system_enable = (UINT8)data;
+ return;
+
+ case 8: // cache tags
+ logerror("sun4: write %08x (& %08x) asi 2 to cache tags @ %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
+ return;
+
+ case 9: // cache data
+ logerror("sun4: write %08x (& %08x) asi 2 to cache data @ %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
+ return;
+
+ case 15: // Type 1 space passthrough
+ switch ((offset >> 22) & 15)
+ {
+ case 0: // keyboard/mouse
+ switch (offset & 1)
+ {
+ case 0:
+ if (mem_mask & 0xffff0000)
+ m_kbdmouse->cb_w(space, 0, data >> 24);
+ if (mem_mask & 0x0000ffff)
+ m_kbdmouse->db_w(space, 0, data >> 24);
+ break;
+ case 1:
+ if (mem_mask & 0xffff0000)
+ m_kbdmouse->ca_w(space, 0, data >> 24);
+ if (mem_mask & 0x0000ffff)
+ m_kbdmouse->da_w(space, 0, data >> 24);
+ break;
+ }
+ break;
+ case 1: // serial ports
+ switch (offset & 1)
+ {
+ case 0:
+ if (mem_mask & 0xffff0000)
+ m_uart->cb_w(space, 0, data >> 24);
+ if (mem_mask & 0x0000ffff)
+ m_uart->db_w(space, 0, data >> 24);
+ break;
+ case 1:
+ if (mem_mask & 0xffff0000)
+ m_uart->ca_w(space, 0, data >> 24);
+ if (mem_mask & 0x0000ffff)
+ m_uart->da_w(space, 0, data >> 24);
+ break;
+ }
+ break;
+ default:
+ logerror("sun4: write unknown type 1 space %08x (& %08x) asi 2, offset %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
+ }
+ break;
+
+ case 0: // IDPROM
+ default:
+ logerror("sun4: write %08x (& %08x) asi 2 to unknown register, offset %x, PC = %x\n", data, mem_mask, offset << 2, m_maincpu->pc());
+ return;
+ }
+ break;
+
+ case 3: // segment map
+ offset <<= 2;
+ while (!(mem_mask & 1))
+ {
+ mem_mask >>= 1;
+ data >>= 1;
+ }
+ SEGMENT(offset) = data;
+ //m_segmap[m_context & 7][(offset >> 18) & 0xfff] &= ~(mem_mask >> 16);
+ //m_segmap[m_context & 7][(offset >> 18) & 0xfff] |= (data >> 16) & (mem_mask >> 16);
+ logerror("sun4: write m_segmap[%d][(%08x >> 18) & 0xfff = %03x] = %08x & %08x\n", m_context & 7, offset << 2, (offset >> 16) & 0xfff, data, mem_mask);
+ break;
+
+ case ASI_PAGE_MAP: // page map
{
- case 3: // context reg
- m_context = (UINT8)data;
- return;
-
- case 4: // system enable reg
- m_system_enable = (UINT8)data;
- return;
-
- case 8: // cache tags
- logerror("sun4: %08x to cache tags @ %x, PC = %x\n", data, offset, m_maincpu->pc());
- return;
+ logerror("sun4: write m_pagemap[(m_segmap[%d][(%08x >> 18) & 0xfff = %03x] = %08x << 6) | ((%08x >> 12) & 0x3f)]] = %08x & %08x\n", m_context & 7, offset << 2,
+ (offset >> 16) & 0xfff, SEGMENT(offset << 2), offset << 2, data, mem_mask);
+ COMBINE_DATA(&PAGE(offset << 2));
+ PAGE(offset << 2) &= 0xff00ffff;
+ break;
+ }
- case 9: // cache data
- logerror("sun4: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc());
- return;
+ case ASI_SUPER_DATA:
+ write_supervisor_data(offset << 2, data, mem_mask);
+ break;
- case 0: // IDPROM
- default:
- return;
- }
- }
- else if (asi < 8 || asi > 11)
- {
- logerror("sun4: %08x to asi %d byte offset %x, PC = %x\n", data, asi, offset << 2, m_maincpu->pc());
+ default:
+ logerror("sun4: write %08x (& %08x) to asi %d byte offset %x, PC = %x\n", data, mem_mask, asi, offset << 2, m_maincpu->pc());
+ break;
}
}
@@ -521,6 +744,21 @@ static MACHINE_CONFIG_START( sun4, sun4_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", MB86901, 16670000)
MCFG_DEVICE_ADDRESS_MAP(AS_PROGRAM, sun4_mem)
+
+ MCFG_SCC8530_ADD(SCC1_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
+ MCFG_SCC8530_ADD(SCC2_TAG, XTAL_4_9152MHz, 0, 0, 0, 0)
+ MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE(RS232A_TAG, rs232_port_device, write_txd))
+ MCFG_Z80SCC_OUT_TXDB_CB(DEVWRITELINE(RS232B_TAG, rs232_port_device, write_txd))
+
+ MCFG_RS232_PORT_ADD(RS232A_TAG, default_rs232_devices, nullptr)
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, rxa_w))
+ MCFG_RS232_DCD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, dcda_w))
+ MCFG_RS232_CTS_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, ctsa_w))
+
+ MCFG_RS232_PORT_ADD(RS232B_TAG, default_rs232_devices, nullptr)
+ MCFG_RS232_RXD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, rxb_w))
+ MCFG_RS232_DCD_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, dcdb_w))
+ MCFG_RS232_CTS_HANDLER(DEVWRITELINE(SCC2_TAG, z80scc_device, ctsb_w))
MACHINE_CONFIG_END
/*