mirror of
https://github.com/holub/mame
synced 2025-07-02 08:39:21 +03:00
Checkpoint
This commit is contained in:
parent
1905f52ac8
commit
ad030cc4f4
@ -165,6 +165,12 @@ void mb86901_device::device_stop()
|
|||||||
|
|
||||||
void mb86901_device::device_reset()
|
void mb86901_device::device_reset()
|
||||||
{
|
{
|
||||||
|
m_queued_tt = 0;
|
||||||
|
m_queued_priority = 0;
|
||||||
|
m_asi = 0;
|
||||||
|
MAE = false;
|
||||||
|
HOLD_BUS = false;
|
||||||
|
|
||||||
PC = 0;
|
PC = 0;
|
||||||
nPC = 4;
|
nPC = 4;
|
||||||
memset(m_r, 0, sizeof(UINT32) * 120);
|
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);
|
bool v = ((arg1 & 0x80000000) == (arg2 & 0x80000000) && (arg2 & 0x80000000) != (result & 0x80000000)) || ((arg1 & 3) != 0) || ((arg2 & 3) != 0);
|
||||||
if (v)
|
if (v)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_tag_overflow);
|
trap(SPARC_TAG_OVERFLOW);
|
||||||
}
|
}
|
||||||
else
|
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);
|
bool v = ((arg1 & 0x80000000) == (arg2 & 0x80000000) && (arg2 & 0x80000000) != (result & 0x80000000)) || ((arg1 & 3) != 0) || ((arg2 & 3) != 0);
|
||||||
if (v)
|
if (v)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_tag_overflow);
|
trap(SPARC_TAG_OVERFLOW);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -795,7 +801,7 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
case 41: // rd psr
|
case 41: // rd psr
|
||||||
if (IS_USER)
|
if (IS_USER)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_privileged_instruction);
|
trap(SPARC_PRIVILEGED_INSTRUCTION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -805,7 +811,7 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
case 42: // rd wim
|
case 42: // rd wim
|
||||||
if (IS_USER)
|
if (IS_USER)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_privileged_instruction);
|
trap(SPARC_PRIVILEGED_INSTRUCTION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -815,7 +821,7 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
case 43: // rd tbr
|
case 43: // rd tbr
|
||||||
if (IS_USER)
|
if (IS_USER)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_privileged_instruction);
|
trap(SPARC_PRIVILEGED_INSTRUCTION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -837,14 +843,14 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
case 49: // wr psr
|
case 49: // wr psr
|
||||||
if (IS_USER)
|
if (IS_USER)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_privileged_instruction);
|
trap(SPARC_PRIVILEGED_INSTRUCTION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UINT32 new_psr = (arg1 ^ arg2) & ~PSR_ZERO_MASK;
|
UINT32 new_psr = (arg1 ^ arg2) & ~PSR_ZERO_MASK;
|
||||||
if ((new_psr & PSR_CWP_MASK) >= WINDOW_COUNT)
|
if ((new_psr & PSR_CWP_MASK) >= WINDOW_COUNT)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_illegal_instruction);
|
trap(SPARC_ILLEGAL_INSTRUCTION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -856,7 +862,7 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
case 50: // wr wim
|
case 50: // wr wim
|
||||||
if (IS_USER)
|
if (IS_USER)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_privileged_instruction);
|
trap(SPARC_PRIVILEGED_INSTRUCTION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -866,7 +872,7 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
case 51: // wr tbr
|
case 51: // wr tbr
|
||||||
if (IS_USER)
|
if (IS_USER)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_privileged_instruction);
|
trap(SPARC_PRIVILEGED_INSTRUCTION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -876,13 +882,13 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
case 52: // FPop1
|
case 52: // FPop1
|
||||||
if (FPU_DISABLED)
|
if (FPU_DISABLED)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_floating_point_disabled);
|
trap(SPARC_FLOATING_POINT_DISABLED);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 53: // FPop2
|
case 53: // FPop2
|
||||||
if (FPU_DISABLED)
|
if (FPU_DISABLED)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_floating_point_disabled);
|
trap(SPARC_FLOATING_POINT_DISABLED);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 56: // jmpl
|
case 56: // jmpl
|
||||||
@ -891,7 +897,7 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
m_icount--;
|
m_icount--;
|
||||||
if (addr & 3)
|
if (addr & 3)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_mem_address_not_aligned);
|
trap(SPARC_MEM_ADDRESS_NOT_ALIGNED);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -909,11 +915,11 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
{
|
{
|
||||||
if (IS_USER)
|
if (IS_USER)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_privileged_instruction);
|
trap(SPARC_PRIVILEGED_INSTRUCTION);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
queue_trap(sparc_illegal_instruction);
|
trap(SPARC_ILLEGAL_INSTRUCTION);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -921,17 +927,17 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
{
|
{
|
||||||
if (IS_USER)
|
if (IS_USER)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_reset, sparc_privileged_instruction);
|
trap(SPARC_RESET, SPARC_PRIVILEGED_INSTRUCTION);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (m_wim & (1 << new_cwp))
|
else if (m_wim & (1 << new_cwp))
|
||||||
{
|
{
|
||||||
queue_trap(sparc_reset, sparc_window_underflow);
|
trap(SPARC_RESET, SPARC_WINDOW_UNDERFLOW);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (ADDRESS & 3)
|
else if (ADDRESS & 3)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_reset, sparc_mem_address_not_aligned);
|
trap(SPARC_RESET, SPARC_MEM_ADDRESS_NOT_ALIGNED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -963,7 +969,7 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
UINT8 new_cwp = ((m_cwp + WINDOW_COUNT) - 1) % WINDOW_COUNT;
|
UINT8 new_cwp = ((m_cwp + WINDOW_COUNT) - 1) % WINDOW_COUNT;
|
||||||
if (m_wim & (1 << new_cwp))
|
if (m_wim & (1 << new_cwp))
|
||||||
{
|
{
|
||||||
queue_trap(sparc_window_overflow);
|
trap(SPARC_WINDOW_OVERFLOW);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -976,7 +982,7 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
UINT8 new_cwp = (m_cwp + 1) % WINDOW_COUNT;
|
UINT8 new_cwp = (m_cwp + 1) % WINDOW_COUNT;
|
||||||
if (m_wim & (1 << new_cwp))
|
if (m_wim & (1 << new_cwp))
|
||||||
{
|
{
|
||||||
queue_trap(sparc_window_overflow);
|
trap(SPARC_WINDOW_UNDERFLOW);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -985,7 +991,7 @@ bool mb86901_device::execute_group2(UINT32 op)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
queue_trap(sparc_illegal_instruction);
|
trap(SPARC_ILLEGAL_INSTRUCTION);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1014,17 +1020,17 @@ bool mb86901_device::check_main_traps(UINT32 op, bool privileged, UINT32 alignme
|
|||||||
bool trap_queued = false;
|
bool trap_queued = false;
|
||||||
if (privileged && !m_s)
|
if (privileged && !m_s)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_privileged_instruction);
|
trap(SPARC_PRIVILEGED_INSTRUCTION);
|
||||||
trap_queued = true;
|
trap_queued = true;
|
||||||
}
|
}
|
||||||
if (alignment & ADDRESS)
|
if (alignment & ADDRESS)
|
||||||
{
|
{
|
||||||
queue_trap(sparc_mem_address_not_aligned);
|
trap(SPARC_MEM_ADDRESS_NOT_ALIGNED);
|
||||||
trap_queued = true;
|
trap_queued = true;
|
||||||
}
|
}
|
||||||
if ((registeralign & RD) || (noimmediate && USEIMM))
|
if ((registeralign & RD) || (noimmediate && USEIMM))
|
||||||
{
|
{
|
||||||
queue_trap(sparc_illegal_instruction);
|
trap(SPARC_ILLEGAL_INSTRUCTION);
|
||||||
trap_queued = true;
|
trap_queued = true;
|
||||||
}
|
}
|
||||||
return trap_queued;
|
return trap_queued;
|
||||||
@ -1051,21 +1057,44 @@ void mb86901_device::execute_group3(UINT32 op)
|
|||||||
switch (OP3)
|
switch (OP3)
|
||||||
{
|
{
|
||||||
case 0: // ld
|
case 0: // ld
|
||||||
|
{
|
||||||
check_main_traps(op, false, 3, 0, false);
|
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;
|
break;
|
||||||
|
}
|
||||||
case 1: // ldub
|
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;
|
break;
|
||||||
|
}
|
||||||
case 2: // lduh
|
case 2: // lduh
|
||||||
|
{
|
||||||
check_main_traps(op, false, 1, 0, false);
|
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;
|
break;
|
||||||
|
}
|
||||||
case 3: // ldd
|
case 3: // ldd
|
||||||
|
{
|
||||||
check_main_traps(op, false, 7, 1, false);
|
check_main_traps(op, false, 7, 1, false);
|
||||||
SET_RDREG(read_word(m_data_asi, ADDRESS));
|
UINT32 result = read_word(m_data_asi, ADDRESS);
|
||||||
REG(RD+1) = read_word(m_data_asi, ADDRESS+4);
|
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;
|
break;
|
||||||
|
}
|
||||||
case 4: // st
|
case 4: // st
|
||||||
check_main_traps(op, false, 3, 0, false);
|
check_main_traps(op, false, 3, 0, false);
|
||||||
write_word(m_data_asi, ADDRESS, RDREG);
|
write_word(m_data_asi, ADDRESS, RDREG);
|
||||||
@ -1080,38 +1109,78 @@ void mb86901_device::execute_group3(UINT32 op)
|
|||||||
case 7: // std
|
case 7: // std
|
||||||
check_main_traps(op, false, 7, 1, false);
|
check_main_traps(op, false, 7, 1, false);
|
||||||
write_word(m_data_asi, ADDRESS, RDREG);
|
write_word(m_data_asi, ADDRESS, RDREG);
|
||||||
|
if (MAE || HOLD_BUS)
|
||||||
|
break;
|
||||||
write_word(m_data_asi, ADDRESS, REG(RD+1));
|
write_word(m_data_asi, ADDRESS, REG(RD+1));
|
||||||
break;
|
break;
|
||||||
case 9: // ldsb
|
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;
|
break;
|
||||||
|
}
|
||||||
case 10: // lsdh
|
case 10: // lsdh
|
||||||
|
{
|
||||||
check_main_traps(op, false, 1, 0, false);
|
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;
|
break;
|
||||||
|
}
|
||||||
case 13: // ldstub
|
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);
|
write_byte(m_data_asi, ADDRESS, 0xff);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 15: // swap, SPARCv8
|
case 15: // swap, SPARCv8
|
||||||
break;
|
break;
|
||||||
case 16: // lda
|
case 16: // lda
|
||||||
|
{
|
||||||
check_main_traps(op, true, 3, 0, true);
|
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;
|
break;
|
||||||
|
}
|
||||||
case 17: // lduba
|
case 17: // lduba
|
||||||
|
{
|
||||||
check_main_traps(op, true, 0, 0, true);
|
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;
|
break;
|
||||||
|
}
|
||||||
case 18: // lduha
|
case 18: // lduha
|
||||||
|
{
|
||||||
check_main_traps(op, true, 1, 0, true);
|
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;
|
break;
|
||||||
|
}
|
||||||
case 19: // ldda
|
case 19: // ldda
|
||||||
|
{
|
||||||
check_main_traps(op, true, 7, 1, true);
|
check_main_traps(op, true, 7, 1, true);
|
||||||
SET_RDREG(read_word(ASI, ADDRESS));
|
UINT32 result = read_word(ASI, ADDRESS);
|
||||||
REG(RD+1) = read_word(ASI, ADDRESS+4);
|
if (MAE || HOLD_BUS)
|
||||||
|
break;
|
||||||
|
SET_RDREG(result);
|
||||||
|
result = read_word(ASI, ADDRESS+4);
|
||||||
|
if (MAE || HOLD_BUS)
|
||||||
|
break;
|
||||||
|
REG(RD+1) = result;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 20: // sta
|
case 20: // sta
|
||||||
check_main_traps(op, true, 3, 0, true);
|
check_main_traps(op, true, 3, 0, true);
|
||||||
write_word(ASI, ADDRESS, RDREG);
|
write_word(ASI, ADDRESS, RDREG);
|
||||||
@ -1127,36 +1196,67 @@ void mb86901_device::execute_group3(UINT32 op)
|
|||||||
case 23: // stda
|
case 23: // stda
|
||||||
check_main_traps(op, true, 7, 1, true);
|
check_main_traps(op, true, 7, 1, true);
|
||||||
write_word(ASI, ADDRESS, RDREG);
|
write_word(ASI, ADDRESS, RDREG);
|
||||||
|
if (MAE || HOLD_BUS)
|
||||||
|
break;
|
||||||
write_word(ASI, ADDRESS+4, REG(RD+1));
|
write_word(ASI, ADDRESS+4, REG(RD+1));
|
||||||
break;
|
break;
|
||||||
case 25: // ldsba
|
case 25: // ldsba
|
||||||
|
{
|
||||||
check_main_traps(op, true, 0, 0, true);
|
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;
|
break;
|
||||||
|
}
|
||||||
case 26: // ldsha
|
case 26: // ldsha
|
||||||
|
{
|
||||||
check_main_traps(op, true, 1, 0, true);
|
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;
|
break;
|
||||||
|
}
|
||||||
case 29: // ldstuba
|
case 29: // ldstuba
|
||||||
|
{
|
||||||
check_main_traps(op, true, 0, 0, true);
|
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);
|
write_byte(ASI, ADDRESS, 0xff);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 31: // swapa, SPARCv8
|
case 31: // swapa, SPARCv8
|
||||||
break;
|
break;
|
||||||
case 32: // ld fpr
|
case 32: // ld fpr
|
||||||
|
if (FPU_DISABLED)
|
||||||
|
trap(SPARC_FLOATING_POINT_DISABLED);
|
||||||
break;
|
break;
|
||||||
case 33: // ld fsr
|
case 33: // ld fsr
|
||||||
|
if (FPU_DISABLED)
|
||||||
|
trap(SPARC_FLOATING_POINT_DISABLED);
|
||||||
break;
|
break;
|
||||||
case 35: // ldd fpr
|
case 35: // ldd fpr
|
||||||
|
if (FPU_DISABLED)
|
||||||
|
trap(SPARC_FLOATING_POINT_DISABLED);
|
||||||
break;
|
break;
|
||||||
case 36: // st fpr
|
case 36: // st fpr
|
||||||
|
if (FPU_DISABLED)
|
||||||
|
trap(SPARC_FLOATING_POINT_DISABLED);
|
||||||
break;
|
break;
|
||||||
case 37: // st fsr
|
case 37: // st fsr
|
||||||
|
if (FPU_DISABLED)
|
||||||
|
trap(SPARC_FLOATING_POINT_DISABLED);
|
||||||
break;
|
break;
|
||||||
case 38: // std fq, SPARCv8
|
case 38: // std fq, SPARCv8
|
||||||
|
if (FPU_DISABLED)
|
||||||
|
trap(SPARC_FLOATING_POINT_DISABLED);
|
||||||
break;
|
break;
|
||||||
case 39: // std fpr
|
case 39: // std fpr
|
||||||
|
if (FPU_DISABLED)
|
||||||
|
trap(SPARC_FLOATING_POINT_DISABLED);
|
||||||
break;
|
break;
|
||||||
case 40: // ld cpr, SPARCv8
|
case 40: // ld cpr, SPARCv8
|
||||||
break;
|
break;
|
||||||
@ -1174,7 +1274,10 @@ void mb86901_device::execute_group3(UINT32 op)
|
|||||||
break;
|
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;
|
UINT32 arg2 = USEIMM ? SIMM7 : RS2REG;
|
||||||
UINT8 tt = 128 + ((RS1REG + arg2) & 0x7f);
|
UINT8 tt = 128 + ((RS1REG + arg2) & 0x7f);
|
||||||
queue_trap(sparc_trap_instruction, tt);
|
trap(SPARC_TRAP_INSTRUCTION, tt);
|
||||||
m_icount -= 3;
|
m_icount -= 3;
|
||||||
return false;
|
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
|
// 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_priority = m_trap_priorities[0];
|
||||||
m_queued_tt = tt_override;
|
m_queued_tt = tt_override;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (type == sparc_trap_instruction)
|
if (type == SPARC_TRAP_INSTRUCTION)
|
||||||
{
|
{
|
||||||
type = tt_override;
|
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)
|
if (m_trap_priorities[type] < m_queued_priority)
|
||||||
{
|
{
|
||||||
m_queued_priority = m_trap_priorities[type];
|
m_queued_priority = m_trap_priorities[type];
|
||||||
@ -1302,6 +1413,7 @@ bool mb86901_device::invoke_queued_traps()
|
|||||||
if (m_queued_priority > 0)
|
if (m_queued_priority > 0)
|
||||||
{
|
{
|
||||||
m_queued_priority = 0;
|
m_queued_priority = 0;
|
||||||
|
m_queued_tt = 0;
|
||||||
|
|
||||||
m_et = false;
|
m_et = false;
|
||||||
m_ps = m_s;
|
m_ps = m_s;
|
||||||
@ -1336,8 +1448,20 @@ void mb86901_device::execute_run()
|
|||||||
|
|
||||||
while (m_icount > 0)
|
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);
|
debugger_instruction_hook(this, m_pc);
|
||||||
|
|
||||||
|
if (HOLD_BUS)
|
||||||
|
{
|
||||||
|
m_icount--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
UINT32 op = GET_OPCODE;
|
UINT32 op = GET_OPCODE;
|
||||||
|
|
||||||
bool update_npc = true;
|
bool update_npc = true;
|
||||||
@ -1390,7 +1514,7 @@ void mb86901_device::execute_run()
|
|||||||
REG(0) = 0;
|
REG(0) = 0;
|
||||||
|
|
||||||
bool trap_taken = invoke_queued_traps();
|
bool trap_taken = invoke_queued_traps();
|
||||||
if (!trap_taken && update_npc)
|
if (!trap_taken && update_npc && !HOLD_BUS)
|
||||||
{
|
{
|
||||||
PC = nPC;
|
PC = nPC;
|
||||||
nPC = PC + 4;
|
nPC = PC + 4;
|
||||||
|
@ -9,6 +9,34 @@
|
|||||||
#ifndef __SPARC_H__
|
#ifndef __SPARC_H__
|
||||||
#define __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
|
class mb86901_device : public cpu_device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -40,8 +68,12 @@ public:
|
|||||||
UINT8 get_asi() { return m_asi; }
|
UINT8 get_asi() { return m_asi; }
|
||||||
UINT32 pc() { return m_pc; }
|
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:
|
protected:
|
||||||
void queue_trap(UINT8 type, UINT8 tt_override = 0);
|
|
||||||
bool invoke_queued_traps();
|
bool invoke_queued_traps();
|
||||||
bool check_main_traps(UINT32 op, bool privileged, UINT32 alignment, UINT8 registeralign, bool noimmediate);
|
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_trap_priorities[256];
|
||||||
UINT8 m_queued_tt;
|
UINT8 m_queued_tt;
|
||||||
UINT8 m_queued_priority;
|
UINT8 m_queued_priority;
|
||||||
|
bool m_mae;
|
||||||
|
bool m_hold_bus;
|
||||||
int m_icount;
|
int m_icount;
|
||||||
|
|
||||||
// debugger helpers
|
// debugger helpers
|
||||||
|
@ -114,35 +114,9 @@
|
|||||||
|
|
||||||
#define Y m_y
|
#define Y m_y
|
||||||
|
|
||||||
enum sparc_trap_type
|
#define ET m_et
|
||||||
{
|
#define PIL m_pil
|
||||||
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 MAE m_mae
|
||||||
|
#define HOLD_BUS m_hold_bus
|
||||||
#endif // __MB86901_DEFS_H__
|
#endif // __MB86901_DEFS_H__
|
@ -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)
|
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)
|
switch(offset)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0: /* Channel B (Printer Port) Control */
|
||||||
/* Channel B (Printer Port) Control */
|
case 1: /* Channel A (Modem Port) Control */
|
||||||
|
|
||||||
if (mode == 1)
|
if (mode == 1)
|
||||||
mode = 0;
|
mode = 0;
|
||||||
else
|
else
|
||||||
reg = 0;
|
reg = 0;
|
||||||
|
|
||||||
result = getbreg();
|
result = (offset == 0) ? getbreg(); : getareg()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 2: /* Channel B (Printer Port) Data */
|
||||||
/* Channel A (Modem Port) Control */
|
case 3:/* Channel A (Modem Port) Data */
|
||||||
if (mode == 1)
|
result = channel[offset == 2 ? 1 : 0].rxData;
|
||||||
mode = 0;
|
|
||||||
else
|
|
||||||
reg = 0;
|
|
||||||
|
|
||||||
result = getareg();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
/* Channel B (Printer Port) Data */
|
|
||||||
result = channel[1].rxData;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
/* Channel A (Modem Port) Data */
|
|
||||||
result = channel[0].rxData;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
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 )
|
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);
|
// printf(" mode %d data %x offset %d \n", mode, data, offset);
|
||||||
|
|
||||||
|
Chan *pChan;
|
||||||
switch(offset)
|
switch(offset)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0: /* Channel B (Printer Port) Control */
|
||||||
/* Channel B (Printer Port) Control */
|
case 1: /* Channel A (Modem Port) Control */
|
||||||
|
{
|
||||||
|
int chan = ((offset == 2) ? 1 : 0);
|
||||||
if (mode == 0)
|
if (mode == 0)
|
||||||
{
|
{
|
||||||
if((data & 0xf0) == 0) // not a reset command
|
if((data & 0xf0) == 0) // not a reset command
|
||||||
{
|
{
|
||||||
mode = 1;
|
mode = 1;
|
||||||
reg = data & 0x0f;
|
reg = data & 0x0f;
|
||||||
// putbreg(data & 0xf0);
|
// putbreg(data & 0xf0);
|
||||||
}
|
}
|
||||||
else if (data == 0x10)
|
else if (data == 0x10)
|
||||||
{
|
{
|
||||||
pChan = &channel[1];
|
|
||||||
// clear ext. interrupts
|
// clear ext. interrupts
|
||||||
pChan->extIRQPending = 0;
|
channel[chan].extIRQPending = 0;
|
||||||
pChan->baudIRQPending = 0;
|
channel[chan].baudIRQPending = 0;
|
||||||
updateirqs();
|
updateirqs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mode = 0;
|
mode = 0;
|
||||||
putreg(1, data);
|
putreg(chan, data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 1:
|
case 2: /* Channel B (Printer Port) Data */
|
||||||
/* Channel A (Modem Port) Control */
|
case 3: /* Channel A (Modem Port) Data */
|
||||||
if (mode == 0)
|
{
|
||||||
|
int chan = ((offset == 2) ? 1 : 0);
|
||||||
|
if (channel[chan].txEnable)
|
||||||
{
|
{
|
||||||
if((data & 0xf0) == 0) // not a reset command
|
channel[chan].txData = data;
|
||||||
{
|
|
||||||
mode = 1;
|
|
||||||
reg = data & 0x0f;
|
|
||||||
// putareg(data & 0xf0);
|
|
||||||
}
|
|
||||||
else if (data == 0x10)
|
|
||||||
{
|
|
||||||
pChan = &channel[0];
|
|
||||||
// clear ext. interrupts
|
|
||||||
pChan->extIRQPending = 0;
|
|
||||||
pChan->baudIRQPending = 0;
|
|
||||||
updateirqs();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mode = 0;
|
|
||||||
putreg(0, data);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
/* Channel B (Printer Port) Data */
|
|
||||||
pChan = &channel[1];
|
|
||||||
|
|
||||||
if (pChan->txEnable)
|
|
||||||
{
|
|
||||||
pChan->txData = data;
|
|
||||||
// local loopback?
|
// local loopback?
|
||||||
if (pChan->reg_val[14] & 0x10)
|
if (channel[chan].reg_val[14] & 0x10)
|
||||||
{
|
{
|
||||||
pChan->rxData = data;
|
channel[chan].rxData = data;
|
||||||
pChan->reg_val[0] |= 0x01; // Rx character available
|
channel[chan].reg_val[0] |= 0x01; // Rx character available
|
||||||
}
|
}
|
||||||
pChan->reg_val[1] |= 0x01; // All sent
|
channel[chan].reg_val[1] |= 0x01; // All sent
|
||||||
pChan->reg_val[0] |= 0x04; // Tx empty
|
channel[chan].reg_val[0] |= 0x04; // Tx empty
|
||||||
pChan->txUnderrun = 1;
|
channel[chan].txUnderrun = 1;
|
||||||
pChan->txIRQPending = 1;
|
channel[chan].txIRQPending = 1;
|
||||||
updateirqs();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
/* Channel A (Modem Port) Data */
|
|
||||||
pChan = &channel[0];
|
|
||||||
|
|
||||||
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();
|
updateirqs();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
AppleTalk check:
|
AppleTalk check:
|
||||||
|
@ -43,6 +43,9 @@ public:
|
|||||||
DECLARE_READ8_MEMBER(reg_r);
|
DECLARE_READ8_MEMBER(reg_r);
|
||||||
DECLARE_WRITE8_MEMBER(reg_w);
|
DECLARE_WRITE8_MEMBER(reg_w);
|
||||||
|
|
||||||
|
void write_reg(int offset, UINT8 data);
|
||||||
|
UINT8 read_reg(int offset);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void device_start() override;
|
virtual void device_start() override;
|
||||||
virtual void device_reset() override;
|
virtual void device_reset() override;
|
||||||
|
@ -387,6 +387,8 @@
|
|||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "cpu/sparc/sparc.h"
|
#include "cpu/sparc/sparc.h"
|
||||||
|
#include "machine/z80scc.h"
|
||||||
|
#include "bus/rs232/rs232.h"
|
||||||
|
|
||||||
#define ENA_NOTBOOT 0x80
|
#define ENA_NOTBOOT 0x80
|
||||||
#define ENA_SDVMA 0x20
|
#define ENA_SDVMA 0x20
|
||||||
@ -394,6 +396,22 @@
|
|||||||
#define ENA_RESET 0x04
|
#define ENA_RESET 0x04
|
||||||
#define ENA_DIAG 0x01
|
#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
|
class sun4_state : public driver_device
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -401,7 +419,10 @@ public:
|
|||||||
: driver_device(mconfig, type, tag)
|
: driver_device(mconfig, type, tag)
|
||||||
, m_maincpu(*this, "maincpu")
|
, m_maincpu(*this, "maincpu")
|
||||||
, m_rom(*this, "user1")
|
, m_rom(*this, "user1")
|
||||||
|
, m_kbdmouse(*this, SCC1_TAG)
|
||||||
|
, m_uart(*this, SCC2_TAG)
|
||||||
, m_rom_ptr(nullptr)
|
, m_rom_ptr(nullptr)
|
||||||
|
, m_context(0)
|
||||||
, m_system_enable(0)
|
, m_system_enable(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -416,39 +437,172 @@ protected:
|
|||||||
|
|
||||||
required_device<mb86901_device> m_maincpu;
|
required_device<mb86901_device> m_maincpu;
|
||||||
required_memory_region m_rom;
|
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_rom_ptr;
|
||||||
UINT32 m_context;
|
UINT32 m_context;
|
||||||
|
UINT16 m_segmap[8][4096];
|
||||||
|
UINT32 m_pagemap[8192];
|
||||||
UINT32 m_system_enable;
|
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 )
|
READ32_MEMBER( sun4_state::sun4_mmu_r )
|
||||||
{
|
{
|
||||||
UINT8 asi = m_maincpu->get_asi();
|
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
|
case ASI_SYSTEM_SPACE:
|
||||||
return m_context;
|
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
|
case 4: // system enable reg
|
||||||
return m_system_enable;
|
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 6: // bus error register
|
case 8: // (d-)cache tags
|
||||||
return 0;
|
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 8: // (d-)cache tags
|
case 9: // (d-)cache data
|
||||||
logerror("sun4: read dcache tags @ %x, PC = %x\n", offset, m_maincpu->pc());
|
logerror("sun4: read dcache data %08x (& %08x) asi 2, offset %x, PC = %x\n", 0xffffffff, mem_mask, offset << 2, m_maincpu->pc());
|
||||||
return 0xffffffff;
|
return 0xffffffff;
|
||||||
|
|
||||||
case 9: // (d-)cache data
|
case 15: // Type 1 space passthrough
|
||||||
logerror("sun4: read dcache data @ %x, PC = %x\n", offset, m_maincpu->pc());
|
switch ((offset >> 22) & 15)
|
||||||
return 0xffffffff;
|
{
|
||||||
|
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 0: // IDPROM - TODO: SPARCstation-1 does not have an ID prom and a timeout should occur.
|
|
||||||
default:
|
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];
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -468,34 +618,107 @@ WRITE32_MEMBER( sun4_state::sun4_mmu_w )
|
|||||||
{
|
{
|
||||||
UINT8 asi = m_maincpu->get_asi();
|
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
|
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,
|
||||||
m_context = (UINT8)data;
|
(offset >> 16) & 0xfff, SEGMENT(offset << 2), offset << 2, data, mem_mask);
|
||||||
return;
|
COMBINE_DATA(&PAGE(offset << 2));
|
||||||
|
PAGE(offset << 2) &= 0xff00ffff;
|
||||||
case 4: // system enable reg
|
break;
|
||||||
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;
|
|
||||||
|
|
||||||
case 9: // cache data
|
|
||||||
logerror("sun4: %08x to cache data @ %x, PC = %x\n", data, offset, m_maincpu->pc());
|
|
||||||
return;
|
|
||||||
|
|
||||||
case 0: // IDPROM
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (asi < 8 || asi > 11)
|
case ASI_SUPER_DATA:
|
||||||
{
|
write_supervisor_data(offset << 2, data, mem_mask);
|
||||||
logerror("sun4: %08x to asi %d byte offset %x, PC = %x\n", data, asi, offset << 2, m_maincpu->pc());
|
break;
|
||||||
|
|
||||||
|
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 */
|
/* basic machine hardware */
|
||||||
MCFG_CPU_ADD("maincpu", MB86901, 16670000)
|
MCFG_CPU_ADD("maincpu", MB86901, 16670000)
|
||||||
MCFG_DEVICE_ADDRESS_MAP(AS_PROGRAM, sun4_mem)
|
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
|
MACHINE_CONFIG_END
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user