diff options
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 |
commit | ad030cc4f49180466ae0d702958b8e243ffdc041 (patch) | |
tree | 38e163365a4b0480cbbee299aad6ae1384641dc5 /src | |
parent | 1905f52ac827e90fa887e954a597b0233fccb5b3 (diff) |
Checkpoint
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/cpu/sparc/mb86901.cpp | 216 | ||||
-rw-r--r-- | src/devices/cpu/sparc/sparc.h | 36 | ||||
-rw-r--r-- | src/devices/cpu/sparc/sparcdefs.h | 34 | ||||
-rw-r--r-- | src/devices/machine/8530scc.cpp | 162 | ||||
-rw-r--r-- | src/devices/machine/8530scc.h | 3 | ||||
-rw-r--r-- | src/mame/drivers/sun4.cpp | 334 |
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 /* |