Merge pull request #990 from MooglyGuy/master

Convert SPARCv8 ops to document-described functionality [Ryan Holtz]
This commit is contained in:
Vas Crabb 2016-06-23 22:21:52 +10:00 committed by GitHub
commit 759275f61a
5 changed files with 433 additions and 175 deletions

View File

@ -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",

View File

@ -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);
}

View File

@ -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);

View File

@ -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__

View 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;
}
}
}