mirror of
https://github.com/holub/mame
synced 2025-07-01 16:19:38 +03:00
Merge pull request #990 from MooglyGuy/master
Convert SPARCv8 ops to document-described functionality [Ryan Holtz]
This commit is contained in:
commit
759275f61a
@ -2378,6 +2378,7 @@ end
|
||||
if (CPUS["MB86901"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/cpu/sparc/mb86901.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/sparc/sparcv8ops.ipp",
|
||||
MAME_DIR .. "src/devices/cpu/sparc/sparcdasm.h",
|
||||
MAME_DIR .. "src/devices/cpu/sparc/sparcdefs.h",
|
||||
MAME_DIR .. "src/devices/cpu/sparc/sparc.h",
|
||||
|
@ -22,8 +22,6 @@
|
||||
#include "sparc.h"
|
||||
#include "sparcdefs.h"
|
||||
|
||||
#define SPARCV8 (0)
|
||||
|
||||
const device_type MB86901 = &device_creator<mb86901_device>;
|
||||
|
||||
const int mb86901_device::NWINDOWS = 7;
|
||||
@ -510,6 +508,10 @@ void mb86901_device::execute_set_input(int inputnum, int state)
|
||||
}
|
||||
|
||||
|
||||
#if SPARCV8
|
||||
#include "sparcv8ops.ipp"
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute_add - execute an add-type opcode
|
||||
//-------------------------------------------------
|
||||
@ -541,16 +543,16 @@ void mb86901_device::execute_add(UINT32 op)
|
||||
UINT32 operand2 = USEIMM ? SIMM13 : RS2REG;
|
||||
|
||||
UINT32 result = 0;
|
||||
if (OP3 == 0 || OP3 == 16)
|
||||
if (ADD || ADDCC)
|
||||
result = RS1REG + operand2;
|
||||
else if (OP3 == 8 || OP3 == 24)
|
||||
else if (ADDX || ADDXCC)
|
||||
result = RS1REG + operand2 + ICC_C;
|
||||
|
||||
|
||||
if (RD != 0)
|
||||
RDREG = result;
|
||||
|
||||
if (OP3 & 16)
|
||||
if (ADDCC || ADDXCC)
|
||||
{
|
||||
CLEAR_ICC;
|
||||
PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
|
||||
@ -603,7 +605,7 @@ void mb86901_device::execute_taddcc(UINT32 op)
|
||||
(!BIT31(RS1REG) && !BIT31(operand2) && BIT31(result)) ||
|
||||
((RS1REG & 3) != 0 || (RS1REG & 3) != 0) ? true : false;
|
||||
|
||||
if (OP3 == 34 && temp_v)
|
||||
if (TADDCCTV && temp_v)
|
||||
{
|
||||
m_trap = 1;
|
||||
m_tag_overflow = true;
|
||||
@ -655,15 +657,15 @@ void mb86901_device::execute_sub(UINT32 op)
|
||||
UINT32 operand2 = USEIMM ? SIMM13 : RS2REG;
|
||||
|
||||
UINT32 result = 0;
|
||||
if (OP3 == 4 || OP3 == 20)
|
||||
if (SUB || SUBCC)
|
||||
result = RS1REG - operand2;
|
||||
else if (OP3 == 12 || OP3 == 28)
|
||||
else if (SUBX || SUBXCC)
|
||||
result = RS1REG - operand2 - ICC_C;
|
||||
|
||||
if (RD != 0)
|
||||
RDREG = result;
|
||||
|
||||
if (OP3 & 16)
|
||||
if (SUBCC || SUBXCC)
|
||||
{
|
||||
CLEAR_ICC;
|
||||
PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
|
||||
@ -717,7 +719,7 @@ void mb86901_device::execute_tsubcc(UINT32 op)
|
||||
(!BIT31(RS1REG) && BIT31(operand2) && BIT31(result)) ||
|
||||
((RS1REG & 3) != 0 || (RS1REG & 3) != 0) ? true : false;
|
||||
|
||||
if (OP3 == 35 && temp_v)
|
||||
if (TSUBCCTV && temp_v)
|
||||
{
|
||||
m_trap = 1;
|
||||
m_tag_overflow = 1;
|
||||
@ -771,31 +773,36 @@ void mb86901_device::execute_logical(UINT32 op)
|
||||
UINT32 result = 0;
|
||||
switch (OP3)
|
||||
{
|
||||
case 1:
|
||||
case 17:
|
||||
case OP3_AND:
|
||||
case OP3_ANDCC:
|
||||
result = RS1REG & operand2;
|
||||
break;
|
||||
case 5:
|
||||
case 21:
|
||||
case OP3_ANDN:
|
||||
case OP3_ANDNCC:
|
||||
result = RS1REG & ~operand2;
|
||||
break;
|
||||
case 2: case 18:
|
||||
case OP3_OR:
|
||||
case OP3_ORCC:
|
||||
result = RS1REG | operand2;
|
||||
break;
|
||||
case 6: case 22:
|
||||
case OP3_ORN:
|
||||
case OP3_ORNCC:
|
||||
result = RS1REG | ~operand2;
|
||||
break;
|
||||
case 3: case 19:
|
||||
case OP3_XOR:
|
||||
case OP3_XORCC:
|
||||
result = RS1REG ^ operand2;
|
||||
break;
|
||||
case 7: case 23:
|
||||
case OP3_XNOR:
|
||||
case OP3_XNORCC:
|
||||
result = RS1REG ^ ~operand2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (RD != 0) RDREG = result;
|
||||
if (RD != 0)
|
||||
RDREG = result;
|
||||
|
||||
if (OP3 & 16)
|
||||
if (ANDCC || ANDNCC || ORCC || ORNCC || XORCC || XNORCC)
|
||||
{
|
||||
CLEAR_ICC;
|
||||
PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
|
||||
@ -824,11 +831,11 @@ void mb86901_device::execute_shift(UINT32 op)
|
||||
*/
|
||||
UINT32 shift_count = USEIMM ? (SIMM13 & 31) : (RS2REG & 31);
|
||||
|
||||
if (OP3 == 37 && RD != 0)
|
||||
if (SLL && RD != 0)
|
||||
RDREG = RS1REG << shift_count;
|
||||
else if (OP3 == 38 && RD != 0)
|
||||
else if (SRL && RD != 0)
|
||||
RDREG = UINT32(RS1REG) >> shift_count;
|
||||
else if (OP3 == 39 && RD != 0)
|
||||
else if (SRA && RD != 0)
|
||||
RDREG = INT32(RS1REG) >> shift_count;
|
||||
}
|
||||
|
||||
@ -907,7 +914,7 @@ void mb86901_device::execute_rdsr(UINT32 op)
|
||||
);
|
||||
*/
|
||||
|
||||
if (((OP3 == 41 || OP3 == 42 || OP3 == 43) || (OP3 == 40 && m_privileged_asr[RS1])) && IS_USER)
|
||||
if (((WRPSR || WRWIM || WRTBR) || (WRASR && m_privileged_asr[RS1])) && IS_USER)
|
||||
{
|
||||
m_trap = 1;
|
||||
m_privileged_instruction = 1;
|
||||
@ -919,14 +926,19 @@ void mb86901_device::execute_rdsr(UINT32 op)
|
||||
}
|
||||
else if (RD != 0)
|
||||
{
|
||||
switch (OP3)
|
||||
if (RDASR)
|
||||
{
|
||||
case OP3_RDASR:
|
||||
if (RS1 == 0) RDREG = Y; break;
|
||||
case OP3_RDPSR: RDREG = PSR; break;
|
||||
case OP3_RDWIM: RDREG = WIM; break;
|
||||
case OP3_RDTBR: RDREG = TBR; break;
|
||||
if (RS1 == 0)
|
||||
{
|
||||
RDREG = Y;
|
||||
}
|
||||
}
|
||||
else if (RDPSR)
|
||||
RDREG = PSR;
|
||||
else if (RDWIM)
|
||||
RDREG = WIM;
|
||||
else if (RDTBR)
|
||||
RDREG = TBR;
|
||||
}
|
||||
}
|
||||
|
||||
@ -985,11 +997,11 @@ void mb86901_device::execute_wrsr(UINT32 op)
|
||||
|
||||
UINT32 result = RS1REG ^ operand2;
|
||||
|
||||
if (OP3 == 48 && RD == 0)
|
||||
if (WRASR && RD == 0)
|
||||
{
|
||||
Y = result;
|
||||
}
|
||||
else if (OP3 == 48)
|
||||
else if (WRASR)
|
||||
{
|
||||
if (m_privileged_asr[RD] && IS_USER)
|
||||
{
|
||||
@ -1006,7 +1018,7 @@ void mb86901_device::execute_wrsr(UINT32 op)
|
||||
// SPARCv8
|
||||
}
|
||||
}
|
||||
else if (OP3 == 49)
|
||||
else if (WRPSR)
|
||||
{
|
||||
if (IS_USER)
|
||||
{
|
||||
@ -1023,7 +1035,7 @@ void mb86901_device::execute_wrsr(UINT32 op)
|
||||
PSR = result &~ PSR_ZERO_MASK;
|
||||
}
|
||||
}
|
||||
else if (OP3 == 50)
|
||||
else if (WRWIM)
|
||||
{
|
||||
if (IS_USER)
|
||||
{
|
||||
@ -1035,7 +1047,7 @@ void mb86901_device::execute_wrsr(UINT32 op)
|
||||
WIM = result & 0x7f;
|
||||
}
|
||||
}
|
||||
else if (OP3 == 51)
|
||||
else if (WRTBR)
|
||||
{
|
||||
if (IS_USER)
|
||||
{
|
||||
@ -1182,7 +1194,7 @@ void mb86901_device::execute_saverestore(UINT32 op)
|
||||
UINT32 operand2 = USEIMM ? SIMM13 : RS2REG;
|
||||
|
||||
UINT32 result = 0;
|
||||
if (OP3 == OP3_SAVE)
|
||||
if (SAVE)
|
||||
{
|
||||
UINT8 new_cwp = ((CWP + NWINDOWS) - 1) % NWINDOWS;
|
||||
if ((WIM & (1 << new_cwp)) != 0)
|
||||
@ -1196,7 +1208,7 @@ void mb86901_device::execute_saverestore(UINT32 op)
|
||||
CWP = new_cwp;
|
||||
}
|
||||
}
|
||||
else if (OP3 == OP3_RESTORE)
|
||||
else if (RESTORE)
|
||||
{
|
||||
UINT8 new_cwp = (CWP + 1) % NWINDOWS;
|
||||
if ((WIM & (1 << new_cwp)) != 0)
|
||||
@ -1351,142 +1363,22 @@ void mb86901_device::execute_group2(UINT32 op)
|
||||
break;
|
||||
|
||||
#if SPARCV8
|
||||
case OP3_UMUL: // SPARCv8
|
||||
{
|
||||
UINT32 arg1 = RS1REG;
|
||||
UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
|
||||
UINT64 result = (UINT64)arg1 * (UINT64)arg2;
|
||||
Y = (UINT32)(result >> 32);
|
||||
SET_RDREG((UINT32)result);
|
||||
case OP3_UMUL:
|
||||
case OP3_SMUL:
|
||||
case OP3_UMULCC:
|
||||
case OP3_SMULCC:
|
||||
execute_mul(op);
|
||||
break;
|
||||
}
|
||||
case OP3_SMUL: // SPARCv8
|
||||
{
|
||||
UINT32 arg1 = RS1REG;
|
||||
UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
|
||||
INT64 result = (INT64)(INT32)arg1 * (INT64)(INT32)arg2;
|
||||
Y = (UINT32)((UINT64)result >> 32);
|
||||
SET_RDREG((UINT32)result);
|
||||
break;
|
||||
}
|
||||
case OP3_UDIV: // SPARCv8
|
||||
{
|
||||
UINT32 arg1 = RS1REG;
|
||||
UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
|
||||
UINT64 dividend = ((UINT64)Y << 32) || arg1;
|
||||
UINT32 divisor = arg2;
|
||||
UINT64 quotient = dividend / divisor;
|
||||
if (quotient > (0xffffffffL + (divisor - 1)))
|
||||
{
|
||||
quotient = 0xffffffff;
|
||||
}
|
||||
SET_RDREG((UINT32)quotient);
|
||||
break;
|
||||
}
|
||||
case OP3_SDIV: // SPARCv8
|
||||
{
|
||||
UINT32 arg1 = RS1REG;
|
||||
UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
|
||||
INT64 dividend = ((INT64)(INT32)Y << 32) || arg1;
|
||||
INT32 divisor = arg2;
|
||||
INT64 quotient = dividend / divisor;
|
||||
if (quotient > 0)
|
||||
{
|
||||
INT32 absdivisor = (divisor < 0) ? -divisor : divisor;
|
||||
if (quotient > (0x7fffffffL + (absdivisor - 1)))
|
||||
{
|
||||
quotient = 0x7fffffff;
|
||||
}
|
||||
}
|
||||
else if (quotient < 0)
|
||||
{
|
||||
if (quotient < (INT64)0xffffffff80000000L)
|
||||
{
|
||||
quotient = 0x80000000;
|
||||
}
|
||||
}
|
||||
SET_RDREG((UINT32)quotient);
|
||||
break;
|
||||
}
|
||||
case OP3_UMULCC: // SPARCv8
|
||||
{
|
||||
UINT32 arg1 = RS1REG;
|
||||
UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
|
||||
UINT64 result = (UINT64)arg1 * (UINT64)arg2;
|
||||
Y = (UINT32)(result >> 32);
|
||||
TEST_ICC_NZ(result);
|
||||
SET_RDREG((UINT32)result);
|
||||
break;
|
||||
}
|
||||
case OP3_SMULCC: // SPARCv8
|
||||
{
|
||||
UINT32 arg1 = RS1REG;
|
||||
UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
|
||||
INT64 result = (INT64)(INT32)arg1 * (INT64)(INT32)arg2;
|
||||
Y = (UINT32)((UINT64)result >> 32);
|
||||
TEST_ICC_NZ(result);
|
||||
SET_RDREG((UINT32)result);
|
||||
break;
|
||||
}
|
||||
case OP3_UDIVCC: // SPARCv8
|
||||
{
|
||||
UINT32 arg1 = RS1REG;
|
||||
UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
|
||||
UINT64 dividend = ((UINT64)Y << 32) || arg1;
|
||||
UINT32 divisor = arg2;
|
||||
UINT64 quotient = dividend / divisor;
|
||||
|
||||
bool v = false;
|
||||
if (quotient > (0xffffffffL + (divisor - 1)))
|
||||
{
|
||||
quotient = 0xffffffff;
|
||||
v = true;
|
||||
}
|
||||
|
||||
TEST_ICC_NZ((UINT32)quotient);
|
||||
if (v)
|
||||
ICC_V_SET;
|
||||
|
||||
SET_RDREG((UINT32)quotient);
|
||||
case OP3_UDIV:
|
||||
case OP3_SDIV:
|
||||
case OP3_UDIVCC:
|
||||
case OP3_SDIVCC:
|
||||
execute_div(op);
|
||||
break;
|
||||
}
|
||||
case OP3_SDIVCC: // SPARCv8
|
||||
{
|
||||
UINT32 arg1 = RS1REG;
|
||||
UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
|
||||
INT64 dividend = ((INT64)(INT32)Y << 32) || arg1;
|
||||
INT32 divisor = arg2;
|
||||
INT64 quotient = dividend / divisor;
|
||||
|
||||
bool v = false;
|
||||
if (quotient > 0)
|
||||
{
|
||||
INT32 absdivisor = (divisor < 0) ? -divisor : divisor;
|
||||
if (quotient > (0x7fffffffL + (absdivisor - 1)))
|
||||
{
|
||||
quotient = 0x7fffffff;
|
||||
v = true;
|
||||
}
|
||||
}
|
||||
else if (quotient < 0)
|
||||
{
|
||||
if (quotient < (INT64)0xffffffff80000000L)
|
||||
{
|
||||
quotient = 0x80000000;
|
||||
v = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (v)
|
||||
ICC_V_SET;
|
||||
TEST_ICC_NZ((UINT32)quotient);
|
||||
|
||||
SET_RDREG((UINT32)quotient);
|
||||
break;
|
||||
}
|
||||
case OP3_CPOP1: // SPARCv8
|
||||
break;
|
||||
case OP3_CPOP2: // SPARCv8
|
||||
case OP3_CPOP1:
|
||||
case OP3_CPOP2:
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -2333,10 +2225,12 @@ void mb86901_device::execute_group3(UINT32 op)
|
||||
execute_ldstub(op);
|
||||
break;
|
||||
|
||||
case OP3_SWAP: // SPARCv8
|
||||
break;
|
||||
case OP3_SWAPA: // SPARCv8
|
||||
#if SPARCV8
|
||||
case OP3_SWAP:
|
||||
case OP3_SWAPA:
|
||||
execute_swap(op);
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (MAE || HOLD_BUS)
|
||||
@ -2805,12 +2699,12 @@ void mb86901_device::dispatch_instruction(UINT32 op)
|
||||
m_illegal_instruction = 1;
|
||||
|
||||
}
|
||||
if (((OP == OP_ALU && (OP3 == OP3_FPOP1 || OP3 == OP3_FPOP2)) || (OP == OP_TYPE0 && OP2 == OP2_FBFCC)) && (!EF || !m_bp_fpu_present))
|
||||
if (((OP == OP_ALU && (FPOP1 || FPOP2)) || (OP == OP_TYPE0 && OP2 == OP2_FBFCC)) && (!EF || !m_bp_fpu_present))
|
||||
{
|
||||
m_trap = 1;
|
||||
m_fp_disabled = 1;
|
||||
}
|
||||
if (((OP == OP_ALU && (OP3 == OP3_CPOP1 || OP3 == OP3_CPOP2)) || (OP == OP_TYPE0 && OP2 == OP2_CBCCC)) && (!EC || !m_bp_cp_present))
|
||||
if (((OP == OP_ALU && (CPOP1 || CPOP2)) || (OP == OP_TYPE0 && OP2 == OP2_CBCCC)) && (!EC || !m_bp_cp_present))
|
||||
{
|
||||
m_trap = 1;
|
||||
m_cp_disabled = 1;
|
||||
@ -2924,7 +2818,7 @@ void mb86901_device::execute_step()
|
||||
{
|
||||
dispatch_instruction(op);
|
||||
|
||||
if (OP3 == OP3_FPOP1 || OP3 == OP3_FPOP2)
|
||||
if (FPOP1 || FPOP2)
|
||||
{
|
||||
complete_fp_execution(op);
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include "sparcdasm.h"
|
||||
|
||||
#define SPARCV8 (0)
|
||||
|
||||
#define SPARC_NO_TRAP 256
|
||||
#define SPARC_RESET 0
|
||||
#define SPARC_INSTRUCTION_ACCESS_EXCEPTION 1
|
||||
@ -100,11 +102,18 @@ protected:
|
||||
void execute_rett(UINT32 op);
|
||||
void execute_saverestore(UINT32 op);
|
||||
void execute_jmpl(UINT32 op);
|
||||
#if SPARCV8
|
||||
void execute_mul(UINT32 op);
|
||||
void execute_div(UINT32 op);
|
||||
#endif
|
||||
void execute_group2(UINT32 op);
|
||||
|
||||
void execute_load(UINT32 op);
|
||||
void execute_store(UINT32 op);
|
||||
void execute_ldstub(UINT32 op);
|
||||
#if SPARCV8
|
||||
void execute_swap(UINT32 op);
|
||||
#endif
|
||||
void execute_group3(UINT32 op);
|
||||
|
||||
bool evaluate_condition(UINT32 op);
|
||||
|
@ -319,7 +319,68 @@
|
||||
#define TICC (OP3 == OP3_TICC)
|
||||
#define RETT (OP3 == OP3_RETT)
|
||||
|
||||
#define SWAP (OP3 == OP3_SWAP)
|
||||
#define SWAPA (OP3 == OP3_SWAPA)
|
||||
|
||||
#define FPOP1 (OP3 == OP3_FPOP1)
|
||||
#define FPOP2 (OP3 == OP3_FPOP2)
|
||||
#define CPOP1 (OP3 == OP3_CPOP1)
|
||||
#define CPOP2 (OP3 == OP3_CPOP2)
|
||||
|
||||
#define LDSTUB (OP3 == OP3_LDSTUB)
|
||||
#define LDSTUBA (OP3 == OP3_LDSTUBA)
|
||||
|
||||
#define ADD (OP3 == OP3_ADD)
|
||||
#define ADDX (OP3 == OP3_ADDX)
|
||||
#define ADDCC (OP3 == OP3_ADDCC)
|
||||
#define ADDXCC (OP3 == OP3_ADDXCC)
|
||||
|
||||
#define SUB (OP3 == OP3_SUB)
|
||||
#define SUBX (OP3 == OP3_SUBX)
|
||||
#define SUBCC (OP3 == OP3_SUBCC)
|
||||
#define SUBXCC (OP3 == OP3_SUBXCC)
|
||||
|
||||
#define TADDCCTV (OP3 == OP3_TADDCCTV)
|
||||
#define TSUBCCTV (OP3 == OP3_TSUBCCTV)
|
||||
|
||||
#define AND (OP3 == OP3_AND)
|
||||
#define OR (OP3 == OP3_OR)
|
||||
#define XOR (OP3 == OP3_XOR)
|
||||
#define ANDN (OP3 == OP3_ANDN)
|
||||
#define ORN (OP3 == OP3_ORN)
|
||||
#define XNOR (OP3 == OP3_XNOR)
|
||||
#define ANDCC (OP3 == OP3_ANDCC)
|
||||
#define ORCC (OP3 == OP3_ORCC)
|
||||
#define XORCC (OP3 == OP3_XORCC)
|
||||
#define ANDNCC (OP3 == OP3_ANDNCC)
|
||||
#define ORNCC (OP3 == OP3_ORNCC)
|
||||
#define XNORCC (OP3 == OP3_XNORCC)
|
||||
|
||||
#define SLL (OP3 == OP3_SLL)
|
||||
#define SRL (OP3 == OP3_SRL)
|
||||
#define SRA (OP3 == OP3_SRA)
|
||||
|
||||
#define RDASR (OP3 == OP3_RDASR)
|
||||
#define RDPSR (OP3 == OP3_RDPSR)
|
||||
#define RDWIM (OP3 == OP3_RDWIM)
|
||||
#define RDTBR (OP3 == OP3_RDTBR)
|
||||
|
||||
#define WRASR (OP3 == OP3_WRASR)
|
||||
#define WRPSR (OP3 == OP3_WRPSR)
|
||||
#define WRWIM (OP3 == OP3_WRWIM)
|
||||
#define WRTBR (OP3 == OP3_WRTBR)
|
||||
|
||||
#define SAVE (OP3 == OP3_SAVE)
|
||||
#define RESTORE (OP3 == OP3_RESTORE)
|
||||
|
||||
#define UMUL (OP3 == OP3_UMUL)
|
||||
#define UMULCC (OP3 == OP3_UMULCC)
|
||||
#define SMUL (OP3 == OP3_SMUL)
|
||||
#define SMULCC (OP3 == OP3_SMULCC)
|
||||
|
||||
#define UDIV (OP3 == OP3_UDIV)
|
||||
#define UDIVCC (OP3 == OP3_UDIVCC)
|
||||
#define SDIV (OP3 == OP3_SDIV)
|
||||
#define SDIVCC (OP3 == OP3_SDIVCC)
|
||||
|
||||
#endif // __MB86901_DEFS_H__
|
293
src/devices/cpu/sparc/sparcv8ops.ipp
Normal file
293
src/devices/cpu/sparc/sparcv8ops.ipp
Normal file
@ -0,0 +1,293 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Ryan Holtz
|
||||
//================================================================
|
||||
//
|
||||
// sparcv8ops.ipp - Emulation for SPARCv8-class instructions
|
||||
//
|
||||
//================================================================
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute_swap - execute a swap instruction
|
||||
//-------------------------------------------------
|
||||
|
||||
void mb86901_device::execute_swap(UINT32 op)
|
||||
{
|
||||
/* The SPARC Instruction Manual: Version 8, page 169, "Appendix C - ISP Descriptions - Atomic Load-Store Unsigned Byte Instructions" (SPARCv8.pdf, pg. 166)
|
||||
|
||||
if (SWAP) then (
|
||||
address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
|
||||
addr_space <- (if (S = 0) then 10 else 11)
|
||||
) else if (SWAPA) then (
|
||||
if (S = 0) then (
|
||||
trap <- 1;
|
||||
privileged_instruction <- 1
|
||||
) else if (i = 1) then (
|
||||
trap <- 1;
|
||||
illegal_instruction <- 1
|
||||
) else (
|
||||
address <- r[rs1] + r[rs1];
|
||||
addr_space <- asi
|
||||
)
|
||||
);
|
||||
next;
|
||||
if (trap = 0) then (
|
||||
temp <- r[rd];
|
||||
while ( (pb_block_ldst_byte = 1) or (pb_block_ldst_word = 1) ) (
|
||||
{ wait for lock(s) to be lifted }
|
||||
{ an implementation actually need only block when another SWAP is pending on
|
||||
the same word in memory as the one addressed by this SWAP, or a LDSTUB is
|
||||
pending on any byte of the word in memory addressed by this SWAP }
|
||||
);
|
||||
next;
|
||||
pb_block_ldst_word <- 1;
|
||||
next;
|
||||
(word, MAE) <- memory_read(addr_space, address);
|
||||
next;
|
||||
if (MAE = 1) then (
|
||||
trap <- 1;
|
||||
data_access_exception = 1
|
||||
)
|
||||
next;
|
||||
if (trap = 0) then (
|
||||
MAE <- memory_write(addr_space, address, 1111, temp);
|
||||
next;
|
||||
pb_block_ldst_word <- 0;
|
||||
if (MAE = 1) then ( { MAE = 1 only due to a "non-resumable machine-check error" }
|
||||
trap <- 1;
|
||||
data_access_exception <- 1
|
||||
) else (
|
||||
if (rd != 0) then r[rd] <- word
|
||||
)
|
||||
);
|
||||
*/
|
||||
|
||||
UINT32 address = 0;
|
||||
UINT8 addr_space = 0;
|
||||
if (SWAP)
|
||||
{
|
||||
address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
|
||||
addr_space = (IS_USER ? 10 : 11);
|
||||
}
|
||||
else if (SWAPA)
|
||||
{
|
||||
if (IS_USER)
|
||||
{
|
||||
m_trap = 1;
|
||||
m_privileged_instruction = 1;
|
||||
}
|
||||
else if (USEIMM)
|
||||
{
|
||||
m_trap = 1;
|
||||
m_illegal_instruction = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
address = RS1REG + RS2REG;
|
||||
addr_space = ASI;
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 word = 0;
|
||||
UINT32 temp = 0;
|
||||
if (!m_trap)
|
||||
{
|
||||
temp = RDREG;
|
||||
while (m_pb_block_ldst_byte || m_pb_block_ldst_word)
|
||||
{
|
||||
// { wait for lock(s) to be lifted }
|
||||
// { an implementation actually need only block when another SWAP is pending on
|
||||
// the same word in memory as the one addressed by this SWAP, or a LDSTUB is
|
||||
// pending on any byte of the word in memory addressed by this SWAP }
|
||||
}
|
||||
|
||||
m_pb_block_ldst_word = 1;
|
||||
|
||||
word = read_sized_word(addr_space, address, 4);
|
||||
|
||||
if (MAE)
|
||||
{
|
||||
m_trap = 1;
|
||||
m_data_access_exception = 1;
|
||||
}
|
||||
}
|
||||
if (!m_trap)
|
||||
{
|
||||
write_sized_word(addr_space, address, temp, 4);
|
||||
|
||||
m_pb_block_ldst_word = 0;
|
||||
if (MAE)
|
||||
{
|
||||
m_trap = 1;
|
||||
m_data_access_exception = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (RD != 0)
|
||||
RDREG = word;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute_mul - execute a multiply opcode
|
||||
//-------------------------------------------------
|
||||
|
||||
void mb86901_device::execute_mul(UINT32 op)
|
||||
{
|
||||
/* The SPARC Instruction Manual: Version 8, page 175, "Appendix C - ISP Descriptions - Multiply Instructions" (SPARCv8.pdf, pg. 172)
|
||||
|
||||
operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
|
||||
|
||||
if (UMUL or UMULScc) then (Y, result) <- multiply_unsigned(r[rs1], operand2)
|
||||
else if (SMUL or SMULcc) then (Y, result) <- multiply_signed(r[rs1], operand2)
|
||||
next;
|
||||
if (rd != 0) then (
|
||||
r[rd] <- result;
|
||||
)
|
||||
if (UMULcc or SMULcc) then (
|
||||
N <- result<31>;
|
||||
Z <- if (result = 0) then 1 else 0;
|
||||
V <- 0
|
||||
C <- 0
|
||||
);
|
||||
*/
|
||||
|
||||
UINT32 operand2 = (USEIMM ? SIMM13 : RS2REG);
|
||||
|
||||
UINT32 result = 0;
|
||||
if (UMUL || UMULCC)
|
||||
{
|
||||
UINT64 dresult = (UINT64)RS1REG * (UINT64)operand2;
|
||||
Y = (UINT32)(dresult >> 32);
|
||||
result = (UINT32)dresult;
|
||||
}
|
||||
else if (SMUL || SMULCC)
|
||||
{
|
||||
INT64 dresult = (INT64)(INT32)RS1REG * (INT64)(INT32)operand2;
|
||||
Y = (UINT32)(dresult >> 32);
|
||||
result = (UINT32)dresult;
|
||||
}
|
||||
|
||||
if (RD != 0)
|
||||
{
|
||||
RDREG = result;
|
||||
}
|
||||
if (UMULCC || SMULCC)
|
||||
{
|
||||
CLEAR_ICC;
|
||||
PSR |= BIT31(result) ? PSR_N_MASK : 0;
|
||||
PSR |= (result == 0) ? PSR_Z_MASK : 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// execute_div - execute a divide opcode
|
||||
//-------------------------------------------------
|
||||
|
||||
void mb86901_device::execute_div(UINT32 op)
|
||||
{
|
||||
/* The SPARC Instruction Manual: Version 8, page 176, "Appendix C - ISP Descriptions - Multiply Instructions" (SPARCv8.pdf, pg. 173)
|
||||
|
||||
operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
|
||||
|
||||
next;
|
||||
if (operand2 = 0) then (
|
||||
trap <- 1;
|
||||
division_by_zero <- 1
|
||||
) else (
|
||||
if (UDIV or UDIVcc) then (
|
||||
temp_64bit <- divide_unsigned(Y[]r[rs1], operand2);
|
||||
next;
|
||||
result <- temp_64bit<31:0>;
|
||||
temp_V <- if (temp_64bit<63:32> = 0) then 0 else 1;
|
||||
) else if (SDIV or SDIVcc) then (
|
||||
temp_64bit <- divide_signed(Y[]r[rs1], operand2);
|
||||
next;
|
||||
result <- temp_64bit<31:0>;
|
||||
temp_V <- if (temp_64bit<63:31> = 0) or
|
||||
(temp_64bit<63:31> = (2^33 - 1)) ) then 0 else 1;
|
||||
) ;
|
||||
next;
|
||||
|
||||
if (temp_V) then (
|
||||
{ result overflowed 32 bits; return largest appropriate integer }
|
||||
if (UDIV or UDIVcc) then result <- 2^32 - 1;
|
||||
else if (SDIV or SDIVcc) then (
|
||||
if (temp_64bit > 0) then result <- 2^31 - 1;
|
||||
else result <- -2^31
|
||||
)
|
||||
);
|
||||
next;
|
||||
|
||||
if (rd != 0) then (
|
||||
r[rd] <- result
|
||||
) ;
|
||||
if (UDIVcc or SDIVcc) then (
|
||||
N <- result<31>;
|
||||
Z <- if (result = 0) then 1 else 0;
|
||||
V <- temp_V;
|
||||
C <- 0
|
||||
)
|
||||
);
|
||||
*/
|
||||
|
||||
UINT32 operand2 = (USEIMM ? SIMM13 : RS2REG);
|
||||
|
||||
if (operand2 == 0)
|
||||
{
|
||||
m_trap = 1;
|
||||
m_division_by_zero = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT32 result = 0;
|
||||
bool temp_v = false;
|
||||
INT64 temp_64bit;
|
||||
if (UDIV || UDIVCC)
|
||||
{
|
||||
temp_64bit = INT64(UINT64((UINT64(Y) << 32) | UINT64(RS1REG)) / operand2);
|
||||
|
||||
result = UINT32(temp_64bit);
|
||||
|
||||
temp_v = ((temp_64bit & 0xffffffff00000000) == 0) ? false : true;
|
||||
}
|
||||
else if (SDIV || SDIVCC)
|
||||
{
|
||||
temp_64bit = INT64(INT64((UINT64(Y) << 32) | UINT64(RS1REG)) / operand2);
|
||||
|
||||
result = UINT32(temp_64bit);
|
||||
|
||||
UINT64 shifted = UINT64(temp_64bit) >> 31;
|
||||
temp_v = (shifted == 0 || shifted == 0x1ffffffff) ? false : true;
|
||||
}
|
||||
|
||||
if (temp_v)
|
||||
{
|
||||
if (UDIV || UDIVCC)
|
||||
{
|
||||
result = 0xffffffff;
|
||||
}
|
||||
else if (SDIV || SDIVCC)
|
||||
{
|
||||
if (temp_64bit > 0)
|
||||
result = 0x7fffffff;
|
||||
else
|
||||
result = 0x80000000;
|
||||
}
|
||||
}
|
||||
|
||||
if (RD != 0)
|
||||
RDREG = result;
|
||||
|
||||
if (UDIVCC || SDIVCC)
|
||||
{
|
||||
CLEAR_ICC;
|
||||
PSR |= BIT31(result) ? PSR_N_MASK : 0;
|
||||
PSR |= (result == 0) ? PSR_Z_MASK : 0;
|
||||
PSR |= temp_v ? PSR_V_MASK : 0;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user