summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author mooglyguy <ryan@mojang.com>2014-11-03 21:18:39 +0100
committer mooglyguy <ryan@mojang.com>2014-11-03 21:18:52 +0100
commite3680d1c8f873c827b8cdb00345a8e0f24e5e150 (patch)
tree88a58c659614d4bb3f3540b366901d7b117a2915
parentf4737e2a4e12060619b9ed2a50165f3d6e59af69 (diff)
rsp: Add VNOP, VNULL, and VRSQ instructions. [MooglyGuy]
-rw-r--r--src/emu/cpu/rsp/rsp.h1
-rw-r--r--src/emu/cpu/rsp/rspdrc.c148
2 files changed, 149 insertions, 0 deletions
diff --git a/src/emu/cpu/rsp/rsp.h b/src/emu/cpu/rsp/rsp.h
index 7c29e22dfa8..6459b0d8c6d 100644
--- a/src/emu/cpu/rsp/rsp.h
+++ b/src/emu/cpu/rsp/rsp.h
@@ -325,6 +325,7 @@ public:
void ccfunc_mtc2_scalar();
void ccfunc_ctc2_scalar();
#endif
+ void ccfunc_rsp_vrsq_scalar();
#if USE_SIMD && SIMUL_SIMD
void ccfunc_backup_regs();
void ccfunc_restore_regs();
diff --git a/src/emu/cpu/rsp/rspdrc.c b/src/emu/cpu/rsp/rspdrc.c
index 6541e4d95df..18e8d301463 100644
--- a/src/emu/cpu/rsp/rspdrc.c
+++ b/src/emu/cpu/rsp/rspdrc.c
@@ -6592,6 +6592,136 @@ static void cfunc_rsp_vmov_scalar(void *param)
}
#endif
+// VRSQ
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal square-root
+
+inline void rsp_device::ccfunc_rsp_vrsq_scalar()
+{
+ int op = m_rsp_state->arg0;
+
+ INT32 shifter = 0;
+ INT32 rec = (INT16)VREG_S(VS2REG, EL & 7);
+ INT32 datainput = (rec < 0) ? (-rec) : (rec);
+
+ if (rec < 0)
+ {
+ if (rec < -32768)
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+
+ if (datainput)
+ {
+ for (int i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ shifter = 0;
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ address = ((address | 0x200) & 0x3fe) | (shifter & 1);
+
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ if (rec < 0)
+ {
+ if (m_dp_allowed)
+ {
+ if (rec < -32768)
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+
+ if (datainput)
+ {
+ for (int i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ shifter = 0;
+ }
+
+ address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ address = ((address | 0x200) & 0x3fe) | (shifter & 1);
+
+ fetchval = rsp_divtable[address];
+ temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0x0000;
+ }
+ rec = temp;
+
+ W_VREG_S(VDREG, VS1REG & 7) = (UINT16)rec;
+ for (int i = 0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+}
+
+static void cfunc_rsp_vrsq_scalar(void *param)
+{
+ ((rsp_device *)param)->ccfunc_rsp_vrsq_scalar();
+}
+
#if USE_SIMD
// VRSQL
//
@@ -7835,6 +7965,11 @@ int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *comp
#endif
return TRUE;
+ case 0x34: /* VRSQ */
+ UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC_block, cfunc_rsp_vrsq_scalar, this);
+ return TRUE;
+
case 0x35: /* VRSQL */
UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
UML_CALLC(block, cfunc_rsp_vrsql_simd, this);
@@ -7857,6 +7992,10 @@ int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *comp
#endif
return TRUE;
+ case 0x37: /* VNOP */
+ case 0x3F: /* VNULL */
+ return TRUE;
+
default:
UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
UML_CALLC(block, cfunc_unimplemented_opcode, this);
@@ -8057,6 +8196,11 @@ int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *comp
UML_CALLC(block, cfunc_rsp_vmov_scalar, this);
return TRUE;
+ case 0x34: /* VRSQ */
+ UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_rsp_vrsq_scalar, this);
+ return TRUE;
+
case 0x35: /* VRSQL */
UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
UML_CALLC(block, cfunc_rsp_vrsql_scalar, this);
@@ -8067,6 +8211,10 @@ int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *comp
UML_CALLC(block, cfunc_rsp_vrsqh_scalar, this);
return TRUE;
+ case 0x37: /* VNOP */
+ case 0x3F: /* VNULL */
+ return TRUE;
+
default:
UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
UML_CALLC(block, cfunc_unimplemented_opcode, this);