summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author therealmogminer@gmail.com <therealmogminer@gmail.com>2016-06-23 14:20:24 +0200
committer therealmogminer@gmail.com <therealmogminer@gmail.com>2016-06-23 14:20:24 +0200
commitff04ed4cc0002ec30f7a6cbc76cb8f63043a05ce (patch)
tree4b7712e5502e0bed4e2ccfef7ef706e234035eeb
parent75677f5e81012c5f66e817f9b912a34e0461f82b (diff)
Convert SPARCv8 ops to document-described functionality
-rw-r--r--scripts/src/cpu.lua1
-rw-r--r--src/devices/cpu/sparc/mb86901.cpp244
-rw-r--r--src/devices/cpu/sparc/sparc.h9
-rw-r--r--src/devices/cpu/sparc/sparcdefs.h61
-rw-r--r--src/devices/cpu/sparc/sparcv8ops.ipp293
5 files changed, 433 insertions, 175 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index d4538b11abb..ef9263c6485 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -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",
diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/mb86901.cpp
index 61dc5043530..2c32279b267 100644
--- a/src/devices/cpu/sparc/mb86901.cpp
+++ b/src/devices/cpu/sparc/mb86901.cpp
@@ -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);
- 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);
+ case OP3_UMUL:
+ case OP3_SMUL:
+ case OP3_UMULCC:
+ case OP3_SMULCC:
+ execute_mul(op);
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);
}
diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h
index bb6c33d9933..b9fd75dbee5 100644
--- a/src/devices/cpu/sparc/sparc.h
+++ b/src/devices/cpu/sparc/sparc.h
@@ -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);
diff --git a/src/devices/cpu/sparc/sparcdefs.h b/src/devices/cpu/sparc/sparcdefs.h
index bf2319d7bb7..2b306323314 100644
--- a/src/devices/cpu/sparc/sparcdefs.h
+++ b/src/devices/cpu/sparc/sparcdefs.h
@@ -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__ \ No newline at end of file
diff --git a/src/devices/cpu/sparc/sparcv8ops.ipp b/src/devices/cpu/sparc/sparcv8ops.ipp
new file mode 100644
index 00000000000..0bb8e9e675e
--- /dev/null
+++ b/src/devices/cpu/sparc/sparcv8ops.ipp
@@ -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;
+ }
+ }
+}