summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Angelo Salese <salese_corp_ltd@email.it>2014-11-20 01:04:54 +0100
committer Angelo Salese <salese_corp_ltd@email.it>2014-11-20 01:04:54 +0100
commit3216fdb9520dcc982bdad0e4da1bc1d67a1068cb (patch)
tree52471bfd7c1dfbd90b20fbd2bf214fd9bfbf7070
parent98f29dc4a7d220cd6d376d7235372d7a0353305f (diff)
parentcdeac07354416571ff158b72e38f43cc859fcedf (diff)
Merge branch 'master' of https://github.com/mamedev/mame
-rw-r--r--src/emu/cpu/cpu.mak20
-rw-r--r--src/emu/cpu/rsp/rsp.c2657
-rw-r--r--src/emu/cpu/rsp/rsp.h259
-rw-r--r--src/emu/cpu/rsp/rspcp2.c2797
-rw-r--r--src/emu/cpu/rsp/rspcp2.h159
-rw-r--r--src/emu/cpu/rsp/rspcp2d.c3796
-rw-r--r--src/emu/cpu/rsp/rspcp2d.h110
-rw-r--r--src/emu/cpu/rsp/rspcp2s.c3633
-rw-r--r--src/emu/cpu/rsp/rspcp2s.h158
-rw-r--r--src/emu/cpu/rsp/rspdrc.c7937
-rw-r--r--src/mame/drivers/sauro.c39
-rw-r--r--src/mame/mame.lst1
12 files changed, 10788 insertions, 10778 deletions
diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak
index e733c15a58b..597ec26fbc7 100644
--- a/src/emu/cpu/cpu.mak
+++ b/src/emu/cpu/cpu.mak
@@ -1814,18 +1814,34 @@ $(CPUOBJ)/minx/minx.o: $(CPUSRC)/minx/minx.c \
ifneq ($(filter RSP,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/rsp
-CPUOBJS += $(CPUOBJ)/rsp/rsp.o $(CPUOBJ)/rsp/rspdrc.o $(CPUOBJ)/rsp/rspfe.o $(DRCOBJ)
+CPUOBJS += $(CPUOBJ)/rsp/rsp.o $(CPUOBJ)/rsp/rspdrc.o $(CPUOBJ)/rsp/rspfe.o $(CPUOBJ)/rsp/rspcp2.o $(CPUOBJ)/rsp/rspcp2d.o $(DRCOBJ)
DASMOBJS += $(CPUOBJ)/rsp/rsp_dasm.o
endif
$(CPUOBJ)/rsp/rsp.o: $(CPUSRC)/rsp/rsp.c \
- $(CPUSRC)/rsp/rsp.h
+ $(CPUSRC)/rsp/rsp.h \
+ $(CPUSRC)/rsp/rspcp2.c \
+ $(CPUSRC)/rsp/rspcp2.h
$(CPUOBJ)/rsp/rspdrc.o: $(CPUSRC)/rsp/rspdrc.c \
$(CPUSRC)/rsp/rsp.h \
$(CPUSRC)/rsp/rspfe.h \
$(DRCDEPS)
+$(CPUOBJ)/rsp/rspcp2.o: $(CPUSRC)/rsp/rspcp2.c \
+ $(CPUSRC)/rsp/rspcp2.h \
+ $(CPUSRC)/rsp/rspdrc.c \
+ $(CPUSRC)/rsp/rsp.c \
+ $(CPUSRC)/rsp/rsp.h
+
+$(CPUOBJ)/rsp/rspcp2d.o: $(CPUSRC)/rsp/rspcp2d.c \
+ $(CPUSRC)/rsp/rspcp2d.h \
+ $(CPUSRC)/rsp/rspcp2.c \
+ $(CPUSRC)/rsp/rspcp2.h \
+ $(CPUSRC)/rsp/rspdrc.c \
+ $(CPUSRC)/rsp/rsp.c \
+ $(CPUSRC)/rsp/rsp.h
+
$(CPUOBJ)/rsp/rspfe.o: $(CPUSRC)/rsp/rspfe.c \
$(CPUSRC)/rsp/rspfe.h
diff --git a/src/emu/cpu/rsp/rsp.c b/src/emu/cpu/rsp/rsp.c
index 3f3715c37e5..0891f04a09f 100644
--- a/src/emu/cpu/rsp/rsp.c
+++ b/src/emu/cpu/rsp/rsp.c
@@ -7,8 +7,9 @@
#include "emu.h"
#include "debugger.h"
#include "rsp.h"
-#include "rspdiv.h"
#include "rspfe.h"
+#include "rspcp2.h"
+#include "rspcp2d.h"
const device_type RSP = &device_creator<rsp_device>;
@@ -36,6 +37,10 @@ extern offs_t rsp_dasm_one(char *buffer, offs_t pc, UINT32 op);
#define UIMM16 ((UINT16)(op))
#define UIMM26 (op & 0x03ffffff)
+#define RSVAL (m_rsp_state->r[RSREG])
+#define RTVAL (m_rsp_state->r[RTREG])
+#define RDVAL (m_rsp_state->r[RDREG])
+
#define JUMP_ABS(addr) { m_nextpc = 0x04001000 | (((addr) << 2) & 0xfff); }
#define JUMP_ABS_L(addr,l) { m_nextpc = 0x04001000 | (((addr) << 2) & 0xfff); m_rsp_state->r[l] = m_rsp_state->pc + 4; }
#define JUMP_REL(offset) { m_nextpc = 0x04001000 | ((m_rsp_state->pc + ((offset) << 2)) & 0xfff); }
@@ -44,32 +49,6 @@ extern offs_t rsp_dasm_one(char *buffer, offs_t pc, UINT32 op);
#define JUMP_PC_L(addr,l) { m_nextpc = 0x04001000 | ((addr) & 0xfff); m_rsp_state->r[l] = m_rsp_state->pc + 4; }
#define LINK(l) { m_rsp_state->r[l] = m_rsp_state->pc + 4; }
-#define VREG_B(reg, offset) m_v[(reg)].b[(offset)^1]
-#define VREG_S(reg, offset) m_v[(reg)].s[(offset)]
-#define VREG_L(reg, offset) m_v[(reg)].l[(offset)]
-
-#define R_VREG_B(reg, offset) m_v[(reg)].b[(offset)^1]
-#define R_VREG_S(reg, offset) (INT16)m_v[(reg)].s[(offset)]
-#define R_VREG_L(reg, offset) m_v[(reg)].l[(offset)]
-
-#define W_VREG_B(reg, offset, val) (m_v[(reg)].b[(offset)^1] = val)
-#define W_VREG_S(reg, offset, val) (m_v[(reg)].s[(offset)] = val)
-#define W_VREG_L(reg, offset, val) (m_v[(reg)].l[(offset)] = val)
-
-#define VEC_EL_2(x,z) (vector_elements[(x)][(z)])
-
-#define ACCUM(x) m_accum[((x))].q
-#define ACCUM_H(x) m_accum[((x))].w[3]
-#define ACCUM_M(x) m_accum[((x))].w[2]
-#define ACCUM_L(x) m_accum[((x))].w[1]
-#define ACCUM_LL(x) m_accum[((x))].w[0]
-
-#define CARRY 0
-#define COMPARE 1
-#define CLIP1 2
-#define ZERO 3
-#define CLIP2 4
-
#define CARRY_FLAG(x) (m_vflag[CARRY][x & 7] != 0 ? 0xffff : 0)
#define COMPARE_FLAG(x) (m_vflag[COMPARE][x & 7] != 0 ? 0xffff : 0)
#define CLIP1_FLAG(x) (m_vflag[CLIP1][x & 7] != 0 ? 0xffff : 0)
@@ -141,28 +120,8 @@ rsp_device::rsp_device(const machine_config &mconfig, const char *tag, device_t
, m_write32(NULL)
, m_rsp_state(NULL)
, m_exec_output(NULL)
-#if SIMUL_SIMD
- , m_old_reciprocal_res(0)
- , m_old_reciprocal_high(0)
- , m_old_dp_allowed(0)
- , m_scalar_reciprocal_res(0)
- , m_scalar_reciprocal_high(0)
- , m_scalar_dp_allowed(0)
- , m_simd_reciprocal_res(0)
- , m_simd_reciprocal_high(0)
- , m_simd_dp_allowed(0)
-#endif
, m_sr(0)
, m_step_count(0)
-#if USE_SIMD
- , m_accum_h(0)
- , m_accum_m(0)
- , m_accum_l(0)
- , m_accum_ll(0)
-#endif
- , m_reciprocal_res(0)
- , m_reciprocal_high(0)
- , m_dp_allowed(0)
, m_ppc(0)
, m_nextpc(0)
, m_dmem32(NULL)
@@ -179,20 +138,6 @@ rsp_device::rsp_device(const machine_config &mconfig, const char *tag, device_t
, m_sp_set_status_func(*this)
{
m_isdrc = mconfig.options().drc() ? true : false;
- memset(m_vres, 0, sizeof(m_vres));
- memset(m_v, 0, sizeof(m_v));
- memset(m_vflag, 0, sizeof(m_vflag));
-#if SIMUL_SIMD
- memset(m_old_r, 0, sizeof(m_old_r));
- memset(m_old_dmem, 0, sizeof(m_old_dmem));
- memset(m_scalar_r, 0, sizeof(m_scalar_r));
- memset(m_scalar_dmem, 0, sizeof(m_scalar_dmem));
-#endif
-#if USE_SIMD
- memset(m_xv, 0, sizeof(m_xv));
- memset(m_xvflag, 0, sizeof(m_xvflag));
-#endif
- memset(m_accum, 0, sizeof(m_accum));
}
offs_t rsp_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
@@ -201,25 +146,27 @@ offs_t rsp_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *opro
return CPU_DISASSEMBLE_NAME( rsp )(this, buffer, pc, oprom, opram, options);
}
-inline UINT8 rsp_device::READ8(UINT32 address)
+UINT8 rsp_device::READ8(UINT32 address)
{
UINT8 ret;
address &= 0xfff;
ret = m_program->read_byte(address);
+ //printf("R8:%08x=%02x\n", address, ret);
return ret;
}
-inline UINT16 rsp_device::READ16(UINT32 address)
+UINT16 rsp_device::READ16(UINT32 address)
{
UINT16 ret;
address &= 0xfff;
ret = (m_program->read_byte(address) << 8) | (m_program->read_byte(address + 1) & 0xff);
+ //printf("R16:%08x=%04x\n", address, ret);
return ret;
}
-inline UINT32 rsp_device::READ32(UINT32 address)
+UINT32 rsp_device::READ32(UINT32 address)
{
UINT32 ret;
address &= 0xfff;
@@ -229,6 +176,7 @@ inline UINT32 rsp_device::READ32(UINT32 address)
(m_program->read_byte(address + 2) << 8) |
(m_program->read_byte(address + 3) << 0);
+ //printf("R32:%08x=%08x\n", address, ret);
return ret;
}
@@ -236,6 +184,7 @@ void rsp_device::WRITE8(UINT32 address, UINT8 data)
{
address &= 0xfff;
m_program->write_byte(address, data);
+ //printf("W8:%08x=%02x\n", address, data);
}
void rsp_device::WRITE16(UINT32 address, UINT16 data)
@@ -244,6 +193,7 @@ void rsp_device::WRITE16(UINT32 address, UINT16 data)
m_program->write_byte(address, data >> 8);
m_program->write_byte(address + 1, data & 0xff);
+ //printf("W16:%08x=%04x\n", address, data);
}
void rsp_device::WRITE32(UINT32 address, UINT32 data)
@@ -254,6 +204,7 @@ void rsp_device::WRITE32(UINT32 address, UINT32 data)
m_program->write_byte(address + 1, (data >> 16) & 0xff);
m_program->write_byte(address + 2, (data >> 8) & 0xff);
m_program->write_byte(address + 3, data & 0xff);
+ //printf("W32:%08x=%08x\n", address, data);
}
/*****************************************************************************/
@@ -370,25 +321,21 @@ void rsp_device::device_start()
m_direct = &m_program->direct();
resolve_cb();
+ if (m_isdrc)
+ {
+ m_cop2 = auto_alloc(machine(), rsp_cop2_drc(*this, machine()));
+ }
+ else
+ {
+ m_cop2 = auto_alloc(machine(), rsp_cop2(*this, machine()));
+ }
+ m_cop2->init();
+ m_cop2->start();
+
// RSP registers should power on to a random state
for(int regIdx = 0; regIdx < 32; regIdx++ )
{
m_rsp_state->r[regIdx] = 0;
- m_v[regIdx].d[0] = 0;
- m_v[regIdx].d[1] = 0;
- }
- CLEAR_CARRY_FLAGS();
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP1_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP2_FLAGS();
- m_reciprocal_res = 0;
- m_reciprocal_high = 0;
-
- // Accumulators do not power on to a random state
- for(int accumIdx = 0; accumIdx < 8; accumIdx++ )
- {
- m_accum[accumIdx].q = 0;
}
m_sr = RSP_STATUS_HALT;
@@ -544,208 +491,14 @@ void rsp_device::state_export(const device_state_entry &entry)
void rsp_device::state_string_export(const device_state_entry &entry, astring &string)
{
- switch (entry.index())
+ const int index = entry.index();
+ if (index >= RSP_V0 && index <= RSP_V31)
{
- case STATE_GENFLAGS:
- string.printf("%s","");
- break;
-
-#if USE_SIMD
- case RSP_V0:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 0], 7), (UINT16)_mm_extract_epi16(m_xv[ 0], 6), (UINT16)_mm_extract_epi16(m_xv[ 0], 5), (UINT16)_mm_extract_epi16(m_xv[ 0], 4), (UINT16)_mm_extract_epi16(m_xv[ 0], 3), (UINT16)_mm_extract_epi16(m_xv[ 0], 2), (UINT16)_mm_extract_epi16(m_xv[ 0], 1), (UINT16)_mm_extract_epi16(m_xv[ 0], 0));
- break;
- case RSP_V1:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 1], 7), (UINT16)_mm_extract_epi16(m_xv[ 1], 6), (UINT16)_mm_extract_epi16(m_xv[ 1], 5), (UINT16)_mm_extract_epi16(m_xv[ 1], 4), (UINT16)_mm_extract_epi16(m_xv[ 1], 3), (UINT16)_mm_extract_epi16(m_xv[ 1], 2), (UINT16)_mm_extract_epi16(m_xv[ 1], 1), (UINT16)_mm_extract_epi16(m_xv[ 1], 0));
- break;
- case RSP_V2:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 2], 7), (UINT16)_mm_extract_epi16(m_xv[ 2], 6), (UINT16)_mm_extract_epi16(m_xv[ 2], 5), (UINT16)_mm_extract_epi16(m_xv[ 2], 4), (UINT16)_mm_extract_epi16(m_xv[ 2], 3), (UINT16)_mm_extract_epi16(m_xv[ 2], 2), (UINT16)_mm_extract_epi16(m_xv[ 2], 1), (UINT16)_mm_extract_epi16(m_xv[ 2], 0));
- break;
- case RSP_V3:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 3], 7), (UINT16)_mm_extract_epi16(m_xv[ 3], 6), (UINT16)_mm_extract_epi16(m_xv[ 3], 5), (UINT16)_mm_extract_epi16(m_xv[ 3], 4), (UINT16)_mm_extract_epi16(m_xv[ 3], 3), (UINT16)_mm_extract_epi16(m_xv[ 3], 2), (UINT16)_mm_extract_epi16(m_xv[ 3], 1), (UINT16)_mm_extract_epi16(m_xv[ 3], 0));
- break;
- case RSP_V4:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 4], 7), (UINT16)_mm_extract_epi16(m_xv[ 4], 6), (UINT16)_mm_extract_epi16(m_xv[ 4], 5), (UINT16)_mm_extract_epi16(m_xv[ 4], 4), (UINT16)_mm_extract_epi16(m_xv[ 4], 3), (UINT16)_mm_extract_epi16(m_xv[ 4], 2), (UINT16)_mm_extract_epi16(m_xv[ 4], 1), (UINT16)_mm_extract_epi16(m_xv[ 4], 0));
- break;
- case RSP_V5:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 5], 7), (UINT16)_mm_extract_epi16(m_xv[ 5], 6), (UINT16)_mm_extract_epi16(m_xv[ 5], 5), (UINT16)_mm_extract_epi16(m_xv[ 5], 4), (UINT16)_mm_extract_epi16(m_xv[ 5], 3), (UINT16)_mm_extract_epi16(m_xv[ 5], 2), (UINT16)_mm_extract_epi16(m_xv[ 5], 1), (UINT16)_mm_extract_epi16(m_xv[ 5], 0));
- break;
- case RSP_V6:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 6], 7), (UINT16)_mm_extract_epi16(m_xv[ 6], 6), (UINT16)_mm_extract_epi16(m_xv[ 6], 5), (UINT16)_mm_extract_epi16(m_xv[ 6], 4), (UINT16)_mm_extract_epi16(m_xv[ 6], 3), (UINT16)_mm_extract_epi16(m_xv[ 6], 2), (UINT16)_mm_extract_epi16(m_xv[ 6], 1), (UINT16)_mm_extract_epi16(m_xv[ 6], 0));
- break;
- case RSP_V7:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 7], 7), (UINT16)_mm_extract_epi16(m_xv[ 7], 6), (UINT16)_mm_extract_epi16(m_xv[ 7], 5), (UINT16)_mm_extract_epi16(m_xv[ 7], 4), (UINT16)_mm_extract_epi16(m_xv[ 7], 3), (UINT16)_mm_extract_epi16(m_xv[ 7], 2), (UINT16)_mm_extract_epi16(m_xv[ 7], 1), (UINT16)_mm_extract_epi16(m_xv[ 7], 0));
- break;
- case RSP_V8:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 8], 7), (UINT16)_mm_extract_epi16(m_xv[ 8], 6), (UINT16)_mm_extract_epi16(m_xv[ 8], 5), (UINT16)_mm_extract_epi16(m_xv[ 8], 4), (UINT16)_mm_extract_epi16(m_xv[ 8], 3), (UINT16)_mm_extract_epi16(m_xv[ 8], 2), (UINT16)_mm_extract_epi16(m_xv[ 8], 1), (UINT16)_mm_extract_epi16(m_xv[ 8], 0));
- break;
- case RSP_V9:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 9], 7), (UINT16)_mm_extract_epi16(m_xv[ 9], 6), (UINT16)_mm_extract_epi16(m_xv[ 9], 5), (UINT16)_mm_extract_epi16(m_xv[ 9], 4), (UINT16)_mm_extract_epi16(m_xv[ 9], 3), (UINT16)_mm_extract_epi16(m_xv[ 9], 2), (UINT16)_mm_extract_epi16(m_xv[ 9], 1), (UINT16)_mm_extract_epi16(m_xv[ 9], 0));
- break;
- case RSP_V10:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[10], 7), (UINT16)_mm_extract_epi16(m_xv[10], 6), (UINT16)_mm_extract_epi16(m_xv[10], 5), (UINT16)_mm_extract_epi16(m_xv[10], 4), (UINT16)_mm_extract_epi16(m_xv[10], 3), (UINT16)_mm_extract_epi16(m_xv[10], 2), (UINT16)_mm_extract_epi16(m_xv[10], 1), (UINT16)_mm_extract_epi16(m_xv[10], 0));
- break;
- case RSP_V11:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[11], 7), (UINT16)_mm_extract_epi16(m_xv[11], 6), (UINT16)_mm_extract_epi16(m_xv[11], 5), (UINT16)_mm_extract_epi16(m_xv[11], 4), (UINT16)_mm_extract_epi16(m_xv[11], 3), (UINT16)_mm_extract_epi16(m_xv[11], 2), (UINT16)_mm_extract_epi16(m_xv[11], 1), (UINT16)_mm_extract_epi16(m_xv[11], 0));
- break;
- case RSP_V12:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[12], 7), (UINT16)_mm_extract_epi16(m_xv[12], 6), (UINT16)_mm_extract_epi16(m_xv[12], 5), (UINT16)_mm_extract_epi16(m_xv[12], 4), (UINT16)_mm_extract_epi16(m_xv[12], 3), (UINT16)_mm_extract_epi16(m_xv[12], 2), (UINT16)_mm_extract_epi16(m_xv[12], 1), (UINT16)_mm_extract_epi16(m_xv[12], 0));
- break;
- case RSP_V13:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[13], 7), (UINT16)_mm_extract_epi16(m_xv[13], 6), (UINT16)_mm_extract_epi16(m_xv[13], 5), (UINT16)_mm_extract_epi16(m_xv[13], 4), (UINT16)_mm_extract_epi16(m_xv[13], 3), (UINT16)_mm_extract_epi16(m_xv[13], 2), (UINT16)_mm_extract_epi16(m_xv[13], 1), (UINT16)_mm_extract_epi16(m_xv[13], 0));
- break;
- case RSP_V14:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[14], 7), (UINT16)_mm_extract_epi16(m_xv[14], 6), (UINT16)_mm_extract_epi16(m_xv[14], 5), (UINT16)_mm_extract_epi16(m_xv[14], 4), (UINT16)_mm_extract_epi16(m_xv[14], 3), (UINT16)_mm_extract_epi16(m_xv[14], 2), (UINT16)_mm_extract_epi16(m_xv[14], 1), (UINT16)_mm_extract_epi16(m_xv[14], 0));
- break;
- case RSP_V15:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[15], 7), (UINT16)_mm_extract_epi16(m_xv[15], 6), (UINT16)_mm_extract_epi16(m_xv[15], 5), (UINT16)_mm_extract_epi16(m_xv[15], 4), (UINT16)_mm_extract_epi16(m_xv[15], 3), (UINT16)_mm_extract_epi16(m_xv[15], 2), (UINT16)_mm_extract_epi16(m_xv[15], 1), (UINT16)_mm_extract_epi16(m_xv[15], 0));
- break;
- case RSP_V16:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[16], 7), (UINT16)_mm_extract_epi16(m_xv[16], 6), (UINT16)_mm_extract_epi16(m_xv[16], 5), (UINT16)_mm_extract_epi16(m_xv[16], 4), (UINT16)_mm_extract_epi16(m_xv[16], 3), (UINT16)_mm_extract_epi16(m_xv[16], 2), (UINT16)_mm_extract_epi16(m_xv[16], 1), (UINT16)_mm_extract_epi16(m_xv[16], 0));
- break;
- case RSP_V17:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[17], 7), (UINT16)_mm_extract_epi16(m_xv[17], 6), (UINT16)_mm_extract_epi16(m_xv[17], 5), (UINT16)_mm_extract_epi16(m_xv[17], 4), (UINT16)_mm_extract_epi16(m_xv[17], 3), (UINT16)_mm_extract_epi16(m_xv[17], 2), (UINT16)_mm_extract_epi16(m_xv[17], 1), (UINT16)_mm_extract_epi16(m_xv[17], 0));
- break;
- case RSP_V18:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[18], 7), (UINT16)_mm_extract_epi16(m_xv[18], 6), (UINT16)_mm_extract_epi16(m_xv[18], 5), (UINT16)_mm_extract_epi16(m_xv[18], 4), (UINT16)_mm_extract_epi16(m_xv[18], 3), (UINT16)_mm_extract_epi16(m_xv[18], 2), (UINT16)_mm_extract_epi16(m_xv[18], 1), (UINT16)_mm_extract_epi16(m_xv[18], 0));
- break;
- case RSP_V19:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[19], 7), (UINT16)_mm_extract_epi16(m_xv[19], 6), (UINT16)_mm_extract_epi16(m_xv[19], 5), (UINT16)_mm_extract_epi16(m_xv[19], 4), (UINT16)_mm_extract_epi16(m_xv[19], 3), (UINT16)_mm_extract_epi16(m_xv[19], 2), (UINT16)_mm_extract_epi16(m_xv[19], 1), (UINT16)_mm_extract_epi16(m_xv[19], 0));
- break;
- case RSP_V20:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[20], 7), (UINT16)_mm_extract_epi16(m_xv[20], 6), (UINT16)_mm_extract_epi16(m_xv[20], 5), (UINT16)_mm_extract_epi16(m_xv[20], 4), (UINT16)_mm_extract_epi16(m_xv[20], 3), (UINT16)_mm_extract_epi16(m_xv[20], 2), (UINT16)_mm_extract_epi16(m_xv[20], 1), (UINT16)_mm_extract_epi16(m_xv[20], 0));
- break;
- case RSP_V21:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[21], 7), (UINT16)_mm_extract_epi16(m_xv[21], 6), (UINT16)_mm_extract_epi16(m_xv[21], 5), (UINT16)_mm_extract_epi16(m_xv[21], 4), (UINT16)_mm_extract_epi16(m_xv[21], 3), (UINT16)_mm_extract_epi16(m_xv[21], 2), (UINT16)_mm_extract_epi16(m_xv[21], 1), (UINT16)_mm_extract_epi16(m_xv[21], 0));
- break;
- case RSP_V22:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[22], 7), (UINT16)_mm_extract_epi16(m_xv[22], 6), (UINT16)_mm_extract_epi16(m_xv[22], 5), (UINT16)_mm_extract_epi16(m_xv[22], 4), (UINT16)_mm_extract_epi16(m_xv[22], 3), (UINT16)_mm_extract_epi16(m_xv[22], 2), (UINT16)_mm_extract_epi16(m_xv[22], 1), (UINT16)_mm_extract_epi16(m_xv[22], 0));
- break;
- case RSP_V23:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[23], 7), (UINT16)_mm_extract_epi16(m_xv[23], 6), (UINT16)_mm_extract_epi16(m_xv[23], 5), (UINT16)_mm_extract_epi16(m_xv[23], 4), (UINT16)_mm_extract_epi16(m_xv[23], 3), (UINT16)_mm_extract_epi16(m_xv[23], 2), (UINT16)_mm_extract_epi16(m_xv[23], 1), (UINT16)_mm_extract_epi16(m_xv[23], 0));
- break;
- case RSP_V24:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[24], 7), (UINT16)_mm_extract_epi16(m_xv[24], 6), (UINT16)_mm_extract_epi16(m_xv[24], 5), (UINT16)_mm_extract_epi16(m_xv[24], 4), (UINT16)_mm_extract_epi16(m_xv[24], 3), (UINT16)_mm_extract_epi16(m_xv[24], 2), (UINT16)_mm_extract_epi16(m_xv[24], 1), (UINT16)_mm_extract_epi16(m_xv[24], 0));
- break;
- case RSP_V25:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[25], 7), (UINT16)_mm_extract_epi16(m_xv[25], 6), (UINT16)_mm_extract_epi16(m_xv[25], 5), (UINT16)_mm_extract_epi16(m_xv[25], 4), (UINT16)_mm_extract_epi16(m_xv[25], 3), (UINT16)_mm_extract_epi16(m_xv[25], 2), (UINT16)_mm_extract_epi16(m_xv[25], 1), (UINT16)_mm_extract_epi16(m_xv[25], 0));
- break;
- case RSP_V26:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[26], 7), (UINT16)_mm_extract_epi16(m_xv[26], 6), (UINT16)_mm_extract_epi16(m_xv[26], 5), (UINT16)_mm_extract_epi16(m_xv[26], 4), (UINT16)_mm_extract_epi16(m_xv[26], 3), (UINT16)_mm_extract_epi16(m_xv[26], 2), (UINT16)_mm_extract_epi16(m_xv[26], 1), (UINT16)_mm_extract_epi16(m_xv[26], 0));
- break;
- case RSP_V27:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[27], 7), (UINT16)_mm_extract_epi16(m_xv[27], 6), (UINT16)_mm_extract_epi16(m_xv[27], 5), (UINT16)_mm_extract_epi16(m_xv[27], 4), (UINT16)_mm_extract_epi16(m_xv[27], 3), (UINT16)_mm_extract_epi16(m_xv[27], 2), (UINT16)_mm_extract_epi16(m_xv[27], 1), (UINT16)_mm_extract_epi16(m_xv[27], 0));
- break;
- case RSP_V28:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[28], 7), (UINT16)_mm_extract_epi16(m_xv[28], 6), (UINT16)_mm_extract_epi16(m_xv[28], 5), (UINT16)_mm_extract_epi16(m_xv[28], 4), (UINT16)_mm_extract_epi16(m_xv[28], 3), (UINT16)_mm_extract_epi16(m_xv[28], 2), (UINT16)_mm_extract_epi16(m_xv[28], 1), (UINT16)_mm_extract_epi16(m_xv[28], 0));
- break;
- case RSP_V29:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[29], 7), (UINT16)_mm_extract_epi16(m_xv[29], 6), (UINT16)_mm_extract_epi16(m_xv[29], 5), (UINT16)_mm_extract_epi16(m_xv[29], 4), (UINT16)_mm_extract_epi16(m_xv[29], 3), (UINT16)_mm_extract_epi16(m_xv[29], 2), (UINT16)_mm_extract_epi16(m_xv[29], 1), (UINT16)_mm_extract_epi16(m_xv[29], 0));
- break;
- case RSP_V30:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[30], 7), (UINT16)_mm_extract_epi16(m_xv[30], 6), (UINT16)_mm_extract_epi16(m_xv[30], 5), (UINT16)_mm_extract_epi16(m_xv[30], 4), (UINT16)_mm_extract_epi16(m_xv[30], 3), (UINT16)_mm_extract_epi16(m_xv[30], 2), (UINT16)_mm_extract_epi16(m_xv[30], 1), (UINT16)_mm_extract_epi16(m_xv[30], 0));
- break;
- case RSP_V31:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[31], 7), (UINT16)_mm_extract_epi16(m_xv[31], 6), (UINT16)_mm_extract_epi16(m_xv[31], 5), (UINT16)_mm_extract_epi16(m_xv[31], 4), (UINT16)_mm_extract_epi16(m_xv[31], 3), (UINT16)_mm_extract_epi16(m_xv[31], 2), (UINT16)_mm_extract_epi16(m_xv[31], 1), (UINT16)_mm_extract_epi16(m_xv[31], 0));
- break;
-#else
- case RSP_V0:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 0, 0), (UINT16)VREG_S( 0, 1), (UINT16)VREG_S( 0, 2), (UINT16)VREG_S( 0, 3), (UINT16)VREG_S( 0, 4), (UINT16)VREG_S( 0, 5), (UINT16)VREG_S( 0, 6), (UINT16)VREG_S( 0, 7));
- break;
- case RSP_V1:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 1, 0), (UINT16)VREG_S( 1, 1), (UINT16)VREG_S( 1, 2), (UINT16)VREG_S( 1, 3), (UINT16)VREG_S( 1, 4), (UINT16)VREG_S( 1, 5), (UINT16)VREG_S( 1, 6), (UINT16)VREG_S( 1, 7));
- break;
- case RSP_V2:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 2, 0), (UINT16)VREG_S( 2, 1), (UINT16)VREG_S( 2, 2), (UINT16)VREG_S( 2, 3), (UINT16)VREG_S( 2, 4), (UINT16)VREG_S( 2, 5), (UINT16)VREG_S( 2, 6), (UINT16)VREG_S( 2, 7));
- break;
- case RSP_V3:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 3, 0), (UINT16)VREG_S( 3, 1), (UINT16)VREG_S( 3, 2), (UINT16)VREG_S( 3, 3), (UINT16)VREG_S( 3, 4), (UINT16)VREG_S( 3, 5), (UINT16)VREG_S( 3, 6), (UINT16)VREG_S( 3, 7));
- break;
- case RSP_V4:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 4, 0), (UINT16)VREG_S( 4, 1), (UINT16)VREG_S( 4, 2), (UINT16)VREG_S( 4, 3), (UINT16)VREG_S( 4, 4), (UINT16)VREG_S( 4, 5), (UINT16)VREG_S( 4, 6), (UINT16)VREG_S( 4, 7));
- break;
- case RSP_V5:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 5, 0), (UINT16)VREG_S( 5, 1), (UINT16)VREG_S( 5, 2), (UINT16)VREG_S( 5, 3), (UINT16)VREG_S( 5, 4), (UINT16)VREG_S( 5, 5), (UINT16)VREG_S( 5, 6), (UINT16)VREG_S( 5, 7));
- break;
- case RSP_V6:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 6, 0), (UINT16)VREG_S( 6, 1), (UINT16)VREG_S( 6, 2), (UINT16)VREG_S( 6, 3), (UINT16)VREG_S( 6, 4), (UINT16)VREG_S( 6, 5), (UINT16)VREG_S( 6, 6), (UINT16)VREG_S( 6, 7));
- break;
- case RSP_V7:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 7, 0), (UINT16)VREG_S( 7, 1), (UINT16)VREG_S( 7, 2), (UINT16)VREG_S( 7, 3), (UINT16)VREG_S( 7, 4), (UINT16)VREG_S( 7, 5), (UINT16)VREG_S( 7, 6), (UINT16)VREG_S( 7, 7));
- break;
- case RSP_V8:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 8, 0), (UINT16)VREG_S( 8, 1), (UINT16)VREG_S( 8, 2), (UINT16)VREG_S( 8, 3), (UINT16)VREG_S( 8, 4), (UINT16)VREG_S( 8, 5), (UINT16)VREG_S( 8, 6), (UINT16)VREG_S( 8, 7));
- break;
- case RSP_V9:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 9, 0), (UINT16)VREG_S( 9, 1), (UINT16)VREG_S( 9, 2), (UINT16)VREG_S( 9, 3), (UINT16)VREG_S( 9, 4), (UINT16)VREG_S( 9, 5), (UINT16)VREG_S( 9, 6), (UINT16)VREG_S( 9, 7));
- break;
- case RSP_V10:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(10, 0), (UINT16)VREG_S(10, 1), (UINT16)VREG_S(10, 2), (UINT16)VREG_S(10, 3), (UINT16)VREG_S(10, 4), (UINT16)VREG_S(10, 5), (UINT16)VREG_S(10, 6), (UINT16)VREG_S(10, 7));
- break;
- case RSP_V11:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(11, 0), (UINT16)VREG_S(11, 1), (UINT16)VREG_S(11, 2), (UINT16)VREG_S(11, 3), (UINT16)VREG_S(11, 4), (UINT16)VREG_S(11, 5), (UINT16)VREG_S(11, 6), (UINT16)VREG_S(11, 7));
- break;
- case RSP_V12:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(12, 0), (UINT16)VREG_S(12, 1), (UINT16)VREG_S(12, 2), (UINT16)VREG_S(12, 3), (UINT16)VREG_S(12, 4), (UINT16)VREG_S(12, 5), (UINT16)VREG_S(12, 6), (UINT16)VREG_S(12, 7));
- break;
- case RSP_V13:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(13, 0), (UINT16)VREG_S(13, 1), (UINT16)VREG_S(13, 2), (UINT16)VREG_S(13, 3), (UINT16)VREG_S(13, 4), (UINT16)VREG_S(13, 5), (UINT16)VREG_S(13, 6), (UINT16)VREG_S(13, 7));
- break;
- case RSP_V14:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(14, 0), (UINT16)VREG_S(14, 1), (UINT16)VREG_S(14, 2), (UINT16)VREG_S(14, 3), (UINT16)VREG_S(14, 4), (UINT16)VREG_S(14, 5), (UINT16)VREG_S(14, 6), (UINT16)VREG_S(14, 7));
- break;
- case RSP_V15:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(15, 0), (UINT16)VREG_S(15, 1), (UINT16)VREG_S(15, 2), (UINT16)VREG_S(15, 3), (UINT16)VREG_S(15, 4), (UINT16)VREG_S(15, 5), (UINT16)VREG_S(15, 6), (UINT16)VREG_S(15, 7));
- break;
- case RSP_V16:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(16, 0), (UINT16)VREG_S(16, 1), (UINT16)VREG_S(16, 2), (UINT16)VREG_S(16, 3), (UINT16)VREG_S(16, 4), (UINT16)VREG_S(16, 5), (UINT16)VREG_S(16, 6), (UINT16)VREG_S(16, 7));
- break;
- case RSP_V17:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(17, 0), (UINT16)VREG_S(17, 1), (UINT16)VREG_S(17, 2), (UINT16)VREG_S(17, 3), (UINT16)VREG_S(17, 4), (UINT16)VREG_S(17, 5), (UINT16)VREG_S(17, 6), (UINT16)VREG_S(17, 7));
- break;
- case RSP_V18:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(18, 0), (UINT16)VREG_S(18, 1), (UINT16)VREG_S(18, 2), (UINT16)VREG_S(18, 3), (UINT16)VREG_S(18, 4), (UINT16)VREG_S(18, 5), (UINT16)VREG_S(18, 6), (UINT16)VREG_S(18, 7));
- break;
- case RSP_V19:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(19, 0), (UINT16)VREG_S(19, 1), (UINT16)VREG_S(19, 2), (UINT16)VREG_S(19, 3), (UINT16)VREG_S(19, 4), (UINT16)VREG_S(19, 5), (UINT16)VREG_S(19, 6), (UINT16)VREG_S(19, 7));
- break;
- case RSP_V20:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(20, 0), (UINT16)VREG_S(20, 1), (UINT16)VREG_S(20, 2), (UINT16)VREG_S(20, 3), (UINT16)VREG_S(20, 4), (UINT16)VREG_S(20, 5), (UINT16)VREG_S(20, 6), (UINT16)VREG_S(20, 7));
- break;
- case RSP_V21:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(21, 0), (UINT16)VREG_S(21, 1), (UINT16)VREG_S(21, 2), (UINT16)VREG_S(21, 3), (UINT16)VREG_S(21, 4), (UINT16)VREG_S(21, 5), (UINT16)VREG_S(21, 6), (UINT16)VREG_S(21, 7));
- break;
- case RSP_V22:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(22, 0), (UINT16)VREG_S(22, 1), (UINT16)VREG_S(22, 2), (UINT16)VREG_S(22, 3), (UINT16)VREG_S(22, 4), (UINT16)VREG_S(22, 5), (UINT16)VREG_S(22, 6), (UINT16)VREG_S(22, 7));
- break;
- case RSP_V23:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(23, 0), (UINT16)VREG_S(23, 1), (UINT16)VREG_S(23, 2), (UINT16)VREG_S(23, 3), (UINT16)VREG_S(23, 4), (UINT16)VREG_S(23, 5), (UINT16)VREG_S(23, 6), (UINT16)VREG_S(23, 7));
- break;
- case RSP_V24:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(24, 0), (UINT16)VREG_S(24, 1), (UINT16)VREG_S(24, 2), (UINT16)VREG_S(24, 3), (UINT16)VREG_S(24, 4), (UINT16)VREG_S(24, 5), (UINT16)VREG_S(24, 6), (UINT16)VREG_S(24, 7));
- break;
- case RSP_V25:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(25, 0), (UINT16)VREG_S(25, 1), (UINT16)VREG_S(25, 2), (UINT16)VREG_S(25, 3), (UINT16)VREG_S(25, 4), (UINT16)VREG_S(25, 5), (UINT16)VREG_S(25, 6), (UINT16)VREG_S(25, 7));
- break;
- case RSP_V26:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(26, 0), (UINT16)VREG_S(26, 1), (UINT16)VREG_S(26, 2), (UINT16)VREG_S(26, 3), (UINT16)VREG_S(26, 4), (UINT16)VREG_S(26, 5), (UINT16)VREG_S(26, 6), (UINT16)VREG_S(26, 7));
- break;
- case RSP_V27:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(27, 0), (UINT16)VREG_S(27, 1), (UINT16)VREG_S(27, 2), (UINT16)VREG_S(27, 3), (UINT16)VREG_S(27, 4), (UINT16)VREG_S(27, 5), (UINT16)VREG_S(27, 6), (UINT16)VREG_S(27, 7));
- break;
- case RSP_V28:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(28, 0), (UINT16)VREG_S(28, 1), (UINT16)VREG_S(28, 2), (UINT16)VREG_S(28, 3), (UINT16)VREG_S(28, 4), (UINT16)VREG_S(28, 5), (UINT16)VREG_S(28, 6), (UINT16)VREG_S(28, 7));
- break;
- case RSP_V29:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(29, 0), (UINT16)VREG_S(29, 1), (UINT16)VREG_S(29, 2), (UINT16)VREG_S(29, 3), (UINT16)VREG_S(29, 4), (UINT16)VREG_S(29, 5), (UINT16)VREG_S(29, 6), (UINT16)VREG_S(29, 7));
- break;
- case RSP_V30:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(30, 0), (UINT16)VREG_S(30, 1), (UINT16)VREG_S(30, 2), (UINT16)VREG_S(30, 3), (UINT16)VREG_S(30, 4), (UINT16)VREG_S(30, 5), (UINT16)VREG_S(30, 6), (UINT16)VREG_S(30, 7));
- break;
- case RSP_V31:
- string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(31, 0), (UINT16)VREG_S(31, 1), (UINT16)VREG_S(31, 2), (UINT16)VREG_S(31, 3), (UINT16)VREG_S(31, 4), (UINT16)VREG_S(31, 5), (UINT16)VREG_S(31, 6), (UINT16)VREG_S(31, 7));
- break;
-#endif
-
+ m_cop2->state_string_export(index, string);
+ }
+ else if (index == STATE_GENFLAGS)
+ {
+ string.printf("%s","");
}
}
@@ -795,2169 +548,24 @@ void rsp_device::device_stop()
m_exec_output = NULL;
/* clean up the DRC */
- if ( m_drcuml )
+ if (m_drcuml)
{
auto_free(machine(), m_drcuml);
}
- if (m_drcfe )
+ if (m_drcfe)
{
auto_free(machine(), m_drcfe);
}
-}
-
-void rsp_device::device_reset()
-{
- m_nextpc = ~0;
-}
-
-void rsp_device::handle_lwc2(UINT32 op)
-{
- int i, end;
- UINT32 ea;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- offset |= 0xffffffc0;
-
- switch ((op >> 11) & 0x1f)
- {
- case 0x00: /* LBV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 00000 | IIII | Offset |
- // --------------------------------------------------
- //
- // Load 1 byte to vector byte index
-
- ea = (base) ? m_rsp_state->r[base] + offset : offset;
- VREG_B(dest, index) = READ8(ea);
- break;
- }
- case 0x01: /* LSV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 00001 | IIII | Offset |
- // --------------------------------------------------
- //
- // Loads 2 bytes starting from vector byte index
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 2) : (offset * 2);
-
- end = index + 2;
-
- for (i=index; i < end; i++)
- {
- VREG_B(dest, i) = READ8(ea);
- ea++;
- }
- break;
- }
- case 0x02: /* LLV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 00010 | IIII | Offset |
- // --------------------------------------------------
- //
- // Loads 4 bytes starting from vector byte index
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 4) : (offset * 4);
-
- end = index + 4;
-
- for (i=index; i < end; i++)
- {
- VREG_B(dest, i) = READ8(ea);
- ea++;
- }
- break;
- }
- case 0x03: /* LDV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 00011 | IIII | Offset |
- // --------------------------------------------------
- //
- // Loads 8 bytes starting from vector byte index
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- end = index + 8;
-
- for (i=index; i < end; i++)
- {
- VREG_B(dest, i) = READ8(ea);
- ea++;
- }
- break;
- }
- case 0x04: /* LQV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 00100 | IIII | Offset |
- // --------------------------------------------------
- //
- // Loads up to 16 bytes starting from vector byte index
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- end = index + (16 - (ea & 0xf));
- if (end > 16) end = 16;
-
- for (i=index; i < end; i++)
- {
- VREG_B(dest, i) = READ8(ea);
- ea++;
- }
- break;
- }
- case 0x05: /* LRV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 00101 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores up to 16 bytes starting from right side until 16-byte boundary
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- index = 16 - ((ea & 0xf) - index);
- end = 16;
- ea &= ~0xf;
-
- for (i=index; i < end; i++)
- {
- VREG_B(dest, i) = READ8(ea);
- ea++;
- }
- break;
- }
- case 0x06: /* LPV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 00110 | IIII | Offset |
- // --------------------------------------------------
- //
- // Loads a byte as the upper 8 bits of each element
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- for (i=0; i < 8; i++)
- {
- VREG_S(dest, i) = READ8(ea + (((16-index) + i) & 0xf)) << 8;
- }
- break;
- }
- case 0x07: /* LUV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 00111 | IIII | Offset |
- // --------------------------------------------------
- //
- // Loads a byte as the bits 14-7 of each element
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- for (i=0; i < 8; i++)
- {
- VREG_S(dest, i) = READ8(ea + (((16-index) + i) & 0xf)) << 7;
- }
- break;
- }
- case 0x08: /* LHV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 01000 | IIII | Offset |
- // --------------------------------------------------
- //
- // Loads a byte as the bits 14-7 of each element, with 2-byte stride
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- for (i=0; i < 8; i++)
- {
- VREG_S(dest, i) = READ8(ea + (((16-index) + (i<<1)) & 0xf)) << 7;
- }
- break;
- }
- case 0x09: /* LFV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 01001 | IIII | Offset |
- // --------------------------------------------------
- //
- // Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- // not sure what happens if 16-byte boundary is crossed...
-
- end = (index >> 1) + 4;
-
- for (i=index >> 1; i < end; i++)
- {
- VREG_S(dest, i) = READ8(ea) << 7;
- ea += 4;
- }
- break;
- }
- case 0x0a: /* LWV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 01010 | IIII | Offset |
- // --------------------------------------------------
- //
- // Loads the full 128-bit vector starting from vector byte index and wrapping to index 0
- // after byte index 15
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- // not sure what happens if 16-byte boundary is crossed...
- if ((ea & 0xf) > 0) fatalerror("RSP: LWV: 16-byte boundary crossing at %08X, recheck this!\n", m_ppc);
-
- end = (16 - index) + 16;
-
- for (i=(16 - index); i < end; i++)
- {
- VREG_B(dest, i & 0xf) = READ8(ea);
- ea += 4;
- }
- break;
- }
- case 0x0b: /* LTV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset |
- // --------------------------------------------------
- //
- // Loads one element to maximum of 8 vectors, while incrementing element index
-
- // FIXME: has a small problem with odd indices
-
- int element;
- int vs = dest;
- int ve = dest + 8;
- if (ve > 32)
- ve = 32;
-
- element = 7 - (index >> 1);
-
- if (index & 1) fatalerror("RSP: LTV: index = %d\n", index);
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- ea = ((ea + 8) & ~0xf) + (index & 1);
- for (i=vs; i < ve; i++)
- {
- element = ((8 - (index >> 1) + (i-vs)) << 1);
- VREG_B(i, (element & 0xf)) = READ8(ea);
- VREG_B(i, ((element + 1) & 0xf)) = READ8(ea + 1);
-
- ea += 2;
- }
- break;
- }
-
- default:
- {
- unimplemented_opcode(op);
- break;
- }
- }
-}
-
-void rsp_device::handle_swc2(UINT32 op)
-{
- int i, end;
- int eaoffset;
- UINT32 ea;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- offset |= 0xffffffc0;
-
- switch ((op >> 11) & 0x1f)
- {
- case 0x00: /* SBV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores 1 byte from vector byte index
-
- ea = (base) ? m_rsp_state->r[base] + offset : offset;
- WRITE8(ea, VREG_B(dest, index));
- break;
- }
- case 0x01: /* SSV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores 2 bytes starting from vector byte index
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 2) : (offset * 2);
-
- end = index + 2;
-
- for (i=index; i < end; i++)
- {
- WRITE8(ea, VREG_B(dest, i));
- ea++;
- }
- break;
- }
- case 0x02: /* SLV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores 4 bytes starting from vector byte index
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 4) : (offset * 4);
-
- end = index + 4;
-
- for (i=index; i < end; i++)
- {
- WRITE8(ea, VREG_B(dest, i));
- ea++;
- }
- break;
- }
- case 0x03: /* SDV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores 8 bytes starting from vector byte index
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- end = index + 8;
-
- for (i=index; i < end; i++)
- {
- WRITE8(ea, VREG_B(dest, i));
- ea++;
- }
- break;
- }
- case 0x04: /* SQV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores up to 16 bytes starting from vector byte index until 16-byte boundary
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- end = index + (16 - (ea & 0xf));
-
- for (i=index; i < end; i++)
- {
- WRITE8(ea, VREG_B(dest, i & 0xf));
- ea++;
- }
- break;
- }
- case 0x05: /* SRV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores up to 16 bytes starting from right side until 16-byte boundary
-
- int o;
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- end = index + (ea & 0xf);
- o = (16 - (ea & 0xf)) & 0xf;
- ea &= ~0xf;
-
- for (i=index; i < end; i++)
- {
- WRITE8(ea, VREG_B(dest, ((i + o) & 0xf)));
- ea++;
- }
- break;
- }
- case 0x06: /* SPV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores upper 8 bits of each element
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
- end = index + 8;
-
- for (i=index; i < end; i++)
- {
- if ((i & 0xf) < 8)
- {
- WRITE8(ea, VREG_B(dest, ((i & 0xf) << 1)));
- }
- else
- {
- WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7);
- }
- ea++;
- }
- break;
- }
- case 0x07: /* SUV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores bits 14-7 of each element
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
- end = index + 8;
-
- for (i=index; i < end; i++)
- {
- if ((i & 0xf) < 8)
- {
- WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7);
- }
- else
- {
- WRITE8(ea, VREG_B(dest, ((i & 0x7) << 1)));
- }
- ea++;
- }
- break;
- }
- case 0x08: /* SHV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores bits 14-7 of each element, with 2-byte stride
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- for (i=0; i < 8; i++)
- {
- UINT8 d = ((VREG_B(dest, ((index + (i << 1) + 0) & 0xf))) << 1) |
- ((VREG_B(dest, ((index + (i << 1) + 1) & 0xf))) >> 7);
-
- WRITE8(ea, d);
- ea += 2;
- }
- break;
- }
- case 0x09: /* SFV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores bits 14-7 of upper or lower quad, with 4-byte stride
-
- // FIXME: only works for index 0 and index 8
-
- if (index & 0x7) osd_printf_debug("RSP: SFV: index = %d at %08X\n", index, m_ppc);
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- eaoffset = ea & 0xf;
- ea &= ~0xf;
-
- end = (index >> 1) + 4;
-
- for (i=index >> 1; i < end; i++)
- {
- WRITE8(ea + (eaoffset & 0xf), VREG_S(dest, i) >> 7);
- eaoffset += 4;
- }
- break;
- }
- case 0x0a: /* SWV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores the full 128-bit vector starting from vector byte index and wrapping to index 0
- // after byte index 15
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- eaoffset = ea & 0xf;
- ea &= ~0xf;
-
- end = index + 16;
-
- for (i=index; i < end; i++)
- {
- WRITE8(ea + (eaoffset & 0xf), VREG_B(dest, i & 0xf));
- eaoffset++;
- }
- break;
- }
- case 0x0b: /* STV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores one element from maximum of 8 vectors, while incrementing element index
-
- int element;
- int vs = dest;
- int ve = dest + 8;
- if (ve > 32)
- ve = 32;
-
- element = 8 - (index >> 1);
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- eaoffset = (ea & 0xf) + (element * 2);
- ea &= ~0xf;
-
- for (i=vs; i < ve; i++)
- {
- WRITE16(ea + (eaoffset & 0xf), VREG_S(i, element & 0x7));
- eaoffset += 2;
- element++;
- }
- break;
- }
-
- default:
- {
- unimplemented_opcode(op);
- break;
- }
- }
-}
-inline UINT16 rsp_device::SATURATE_ACCUM(int accum, int slice, UINT16 negative, UINT16 positive)
-{
- if ((INT16)ACCUM_H(accum) < 0)
+ if (m_cop2)
{
- if ((UINT16)(ACCUM_H(accum)) != 0xffff)
- {
- return negative;
- }
- else
- {
- if ((INT16)ACCUM_M(accum) >= 0)
- {
- return negative;
- }
- else
- {
- if (slice == 0)
- {
- return ACCUM_L(accum);
- }
- else if (slice == 1)
- {
- return ACCUM_M(accum);
- }
- }
- }
+ auto_free(machine(), m_cop2);
}
- else
- {
- if ((UINT16)(ACCUM_H(accum)) != 0)
- {
- return positive;
- }
- else
- {
- if ((INT16)ACCUM_M(accum) < 0)
- {
- return positive;
- }
- else
- {
- if (slice == 0)
- {
- return ACCUM_L(accum);
- }
- else
- {
- return ACCUM_M(accum);
- }
- }
- }
- }
-
- return 0;
}
-inline UINT16 rsp_device::SATURATE_ACCUM1(int accum, UINT16 negative, UINT16 positive)
-{
- if ((INT16)ACCUM_H(accum) < 0)
- {
- if ((UINT16)(ACCUM_H(accum)) != 0xffff)
- {
- return negative;
- }
- else
- {
- if ((INT16)ACCUM_M(accum) >= 0)
- {
- return negative;
- }
- else
- {
- return ACCUM_M(accum);
- }
- }
- }
- else
- {
- if ((UINT16)(ACCUM_H(accum)) != 0)
- {
- return positive;
- }
- else
- {
- if ((INT16)ACCUM_M(accum) < 0)
- {
- return positive;
- }
- else
- {
- return ACCUM_M(accum);
- }
- }
- }
-}
-
-#define WRITEBACK_RESULT() {memcpy(&m_v[VDREG].s[0], &vres[0], 16);}
-
-void rsp_device::handle_vector_ops(UINT32 op)
+void rsp_device::device_reset()
{
- int i;
- UINT32 VS1REG = (op >> 11) & 0x1f;
- UINT32 VS2REG = (op >> 16) & 0x1f;
- UINT32 VDREG = (op >> 6) & 0x1f;
- UINT32 EL = (op >> 21) & 0xf;
- INT16 vres[8];
-
- // Opcode legend:
- // E = VS2 element type
- // S = VS1, Source vector 1
- // T = VS2, Source vector 2
- // D = Destination vector
-
- switch (op & 0x3f)
- {
- case 0x00: /* VMULF */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000000 |
- // ------------------------------------------------------
- //
- // Multiplies signed integer by signed integer * 2
-
- for (i=0; i < 8; i++)
- {
- INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
- INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- if (s1 == -32768 && s2 == -32768)
- {
- // overflow
- ACCUM_H(i) = 0;
- ACCUM_M(i) = -32768;
- ACCUM_L(i) = -32768;
- vres[i] = 0x7fff;
- }
- else
- {
- INT64 r = s1 * s2 * 2;
- r += 0x8000; // rounding ?
- ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit
- ACCUM_M(i) = (INT16)(r >> 16);
- ACCUM_L(i) = (UINT16)(r);
- vres[i] = ACCUM_M(i);
- }
- }
- WRITEBACK_RESULT();
-
- break;
- }
-
- case 0x01: /* VMULU */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 |
- // ------------------------------------------------------
- //
-
- for (i=0; i < 8; i++)
- {
- INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
- INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- INT64 r = s1 * s2 * 2;
- r += 0x8000; // rounding ?
-
- ACCUM_H(i) = (UINT16)(r >> 32);
- ACCUM_M(i) = (UINT16)(r >> 16);
- ACCUM_L(i) = (UINT16)(r);
-
- if (r < 0)
- {
- vres[i] = 0;
- }
- else if (((INT16)(ACCUM_H(i)) ^ (INT16)(ACCUM_M(i))) < 0)
- {
- vres[i] = -1;
- }
- else
- {
- vres[i] = ACCUM_M(i);
- }
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x04: /* VMUDL */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000100 |
- // ------------------------------------------------------
- //
- // Multiplies unsigned fraction by unsigned fraction
- // Stores the higher 16 bits of the 32-bit result to accumulator
- // The low slice of accumulator is stored into destination element
-
- for (i=0; i < 8; i++)
- {
- UINT32 s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
- UINT32 s2 = (UINT32)(UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
- UINT32 r = s1 * s2;
-
- ACCUM_H(i) = 0;
- ACCUM_M(i) = 0;
- ACCUM_L(i) = (UINT16)(r >> 16);
-
- vres[i] = ACCUM_L(i);
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x05: /* VMUDM */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000101 |
- // ------------------------------------------------------
- //
- // Multiplies signed integer by unsigned fraction
- // The result is stored into accumulator
- // The middle slice of accumulator is stored into destination element
-
- for (i=0; i < 8; i++)
- {
- INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
- INT32 s2 = (UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i)); // not sign-extended
- INT32 r = s1 * s2;
-
- ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit
- ACCUM_M(i) = (INT16)(r >> 16);
- ACCUM_L(i) = (UINT16)(r);
-
- vres[i] = ACCUM_M(i);
- }
- WRITEBACK_RESULT();
- break;
-
- }
-
- case 0x06: /* VMUDN */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 |
- // ------------------------------------------------------
- //
- // Multiplies unsigned fraction by signed integer
- // The result is stored into accumulator
- // The low slice of accumulator is stored into destination element
-
- for (i=0; i < 8; i++)
- {
- INT32 s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended
- INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
- INT32 r = s1 * s2;
-
- ACCUM_H(i) = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit
- ACCUM_M(i) = (INT16)(r >> 16);
- ACCUM_L(i) = (UINT16)(r);
-
- vres[i] = ACCUM_L(i);
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x07: /* VMUDH */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000111 |
- // ------------------------------------------------------
- //
- // Multiplies signed integer by signed integer
- // The result is stored into highest 32 bits of accumulator, the low slice is zero
- // The highest 32 bits of accumulator is saturated into destination element
-
- for (i=0; i < 8; i++)
- {
- INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
- INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
- INT32 r = s1 * s2;
-
- ACCUM_H(i) = (INT16)(r >> 16);
- ACCUM_M(i) = (UINT16)(r);
- ACCUM_L(i) = 0;
-
- if (r < -32768) r = -32768;
- if (r > 32767) r = 32767;
- vres[i] = (INT16)(r);
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x08: /* VMACF */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001000 |
- // ------------------------------------------------------
- //
- // Multiplies signed integer by signed integer * 2
- // The result is added to accumulator
-
- for (i=0; i < 8; i++)
- {
- INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
- INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
- INT32 r = s1 * s2;
-
- UINT64 q = (UINT64)(UINT16)ACCUM_LL(i);
- q |= (((UINT64)(UINT16)ACCUM_L(i)) << 16);
- q |= (((UINT64)(UINT16)ACCUM_M(i)) << 32);
- q |= (((UINT64)(UINT16)ACCUM_H(i)) << 48);
-
- q += (INT64)(r) << 17;
-
- ACCUM_LL(i) = (UINT16)q;
- ACCUM_L(i) = (UINT16)(q >> 16);
- ACCUM_M(i) = (UINT16)(q >> 32);
- ACCUM_H(i) = (UINT16)(q >> 48);
-
- vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x09: /* VMACU */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 |
- // ------------------------------------------------------
- //
-
- for (i = 0; i < 8; i++)
- {
- INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
- INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
- INT32 r1 = s1 * s2;
- UINT32 r2 = (UINT16)ACCUM_L(i) + ((UINT16)(r1) * 2);
- UINT32 r3 = (UINT16)ACCUM_M(i) + (UINT16)((r1 >> 16) * 2) + (UINT16)(r2 >> 16);
-
- ACCUM_L(i) = (UINT16)(r2);
- ACCUM_M(i) = (UINT16)(r3);
- ACCUM_H(i) += (UINT16)(r3 >> 16) + (UINT16)(r1 >> 31);
-
- if ((INT16)ACCUM_H(i) < 0)
- {
- vres[i] = 0;
- }
- else
- {
- if (ACCUM_H(i) != 0)
- {
- vres[i] = 0xffffu;
- }
- else
- {
- if ((INT16)ACCUM_M(i) < 0)
- {
- vres[i] = 0xffffu;
- }
- else
- {
- vres[i] = ACCUM_M(i);
- }
- }
- }
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x0c: /* VMADL */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001100 |
- // ------------------------------------------------------
- //
- // Multiplies unsigned fraction by unsigned fraction
- // Adds the higher 16 bits of the 32-bit result to accumulator
- // The low slice of accumulator is stored into destination element
-
- for (i = 0; i < 8; i++)
- {
- UINT32 s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
- UINT32 s2 = (UINT32)(UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
- UINT32 r1 = s1 * s2;
- UINT32 r2 = (UINT16)ACCUM_L(i) + (r1 >> 16);
- UINT32 r3 = (UINT16)ACCUM_M(i) + (r2 >> 16);
-
- ACCUM_L(i) = (UINT16)(r2);
- ACCUM_M(i) = (UINT16)(r3);
- ACCUM_H(i) += (INT16)(r3 >> 16);
-
- vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x0d: /* VMADM */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 |
- // ------------------------------------------------------
- //
- // Multiplies signed integer by unsigned fraction
- // The result is added into accumulator
- // The middle slice of accumulator is stored into destination element
-
- for (i=0; i < 8; i++)
- {
- UINT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
- UINT32 s2 = (UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i)); // not sign-extended
- UINT32 r1 = s1 * s2;
- UINT32 r2 = (UINT16)ACCUM_L(i) + (UINT16)(r1);
- UINT32 r3 = (UINT16)ACCUM_M(i) + (r1 >> 16) + (r2 >> 16);
-
- ACCUM_L(i) = (UINT16)(r2);
- ACCUM_M(i) = (UINT16)(r3);
- ACCUM_H(i) += (UINT16)(r3 >> 16);
- if ((INT32)(r1) < 0)
- ACCUM_H(i) -= 1;
-
- vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x0e: /* VMADN */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 |
- // ------------------------------------------------------
- //
- // Multiplies unsigned fraction by signed integer
- // The result is added into accumulator
- // The low slice of accumulator is stored into destination element
-
- for (i=0; i < 8; i++)
- {
- INT32 s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended
- INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- UINT64 q = (UINT64)ACCUM_LL(i);
- q |= (((UINT64)ACCUM_L(i)) << 16);
- q |= (((UINT64)ACCUM_M(i)) << 32);
- q |= (((UINT64)ACCUM_H(i)) << 48);
- q += (INT64)(s1*s2) << 16;
-
- ACCUM_LL(i) = (UINT16)q;
- ACCUM_L(i) = (UINT16)(q >> 16);
- ACCUM_M(i) = (UINT16)(q >> 32);
- ACCUM_H(i) = (UINT16)(q >> 48);
-
- vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
- }
- WRITEBACK_RESULT();
-
- break;
- }
-
- case 0x0f: /* VMADH */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001111 |
- // ------------------------------------------------------
- //
- // Multiplies signed integer by signed integer
- // The result is added into highest 32 bits of accumulator, the low slice is zero
- // The highest 32 bits of accumulator is saturated into destination element
-
- for (i = 0; i < 8; i++)
- {
- INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
- INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- INT32 accum = (UINT32)(UINT16)ACCUM_M(i);
- accum |= ((UINT32)((UINT16)ACCUM_H(i))) << 16;
- accum += s1 * s2;
-
- ACCUM_H(i) = (UINT16)(accum >> 16);
- ACCUM_M(i) = (UINT16)accum;
-
- vres[i] = SATURATE_ACCUM1(i, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
-
- break;
- }
-
- case 0x10: /* VADD */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010000 |
- // ------------------------------------------------------
- //
- // Adds two vector registers and carry flag, the result is saturated to 32767
-
- // TODO: check VS2REG == VDREG
-
- for (i=0; i < 8; i++)
- {
- INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
- INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
- INT32 r = s1 + s2 + (CARRY_FLAG(i) != 0 ? 1 : 0);
-
- ACCUM_L(i) = (INT16)(r);
-
- if (r > 32767) r = 32767;
- if (r < -32768) r = -32768;
- vres[i] = (INT16)(r);
- }
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x11: /* VSUB */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010001 |
- // ------------------------------------------------------
- //
- // Subtracts two vector registers and carry flag, the result is saturated to -32768
-
- // TODO: check VS2REG == VDREG
-
- for (i = 0; i < 8; i++)
- {
- INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
- INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
- INT32 r = s1 - s2 - (CARRY_FLAG(i) != 0 ? 1 : 0);
-
- ACCUM_L(i) = (INT16)(r);
-
- if (r > 32767) r = 32767;
- if (r < -32768) r = -32768;
-
- vres[i] = (INT16)(r);
- }
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x13: /* VABS */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010011 |
- // ------------------------------------------------------
- //
- // Changes the sign of source register 2 if source register 1 is negative and stores
- // the result to destination register
-
- for (i=0; i < 8; i++)
- {
- INT16 s1 = (INT16)VREG_S(VS1REG, i);
- INT16 s2 = (INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- if (s1 < 0)
- {
- if (s2 == -32768)
- {
- vres[i] = 32767;
- }
- else
- {
- vres[i] = -s2;
- }
- }
- else if (s1 > 0)
- {
- vres[i] = s2;
- }
- else
- {
- vres[i] = 0;
- }
-
- ACCUM_L(i) = vres[i];
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x14: /* VADDC */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010100 |
- // ------------------------------------------------------
- //
- // Adds two vector registers, the carry out is stored into carry register
-
- // TODO: check VS2REG = VDREG
-
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
-
- for (i=0; i < 8; i++)
- {
- INT32 s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
- INT32 s2 = (UINT32)(UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
- INT32 r = s1 + s2;
-
- vres[i] = (INT16)(r);
- ACCUM_L(i) = (INT16)(r);
-
- if (r & 0xffff0000)
- {
- SET_CARRY_FLAG(i);
- }
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x15: /* VSUBC */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010101 |
- // ------------------------------------------------------
- //
- // Subtracts two vector registers, the carry out is stored into carry register
-
- // TODO: check VS2REG = VDREG
-
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
-
- for (i=0; i < 8; i++)
- {
- INT32 s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
- INT32 s2 = (UINT32)(UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
- INT32 r = s1 - s2;
-
- vres[i] = (INT16)(r);
- ACCUM_L(i) = (UINT16)(r);
-
- if ((UINT16)(r) != 0)
- {
- SET_ZERO_FLAG(i);
- }
- if (r & 0xffff0000)
- {
- SET_CARRY_FLAG(i);
- }
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x1d: /* VSAW */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 011101 |
- // ------------------------------------------------------
- //
- // Stores high, middle or low slice of accumulator to destination vector
-
- switch (EL)
- {
- case 0x08: // VSAWH
- {
- for (i=0; i < 8; i++)
- {
- VREG_S(VDREG, i) = ACCUM_H(i);
- }
- break;
- }
- case 0x09: // VSAWM
- {
- for (i=0; i < 8; i++)
- {
- VREG_S(VDREG, i) = ACCUM_M(i);
- }
- break;
- }
- case 0x0a: // VSAWL
- {
- for (i=0; i < 8; i++)
- {
- VREG_S(VDREG, i) = ACCUM_L(i);
- }
- break;
- }
- default: //fatalerror("RSP: VSAW: el = %d\n", EL);//???????
- printf("RSP: VSAW: el = %d\n", EL);//??? ???
- exit(0);
- }
- break;
- }
-
- case 0x20: /* VLT */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100000 |
- // ------------------------------------------------------
- //
- // Sets compare flags if elements in VS1 are less than VS2
- // Moves the element in VS2 to destination vector
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (i=0; i < 8; i++)
- {
- INT16 s1, s2;
- s1 = VREG_S(VS1REG, i);
- s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
- if (s1 < s2)
- {
- SET_COMPARE_FLAG(i);
- }
- else if (s1 == s2)
- {
- if (ZERO_FLAG(i) != 0 && CARRY_FLAG(i) != 0)
- {
- SET_COMPARE_FLAG(i);
- }
- }
-
- if (COMPARE_FLAG(i) != 0)
- {
- vres[i] = s1;
- }
- else
- {
- vres[i] = s2;
- }
-
- ACCUM_L(i) = vres[i];
- }
-
- CLEAR_CARRY_FLAGS();
- CLEAR_ZERO_FLAGS();
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x21: /* VEQ */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100001 |
- // ------------------------------------------------------
- //
- // Sets compare flags if elements in VS1 are equal with VS2
- // Moves the element in VS2 to destination vector
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (i = 0; i < 8; i++)
- {
- INT16 s1 = VREG_S(VS1REG, i);
- INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- if ((s1 == s2) && ZERO_FLAG(i) == 0)
- {
- SET_COMPARE_FLAG(i);
- vres[i] = s1;
- }
- else
- {
- vres[i] = s2;
- }
- ACCUM_L(i) = vres[i];
- }
-
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x22: /* VNE */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100010 |
- // ------------------------------------------------------
- //
- // Sets compare flags if elements in VS1 are not equal with VS2
- // Moves the element in VS2 to destination vector
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (i = 0; i < 8; i++)
- {
- INT16 s1 = VREG_S(VS1REG, i);
- INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- if (s1 != s2 || ZERO_FLAG(i) != 0)
- {
- SET_COMPARE_FLAG(i);
- vres[i] = s1;
- }
- else
- {
- vres[i] = s2;
- }
- ACCUM_L(i) = vres[i];
- }
-
- CLEAR_CARRY_FLAGS();
- CLEAR_ZERO_FLAGS();
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x23: /* VGE */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100011 |
- // ------------------------------------------------------
- //
- // Sets compare flags if elements in VS1 are greater or equal with VS2
- // Moves the element in VS2 to destination vector
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (i=0; i < 8; i++)
- {
- INT16 s1 = VREG_S(VS1REG, i);
- INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- if ((s1 == s2 && (ZERO_FLAG(i) == 0 || CARRY_FLAG(i) == 0)) || s1 > s2)
- {
- SET_COMPARE_FLAG(i);
- vres[i] = s1;
- }
- else
- {
- vres[i] = s2;
- }
-
- ACCUM_L(i) = vres[i];
- }
-
- CLEAR_CARRY_FLAGS();
- CLEAR_ZERO_FLAGS();
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x24: /* VCL */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 |
- // ------------------------------------------------------
- //
- // Vector clip low
-
- for (i = 0; i < 8; i++)
- {
- INT16 s1 = VREG_S(VS1REG, i);
- INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- if (CARRY_FLAG(i) != 0)
- {
- if (ZERO_FLAG(i) != 0)
- {
- if (COMPARE_FLAG(i) != 0)
- {
- ACCUM_L(i) = -(UINT16)s2;
- }
- else
- {
- ACCUM_L(i) = s1;
- }
- }
- else
- {
- if (CLIP1_FLAG(i) != 0)
- {
- if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) > 0x10000)
- {
-
- ACCUM_L(i) = s1;
- CLEAR_COMPARE_FLAG(i);
- }
- else
- {
- ACCUM_L(i) = -((UINT16)s2);
- SET_COMPARE_FLAG(i);
- }
- }
- else
- {
- if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0)
- {
- ACCUM_L(i) = s1;
- CLEAR_COMPARE_FLAG(i);
- }
- else
- {
- ACCUM_L(i) = -((UINT16)s2);
- SET_COMPARE_FLAG(i);
- }
- }
- }
- }
- else
- {
- if (ZERO_FLAG(i) != 0)
- {
- if (CLIP2_FLAG(i) != 0)
- {
- ACCUM_L(i) = s2;
- }
- else
- {
- ACCUM_L(i) = s1;
- }
- }
- else
- {
- if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0)
- {
- ACCUM_L(i) = s2;
- SET_CLIP2_FLAG(i);
- }
- else
- {
- ACCUM_L(i) = s1;
- CLEAR_CLIP2_FLAG(i);
- }
- }
- }
-
- vres[i] = ACCUM_L(i);
- }
- CLEAR_CARRY_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP1_FLAGS();
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x25: /* VCH */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 |
- // ------------------------------------------------------
- //
- // Vector clip high
-
- CLEAR_CARRY_FLAGS();
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP1_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP2_FLAGS();
- UINT32 vce = 0;
-
- for (i=0; i < 8; i++)
- {
- INT16 s1 = VREG_S(VS1REG, i);
- INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- if ((s1 ^ s2) < 0)
- {
- vce = (s1 + s2 == -1);
- SET_CARRY_FLAG(i);
- if (s2 < 0)
- {
- SET_CLIP2_FLAG(i);
- }
-
- if (s1 + s2 <= 0)
- {
- SET_COMPARE_FLAG(i);
- vres[i] = -((UINT16)s2);
- }
- else
- {
- vres[i] = s1;
- }
-
- if (s1 + s2 != 0)
- {
- if (s1 != ~s2)
- {
- SET_ZERO_FLAG(i);
- }
- }
- }
- else
- {
- vce = 0;
- if (s2 < 0)
- {
- SET_COMPARE_FLAG(i);
- }
- if (s1 - s2 >= 0)
- {
- SET_CLIP2_FLAG(i);
- vres[i] = s2;
- }
- else
- {
- vres[i] = s1;
- }
-
- if ((s1 - s2) != 0)
- {
- if (s1 != ~s2)
- {
- SET_ZERO_FLAG(i);
- }
- }
- }
- if (vce != 0)
- {
- SET_CLIP1_FLAG(i);
- }
- ACCUM_L(i) = vres[i];
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x26: /* VCR */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 |
- // ------------------------------------------------------
- //
- // Vector clip reverse
-
- CLEAR_CARRY_FLAGS();
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP1_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (i=0; i < 8; i++)
- {
- INT16 s1 = VREG_S(VS1REG, i);
- INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- if ((INT16)(s1 ^ s2) < 0)
- {
- if (s2 < 0)
- {
- SET_CLIP2_FLAG(i);
- }
- if ((s1 + s2) <= 0)
- {
- ACCUM_L(i) = ~((UINT16)s2);
- SET_COMPARE_FLAG(i);
- }
- else
- {
- ACCUM_L(i) = s1;
- }
- }
- else
- {
- if (s2 < 0)
- {
- SET_COMPARE_FLAG(i);
- }
- if ((s1 - s2) >= 0)
- {
- ACCUM_L(i) = s2;
- SET_CLIP2_FLAG(i);
- }
- else
- {
- ACCUM_L(i) = s1;
- }
- }
-
- vres[i] = ACCUM_L(i);
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x27: /* VMRG */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100111 |
- // ------------------------------------------------------
- //
- // Merges two vectors according to compare flags
-
- for (i = 0; i < 8; i++)
- {
- if (COMPARE_FLAG(i) != 0)
- {
- vres[i] = VREG_S(VS1REG, i);
- }
- else
- {
- vres[i] = VREG_S(VS2REG, VEC_EL_2(EL, i));
- }
-
- ACCUM_L(i) = vres[i];
- }
- WRITEBACK_RESULT();
- break;
- }
- case 0x28: /* VAND */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 |
- // ------------------------------------------------------
- //
- // Bitwise AND of two vector registers
-
- for (i = 0; i < 8; i++)
- {
- vres[i] = VREG_S(VS1REG, i) & VREG_S(VS2REG, VEC_EL_2(EL, i));
- ACCUM_L(i) = vres[i];
- }
- WRITEBACK_RESULT();
- break;
- }
- case 0x29: /* VNAND */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101001 |
- // ------------------------------------------------------
- //
- // Bitwise NOT AND of two vector registers
-
- for (i = 0; i < 8; i++)
- {
- vres[i] = ~((VREG_S(VS1REG, i) & VREG_S(VS2REG, VEC_EL_2(EL, i))));
- ACCUM_L(i) = vres[i];
- }
- WRITEBACK_RESULT();
- break;
- }
- case 0x2a: /* VOR */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101010 |
- // ------------------------------------------------------
- //
- // Bitwise OR of two vector registers
-
- for (i = 0; i < 8; i++)
- {
- vres[i] = VREG_S(VS1REG, i) | VREG_S(VS2REG, VEC_EL_2(EL, i));
- ACCUM_L(i) = vres[i];
- }
- WRITEBACK_RESULT();
- break;
- }
- case 0x2b: /* VNOR */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101011 |
- // ------------------------------------------------------
- //
- // Bitwise NOT OR of two vector registers
-
- for (i=0; i < 8; i++)
- {
- vres[i] = ~((VREG_S(VS1REG, i) | VREG_S(VS2REG, VEC_EL_2(EL, i))));
- ACCUM_L(i) = vres[i];
- }
- WRITEBACK_RESULT();
- break;
- }
- case 0x2c: /* VXOR */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101100 |
- // ------------------------------------------------------
- //
- // Bitwise XOR of two vector registers
-
- for (i=0; i < 8; i++)
- {
- vres[i] = VREG_S(VS1REG, i) ^ VREG_S(VS2REG, VEC_EL_2(EL, i));
- ACCUM_L(i) = vres[i];
- }
- WRITEBACK_RESULT();
- break;
- }
- case 0x2d: /* VNXOR */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 |
- // ------------------------------------------------------
- //
- // Bitwise NOT XOR of two vector registers
-
- for (i=0; i < 8; i++)
- {
- vres[i] = ~((VREG_S(VS1REG, i) ^ VREG_S(VS2REG, VEC_EL_2(EL, i))));
- ACCUM_L(i) = vres[i];
- }
- WRITEBACK_RESULT();
- break;
- }
-
- case 0x30: /* VRCP */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 |
- // ------------------------------------------------------
- //
- // Calculates reciprocal
- INT32 shifter = 0;
-
- INT32 rec = (INT16)(VREG_S(VS2REG, EL & 7));
- INT32 datainput = (rec < 0) ? (-rec) : rec;
- if (datainput)
- {
- for (i = 0; i < 32; i++)
- {
- if (datainput & (1 << ((~i) & 0x1f)))
- {
- shifter = i;
- break;
- }
- }
- }
- else
- {
- shifter = 0x10;
- }
-
- INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
- INT32 fetchval = rsp_divtable[address];
- INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
- if (rec < 0)
- {
- temp = ~temp;
- }
- if (!rec)
- {
- temp = 0x7fffffff;
- }
- else if (rec == 0xffff8000)
- {
- temp = 0xffff0000;
- }
- rec = temp;
-
- m_reciprocal_res = rec;
- m_dp_allowed = 0;
-
- VREG_S(VDREG, VS1REG & 7) = (UINT16)(rec & 0xffff);
-
- for (i = 0; i < 8; i++)
- {
- ACCUM_L(i) = VREG_S(VS2REG, VEC_EL_2(EL, i));
- }
-
-
- break;
- }
-
- case 0x31: /* VRCPL */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 |
- // ------------------------------------------------------
- //
- // Calculates reciprocal low part
-
- INT32 shifter = 0;
-
- INT32 rec = (INT16)VREG_S(VS2REG, EL & 7);
- INT32 datainput = rec;
-
- if (m_dp_allowed)
- {
- rec = (rec & 0x0000ffff) | m_reciprocal_high;
- datainput = rec;
-
- if (rec < 0)
- {
- if (rec < -32768)
- {
- datainput = ~datainput;
- }
- else
- {
- datainput = -datainput;
- }
- }
- }
- else if (datainput < 0)
- {
- datainput = -datainput;
-
- shifter = 0x10;
- }
-
-
- for (i = 0; i < 32; i++)
- {
- if (datainput & (1 << ((~i) & 0x1f)))
- {
- shifter = i;
- break;
- }
- }
-
- INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
- INT32 fetchval = rsp_divtable[address];
- INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
- temp ^= rec >> 31;
-
- if (!rec)
- {
- temp = 0x7fffffff;
- }
- else if (rec == 0xffff8000)
- {
- temp = 0xffff0000;
- }
- rec = temp;
-
- m_reciprocal_res = rec;
- m_dp_allowed = 0;
-
- VREG_S(VDREG, VS1REG & 7) = (UINT16)(rec & 0xffff);
-
- for (i = 0; i < 8; i++)
- {
- ACCUM_L(i) = VREG_S(VS2REG, VEC_EL_2(EL, i));
- }
-
- break;
- }
-
- case 0x32: /* VRCPH */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 |
- // ------------------------------------------------------
- //
- // Calculates reciprocal high part
-
- m_reciprocal_high = (VREG_S(VS2REG, EL & 7)) << 16;
- m_dp_allowed = 1;
-
- for (i = 0; i < 8; i++)
- {
- ACCUM_L(i) = VREG_S(VS2REG, VEC_EL_2(EL, i));
- }
-
- VREG_S(VDREG, VS1REG & 7) = (INT16)(m_reciprocal_res >> 16);
-
- break;
- }
-
- case 0x33: /* VMOV */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110011 |
- // ------------------------------------------------------
- //
- // Moves element from vector to destination vector
-
- VREG_S(VDREG, VS1REG & 7) = VREG_S(VS2REG, EL & 7);
- for (i = 0; i < 8; i++)
- {
- ACCUM_L(i) = VREG_S(VS2REG, VEC_EL_2(EL, i));
- }
- break;
- }
-
- case 0x34: /* VRSQ */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 |
- // ------------------------------------------------------
- //
- // Calculates reciprocal square-root
-
- INT32 shifter = 0;
-
- INT32 rec = (INT16)(VREG_S(VS2REG, EL & 7));
- INT32 datainput = (rec < 0) ? (-rec) : rec;
- if (datainput)
- {
- for (i = 0; i < 32; i++)
- {
- if (datainput & (1 << ((~i) & 0x1f)))//?.?.??? 31 - i
- {
- shifter = i;
- break;
- }
- }
- }
- else
- {
- shifter = 0x10;
- }
-
- 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;
-
- m_reciprocal_res = rec;
- m_dp_allowed = 0;
-
- VREG_S(VDREG, VS1REG & 7) = (UINT16)(rec & 0xffff);
-
- for (i = 0; i < 8; i++)
- {
- ACCUM_L(i) = VREG_S(VS2REG, VEC_EL_2(EL, i));
- }
-
- break;
- }
-
- case 0x35: /* VRSQL */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 |
- // ------------------------------------------------------
- //
- // Calculates reciprocal square-root low part
-
- INT32 shifter = 0;
- INT32 rec = (INT16)VREG_S(VS2REG, EL & 7);
- INT32 datainput = rec;
-
- if (m_dp_allowed)
- {
- rec = (rec & 0x0000ffff) | m_reciprocal_high;
- datainput = rec;
-
- if (rec < 0)
- {
- if (rec < -32768)
- {
- datainput = ~datainput;
- }
- else
- {
- datainput = -datainput;
- }
- }
- }
- else if (datainput < 0)
- {
- datainput = -datainput;
-
- shifter = 0x10;
- }
-
- if (datainput)
- {
- for (i = 0; i < 32; i++)
- {
- if (datainput & (1 << ((~i) & 0x1f)))
- {
- shifter = i;
- break;
- }
- }
- }
-
- 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);
- temp ^= rec >> 31;
-
- if (!rec)
- {
- temp = 0x7fffffff;
- }
- else if (rec == 0xffff8000)
- {
- temp = 0xffff0000;
- }
- rec = temp;
-
- m_reciprocal_res = rec;
- m_dp_allowed = 0;
-
- VREG_S(VDREG, VS1REG & 7) = (UINT16)(rec & 0xffff);
-
- for (i = 0; i < 8; i++)
- {
- ACCUM_L(i) = VREG_S(VS2REG, VEC_EL_2(EL, i));
- }
-
- break;
- }
-
- case 0x36: /* VRSQH */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110110 |
- // ------------------------------------------------------
- //
- // Calculates reciprocal square-root high part
-
- m_reciprocal_high = (VREG_S(VS2REG, EL & 7)) << 16;
- m_dp_allowed = 1;
-
- for (i=0; i < 8; i++)
- {
- ACCUM_L(i) = VREG_S(VS2REG, VEC_EL_2(EL, i));
- }
-
- VREG_S(VDREG, VS1REG & 7) = (INT16)(m_reciprocal_res >> 16); // store high part
- break;
- }
-
- case 0x37: /* VNOP */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110111 |
- // ------------------------------------------------------
- //
- // Vector null instruction
-
- break;
- }
-
- default: unimplemented_opcode(op); break;
- }
+ m_nextpc = ~0;
}
void rsp_device::execute_run()
@@ -3009,9 +617,6 @@ void rsp_device::execute_run()
{
m_sp_set_status_func(0, 0x3, 0xffffffff);
m_rsp_state->icount = MIN(m_rsp_state->icount, 1);
-
- if (LOG_INSTRUCTION_EXECUTION) fprintf(m_exec_output, "\n---------- break ----------\n\n");
-
break;
}
case 0x20: /* ADD */ if (RDREG) RDVAL = (INT32)(RSVAL + RTVAL); break;
@@ -3070,173 +675,7 @@ void rsp_device::execute_run()
case 0x12: /* COP2 */
{
- switch ((op >> 21) & 0x1f)
- {
- case 0x00: /* MFC2 */
- {
- // 31 25 20 15 10 6 0
- // ---------------------------------------------------
- // | 010010 | 00000 | TTTTT | DDDDD | IIII | 0000000 |
- // ---------------------------------------------------
- //
-
- int el = (op >> 7) & 0xf;
- UINT16 b1 = VREG_B(RDREG, (el+0) & 0xf);
- UINT16 b2 = VREG_B(RDREG, (el+1) & 0xf);
- if (RTREG) RTVAL = (INT32)(INT16)((b1 << 8) | (b2));
- break;
- }
- case 0x02: /* CFC2 */
- {
- // 31 25 20 15 10 0
- // ------------------------------------------------
- // | 010010 | 00010 | TTTTT | DDDDD | 00000000000 |
- // ------------------------------------------------
- //
-
- if (RTREG)
- {
- switch(RDREG)
- {
- case 0:
- RTVAL = ((CARRY_FLAG(0) & 1) << 0) |
- ((CARRY_FLAG(1) & 1) << 1) |
- ((CARRY_FLAG(2) & 1) << 2) |
- ((CARRY_FLAG(3) & 1) << 3) |
- ((CARRY_FLAG(4) & 1) << 4) |
- ((CARRY_FLAG(5) & 1) << 5) |
- ((CARRY_FLAG(6) & 1) << 6) |
- ((CARRY_FLAG(7) & 1) << 7) |
- ((ZERO_FLAG(0) & 1) << 8) |
- ((ZERO_FLAG(1) & 1) << 9) |
- ((ZERO_FLAG(2) & 1) << 10) |
- ((ZERO_FLAG(3) & 1) << 11) |
- ((ZERO_FLAG(4) & 1) << 12) |
- ((ZERO_FLAG(5) & 1) << 13) |
- ((ZERO_FLAG(6) & 1) << 14) |
- ((ZERO_FLAG(7) & 1) << 15);
- if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
- break;
- case 1:
- RTVAL = ((COMPARE_FLAG(0) & 1) << 0) |
- ((COMPARE_FLAG(1) & 1) << 1) |
- ((COMPARE_FLAG(2) & 1) << 2) |
- ((COMPARE_FLAG(3) & 1) << 3) |
- ((COMPARE_FLAG(4) & 1) << 4) |
- ((COMPARE_FLAG(5) & 1) << 5) |
- ((COMPARE_FLAG(6) & 1) << 6) |
- ((COMPARE_FLAG(7) & 1) << 7) |
- ((CLIP2_FLAG(0) & 1) << 8) |
- ((CLIP2_FLAG(1) & 1) << 9) |
- ((CLIP2_FLAG(2) & 1) << 10) |
- ((CLIP2_FLAG(3) & 1) << 11) |
- ((CLIP2_FLAG(4) & 1) << 12) |
- ((CLIP2_FLAG(5) & 1) << 13) |
- ((CLIP2_FLAG(6) & 1) << 14) |
- ((CLIP2_FLAG(7) & 1) << 15);
- if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
- break;
- case 2:
- // Anciliary clipping flags
- RTVAL = ((CLIP1_FLAG(0) & 1) << 0) |
- ((CLIP1_FLAG(1) & 1) << 1) |
- ((CLIP1_FLAG(2) & 1) << 2) |
- ((CLIP1_FLAG(3) & 1) << 3) |
- ((CLIP1_FLAG(4) & 1) << 4) |
- ((CLIP1_FLAG(5) & 1) << 5) |
- ((CLIP1_FLAG(6) & 1) << 6) |
- ((CLIP1_FLAG(7) & 1) << 7);
- }
- }
- break;
- }
- case 0x04: /* MTC2 */
- {
- // 31 25 20 15 10 6 0
- // ---------------------------------------------------
- // | 010010 | 00100 | TTTTT | DDDDD | IIII | 0000000 |
- // ---------------------------------------------------
- //
-
- int el = (op >> 7) & 0xf;
- W_VREG_B(RDREG, (el+0) & 0xf, (RTVAL >> 8) & 0xff);
- W_VREG_B(RDREG, (el+1) & 0xf, (RTVAL >> 0) & 0xff);
- break;
- }
- case 0x06: /* CTC2 */
- {
- // 31 25 20 15 10 0
- // ------------------------------------------------
- // | 010010 | 00110 | TTTTT | DDDDD | 00000000000 |
- // ------------------------------------------------
- //
-
- switch(RDREG)
- {
- case 0:
- CLEAR_CARRY_FLAGS();
- CLEAR_ZERO_FLAGS();
- if (RTVAL & (1 << 0)) { SET_CARRY_FLAG(0); }
- if (RTVAL & (1 << 1)) { SET_CARRY_FLAG(1); }
- if (RTVAL & (1 << 2)) { SET_CARRY_FLAG(2); }
- if (RTVAL & (1 << 3)) { SET_CARRY_FLAG(3); }
- if (RTVAL & (1 << 4)) { SET_CARRY_FLAG(4); }
- if (RTVAL & (1 << 5)) { SET_CARRY_FLAG(5); }
- if (RTVAL & (1 << 6)) { SET_CARRY_FLAG(6); }
- if (RTVAL & (1 << 7)) { SET_CARRY_FLAG(7); }
- if (RTVAL & (1 << 8)) { SET_ZERO_FLAG(0); }
- if (RTVAL & (1 << 9)) { SET_ZERO_FLAG(1); }
- if (RTVAL & (1 << 10)) { SET_ZERO_FLAG(2); }
- if (RTVAL & (1 << 11)) { SET_ZERO_FLAG(3); }
- if (RTVAL & (1 << 12)) { SET_ZERO_FLAG(4); }
- if (RTVAL & (1 << 13)) { SET_ZERO_FLAG(5); }
- if (RTVAL & (1 << 14)) { SET_ZERO_FLAG(6); }
- if (RTVAL & (1 << 15)) { SET_ZERO_FLAG(7); }
- break;
- case 1:
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
- if (RTVAL & (1 << 0)) { SET_COMPARE_FLAG(0); }
- if (RTVAL & (1 << 1)) { SET_COMPARE_FLAG(1); }
- if (RTVAL & (1 << 2)) { SET_COMPARE_FLAG(2); }
- if (RTVAL & (1 << 3)) { SET_COMPARE_FLAG(3); }
- if (RTVAL & (1 << 4)) { SET_COMPARE_FLAG(4); }
- if (RTVAL & (1 << 5)) { SET_COMPARE_FLAG(5); }
- if (RTVAL & (1 << 6)) { SET_COMPARE_FLAG(6); }
- if (RTVAL & (1 << 7)) { SET_COMPARE_FLAG(7); }
- if (RTVAL & (1 << 8)) { SET_CLIP2_FLAG(0); }
- if (RTVAL & (1 << 9)) { SET_CLIP2_FLAG(1); }
- if (RTVAL & (1 << 10)) { SET_CLIP2_FLAG(2); }
- if (RTVAL & (1 << 11)) { SET_CLIP2_FLAG(3); }
- if (RTVAL & (1 << 12)) { SET_CLIP2_FLAG(4); }
- if (RTVAL & (1 << 13)) { SET_CLIP2_FLAG(5); }
- if (RTVAL & (1 << 14)) { SET_CLIP2_FLAG(6); }
- if (RTVAL & (1 << 15)) { SET_CLIP2_FLAG(7); }
- break;
- case 2:
- CLEAR_CLIP1_FLAGS();
- if (RTVAL & (1 << 0)) { SET_CLIP1_FLAG(0); }
- if (RTVAL & (1 << 1)) { SET_CLIP1_FLAG(1); }
- if (RTVAL & (1 << 2)) { SET_CLIP1_FLAG(2); }
- if (RTVAL & (1 << 3)) { SET_CLIP1_FLAG(3); }
- if (RTVAL & (1 << 4)) { SET_CLIP1_FLAG(4); }
- if (RTVAL & (1 << 5)) { SET_CLIP1_FLAG(5); }
- if (RTVAL & (1 << 6)) { SET_CLIP1_FLAG(6); }
- if (RTVAL & (1 << 7)) { SET_CLIP1_FLAG(7); }
- break;
- }
- break;
- }
-
- case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
- case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
- {
- handle_vector_ops(op);
- break;
- }
-
- default: unimplemented_opcode(op); break;
- }
+ m_cop2->handle_cop2(op);
break;
}
@@ -3248,8 +687,8 @@ void rsp_device::execute_run()
case 0x28: /* SB */ WRITE8(RSVAL + SIMM16, RTVAL); break;
case 0x29: /* SH */ WRITE16(RSVAL + SIMM16, RTVAL); break;
case 0x2b: /* SW */ WRITE32(RSVAL + SIMM16, RTVAL); break;
- case 0x32: /* LWC2 */ handle_lwc2(op); break;
- case 0x3a: /* SWC2 */ handle_swc2(op); break;
+ case 0x32: /* LWC2 */ m_cop2->handle_lwc2(op); break;
+ case 0x3a: /* SWC2 */ m_cop2->handle_swc2(op); break;
default:
{
@@ -3262,7 +701,6 @@ void rsp_device::execute_run()
{
int i, l;
static UINT32 prev_regs[32];
- static VECTOR_REG prev_vecs[32];
char string[200];
rsp_dasm_one(string, m_ppc, op);
@@ -3288,16 +726,7 @@ void rsp_device::execute_run()
prev_regs[i] = m_rsp_state->r[i];
}
- for (i=0; i < 32; i++)
- {
- if (m_v[i].d[0] != prev_vecs[i].d[0] || m_v[i].d[1] != prev_vecs[i].d[1])
- {
- fprintf(m_exec_output, "V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X ", i,
- (UINT16)VREG_S(i,0), (UINT16)VREG_S(i,1), (UINT16)VREG_S(i,2), (UINT16)VREG_S(i,3), (UINT16)VREG_S(i,4), (UINT16)VREG_S(i,5), (UINT16)VREG_S(i,6), (UINT16)VREG_S(i,7));
- }
- prev_vecs[i].d[0] = m_v[i].d[0];
- prev_vecs[i].d[1] = m_v[i].d[1];
- }
+ m_cop2->log_instruction_execution();
fprintf(m_exec_output, "\n");
diff --git a/src/emu/cpu/rsp/rsp.h b/src/emu/cpu/rsp/rsp.h
index 2219cb8082d..b654c555b02 100644
--- a/src/emu/cpu/rsp/rsp.h
+++ b/src/emu/cpu/rsp/rsp.h
@@ -16,17 +16,9 @@
#ifndef __RSP_H__
#define __RSP_H__
-
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
-#define USE_SIMD (0)
-#define SIMUL_SIMD (0)
-
-#if USE_SIMD
-#include <tmmintrin.h>
-#endif
-
/***************************************************************************
REGISTER ENUMERATION
***************************************************************************/
@@ -87,10 +79,6 @@ enum
#define RDREG ((op >> 11) & 31)
#define SHIFT ((op >> 6) & 31)
-#define RSVAL (m_rsp_state->r[RSREG])
-#define RTVAL (m_rsp_state->r[RTREG])
-#define RDVAL (m_rsp_state->r[RDREG])
-
#define FRREG ((op >> 21) & 31)
#define FTREG ((op >> 16) & 31)
#define FSREG ((op >> 11) & 31)
@@ -123,21 +111,6 @@ enum
#define RSPDRC_STRICT_VERIFY 0x0001 /* verify all instructions */
-union VECTOR_REG
-{
- UINT64 d[2];
- UINT32 l[4];
- INT16 s[8];
- UINT8 b[16];
-};
-
-union ACCUMULATOR_REG
-{
- UINT64 q;
- UINT32 l[2];
- UINT16 w[4];
-};
-
#define MCFG_RSP_DP_REG_R_CB(_devcb) \
devcb = &rsp_device::static_set_dp_reg_r_callback(*device, DEVCB_##_devcb);
@@ -155,10 +128,14 @@ union ACCUMULATOR_REG
class rsp_frontend;
+class rsp_cop2;
class rsp_device : public cpu_device
{
friend class rsp_frontend;
+ friend class rsp_cop2;
+ friend class rsp_cop2_drc;
+ friend class rsp_cop2_simd;
public:
// construction/destruction
@@ -187,149 +164,6 @@ public:
void ccfunc_unimplemented_opcode();
void ccfunc_sp_set_status_cb();
void ccfunc_unimplemented();
-#if USE_SIMD
- void ccfunc_rsp_lbv_simd();
- void ccfunc_rsp_lsv_simd();
- void ccfunc_rsp_llv_simd();
- void ccfunc_rsp_ldv_simd();
- void ccfunc_rsp_lqv_simd();
- void ccfunc_rsp_lrv_simd();
- void ccfunc_rsp_lpv_simd();
- void ccfunc_rsp_luv_simd();
- void ccfunc_rsp_lhv_simd();
- void ccfunc_rsp_lfv_simd();
- void ccfunc_rsp_lwv_simd();
- void ccfunc_rsp_ltv_simd();
- void ccfunc_rsp_sbv_simd();
- void ccfunc_rsp_ssv_simd();
- void ccfunc_rsp_slv_simd();
- void ccfunc_rsp_sdv_simd();
- void ccfunc_rsp_sqv_simd();
- void ccfunc_rsp_srv_simd();
- void ccfunc_rsp_spv_simd();
- void ccfunc_rsp_suv_simd();
- void ccfunc_rsp_shv_simd();
- void ccfunc_rsp_sfv_simd();
- void ccfunc_rsp_swv_simd();
- void ccfunc_rsp_stv_simd();
- void ccfunc_rsp_vmulf_simd();
- void ccfunc_rsp_vmulu_simd();
- void ccfunc_rsp_vmudl_simd();
- void ccfunc_rsp_vmudm_simd();
- void ccfunc_rsp_vmudn_simd();
- void ccfunc_rsp_vmudh_simd();
- void ccfunc_rsp_vmacf_simd();
- void ccfunc_rsp_vmacu_simd();
- void ccfunc_rsp_vmadl_simd();
- void ccfunc_rsp_vmadm_simd();
- void ccfunc_rsp_vmadn_simd();
- void ccfunc_rsp_vmadh_simd();
- void ccfunc_rsp_vadd_simd();
- void ccfunc_rsp_vsub_simd();
- void ccfunc_rsp_vabs_simd();
- void ccfunc_rsp_vaddc_simd();
- void ccfunc_rsp_vsubc_simd();
- void ccfunc_rsp_vsaw_simd();
- void ccfunc_rsp_vlt_simd();
- void ccfunc_rsp_veq_simd();
- void ccfunc_rsp_vne_simd();
- void ccfunc_rsp_vge_simd();
- void ccfunc_rsp_vcl_simd();
- void ccfunc_rsp_vch_simd();
- void ccfunc_rsp_vcr_simd();
- void ccfunc_rsp_vmrg_simd();
- void ccfunc_rsp_vand_simd();
- void ccfunc_rsp_vnand_simd();
- void ccfunc_rsp_vor_simd();
- void ccfunc_rsp_vnor_simd();
- void ccfunc_rsp_vxor_simd();
- void ccfunc_rsp_vnxor_simd();
- void ccfunc_rsp_vrcp_simd();
- void ccfunc_rsp_vrcpl_simd();
- void ccfunc_rsp_vrcph_simd();
- void ccfunc_rsp_vmov_simd();
- void ccfunc_rsp_vrsql_simd();
- void ccfunc_rsp_vrsqh_simd();
- void ccfunc_mfc2_simd();
- void ccfunc_cfc2_simd();
- void ccfunc_mtc2_simd();
- void ccfunc_ctc2_simd();
-#endif
-#if (!USE_SIMD || SIMUL_SIMD)
- void ccfunc_rsp_lbv_scalar();
- void ccfunc_rsp_lsv_scalar();
- void ccfunc_rsp_llv_scalar();
- void ccfunc_rsp_ldv_scalar();
- void ccfunc_rsp_lqv_scalar();
- void ccfunc_rsp_lrv_scalar();
- void ccfunc_rsp_lpv_scalar();
- void ccfunc_rsp_luv_scalar();
- void ccfunc_rsp_lhv_scalar();
- void ccfunc_rsp_lfv_scalar();
- void ccfunc_rsp_lwv_scalar();
- void ccfunc_rsp_ltv_scalar();
- void ccfunc_rsp_sbv_scalar();
- void ccfunc_rsp_ssv_scalar();
- void ccfunc_rsp_slv_scalar();
- void ccfunc_rsp_sdv_scalar();
- void ccfunc_rsp_sqv_scalar();
- void ccfunc_rsp_srv_scalar();
- void ccfunc_rsp_spv_scalar();
- void ccfunc_rsp_suv_scalar();
- void ccfunc_rsp_shv_scalar();
- void ccfunc_rsp_sfv_scalar();
- void ccfunc_rsp_swv_scalar();
- void ccfunc_rsp_stv_scalar();
- void ccfunc_rsp_vmulf_scalar();
- void ccfunc_rsp_vmulu_scalar();
- void ccfunc_rsp_vmudl_scalar();
- void ccfunc_rsp_vmudm_scalar();
- void ccfunc_rsp_vmudn_scalar();
- void ccfunc_rsp_vmudh_scalar();
- void ccfunc_rsp_vmacf_scalar();
- void ccfunc_rsp_vmacu_scalar();
- void ccfunc_rsp_vmadl_scalar();
- void ccfunc_rsp_vmadm_scalar();
- void ccfunc_rsp_vmadn_scalar();
- void ccfunc_rsp_vmadh_scalar();
- void ccfunc_rsp_vadd_scalar();
- void ccfunc_rsp_vsub_scalar();
- void ccfunc_rsp_vabs_scalar();
- void ccfunc_rsp_vaddc_scalar();
- void ccfunc_rsp_vsubc_scalar();
- void ccfunc_rsp_vaddb_scalar();
- void ccfunc_rsp_vsaw_scalar();
- void ccfunc_rsp_vlt_scalar();
- void ccfunc_rsp_veq_scalar();
- void ccfunc_rsp_vne_scalar();
- void ccfunc_rsp_vge_scalar();
- void ccfunc_rsp_vcl_scalar();
- void ccfunc_rsp_vch_scalar();
- void ccfunc_rsp_vcr_scalar();
- void ccfunc_rsp_vmrg_scalar();
- void ccfunc_rsp_vand_scalar();
- void ccfunc_rsp_vnand_scalar();
- void ccfunc_rsp_vor_scalar();
- void ccfunc_rsp_vnor_scalar();
- void ccfunc_rsp_vxor_scalar();
- void ccfunc_rsp_vnxor_scalar();
- void ccfunc_rsp_vrcp_scalar();
- void ccfunc_rsp_vrcpl_scalar();
- void ccfunc_rsp_vrcph_scalar();
- void ccfunc_rsp_vmov_scalar();
- void ccfunc_rsp_vrsql_scalar();
- void ccfunc_rsp_vrsqh_scalar();
- void ccfunc_mfc2_scalar();
- void ccfunc_cfc2_scalar();
- 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();
- void ccfunc_verify_regs();
-#endif
protected:
// device-level overrides
@@ -358,6 +192,17 @@ protected:
virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
+ void unimplemented_opcode(UINT32 op);
+
+ /* internal compiler state */
+ struct compiler_state
+ {
+ UINT32 cycles; /* accumulated cycles */
+ UINT8 checkints; /* need to check interrupts before next instruction */
+ UINT8 checksoftints; /* need to check software interrupts before next instruction */
+ uml::code_label labelnum; /* index for local labels */
+ };
+
private:
address_space_config m_program_config;
@@ -370,17 +215,6 @@ private:
void * base; /* base in memory where the RAM lives */
};
-
- /* internal compiler state */
- struct compiler_state
- {
- UINT32 cycles; /* accumulated cycles */
- UINT8 checkints; /* need to check interrupts before next instruction */
- UINT8 checksoftints; /* need to check software interrupts before next instruction */
- uml::code_label labelnum; /* index for local labels */
- };
-
-
/* core state */
drc_cache m_cache; /* pointer to the DRC code cache */
drcuml_state * m_drcuml; /* DRC UML generator state */
@@ -395,7 +229,6 @@ private:
const char * m_format; /* format string for print_debug */
UINT32 m_arg2; /* print_debug argument 3 */
UINT32 m_arg3; /* print_debug argument 4 */
- UINT32 m_vres[8]; /* used for temporary vector results */
/* register mappings */
uml::parameter m_regmap[34]; /* parameter to register mappings for all 32 integer registers */
@@ -425,49 +258,9 @@ private:
FILE *m_exec_output;
- VECTOR_REG m_v[32];
- UINT16 m_vflag[6][8];
-
-#if SIMUL_SIMD
- UINT32 m_old_r[35];
- UINT8 m_old_dmem[4096];
-
- UINT32 m_scalar_r[35];
- UINT8 m_scalar_dmem[4096];
-
- INT32 m_old_reciprocal_res;
- UINT32 m_old_reciprocal_high;
- INT32 m_old_dp_allowed;
-
- INT32 m_scalar_reciprocal_res;
- UINT32 m_scalar_reciprocal_high;
- INT32 m_scalar_dp_allowed;
-
- INT32 m_simd_reciprocal_res;
- UINT32 m_simd_reciprocal_high;
- INT32 m_simd_dp_allowed;
-#endif
-
-#if USE_SIMD
- // Mirror of v[] for now, to be used in parallel as
- // more vector ops are transitioned over
- __m128i m_xv[32];
- __m128i m_xvflag[6];
-#endif
UINT32 m_sr;
UINT32 m_step_count;
- ACCUMULATOR_REG m_accum[8];
-#if USE_SIMD
- __m128i m_accum_h;
- __m128i m_accum_m;
- __m128i m_accum_l;
- __m128i m_accum_ll;
-#endif
- INT32 m_reciprocal_res;
- UINT32 m_reciprocal_high;
- INT32 m_dp_allowed;
-
UINT32 m_ppc;
UINT32 m_nextpc;
@@ -476,6 +269,8 @@ protected:
direct_read_data *m_direct;
private:
+ rsp_cop2 *m_cop2;
+
UINT32 *m_dmem32;
UINT16 *m_dmem16;
UINT8 *m_dmem8;
@@ -501,24 +296,6 @@ private:
void WRITE32(UINT32 address, UINT32 data);
UINT32 get_cop0_reg(int reg);
void set_cop0_reg(int reg, UINT32 data);
- void unimplemented_opcode(UINT32 op);
- void handle_lwc2(UINT32 op);
- void handle_swc2(UINT32 op);
- UINT16 SATURATE_ACCUM(int accum, int slice, UINT16 negative, UINT16 positive);
- UINT16 SATURATE_ACCUM1(int accum, UINT16 negative, UINT16 positive);
- void handle_vector_ops(UINT32 op);
-#if USE_SIMD
- UINT16 VEC_ACCUM_H(int x);
- UINT16 VEC_ACCUM_M(int x);
- UINT16 VEC_ACCUM_L(int x);
- UINT16 VEC_ACCUM_LL(int x);
- UINT16 VEC_CARRY_FLAG(const int x);
- UINT16 VEC_COMPARE_FLAG(const int x);
- UINT16 VEC_CLIP1_FLAG(const int x);
- UINT16 VEC_ZERO_FLAG(const int x);
- UINT16 VEC_CLIP2_FLAG(const int x);
- UINT16 VEC_SATURATE_ACCUM(int accum, int slice, UINT16 negative, UINT16 positive);
-#endif
void load_fast_iregs(drcuml_block *block);
void save_fast_iregs(drcuml_block *block);
UINT8 DM_READ8(UINT32 address);
@@ -528,8 +305,6 @@ private:
void DM_WRITE16(UINT32 address, UINT16 data);
void DM_WRITE32(UINT32 address, UINT32 data);
void rspcom_init();
- int generate_lwc2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
- int generate_swc2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
void execute_run_drc();
void code_flush_cache();
void code_compile_block(offs_t pc);
diff --git a/src/emu/cpu/rsp/rspcp2.c b/src/emu/cpu/rsp/rspcp2.c
new file mode 100644
index 00000000000..d1124d248ef
--- /dev/null
+++ b/src/emu/cpu/rsp/rspcp2.c
@@ -0,0 +1,2797 @@
+/***************************************************************************
+
+ rspcp2.c
+
+ Universal machine language-based Nintendo/SGI RSP COP2 emulator.
+ Written by Harmony of the MESS team.
+
+ Copyright the MESS team.
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "rsp.h"
+#include "rspdiv.h"
+#include "rspcp2.h"
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+
+using namespace uml;
+
+extern offs_t rsp_dasm_one(char *buffer, offs_t pc, UINT32 op);
+
+/***************************************************************************
+ Helpful Defines
+***************************************************************************/
+
+#define VDREG ((op >> 6) & 0x1f)
+#define VS1REG ((op >> 11) & 0x1f)
+#define VS2REG ((op >> 16) & 0x1f)
+#define EL ((op >> 21) & 0xf)
+
+#define RSVAL (m_rsp.m_rsp_state->r[RSREG])
+#define RTVAL (m_rsp.m_rsp_state->r[RTREG])
+#define RDVAL (m_rsp.m_rsp_state->r[RDREG])
+
+#define VREG_B(reg, offset) m_v[(reg)].b[(offset)^1]
+#define VREG_S(reg, offset) m_v[(reg)].s[(offset)]
+#define VREG_L(reg, offset) m_v[(reg)].l[(offset)]
+
+#define R_VREG_B(reg, offset) m_v[(reg)].b[(offset)^1]
+#define R_VREG_S(reg, offset) (INT16)m_v[(reg)].s[(offset)]
+#define R_VREG_L(reg, offset) m_v[(reg)].l[(offset)]
+
+#define W_VREG_B(reg, offset, val) (m_v[(reg)].b[(offset)^1] = val)
+#define W_VREG_S(reg, offset, val) (m_v[(reg)].s[(offset)] = val)
+#define W_VREG_L(reg, offset, val) (m_v[(reg)].l[(offset)] = val)
+
+#define VEC_EL_2(x,z) (vector_elements_2[(x)][(z)])
+
+#define CARRY 0
+#define COMPARE 1
+#define CLIP1 2
+#define ZERO 3
+#define CLIP2 4
+
+#define ACCUM(x) m_accum[x].q
+#define ACCUM_H(x) (UINT16)m_accum[x].w[3]
+#define ACCUM_M(x) (UINT16)m_accum[x].w[2]
+#define ACCUM_L(x) (UINT16)m_accum[x].w[1]
+#define ACCUM_LL(x) (UINT16)m_accum[x].w[0]
+
+#define SET_ACCUM_H(v, x) m_accum[x].w[3] = v;
+#define SET_ACCUM_M(v, x) m_accum[x].w[2] = v;
+#define SET_ACCUM_L(v, x) m_accum[x].w[1] = v;
+#define SET_ACCUM_LL(v, x) m_accum[x].w[0] = v;
+
+#define CARRY_FLAG(x) (m_vflag[CARRY][x & 7] != 0 ? 0xffff : 0)
+#define COMPARE_FLAG(x) (m_vflag[COMPARE][x & 7] != 0 ? 0xffff : 0)
+#define CLIP1_FLAG(x) (m_vflag[CLIP1][x & 7] != 0 ? 0xffff : 0)
+#define ZERO_FLAG(x) (m_vflag[ZERO][x & 7] != 0 ? 0xffff : 0)
+#define CLIP2_FLAG(x) (m_vflag[CLIP2][x & 7] != 0 ? 0xffff : 0)
+
+#define CLEAR_CARRY_FLAGS() { memset(m_vflag[CARRY], 0, 16); }
+#define CLEAR_COMPARE_FLAGS() { memset(m_vflag[COMPARE], 0, 16); }
+#define CLEAR_CLIP1_FLAGS() { memset(m_vflag[CLIP1], 0, 16); }
+#define CLEAR_ZERO_FLAGS() { memset(m_vflag[ZERO], 0, 16); }
+#define CLEAR_CLIP2_FLAGS() { memset(m_vflag[CLIP2], 0, 16); }
+
+#define SET_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0xffff; }
+#define SET_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0xffff; }
+#define SET_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0xffff; }
+#define SET_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0xffff; }
+#define SET_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0xffff; }
+
+#define CLEAR_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0; }
+#define CLEAR_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0; }
+#define CLEAR_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0; }
+#define CLEAR_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0; }
+#define CLEAR_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0; }
+
+#define WRITEBACK_RESULT() { \
+ VREG_S(VDREG, 0) = m_vres[0]; \
+ VREG_S(VDREG, 1) = m_vres[1]; \
+ VREG_S(VDREG, 2) = m_vres[2]; \
+ VREG_S(VDREG, 3) = m_vres[3]; \
+ VREG_S(VDREG, 4) = m_vres[4]; \
+ VREG_S(VDREG, 5) = m_vres[5]; \
+ VREG_S(VDREG, 6) = m_vres[6]; \
+ VREG_S(VDREG, 7) = m_vres[7]; \
+}
+
+static const int vector_elements_2[16][8] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // none
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // ???
+ { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q
+ { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q
+ { 0, 0, 0, 0, 4, 4, 4, 4 }, // 0h
+ { 1, 1, 1, 1, 5, 5, 5, 5 }, // 1h
+ { 2, 2, 2, 2, 6, 6, 6, 6 }, // 2h
+ { 3, 3, 3, 3, 7, 7, 7, 7 }, // 3h
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
+ { 1, 1, 1, 1, 1, 1, 1, 1 }, // 1
+ { 2, 2, 2, 2, 2, 2, 2, 2 }, // 2
+ { 3, 3, 3, 3, 3, 3, 3, 3 }, // 3
+ { 4, 4, 4, 4, 4, 4, 4, 4 }, // 4
+ { 5, 5, 5, 5, 5, 5, 5, 5 }, // 5
+ { 6, 6, 6, 6, 6, 6, 6, 6 }, // 6
+ { 7, 7, 7, 7, 7, 7, 7, 7 }, // 7
+};
+
+rsp_cop2::rsp_cop2(rsp_device &rsp, running_machine &machine)
+ : m_rsp(rsp)
+ , m_machine(machine)
+ , m_reciprocal_res(0)
+ , m_reciprocal_high(0)
+ , m_dp_allowed(0)
+{
+ memset(m_vres, 0, sizeof(m_vres));
+ memset(m_v, 0, sizeof(m_v));
+ memset(m_vflag, 0, sizeof(m_vflag));
+ memset(m_accum, 0, sizeof(m_accum));
+}
+
+void rsp_cop2::init()
+{
+ CLEAR_CARRY_FLAGS();
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP1_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+}
+
+void rsp_cop2::start()
+{
+ for(int regIdx = 0; regIdx < 32; regIdx++ )
+ {
+ m_v[regIdx].d[0] = 0;
+ m_v[regIdx].d[1] = 0;
+ }
+
+ CLEAR_CARRY_FLAGS();
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP1_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+ m_reciprocal_res = 0;
+ m_reciprocal_high = 0;
+
+ // Accumulators do not power on to a random state
+ for(int accumIdx = 0; accumIdx < 8; accumIdx++ )
+ {
+ m_accum[accumIdx].q = 0;
+ }
+}
+
+void rsp_cop2::state_string_export(const int index, astring &string)
+{
+ switch (index)
+ {
+ case RSP_V0:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 0, 0), (UINT16)VREG_S( 0, 1), (UINT16)VREG_S( 0, 2), (UINT16)VREG_S( 0, 3), (UINT16)VREG_S( 0, 4), (UINT16)VREG_S( 0, 5), (UINT16)VREG_S( 0, 6), (UINT16)VREG_S( 0, 7));
+ break;
+ case RSP_V1:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 1, 0), (UINT16)VREG_S( 1, 1), (UINT16)VREG_S( 1, 2), (UINT16)VREG_S( 1, 3), (UINT16)VREG_S( 1, 4), (UINT16)VREG_S( 1, 5), (UINT16)VREG_S( 1, 6), (UINT16)VREG_S( 1, 7));
+ break;
+ case RSP_V2:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 2, 0), (UINT16)VREG_S( 2, 1), (UINT16)VREG_S( 2, 2), (UINT16)VREG_S( 2, 3), (UINT16)VREG_S( 2, 4), (UINT16)VREG_S( 2, 5), (UINT16)VREG_S( 2, 6), (UINT16)VREG_S( 2, 7));
+ break;
+ case RSP_V3:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 3, 0), (UINT16)VREG_S( 3, 1), (UINT16)VREG_S( 3, 2), (UINT16)VREG_S( 3, 3), (UINT16)VREG_S( 3, 4), (UINT16)VREG_S( 3, 5), (UINT16)VREG_S( 3, 6), (UINT16)VREG_S( 3, 7));
+ break;
+ case RSP_V4:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 4, 0), (UINT16)VREG_S( 4, 1), (UINT16)VREG_S( 4, 2), (UINT16)VREG_S( 4, 3), (UINT16)VREG_S( 4, 4), (UINT16)VREG_S( 4, 5), (UINT16)VREG_S( 4, 6), (UINT16)VREG_S( 4, 7));
+ break;
+ case RSP_V5:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 5, 0), (UINT16)VREG_S( 5, 1), (UINT16)VREG_S( 5, 2), (UINT16)VREG_S( 5, 3), (UINT16)VREG_S( 5, 4), (UINT16)VREG_S( 5, 5), (UINT16)VREG_S( 5, 6), (UINT16)VREG_S( 5, 7));
+ break;
+ case RSP_V6:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 6, 0), (UINT16)VREG_S( 6, 1), (UINT16)VREG_S( 6, 2), (UINT16)VREG_S( 6, 3), (UINT16)VREG_S( 6, 4), (UINT16)VREG_S( 6, 5), (UINT16)VREG_S( 6, 6), (UINT16)VREG_S( 6, 7));
+ break;
+ case RSP_V7:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 7, 0), (UINT16)VREG_S( 7, 1), (UINT16)VREG_S( 7, 2), (UINT16)VREG_S( 7, 3), (UINT16)VREG_S( 7, 4), (UINT16)VREG_S( 7, 5), (UINT16)VREG_S( 7, 6), (UINT16)VREG_S( 7, 7));
+ break;
+ case RSP_V8:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 8, 0), (UINT16)VREG_S( 8, 1), (UINT16)VREG_S( 8, 2), (UINT16)VREG_S( 8, 3), (UINT16)VREG_S( 8, 4), (UINT16)VREG_S( 8, 5), (UINT16)VREG_S( 8, 6), (UINT16)VREG_S( 8, 7));
+ break;
+ case RSP_V9:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 9, 0), (UINT16)VREG_S( 9, 1), (UINT16)VREG_S( 9, 2), (UINT16)VREG_S( 9, 3), (UINT16)VREG_S( 9, 4), (UINT16)VREG_S( 9, 5), (UINT16)VREG_S( 9, 6), (UINT16)VREG_S( 9, 7));
+ break;
+ case RSP_V10:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(10, 0), (UINT16)VREG_S(10, 1), (UINT16)VREG_S(10, 2), (UINT16)VREG_S(10, 3), (UINT16)VREG_S(10, 4), (UINT16)VREG_S(10, 5), (UINT16)VREG_S(10, 6), (UINT16)VREG_S(10, 7));
+ break;
+ case RSP_V11:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(11, 0), (UINT16)VREG_S(11, 1), (UINT16)VREG_S(11, 2), (UINT16)VREG_S(11, 3), (UINT16)VREG_S(11, 4), (UINT16)VREG_S(11, 5), (UINT16)VREG_S(11, 6), (UINT16)VREG_S(11, 7));
+ break;
+ case RSP_V12:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(12, 0), (UINT16)VREG_S(12, 1), (UINT16)VREG_S(12, 2), (UINT16)VREG_S(12, 3), (UINT16)VREG_S(12, 4), (UINT16)VREG_S(12, 5), (UINT16)VREG_S(12, 6), (UINT16)VREG_S(12, 7));
+ break;
+ case RSP_V13:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(13, 0), (UINT16)VREG_S(13, 1), (UINT16)VREG_S(13, 2), (UINT16)VREG_S(13, 3), (UINT16)VREG_S(13, 4), (UINT16)VREG_S(13, 5), (UINT16)VREG_S(13, 6), (UINT16)VREG_S(13, 7));
+ break;
+ case RSP_V14:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(14, 0), (UINT16)VREG_S(14, 1), (UINT16)VREG_S(14, 2), (UINT16)VREG_S(14, 3), (UINT16)VREG_S(14, 4), (UINT16)VREG_S(14, 5), (UINT16)VREG_S(14, 6), (UINT16)VREG_S(14, 7));
+ break;
+ case RSP_V15:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(15, 0), (UINT16)VREG_S(15, 1), (UINT16)VREG_S(15, 2), (UINT16)VREG_S(15, 3), (UINT16)VREG_S(15, 4), (UINT16)VREG_S(15, 5), (UINT16)VREG_S(15, 6), (UINT16)VREG_S(15, 7));
+ break;
+ case RSP_V16:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(16, 0), (UINT16)VREG_S(16, 1), (UINT16)VREG_S(16, 2), (UINT16)VREG_S(16, 3), (UINT16)VREG_S(16, 4), (UINT16)VREG_S(16, 5), (UINT16)VREG_S(16, 6), (UINT16)VREG_S(16, 7));
+ break;
+ case RSP_V17:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(17, 0), (UINT16)VREG_S(17, 1), (UINT16)VREG_S(17, 2), (UINT16)VREG_S(17, 3), (UINT16)VREG_S(17, 4), (UINT16)VREG_S(17, 5), (UINT16)VREG_S(17, 6), (UINT16)VREG_S(17, 7));
+ break;
+ case RSP_V18:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(18, 0), (UINT16)VREG_S(18, 1), (UINT16)VREG_S(18, 2), (UINT16)VREG_S(18, 3), (UINT16)VREG_S(18, 4), (UINT16)VREG_S(18, 5), (UINT16)VREG_S(18, 6), (UINT16)VREG_S(18, 7));
+ break;
+ case RSP_V19:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(19, 0), (UINT16)VREG_S(19, 1), (UINT16)VREG_S(19, 2), (UINT16)VREG_S(19, 3), (UINT16)VREG_S(19, 4), (UINT16)VREG_S(19, 5), (UINT16)VREG_S(19, 6), (UINT16)VREG_S(19, 7));
+ break;
+ case RSP_V20:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(20, 0), (UINT16)VREG_S(20, 1), (UINT16)VREG_S(20, 2), (UINT16)VREG_S(20, 3), (UINT16)VREG_S(20, 4), (UINT16)VREG_S(20, 5), (UINT16)VREG_S(20, 6), (UINT16)VREG_S(20, 7));
+ break;
+ case RSP_V21:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(21, 0), (UINT16)VREG_S(21, 1), (UINT16)VREG_S(21, 2), (UINT16)VREG_S(21, 3), (UINT16)VREG_S(21, 4), (UINT16)VREG_S(21, 5), (UINT16)VREG_S(21, 6), (UINT16)VREG_S(21, 7));
+ break;
+ case RSP_V22:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(22, 0), (UINT16)VREG_S(22, 1), (UINT16)VREG_S(22, 2), (UINT16)VREG_S(22, 3), (UINT16)VREG_S(22, 4), (UINT16)VREG_S(22, 5), (UINT16)VREG_S(22, 6), (UINT16)VREG_S(22, 7));
+ break;
+ case RSP_V23:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(23, 0), (UINT16)VREG_S(23, 1), (UINT16)VREG_S(23, 2), (UINT16)VREG_S(23, 3), (UINT16)VREG_S(23, 4), (UINT16)VREG_S(23, 5), (UINT16)VREG_S(23, 6), (UINT16)VREG_S(23, 7));
+ break;
+ case RSP_V24:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(24, 0), (UINT16)VREG_S(24, 1), (UINT16)VREG_S(24, 2), (UINT16)VREG_S(24, 3), (UINT16)VREG_S(24, 4), (UINT16)VREG_S(24, 5), (UINT16)VREG_S(24, 6), (UINT16)VREG_S(24, 7));
+ break;
+ case RSP_V25:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(25, 0), (UINT16)VREG_S(25, 1), (UINT16)VREG_S(25, 2), (UINT16)VREG_S(25, 3), (UINT16)VREG_S(25, 4), (UINT16)VREG_S(25, 5), (UINT16)VREG_S(25, 6), (UINT16)VREG_S(25, 7));
+ break;
+ case RSP_V26:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(26, 0), (UINT16)VREG_S(26, 1), (UINT16)VREG_S(26, 2), (UINT16)VREG_S(26, 3), (UINT16)VREG_S(26, 4), (UINT16)VREG_S(26, 5), (UINT16)VREG_S(26, 6), (UINT16)VREG_S(26, 7));
+ break;
+ case RSP_V27:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(27, 0), (UINT16)VREG_S(27, 1), (UINT16)VREG_S(27, 2), (UINT16)VREG_S(27, 3), (UINT16)VREG_S(27, 4), (UINT16)VREG_S(27, 5), (UINT16)VREG_S(27, 6), (UINT16)VREG_S(27, 7));
+ break;
+ case RSP_V28:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(28, 0), (UINT16)VREG_S(28, 1), (UINT16)VREG_S(28, 2), (UINT16)VREG_S(28, 3), (UINT16)VREG_S(28, 4), (UINT16)VREG_S(28, 5), (UINT16)VREG_S(28, 6), (UINT16)VREG_S(28, 7));
+ break;
+ case RSP_V29:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(29, 0), (UINT16)VREG_S(29, 1), (UINT16)VREG_S(29, 2), (UINT16)VREG_S(29, 3), (UINT16)VREG_S(29, 4), (UINT16)VREG_S(29, 5), (UINT16)VREG_S(29, 6), (UINT16)VREG_S(29, 7));
+ break;
+ case RSP_V30:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(30, 0), (UINT16)VREG_S(30, 1), (UINT16)VREG_S(30, 2), (UINT16)VREG_S(30, 3), (UINT16)VREG_S(30, 4), (UINT16)VREG_S(30, 5), (UINT16)VREG_S(30, 6), (UINT16)VREG_S(30, 7));
+ break;
+ case RSP_V31:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(31, 0), (UINT16)VREG_S(31, 1), (UINT16)VREG_S(31, 2), (UINT16)VREG_S(31, 3), (UINT16)VREG_S(31, 4), (UINT16)VREG_S(31, 5), (UINT16)VREG_S(31, 6), (UINT16)VREG_S(31, 7));
+ break;
+ }
+}
+
+/***************************************************************************
+ Vector Load Instructions
+***************************************************************************/
+
+void rsp_cop2::handle_lwc2(UINT32 op)
+{
+ int i, end;
+ UINT32 ea;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ offset |= 0xffffffc0;
+
+ switch ((op >> 11) & 0x1f)
+ {
+ case 0x00: /* LBV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Load 1 byte to vector byte index
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset;
+ VREG_B(dest, index) = m_rsp.READ8(ea);
+ break;
+ }
+ case 0x01: /* LSV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads 2 bytes starting from vector byte index
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 2) : (offset * 2);
+
+ end = index + 2;
+
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = m_rsp.READ8(ea);
+ ea++;
+ }
+ break;
+ }
+ case 0x02: /* LLV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads 4 bytes starting from vector byte index
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 4) : (offset * 4);
+
+ end = index + 4;
+
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = m_rsp.READ8(ea);
+ ea++;
+ }
+ break;
+ }
+ case 0x03: /* LDV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads 8 bytes starting from vector byte index
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ end = index + 8;
+
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = m_rsp.READ8(ea);
+ ea++;
+ }
+ break;
+ }
+ case 0x04: /* LQV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00100 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads up to 16 bytes starting from vector byte index
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ end = index + (16 - (ea & 0xf));
+ if (end > 16) end = 16;
+
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = m_rsp.READ8(ea);
+ ea++;
+ }
+ break;
+ }
+ case 0x05: /* LRV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00101 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores up to 16 bytes starting from right side until 16-byte boundary
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ index = 16 - ((ea & 0xf) - index);
+ end = 16;
+ ea &= ~0xf;
+
+ for (i=index; i < end; i++)
+ {
+ VREG_B(dest, i) = m_rsp.READ8(ea);
+ ea++;
+ }
+ break;
+ }
+ case 0x06: /* LPV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00110 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the upper 8 bits of each element
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(dest, i) = m_rsp.READ8(ea + (((16-index) + i) & 0xf)) << 8;
+ }
+ break;
+ }
+ case 0x07: /* LUV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 00111 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the bits 14-7 of each element
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(dest, i) = m_rsp.READ8(ea + (((16-index) + i) & 0xf)) << 7;
+ }
+ break;
+ }
+ case 0x08: /* LHV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the bits 14-7 of each element, with 2-byte stride
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(dest, i) = m_rsp.READ8(ea + (((16-index) + (i<<1)) & 0xf)) << 7;
+ }
+ break;
+ }
+ case 0x09: /* LFV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ // not sure what happens if 16-byte boundary is crossed...
+
+ end = (index >> 1) + 4;
+
+ for (i=index >> 1; i < end; i++)
+ {
+ VREG_S(dest, i) = m_rsp.READ8(ea) << 7;
+ ea += 4;
+ }
+ break;
+ }
+ case 0x0a: /* LWV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads the full 128-bit vector starting from vector byte index and wrapping to index 0
+ // after byte index 15
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ end = (16 - index) + 16;
+
+ for (i=(16 - index); i < end; i++)
+ {
+ VREG_B(dest, i & 0xf) = m_rsp.READ8(ea);
+ ea += 4;
+ }
+ break;
+ }
+ case 0x0b: /* LTV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Loads one element to maximum of 8 vectors, while incrementing element index
+
+ // FIXME: has a small problem with odd indices
+
+ int element;
+ int vs = dest;
+ int ve = dest + 8;
+ if (ve > 32)
+ ve = 32;
+
+ element = 7 - (index >> 1);
+
+ if (index & 1) fatalerror("RSP: LTV: index = %d\n", index);
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ ea = ((ea + 8) & ~0xf) + (index & 1);
+ for (i=vs; i < ve; i++)
+ {
+ element = ((8 - (index >> 1) + (i-vs)) << 1);
+ VREG_B(i, (element & 0xf)) = m_rsp.READ8(ea);
+ VREG_B(i, ((element + 1) & 0xf)) = m_rsp.READ8(ea + 1);
+
+ ea += 2;
+ }
+ break;
+ }
+
+ default:
+ {
+ m_rsp.unimplemented_opcode(op);
+ break;
+ }
+ }
+}
+
+
+/***************************************************************************
+ Vector Store Instructions
+***************************************************************************/
+
+void rsp_cop2::handle_swc2(UINT32 op)
+{
+ int i, end;
+ int eaoffset;
+ UINT32 ea;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ offset |= 0xffffffc0;
+
+ switch ((op >> 11) & 0x1f)
+ {
+ case 0x00: /* SBV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 1 byte from vector byte index
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset;
+ m_rsp.WRITE8(ea, VREG_B(dest, index));
+ break;
+ }
+ case 0x01: /* SSV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 2 bytes starting from vector byte index
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 2) : (offset * 2);
+
+ end = index + 2;
+
+ for (i=index; i < end; i++)
+ {
+ m_rsp.WRITE8(ea, VREG_B(dest, i));
+ ea++;
+ }
+ break;
+ }
+ case 0x02: /* SLV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 4 bytes starting from vector byte index
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 4) : (offset * 4);
+
+ end = index + 4;
+
+ for (i=index; i < end; i++)
+ {
+ m_rsp.WRITE8(ea, VREG_B(dest, i));
+ ea++;
+ }
+ break;
+ }
+ case 0x03: /* SDV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 8 bytes starting from vector byte index
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ end = index + 8;
+
+ for (i=index; i < end; i++)
+ {
+ m_rsp.WRITE8(ea, VREG_B(dest, i));
+ ea++;
+ }
+ break;
+ }
+ case 0x04: /* SQV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores up to 16 bytes starting from vector byte index until 16-byte boundary
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ end = index + (16 - (ea & 0xf));
+
+ for (i=index; i < end; i++)
+ {
+ m_rsp.WRITE8(ea, VREG_B(dest, i & 0xf));
+ ea++;
+ }
+ break;
+ }
+ case 0x05: /* SRV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores up to 16 bytes starting from right side until 16-byte boundary
+
+ int o;
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ end = index + (ea & 0xf);
+ o = (16 - (ea & 0xf)) & 0xf;
+ ea &= ~0xf;
+
+ for (i=index; i < end; i++)
+ {
+ m_rsp.WRITE8(ea, VREG_B(dest, ((i + o) & 0xf)));
+ ea++;
+ }
+ break;
+ }
+ case 0x06: /* SPV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores upper 8 bits of each element
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+ end = index + 8;
+
+ for (i=index; i < end; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ m_rsp.WRITE8(ea, VREG_B(dest, ((i & 0xf) << 1)));
+ }
+ else
+ {
+ m_rsp.WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7);
+ }
+ ea++;
+ }
+ break;
+ }
+ case 0x07: /* SUV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores bits 14-7 of each element
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+ end = index + 8;
+
+ for (i=index; i < end; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ m_rsp.WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7);
+ }
+ else
+ {
+ m_rsp.WRITE8(ea, VREG_B(dest, ((i & 0x7) << 1)));
+ }
+ ea++;
+ }
+ break;
+ }
+ case 0x08: /* SHV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores bits 14-7 of each element, with 2-byte stride
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ for (i=0; i < 8; i++)
+ {
+ UINT8 d = ((VREG_B(dest, ((index + (i << 1) + 0) & 0xf))) << 1) |
+ ((VREG_B(dest, ((index + (i << 1) + 1) & 0xf))) >> 7);
+
+ m_rsp.WRITE8(ea, d);
+ ea += 2;
+ }
+ break;
+ }
+ case 0x09: /* SFV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores bits 14-7 of upper or lower quad, with 4-byte stride
+
+ // FIXME: only works for index 0 and index 8
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ eaoffset = ea & 0xf;
+ ea &= ~0xf;
+
+ end = (index >> 1) + 4;
+
+ for (i=index >> 1; i < end; i++)
+ {
+ m_rsp.WRITE8(ea + (eaoffset & 0xf), VREG_S(dest, i) >> 7);
+ eaoffset += 4;
+ }
+ break;
+ }
+ case 0x0a: /* SWV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores the full 128-bit vector starting from vector byte index and wrapping to index 0
+ // after byte index 15
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ eaoffset = ea & 0xf;
+ ea &= ~0xf;
+
+ end = index + 16;
+
+ for (i=index; i < end; i++)
+ {
+ m_rsp.WRITE8(ea + (eaoffset & 0xf), VREG_B(dest, i & 0xf));
+ eaoffset++;
+ }
+ break;
+ }
+ case 0x0b: /* STV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores one element from maximum of 8 vectors, while incrementing element index
+
+ int element;
+ int vs = dest;
+ int ve = dest + 8;
+ if (ve > 32)
+ ve = 32;
+
+ element = 8 - (index >> 1);
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ eaoffset = (ea & 0xf) + (element * 2);
+ ea &= ~0xf;
+
+ for (i=vs; i < ve; i++)
+ {
+ m_rsp.WRITE16(ea + (eaoffset & 0xf), VREG_S(i, element & 0x7));
+ eaoffset += 2;
+ element++;
+ }
+ break;
+ }
+
+ default:
+ {
+ m_rsp.unimplemented_opcode(op);
+ break;
+ }
+ }
+}
+
+/***************************************************************************
+ Vector Accumulator Helpers
+***************************************************************************/
+
+inline UINT16 rsp_cop2::SATURATE_ACCUM1(int accum, UINT16 negative, UINT16 positive)
+{
+if ((INT16)ACCUM_H(accum) < 0)
+{
+if ((UINT16)(ACCUM_H(accum)) != 0xffff)
+{
+return negative;
+}
+else
+{
+if ((INT16)ACCUM_M(accum) >= 0)
+{
+return negative;
+}
+else
+{
+return ACCUM_M(accum);
+}
+}
+}
+else
+{
+if ((UINT16)(ACCUM_H(accum)) != 0)
+{
+return positive;
+}
+else
+{
+if ((INT16)ACCUM_M(accum) < 0)
+{
+return positive;
+}
+else
+{
+return ACCUM_M(accum);
+}
+}
+}
+}
+
+UINT16 rsp_cop2::SATURATE_ACCUM(int accum, int slice, UINT16 negative, UINT16 positive)
+{
+ if ((INT16)ACCUM_H(accum) < 0)
+ {
+ if ((UINT16)(ACCUM_H(accum)) != 0xffff)
+ {
+ return negative;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(accum) >= 0)
+ {
+ return negative;
+ }
+ else
+ {
+ if (slice == 0)
+ {
+ return ACCUM_L(accum);
+ }
+ else if (slice == 1)
+ {
+ return ACCUM_M(accum);
+ }
+ }
+ }
+ }
+ else
+ {
+ if ((UINT16)(ACCUM_H(accum)) != 0)
+ {
+ return positive;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(accum) < 0)
+ {
+ return positive;
+ }
+ else
+ {
+ if (slice == 0)
+ {
+ return ACCUM_L(accum);
+ }
+ else
+ {
+ return ACCUM_M(accum);
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+/***************************************************************************
+ Vector Opcodes
+***************************************************************************/
+
+void rsp_cop2::handle_vector_ops(UINT32 op)
+{
+ int i;
+
+ // Opcode legend:
+ // E = VS2 element type
+ // S = VS1, Source vector 1
+ // T = VS2, Source vector 2
+ // D = Destination vector
+
+ switch (op & 0x3f)
+ {
+ case 0x00: /* VMULF */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000000 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by signed integer * 2
+
+ for (i=0; i < 8; i++)
+ {
+ INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+
+ if (s1 == -32768 && s2 == -32768)
+ {
+ // overflow
+ SET_ACCUM_H(0, i);
+ SET_ACCUM_M(-32768, i);
+ SET_ACCUM_L(-32768, i);
+ m_vres[i] = 0x7fff;
+ }
+ else
+ {
+ INT64 r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+ SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit
+ SET_ACCUM_M((INT16)(r >> 16), i);
+ SET_ACCUM_L((UINT16)(r), i);
+ m_vres[i] = ACCUM_M(i);
+ }
+ }
+ WRITEBACK_RESULT();
+
+ break;
+ }
+
+ case 0x01: /* VMULU */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 |
+ // ------------------------------------------------------
+ //
+
+ for (i=0; i < 8; i++)
+ {
+ INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+
+ INT64 r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+
+ SET_ACCUM_H((UINT16)(r >> 32), i);
+ SET_ACCUM_M((UINT16)(r >> 16), i);
+ SET_ACCUM_L((UINT16)(r), i);
+
+ if (r < 0)
+ {
+ m_vres[i] = 0;
+ }
+ else if (((INT16)(ACCUM_H(i)) ^ (INT16)(ACCUM_M(i))) < 0)
+ {
+ m_vres[i] = -1;
+ }
+ else
+ {
+ m_vres[i] = ACCUM_M(i);
+ }
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x04: /* VMUDL */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000100 |
+ // ------------------------------------------------------
+ //
+ // Multiplies unsigned fraction by unsigned fraction
+ // Stores the higher 16 bits of the 32-bit result to accumulator
+ // The low slice of accumulator is stored into destination element
+
+ for (i=0; i < 8; i++)
+ {
+ UINT32 s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ UINT32 s2 = (UINT32)(UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+ UINT32 r = s1 * s2;
+
+ SET_ACCUM_H(0, i);
+ SET_ACCUM_M(0, i);
+ SET_ACCUM_L((UINT16)(r >> 16), i);
+
+ m_vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x05: /* VMUDM */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000101 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by unsigned fraction
+ // The result is stored into accumulator
+ // The middle slice of accumulator is stored into destination element
+
+ for (i=0; i < 8; i++)
+ {
+ INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ INT32 s2 = (UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i)); // not sign-extended
+ INT32 r = s1 * s2;
+
+ SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit
+ SET_ACCUM_M((INT16)(r >> 16), i);
+ SET_ACCUM_L((UINT16)(r), i);
+
+ m_vres[i] = ACCUM_M(i);
+ }
+ WRITEBACK_RESULT();
+ break;
+
+ }
+
+ case 0x06: /* VMUDN */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 |
+ // ------------------------------------------------------
+ //
+ // Multiplies unsigned fraction by signed integer
+ // The result is stored into accumulator
+ // The low slice of accumulator is stored into destination element
+
+ for (i=0; i < 8; i++)
+ {
+ INT32 s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended
+ INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+ INT32 r = s1 * s2;
+
+ SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit
+ SET_ACCUM_M((INT16)(r >> 16), i);
+ SET_ACCUM_L((UINT16)(r), i);
+
+ m_vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x07: /* VMUDH */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000111 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by signed integer
+ // The result is stored into highest 32 bits of accumulator, the low slice is zero
+ // The highest 32 bits of accumulator is saturated into destination element
+
+ for (i=0; i < 8; i++)
+ {
+ INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+ INT32 r = s1 * s2;
+
+ SET_ACCUM_H((INT16)(r >> 16), i);
+ SET_ACCUM_M((UINT16)(r), i);
+ SET_ACCUM_L(0, i);
+
+ if (r < -32768) r = -32768;
+ if (r > 32767) r = 32767;
+ m_vres[i] = (INT16)(r);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x08: /* VMACF */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001000 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by signed integer * 2
+ // The result is added to accumulator
+
+ for (i=0; i < 8; i++)
+ {
+ INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+ INT32 r = s1 * s2;
+
+ UINT64 q = (UINT64)(UINT16)ACCUM_LL(i);
+ q |= (((UINT64)(UINT16)ACCUM_L(i)) << 16);
+ q |= (((UINT64)(UINT16)ACCUM_M(i)) << 32);
+ q |= (((UINT64)(UINT16)ACCUM_H(i)) << 48);
+
+ q += (INT64)(r) << 17;
+
+ SET_ACCUM_LL((UINT16)q, i);
+ SET_ACCUM_L((UINT16)(q >> 16), i);
+ SET_ACCUM_M((UINT16)(q >> 32), i);
+ SET_ACCUM_H((UINT16)(q >> 48), i);
+
+ m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x09: /* VMACU */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 |
+ // ------------------------------------------------------
+ //
+
+ for (i = 0; i < 8; i++)
+ {
+ INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+ INT32 r1 = s1 * s2;
+ UINT32 r2 = (UINT16)ACCUM_L(i) + ((UINT16)(r1) * 2);
+ UINT32 r3 = (UINT16)ACCUM_M(i) + (UINT16)((r1 >> 16) * 2) + (UINT16)(r2 >> 16);
+
+ SET_ACCUM_L((UINT16)(r2), i);
+ SET_ACCUM_M((UINT16)(r3), i);
+ SET_ACCUM_H(ACCUM_H(i) + (UINT16)(r3 >> 16) + (UINT16)(r1 >> 31), i);
+
+ if ((INT16)ACCUM_H(i) < 0)
+ {
+ m_vres[i] = 0;
+ }
+ else
+ {
+ if (ACCUM_H(i) != 0)
+ {
+ m_vres[i] = 0xffff;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(i) < 0)
+ {
+ m_vres[i] = 0xffff;
+ }
+ else
+ {
+ m_vres[i] = ACCUM_M(i);
+ }
+ }
+ }
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x0c: /* VMADL */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001100 |
+ // ------------------------------------------------------
+ //
+ // Multiplies unsigned fraction by unsigned fraction
+ // Adds the higher 16 bits of the 32-bit result to accumulator
+ // The low slice of accumulator is stored into destination element
+
+ for (i = 0; i < 8; i++)
+ {
+ UINT32 s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ UINT32 s2 = (UINT32)(UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+ UINT32 r1 = s1 * s2;
+ UINT32 r2 = (UINT16)ACCUM_L(i) + (r1 >> 16);
+ UINT32 r3 = (UINT16)ACCUM_M(i) + (r2 >> 16);
+
+ SET_ACCUM_L((UINT16)(r2), i);
+ SET_ACCUM_M((UINT16)(r3), i);
+ SET_ACCUM_H(ACCUM_H(i) + (INT16)(r3 >> 16), i);
+
+ m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x0d: /* VMADM */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by unsigned fraction
+ // The result is added into accumulator
+ // The middle slice of accumulator is stored into destination element
+
+ for (i=0; i < 8; i++)
+ {
+ UINT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ UINT32 s2 = (UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i)); // not sign-extended
+ UINT32 r1 = s1 * s2;
+ UINT32 r2 = (UINT16)ACCUM_L(i) + (UINT16)(r1);
+ UINT32 r3 = (UINT16)ACCUM_M(i) + (r1 >> 16) + (r2 >> 16);
+
+ SET_ACCUM_L((UINT16)(r2), i);
+ SET_ACCUM_M((UINT16)(r3), i);
+ SET_ACCUM_H(ACCUM_H(i) + (UINT16)(r3 >> 16), i);
+ if ((INT32)(r1) < 0)
+ SET_ACCUM_H(i, ACCUM_H(i) - 1);
+
+ m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x0e: /* VMADN */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 |
+ // ------------------------------------------------------
+ //
+ // Multiplies unsigned fraction by signed integer
+ // The result is added into accumulator
+ // The low slice of accumulator is stored into destination element
+
+ for (i=0; i < 8; i++)
+ {
+ INT32 s1 = (UINT16)VREG_S(VS1REG, i); // not sign-extended
+ INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+
+ UINT64 q = (UINT64)ACCUM_LL(i);
+ q |= (((UINT64)ACCUM_L(i)) << 16);
+ q |= (((UINT64)ACCUM_M(i)) << 32);
+ q |= (((UINT64)ACCUM_H(i)) << 48);
+ q += (INT64)(s1*s2) << 16;
+
+ SET_ACCUM_LL((UINT16)q, i);
+ SET_ACCUM_L((UINT16)(q >> 16), i);
+ SET_ACCUM_M((UINT16)(q >> 32), i);
+ SET_ACCUM_H((UINT16)(q >> 48), i);
+
+ m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
+ }
+ WRITEBACK_RESULT();
+
+ break;
+ }
+
+ case 0x0f: /* VMADH */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001111 |
+ // ------------------------------------------------------
+ //
+ // Multiplies signed integer by signed integer
+ // The result is added into highest 32 bits of accumulator, the low slice is zero
+ // The highest 32 bits of accumulator is saturated into destination element
+
+ for (i = 0; i < 8; i++)
+ {
+ INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+
+ INT32 accum = (UINT32)(UINT16)ACCUM_M(i);
+ accum |= ((UINT32)((UINT16)ACCUM_H(i))) << 16;
+ accum += s1 * s2;
+
+ SET_ACCUM_H((UINT16)(accum >> 16), i);
+ SET_ACCUM_M((UINT16)accum, i);
+
+ m_vres[i] = SATURATE_ACCUM1(i, 0x8000, 0x7fff);
+ }
+ WRITEBACK_RESULT();
+
+ break;
+ }
+
+ case 0x10: /* VADD */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010000 |
+ // ------------------------------------------------------
+ //
+ // Adds two vector registers and carry flag, the result is saturated to 32767
+
+ // TODO: check VS2REG == VDREG
+
+ for (i=0; i < 8; i++)
+ {
+ INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+ INT32 r = s1 + s2 + (CARRY_FLAG(i) != 0 ? 1 : 0);
+
+ SET_ACCUM_L((INT16)(r), i);
+
+ if (r > 32767) r = 32767;
+ if (r < -32768) r = -32768;
+ m_vres[i] = (INT16)(r);
+ }
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x11: /* VSUB */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010001 |
+ // ------------------------------------------------------
+ //
+ // Subtracts two vector registers and carry flag, the result is saturated to -32768
+
+ // TODO: check VS2REG == VDREG
+
+ for (i = 0; i < 8; i++)
+ {
+ INT32 s1 = (INT32)(INT16)VREG_S(VS1REG, i);
+ INT32 s2 = (INT32)(INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+ INT32 r = s1 - s2 - (CARRY_FLAG(i) != 0 ? 1 : 0);
+
+ SET_ACCUM_L((INT16)(r), i);
+
+ if (r > 32767) r = 32767;
+ if (r < -32768) r = -32768;
+
+ m_vres[i] = (INT16)(r);
+ }
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x13: /* VABS */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010011 |
+ // ------------------------------------------------------
+ //
+ // Changes the sign of source register 2 if source register 1 is negative and stores
+ // the result to destination register
+
+ for (i=0; i < 8; i++)
+ {
+ INT16 s1 = (INT16)VREG_S(VS1REG, i);
+ INT16 s2 = (INT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+
+ if (s1 < 0)
+ {
+ if (s2 == -32768)
+ {
+ m_vres[i] = 32767;
+ }
+ else
+ {
+ m_vres[i] = -s2;
+ }
+ }
+ else if (s1 > 0)
+ {
+ m_vres[i] = s2;
+ }
+ else
+ {
+ m_vres[i] = 0;
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x14: /* VADDC */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010100 |
+ // ------------------------------------------------------
+ //
+ // Adds two vector registers, the carry out is stored into carry register
+
+ // TODO: check VS2REG = VDREG
+
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+
+ for (i=0; i < 8; i++)
+ {
+ INT32 s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ INT32 s2 = (UINT32)(UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+ INT32 r = s1 + s2;
+
+ m_vres[i] = (INT16)(r);
+ SET_ACCUM_L((INT16)(r), i);
+
+ if (r & 0xffff0000)
+ {
+ SET_CARRY_FLAG(i);
+ }
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x15: /* VSUBC */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010101 |
+ // ------------------------------------------------------
+ //
+ // Subtracts two vector registers, the carry out is stored into carry register
+
+ // TODO: check VS2REG = VDREG
+
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+
+ for (i=0; i < 8; i++)
+ {
+ INT32 s1 = (UINT32)(UINT16)VREG_S(VS1REG, i);
+ INT32 s2 = (UINT32)(UINT16)VREG_S(VS2REG, VEC_EL_2(EL, i));
+ INT32 r = s1 - s2;
+
+ m_vres[i] = (INT16)(r);
+ SET_ACCUM_L((UINT16)(r), i);
+
+ if ((UINT16)(r) != 0)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ if (r & 0xffff0000)
+ {
+ SET_CARRY_FLAG(i);
+ }
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x1d: /* VSAW */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 011101 |
+ // ------------------------------------------------------
+ //
+ // Stores high, middle or low slice of accumulator to destination vector
+
+ switch (EL)
+ {
+ case 0x08: // VSAWH
+ {
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(VDREG, i) = ACCUM_H(i);
+ }
+ break;
+ }
+ case 0x09: // VSAWM
+ {
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(VDREG, i) = ACCUM_M(i);
+ }
+ break;
+ }
+ case 0x0a: // VSAWL
+ {
+ for (i=0; i < 8; i++)
+ {
+ VREG_S(VDREG, i) = ACCUM_L(i);
+ }
+ break;
+ }
+ default: //fatalerror("RSP: VSAW: el = %d\n", EL);//???????
+ printf("RSP: VSAW: el = %d\n", EL);//??? ???
+ exit(0);
+ }
+ break;
+ }
+
+ case 0x20: /* VLT */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100000 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are less than VS2
+ // Moves the element in VS2 to destination vector
+
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ for (i=0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ s1 = VREG_S(VS1REG, i);
+ s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
+ if (s1 < s2)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ else if (s1 == s2)
+ {
+ if (ZERO_FLAG(i) != 0 && CARRY_FLAG(i) != 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ }
+
+ if (COMPARE_FLAG(i) != 0)
+ {
+ m_vres[i] = s1;
+ }
+ else
+ {
+ m_vres[i] = s2;
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+
+ CLEAR_CARRY_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x21: /* VEQ */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100001 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are equal with VS2
+ // Moves the element in VS2 to destination vector
+
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ for (i = 0; i < 8; i++)
+ {
+ INT16 s1 = VREG_S(VS1REG, i);
+ INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
+
+ if ((s1 == s2) && ZERO_FLAG(i) == 0)
+ {
+ SET_COMPARE_FLAG(i);
+ m_vres[i] = s1;
+ }
+ else
+ {
+ m_vres[i] = s2;
+ }
+ SET_ACCUM_L(m_vres[i], i);
+ }
+
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x22: /* VNE */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100010 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are not equal with VS2
+ // Moves the element in VS2 to destination vector
+
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ for (i = 0; i < 8; i++)
+ {
+ INT16 s1 = VREG_S(VS1REG, i);
+ INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
+
+ if (s1 != s2 || ZERO_FLAG(i) != 0)
+ {
+ SET_COMPARE_FLAG(i);
+ m_vres[i] = s1;
+ }
+ else
+ {
+ m_vres[i] = s2;
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+
+ CLEAR_CARRY_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x23: /* VGE */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100011 |
+ // ------------------------------------------------------
+ //
+ // Sets compare flags if elements in VS1 are greater or equal with VS2
+ // Moves the element in VS2 to destination vector
+
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ for (i=0; i < 8; i++)
+ {
+ INT16 s1 = VREG_S(VS1REG, i);
+ INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
+
+ if ((s1 == s2 && (ZERO_FLAG(i) == 0 || CARRY_FLAG(i) == 0)) || s1 > s2)
+ {
+ SET_COMPARE_FLAG(i);
+ m_vres[i] = s1;
+ }
+ else
+ {
+ m_vres[i] = s2;
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+
+ CLEAR_CARRY_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x24: /* VCL */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 |
+ // ------------------------------------------------------
+ //
+ // Vector clip low
+
+ for (i = 0; i < 8; i++)
+ {
+ INT16 s1 = VREG_S(VS1REG, i);
+ INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
+
+ if (CARRY_FLAG(i) != 0)
+ {
+ if (ZERO_FLAG(i) != 0)
+ {
+ if (COMPARE_FLAG(i) != 0)
+ {
+ SET_ACCUM_L(-(UINT16)s2, i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+ else
+ {
+ if (CLIP1_FLAG(i) != 0)
+ {
+ if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) > 0x10000)
+ {
+ SET_ACCUM_L(s1, i);
+ CLEAR_COMPARE_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(-((UINT16)s2), i);
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ else
+ {
+ if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0)
+ {
+ SET_ACCUM_L(s1, i);
+ CLEAR_COMPARE_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(-((UINT16)s2), i);
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (ZERO_FLAG(i) != 0)
+ {
+ if (CLIP2_FLAG(i) != 0)
+ {
+ SET_ACCUM_L(s2, i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+ else
+ {
+ if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0)
+ {
+ SET_ACCUM_L(s2, i);
+ SET_CLIP2_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ CLEAR_CLIP2_FLAG(i);
+ }
+ }
+ }
+
+ m_vres[i] = ACCUM_L(i);
+ }
+ CLEAR_CARRY_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CLIP1_FLAGS();
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x25: /* VCH */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 |
+ // ------------------------------------------------------
+ //
+ // Vector clip high
+
+ CLEAR_CARRY_FLAGS();
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP1_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+ UINT32 vce = 0;
+
+ for (i=0; i < 8; i++)
+ {
+ INT16 s1 = VREG_S(VS1REG, i);
+ INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
+
+ if ((s1 ^ s2) < 0)
+ {
+ vce = (s1 + s2 == -1);
+ SET_CARRY_FLAG(i);
+ if (s2 < 0)
+ {
+ SET_CLIP2_FLAG(i);
+ }
+
+ if (s1 + s2 <= 0)
+ {
+ SET_COMPARE_FLAG(i);
+ m_vres[i] = -((UINT16)s2);
+ }
+ else
+ {
+ m_vres[i] = s1;
+ }
+
+ if (s1 + s2 != 0)
+ {
+ if (s1 != ~s2)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ }
+ }
+ else
+ {
+ vce = 0;
+ if (s2 < 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ if (s1 - s2 >= 0)
+ {
+ SET_CLIP2_FLAG(i);
+ m_vres[i] = s2;
+ }
+ else
+ {
+ m_vres[i] = s1;
+ }
+
+ if ((s1 - s2) != 0)
+ {
+ if (s1 != ~s2)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ }
+ }
+ if (vce != 0)
+ {
+ SET_CLIP1_FLAG(i);
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x26: /* VCR */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 |
+ // ------------------------------------------------------
+ //
+ // Vector clip reverse
+
+ CLEAR_CARRY_FLAGS();
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP1_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ for (i=0; i < 8; i++)
+ {
+ INT16 s1 = VREG_S(VS1REG, i);
+ INT16 s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
+
+ if ((INT16)(s1 ^ s2) < 0)
+ {
+ if (s2 < 0)
+ {
+ SET_CLIP2_FLAG(i);
+ }
+ if ((s1 + s2) <= 0)
+ {
+ SET_ACCUM_L(~((UINT16)s2), i);
+ SET_COMPARE_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+ else
+ {
+ if (s2 < 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ if ((s1 - s2) >= 0)
+ {
+ SET_ACCUM_L(s2, i);
+ SET_CLIP2_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+
+ m_vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x27: /* VMRG */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100111 |
+ // ------------------------------------------------------
+ //
+ // Merges two vectors according to compare flags
+
+ for (i = 0; i < 8; i++)
+ {
+ if (COMPARE_FLAG(i) != 0)
+ {
+ m_vres[i] = VREG_S(VS1REG, i);
+ }
+ else
+ {
+ m_vres[i] = VREG_S(VS2REG, VEC_EL_2(EL, i));
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x28: /* VAND */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 |
+ // ------------------------------------------------------
+ //
+ // Bitwise AND of two vector registers
+
+ for (i = 0; i < 8; i++)
+ {
+ m_vres[i] = VREG_S(VS1REG, i) & VREG_S(VS2REG, VEC_EL_2(EL, i));
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x29: /* VNAND */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101001 |
+ // ------------------------------------------------------
+ //
+ // Bitwise NOT AND of two vector registers
+
+ for (i = 0; i < 8; i++)
+ {
+ m_vres[i] = ~((VREG_S(VS1REG, i) & VREG_S(VS2REG, VEC_EL_2(EL, i))));
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x2a: /* VOR */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101010 |
+ // ------------------------------------------------------
+ //
+ // Bitwise OR of two vector registers
+
+ for (i = 0; i < 8; i++)
+ {
+ m_vres[i] = VREG_S(VS1REG, i) | VREG_S(VS2REG, VEC_EL_2(EL, i));
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x2b: /* VNOR */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101011 |
+ // ------------------------------------------------------
+ //
+ // Bitwise NOT OR of two vector registers
+
+ for (i=0; i < 8; i++)
+ {
+ m_vres[i] = ~((VREG_S(VS1REG, i) | VREG_S(VS2REG, VEC_EL_2(EL, i))));
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x2c: /* VXOR */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101100 |
+ // ------------------------------------------------------
+ //
+ // Bitwise XOR of two vector registers
+
+ for (i=0; i < 8; i++)
+ {
+ m_vres[i] = VREG_S(VS1REG, i) ^ VREG_S(VS2REG, VEC_EL_2(EL, i));
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+ case 0x2d: /* VNXOR */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 |
+ // ------------------------------------------------------
+ //
+ // Bitwise NOT XOR of two vector registers
+
+ for (i=0; i < 8; i++)
+ {
+ m_vres[i] = ~((VREG_S(VS1REG, i) ^ VREG_S(VS2REG, VEC_EL_2(EL, i))));
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x30: /* VRCP */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal
+ INT32 shifter = 0;
+
+ INT32 rec = (INT16)(VREG_S(VS2REG, EL & 7));
+ INT32 datainput = (rec < 0) ? (-rec) : rec;
+ if (datainput)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ shifter = 0x10;
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ m_reciprocal_res = rec;
+ m_dp_allowed = 0;
+
+ VREG_S(VDREG, VS1REG & 7) = (UINT16)(rec & 0xffff);
+
+ for (i = 0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+
+
+ break;
+ }
+
+ case 0x31: /* VRCPL */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal low part
+
+ INT32 shifter = 0;
+
+ INT32 rec = (INT16)VREG_S(VS2REG, EL & 7);
+ INT32 datainput = rec;
+
+ if (m_dp_allowed)
+ {
+ rec = (rec & 0x0000ffff) | m_reciprocal_high;
+ datainput = rec;
+
+ if (rec < 0)
+ {
+ if (rec < -32768)
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+ }
+ else if (datainput < 0)
+ {
+ datainput = -datainput;
+
+ shifter = 0x10;
+ }
+
+
+ for (i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
+ temp ^= rec >> 31;
+
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ m_reciprocal_res = rec;
+ m_dp_allowed = 0;
+
+ VREG_S(VDREG, VS1REG & 7) = (UINT16)(rec & 0xffff);
+
+ for (i = 0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+
+ break;
+ }
+
+ case 0x32: /* VRCPH */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal high part
+
+ m_reciprocal_high = (VREG_S(VS2REG, EL & 7)) << 16;
+ m_dp_allowed = 1;
+
+ for (i = 0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+
+ VREG_S(VDREG, VS1REG & 7) = (INT16)(m_reciprocal_res >> 16);
+
+ break;
+ }
+
+ case 0x33: /* VMOV */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110011 |
+ // ------------------------------------------------------
+ //
+ // Moves element from vector to destination vector
+
+ VREG_S(VDREG, VS1REG & 7) = VREG_S(VS2REG, EL & 7);
+ for (i = 0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+ break;
+ }
+
+ case 0x34: /* VRSQ */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal square-root
+
+ INT32 shifter = 0;
+
+ INT32 rec = (INT16)(VREG_S(VS2REG, EL & 7));
+ INT32 datainput = (rec < 0) ? (-rec) : rec;
+ if (datainput)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))//?.?.??? 31 - i
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ shifter = 0x10;
+ }
+
+ 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;
+
+ m_reciprocal_res = rec;
+ m_dp_allowed = 0;
+
+ VREG_S(VDREG, VS1REG & 7) = (UINT16)(rec & 0xffff);
+
+ for (i = 0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+
+ break;
+ }
+
+ case 0x35: /* VRSQL */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal square-root low part
+
+ INT32 shifter = 0;
+ INT32 rec = (INT16)VREG_S(VS2REG, EL & 7);
+ INT32 datainput = rec;
+
+ if (m_dp_allowed)
+ {
+ rec = (rec & 0x0000ffff) | m_reciprocal_high;
+ datainput = rec;
+
+ if (rec < 0)
+ {
+ if (rec < -32768)
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+ }
+ else if (datainput < 0)
+ {
+ datainput = -datainput;
+
+ shifter = 0x10;
+ }
+
+ if (datainput)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+
+ 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);
+ temp ^= rec >> 31;
+
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ m_reciprocal_res = rec;
+ m_dp_allowed = 0;
+
+ VREG_S(VDREG, VS1REG & 7) = (UINT16)(rec & 0xffff);
+
+ for (i = 0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+
+ break;
+ }
+
+ case 0x36: /* VRSQH */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110110 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal square-root high part
+
+ m_reciprocal_high = (VREG_S(VS2REG, EL & 7)) << 16;
+ m_dp_allowed = 1;
+
+ for (i=0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+
+ VREG_S(VDREG, VS1REG & 7) = (INT16)(m_reciprocal_res >> 16); // store high part
+ break;
+ }
+
+ case 0x37: /* VNOP */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110111 |
+ // ------------------------------------------------------
+ //
+ // Vector null instruction
+
+ break;
+ }
+
+ default: m_rsp.unimplemented_opcode(op); break;
+ }
+}
+
+/***************************************************************************
+ Vector Flag Reading/Writing
+***************************************************************************/
+
+void rsp_cop2::handle_cop2(UINT32 op)
+{
+ switch ((op >> 21) & 0x1f)
+ {
+ case 0x00: /* MFC2 */
+ {
+ // 31 25 20 15 10 6 0
+ // ---------------------------------------------------
+ // | 010010 | 00000 | TTTTT | DDDDD | IIII | 0000000 |
+ // ---------------------------------------------------
+ //
+ int el = (op >> 7) & 0xf;
+ UINT16 b1 = VREG_B(RDREG, (el+0) & 0xf);
+ UINT16 b2 = VREG_B(RDREG, (el+1) & 0xf);
+ if (RTREG) RTVAL = (INT32)(INT16)((b1 << 8) | (b2));
+ break;
+ }
+
+ case 0x02: /* CFC2 */
+ {
+ // 31 25 20 15 10 0
+ // ------------------------------------------------
+ // | 010010 | 00010 | TTTTT | DDDDD | 00000000000 |
+ // ------------------------------------------------
+ //
+ if (RTREG)
+ {
+ switch(RDREG)
+ {
+ case 0:
+ RTVAL = ((CARRY_FLAG(0) & 1) << 0) |
+ ((CARRY_FLAG(1) & 1) << 1) |
+ ((CARRY_FLAG(2) & 1) << 2) |
+ ((CARRY_FLAG(3) & 1) << 3) |
+ ((CARRY_FLAG(4) & 1) << 4) |
+ ((CARRY_FLAG(5) & 1) << 5) |
+ ((CARRY_FLAG(6) & 1) << 6) |
+ ((CARRY_FLAG(7) & 1) << 7) |
+ ((ZERO_FLAG(0) & 1) << 8) |
+ ((ZERO_FLAG(1) & 1) << 9) |
+ ((ZERO_FLAG(2) & 1) << 10) |
+ ((ZERO_FLAG(3) & 1) << 11) |
+ ((ZERO_FLAG(4) & 1) << 12) |
+ ((ZERO_FLAG(5) & 1) << 13) |
+ ((ZERO_FLAG(6) & 1) << 14) |
+ ((ZERO_FLAG(7) & 1) << 15);
+ if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
+ break;
+ case 1:
+ RTVAL = ((COMPARE_FLAG(0) & 1) << 0) |
+ ((COMPARE_FLAG(1) & 1) << 1) |
+ ((COMPARE_FLAG(2) & 1) << 2) |
+ ((COMPARE_FLAG(3) & 1) << 3) |
+ ((COMPARE_FLAG(4) & 1) << 4) |
+ ((COMPARE_FLAG(5) & 1) << 5) |
+ ((COMPARE_FLAG(6) & 1) << 6) |
+ ((COMPARE_FLAG(7) & 1) << 7) |
+ ((CLIP2_FLAG(0) & 1) << 8) |
+ ((CLIP2_FLAG(1) & 1) << 9) |
+ ((CLIP2_FLAG(2) & 1) << 10) |
+ ((CLIP2_FLAG(3) & 1) << 11) |
+ ((CLIP2_FLAG(4) & 1) << 12) |
+ ((CLIP2_FLAG(5) & 1) << 13) |
+ ((CLIP2_FLAG(6) & 1) << 14) |
+ ((CLIP2_FLAG(7) & 1) << 15);
+ if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
+ break;
+ case 2:
+ // Anciliary clipping flags
+ RTVAL = ((CLIP1_FLAG(0) & 1) << 0) |
+ ((CLIP1_FLAG(1) & 1) << 1) |
+ ((CLIP1_FLAG(2) & 1) << 2) |
+ ((CLIP1_FLAG(3) & 1) << 3) |
+ ((CLIP1_FLAG(4) & 1) << 4) |
+ ((CLIP1_FLAG(5) & 1) << 5) |
+ ((CLIP1_FLAG(6) & 1) << 6) |
+ ((CLIP1_FLAG(7) & 1) << 7);
+ }
+ }
+ break;
+ }
+
+ case 0x04: /* MTC2 */
+ {
+ // 31 25 20 15 10 6 0
+ // ---------------------------------------------------
+ // | 010010 | 00100 | TTTTT | DDDDD | IIII | 0000000 |
+ // ---------------------------------------------------
+ //
+ int el = (op >> 7) & 0xf;
+ W_VREG_B(RDREG, (el+0) & 0xf, (RTVAL >> 8) & 0xff);
+ W_VREG_B(RDREG, (el+1) & 0xf, (RTVAL >> 0) & 0xff);
+ break;
+ }
+
+ case 0x06: /* CTC2 */
+ {
+ // 31 25 20 15 10 0
+ // ------------------------------------------------
+ // | 010010 | 00110 | TTTTT | DDDDD | 00000000000 |
+ // ------------------------------------------------
+ //
+ switch(RDREG)
+ {
+ case 0:
+ CLEAR_CARRY_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ if (RTVAL & (1 << 0)) { SET_CARRY_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_CARRY_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_CARRY_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_CARRY_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_CARRY_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_CARRY_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_CARRY_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_CARRY_FLAG(7); }
+ if (RTVAL & (1 << 8)) { SET_ZERO_FLAG(0); }
+ if (RTVAL & (1 << 9)) { SET_ZERO_FLAG(1); }
+ if (RTVAL & (1 << 10)) { SET_ZERO_FLAG(2); }
+ if (RTVAL & (1 << 11)) { SET_ZERO_FLAG(3); }
+ if (RTVAL & (1 << 12)) { SET_ZERO_FLAG(4); }
+ if (RTVAL & (1 << 13)) { SET_ZERO_FLAG(5); }
+ if (RTVAL & (1 << 14)) { SET_ZERO_FLAG(6); }
+ if (RTVAL & (1 << 15)) { SET_ZERO_FLAG(7); }
+ break;
+
+ case 1:
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+ if (RTVAL & (1 << 0)) { SET_COMPARE_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_COMPARE_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_COMPARE_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_COMPARE_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_COMPARE_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_COMPARE_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_COMPARE_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_COMPARE_FLAG(7); }
+ if (RTVAL & (1 << 8)) { SET_CLIP2_FLAG(0); }
+ if (RTVAL & (1 << 9)) { SET_CLIP2_FLAG(1); }
+ if (RTVAL & (1 << 10)) { SET_CLIP2_FLAG(2); }
+ if (RTVAL & (1 << 11)) { SET_CLIP2_FLAG(3); }
+ if (RTVAL & (1 << 12)) { SET_CLIP2_FLAG(4); }
+ if (RTVAL & (1 << 13)) { SET_CLIP2_FLAG(5); }
+ if (RTVAL & (1 << 14)) { SET_CLIP2_FLAG(6); }
+ if (RTVAL & (1 << 15)) { SET_CLIP2_FLAG(7); }
+ break;
+
+ case 2:
+ CLEAR_CLIP1_FLAGS();
+ if (RTVAL & (1 << 0)) { SET_CLIP1_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_CLIP1_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_CLIP1_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_CLIP1_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_CLIP1_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_CLIP1_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_CLIP1_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_CLIP1_FLAG(7); }
+ break;
+ }
+ break;
+ }
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ {
+ handle_vector_ops(op);
+ break;
+ }
+
+ default:
+ m_rsp.unimplemented_opcode(op);
+ break;
+ }
+}
+
+inline void rsp_cop2::mfc2()
+{
+ UINT32 op = m_op;
+ int el = (op >> 7) & 0xf;
+
+ UINT16 b1 = VREG_B(VS1REG, (el+0) & 0xf);
+ UINT16 b2 = VREG_B(VS1REG, (el+1) & 0xf);
+ if (RTREG) RTVAL = (INT32)(INT16)((b1 << 8) | (b2));
+}
+
+inline void rsp_cop2::cfc2()
+{
+ UINT32 op = m_op;
+ if (RTREG)
+ {
+ switch(RDREG)
+ {
+ case 0:
+ RTVAL = ((CARRY_FLAG(0) & 1) << 0) |
+ ((CARRY_FLAG(1) & 1) << 1) |
+ ((CARRY_FLAG(2) & 1) << 2) |
+ ((CARRY_FLAG(3) & 1) << 3) |
+ ((CARRY_FLAG(4) & 1) << 4) |
+ ((CARRY_FLAG(5) & 1) << 5) |
+ ((CARRY_FLAG(6) & 1) << 6) |
+ ((CARRY_FLAG(7) & 1) << 7) |
+ ((ZERO_FLAG(0) & 1) << 8) |
+ ((ZERO_FLAG(1) & 1) << 9) |
+ ((ZERO_FLAG(2) & 1) << 10) |
+ ((ZERO_FLAG(3) & 1) << 11) |
+ ((ZERO_FLAG(4) & 1) << 12) |
+ ((ZERO_FLAG(5) & 1) << 13) |
+ ((ZERO_FLAG(6) & 1) << 14) |
+ ((ZERO_FLAG(7) & 1) << 15);
+ if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
+ break;
+ case 1:
+ RTVAL = ((COMPARE_FLAG(0) & 1) << 0) |
+ ((COMPARE_FLAG(1) & 1) << 1) |
+ ((COMPARE_FLAG(2) & 1) << 2) |
+ ((COMPARE_FLAG(3) & 1) << 3) |
+ ((COMPARE_FLAG(4) & 1) << 4) |
+ ((COMPARE_FLAG(5) & 1) << 5) |
+ ((COMPARE_FLAG(6) & 1) << 6) |
+ ((COMPARE_FLAG(7) & 1) << 7) |
+ ((CLIP2_FLAG(0) & 1) << 8) |
+ ((CLIP2_FLAG(1) & 1) << 9) |
+ ((CLIP2_FLAG(2) & 1) << 10) |
+ ((CLIP2_FLAG(3) & 1) << 11) |
+ ((CLIP2_FLAG(4) & 1) << 12) |
+ ((CLIP2_FLAG(5) & 1) << 13) |
+ ((CLIP2_FLAG(6) & 1) << 14) |
+ ((CLIP2_FLAG(7) & 1) << 15);
+ if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
+ break;
+ case 2:
+ RTVAL = ((CLIP1_FLAG(0) & 1) << 0) |
+ ((CLIP1_FLAG(1) & 1) << 1) |
+ ((CLIP1_FLAG(2) & 1) << 2) |
+ ((CLIP1_FLAG(3) & 1) << 3) |
+ ((CLIP1_FLAG(4) & 1) << 4) |
+ ((CLIP1_FLAG(5) & 1) << 5) |
+ ((CLIP1_FLAG(6) & 1) << 6) |
+ ((CLIP1_FLAG(7) & 1) << 7);
+ break;
+ }
+ }
+}
+
+inline void rsp_cop2::mtc2()
+{
+ UINT32 op = m_op;
+ int el = (op >> 7) & 0xf;
+ VREG_B(VS1REG, (el+0) & 0xf) = (RTVAL >> 8) & 0xff;
+ VREG_B(VS1REG, (el+1) & 0xf) = (RTVAL >> 0) & 0xff;
+}
+
+inline void rsp_cop2::ctc2()
+{
+ UINT32 op = m_op;
+ switch(RDREG)
+ {
+ case 0:
+ CLEAR_CARRY_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ m_vflag[0][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
+ m_vflag[0][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
+ m_vflag[0][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
+ m_vflag[0][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
+ m_vflag[0][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
+ m_vflag[0][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
+ m_vflag[0][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
+ m_vflag[0][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 0)) { SET_CARRY_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_CARRY_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_CARRY_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_CARRY_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_CARRY_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_CARRY_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_CARRY_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_CARRY_FLAG(7); }
+ m_vflag[3][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0;
+ m_vflag[3][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0;
+ m_vflag[3][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0;
+ m_vflag[3][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0;
+ m_vflag[3][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0;
+ m_vflag[3][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0;
+ m_vflag[3][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0;
+ m_vflag[3][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 8)) { SET_ZERO_FLAG(0); }
+ if (RTVAL & (1 << 9)) { SET_ZERO_FLAG(1); }
+ if (RTVAL & (1 << 10)) { SET_ZERO_FLAG(2); }
+ if (RTVAL & (1 << 11)) { SET_ZERO_FLAG(3); }
+ if (RTVAL & (1 << 12)) { SET_ZERO_FLAG(4); }
+ if (RTVAL & (1 << 13)) { SET_ZERO_FLAG(5); }
+ if (RTVAL & (1 << 14)) { SET_ZERO_FLAG(6); }
+ if (RTVAL & (1 << 15)) { SET_ZERO_FLAG(7); }
+ break;
+ case 1:
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+ m_vflag[1][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
+ m_vflag[1][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
+ m_vflag[1][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
+ m_vflag[1][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
+ m_vflag[1][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
+ m_vflag[1][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
+ m_vflag[1][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
+ m_vflag[1][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 0)) { SET_COMPARE_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_COMPARE_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_COMPARE_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_COMPARE_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_COMPARE_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_COMPARE_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_COMPARE_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_COMPARE_FLAG(7); }
+ m_vflag[4][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0;
+ m_vflag[4][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0;
+ m_vflag[4][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0;
+ m_vflag[4][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0;
+ m_vflag[4][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0;
+ m_vflag[4][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0;
+ m_vflag[4][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0;
+ m_vflag[4][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 8)) { SET_CLIP2_FLAG(0); }
+ if (RTVAL & (1 << 9)) { SET_CLIP2_FLAG(1); }
+ if (RTVAL & (1 << 10)) { SET_CLIP2_FLAG(2); }
+ if (RTVAL & (1 << 11)) { SET_CLIP2_FLAG(3); }
+ if (RTVAL & (1 << 12)) { SET_CLIP2_FLAG(4); }
+ if (RTVAL & (1 << 13)) { SET_CLIP2_FLAG(5); }
+ if (RTVAL & (1 << 14)) { SET_CLIP2_FLAG(6); }
+ if (RTVAL & (1 << 15)) { SET_CLIP2_FLAG(7); }
+ break;
+ case 2:
+ CLEAR_CLIP1_FLAGS();
+ m_vflag[2][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
+ m_vflag[2][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
+ m_vflag[2][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
+ m_vflag[2][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
+ m_vflag[2][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
+ m_vflag[2][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
+ m_vflag[2][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
+ m_vflag[2][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 0)) { SET_CLIP1_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_CLIP1_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_CLIP1_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_CLIP1_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_CLIP1_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_CLIP1_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_CLIP1_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_CLIP1_FLAG(7); }
+ break;
+ }
+}
+
+void rsp_cop2::log_instruction_execution()
+{
+ static VECTOR_REG prev_vecs[32];
+
+ for (int i = 0; i < 32; i++)
+ {
+ if (m_v[i].d[0] != prev_vecs[i].d[0] || m_v[i].d[1] != prev_vecs[i].d[1])
+ {
+ fprintf(m_rsp.m_exec_output, "V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X ", i,
+ (UINT16)VREG_S(i,0), (UINT16)VREG_S(i,1), (UINT16)VREG_S(i,2), (UINT16)VREG_S(i,3), (UINT16)VREG_S(i,4), (UINT16)VREG_S(i,5), (UINT16)VREG_S(i,6), (UINT16)VREG_S(i,7));
+ }
+ prev_vecs[i].d[0] = m_v[i].d[0];
+ prev_vecs[i].d[1] = m_v[i].d[1];
+ }
+}
diff --git a/src/emu/cpu/rsp/rspcp2.h b/src/emu/cpu/rsp/rspcp2.h
new file mode 100644
index 00000000000..4dc83f62268
--- /dev/null
+++ b/src/emu/cpu/rsp/rspcp2.h
@@ -0,0 +1,159 @@
+/***************************************************************************
+
+ rspcp2.h
+
+ Interface file for Reality Signal Processor (RSP) vector extensions.
+
+ Copyright the MESS team
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __RSPCP2_H__
+#define __RSPCP2_H__
+
+#include "cpu/drcuml.h"
+#include "rsp.h"
+
+#define USE_SIMD (0)
+#define SIMUL_SIMD (0)
+
+union VECTOR_REG
+{
+ UINT64 d[2];
+ UINT32 l[4];
+ INT16 s[8];
+ UINT8 b[16];
+};
+
+union ACCUMULATOR_REG
+{
+ UINT64 q;
+ UINT32 l[2];
+ UINT16 w[4];
+};
+
+struct compiler_state;
+
+class rsp_cop2
+{
+ friend class rsp_device;
+
+protected:
+ rsp_cop2(rsp_device &rsp, running_machine &machine);
+
+ virtual void init();
+ virtual void start();
+
+ virtual int generate_cop2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc) { return TRUE; }
+ virtual int generate_lwc2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc) { return TRUE; }
+ virtual int generate_swc2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc) { return TRUE; }
+
+ virtual void state_string_export(const int index, astring &string);
+
+public:
+ virtual void lbv() { }
+ virtual void lsv() { }
+ virtual void llv() { }
+ virtual void ldv() { }
+ virtual void lqv() { }
+ virtual void lrv() { }
+ virtual void lpv() { }
+ virtual void luv() { }
+ virtual void lhv() { }
+ virtual void lfv() { }
+ virtual void lwv() { }
+ virtual void ltv() { }
+ virtual void sbv() { }
+ virtual void ssv() { }
+ virtual void slv() { }
+ virtual void sdv() { }
+ virtual void sqv() { }
+ virtual void srv() { }
+ virtual void spv() { }
+ virtual void suv() { }
+ virtual void shv() { }
+ virtual void sfv() { }
+ virtual void swv() { }
+ virtual void stv() { }
+ virtual void vmulf() { }
+ virtual void vmulu() { }
+ virtual void vmudl() { }
+ virtual void vmudm() { }
+ virtual void vmudn() { }
+ virtual void vmudh() { }
+ virtual void vmacf() { }
+ virtual void vmacu() { }
+ virtual void vmadl() { }
+ virtual void vmadm() { }
+ virtual void vmadn() { }
+ virtual void vmadh() { }
+ virtual void vadd() { }
+ virtual void vsub() { }
+ virtual void vabs() { }
+ virtual void vaddc() { }
+ virtual void vsubc() { }
+ virtual void vaddb() { }
+ virtual void vsaw() { }
+ virtual void vlt() { }
+ virtual void veq() { }
+ virtual void vne() { }
+ virtual void vge() { }
+ virtual void vcl() { }
+ virtual void vch() { }
+ virtual void vcr() { }
+ virtual void vmrg() { }
+ virtual void vand() { }
+ virtual void vnand() { }
+ virtual void vor() { }
+ virtual void vnor() { }
+ virtual void vxor() { }
+ virtual void vnxor() { }
+ virtual void vrcp() { }
+ virtual void vrcpl() { }
+ virtual void vrcph() { }
+ virtual void vmov() { }
+ virtual void vrsql() { }
+ virtual void vrsqh() { }
+ virtual void vrsq() { }
+ virtual void mfc2();
+ virtual void cfc2();
+ virtual void mtc2();
+ virtual void ctc2();
+
+ virtual void handle_cop2(UINT32 op);
+
+ void log_instruction_execution();
+ virtual void cfunc_unimplemented_opcode() { }
+
+protected:
+ virtual int generate_vector_opcode(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc) { return TRUE; }
+
+ UINT16 SATURATE_ACCUM(int accum, int slice, UINT16 negative, UINT16 positive);
+ UINT16 SATURATE_ACCUM1(int accum, UINT16 negative, UINT16 positive);
+
+ UINT32 m_op;
+
+ rsp_device& m_rsp;
+ running_machine& m_machine;
+ UINT32 m_vres[8]; /* used for temporary vector results */
+
+ VECTOR_REG m_v[32];
+
+ ACCUMULATOR_REG m_accum[8];
+ UINT16 m_vflag[6][8];
+
+ INT32 m_reciprocal_res;
+ UINT32 m_reciprocal_high;
+ INT32 m_dp_allowed;
+
+private:
+ void handle_lwc2(UINT32 op);
+ void handle_swc2(UINT32 op);
+ void handle_vector_ops(UINT32 op);
+};
+
+#endif /* __RSPCP2_H__ */ \ No newline at end of file
diff --git a/src/emu/cpu/rsp/rspcp2d.c b/src/emu/cpu/rsp/rspcp2d.c
new file mode 100644
index 00000000000..c0bee5b11b1
--- /dev/null
+++ b/src/emu/cpu/rsp/rspcp2d.c
@@ -0,0 +1,3796 @@
+/***************************************************************************
+
+ rspcp2d.c
+
+ Universal machine language-based Nintendo/SGI RSP COP2 emulator.
+ Written by Harmony of the MESS team.
+
+ Copyright the MESS team.
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "rsp.h"
+#include "rspdiv.h"
+#include "rspcp2.h"
+#include "rspcp2d.h"
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+
+using namespace uml;
+
+extern offs_t rsp_dasm_one(char *buffer, offs_t pc, UINT32 op);
+
+/***************************************************************************
+ Helpful Defines
+***************************************************************************/
+
+#define VDREG ((op >> 6) & 0x1f)
+#define VS1REG ((op >> 11) & 0x1f)
+#define VS2REG ((op >> 16) & 0x1f)
+#define EL ((op >> 21) & 0xf)
+
+#define RSVAL (m_rsp.m_rsp_state->r[RSREG])
+#define RTVAL (m_rsp.m_rsp_state->r[RTREG])
+#define RDVAL (m_rsp.m_rsp_state->r[RDREG])
+
+#define VREG_B(reg, offset) m_v[(reg)].b[(offset)^1]
+#define W_VREG_S(reg, offset) m_v[(reg)].s[(offset)]
+#define VREG_S(reg, offset) (INT16)m_v[(reg)].s[(offset)]
+
+#define VEC_EL_2(x,z) (vector_elements_2[(x)][(z)])
+
+#define ACCUM(x) m_accum[x].q
+
+#define CARRY 0
+#define COMPARE 1
+#define CLIP1 2
+#define ZERO 3
+#define CLIP2 4
+
+static void cfunc_mfc2(void *param);
+static void cfunc_cfc2(void *param);
+static void cfunc_mtc2(void *param);
+static void cfunc_ctc2(void *param);
+
+#define ACCUM_H(x) (UINT16)m_accum[x].w[3]
+#define ACCUM_M(x) (UINT16)m_accum[x].w[2]
+#define ACCUM_L(x) (UINT16)m_accum[x].w[1]
+#define ACCUM_LL(x) (UINT16)m_accum[x].w[0]
+
+#define SET_ACCUM_H(v, x) m_accum[x].w[3] = v;
+#define SET_ACCUM_M(v, x) m_accum[x].w[2] = v;
+#define SET_ACCUM_L(v, x) m_accum[x].w[1] = v;
+#define SET_ACCUM_LL(v, x) m_accum[x].w[0] = v;
+
+#define GET_VS1(out, i) out = VREG_S(VS1REG, i)
+#define GET_VS2(out, i) out = VREG_S(VS2REG, VEC_EL_2(EL, i))
+
+#define CARRY_FLAG(x) (m_vflag[CARRY][x & 7] != 0 ? 0xffff : 0)
+#define COMPARE_FLAG(x) (m_vflag[COMPARE][x & 7] != 0 ? 0xffff : 0)
+#define CLIP1_FLAG(x) (m_vflag[CLIP1][x & 7] != 0 ? 0xffff : 0)
+#define ZERO_FLAG(x) (m_vflag[ZERO][x & 7] != 0 ? 0xffff : 0)
+#define CLIP2_FLAG(x) (m_vflag[CLIP2][x & 7] != 0 ? 0xffff : 0)
+
+#define CLEAR_CARRY_FLAGS() { memset(m_vflag[CARRY], 0, 16); }
+#define CLEAR_COMPARE_FLAGS() { memset(m_vflag[COMPARE], 0, 16); }
+#define CLEAR_CLIP1_FLAGS() { memset(m_vflag[CLIP1], 0, 16); }
+#define CLEAR_ZERO_FLAGS() { memset(m_vflag[ZERO], 0, 16); }
+#define CLEAR_CLIP2_FLAGS() { memset(m_vflag[CLIP2], 0, 16); }
+
+#define SET_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0xffff; }
+#define SET_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0xffff; }
+#define SET_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0xffff; }
+#define SET_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0xffff; }
+#define SET_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0xffff; }
+
+#define CLEAR_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0; }
+#define CLEAR_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0; }
+#define CLEAR_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0; }
+#define CLEAR_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0; }
+#define CLEAR_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0; }
+
+#define WRITEBACK_RESULT() { \
+ W_VREG_S(VDREG, 0) = m_vres[0]; \
+ W_VREG_S(VDREG, 1) = m_vres[1]; \
+ W_VREG_S(VDREG, 2) = m_vres[2]; \
+ W_VREG_S(VDREG, 3) = m_vres[3]; \
+ W_VREG_S(VDREG, 4) = m_vres[4]; \
+ W_VREG_S(VDREG, 5) = m_vres[5]; \
+ W_VREG_S(VDREG, 6) = m_vres[6]; \
+ W_VREG_S(VDREG, 7) = m_vres[7]; \
+}
+
+static const int vector_elements_2[16][8] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // none
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // ???
+ { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q
+ { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q
+ { 0, 0, 0, 0, 4, 4, 4, 4 }, // 0h
+ { 1, 1, 1, 1, 5, 5, 5, 5 }, // 1h
+ { 2, 2, 2, 2, 6, 6, 6, 6 }, // 2h
+ { 3, 3, 3, 3, 7, 7, 7, 7 }, // 3h
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
+ { 1, 1, 1, 1, 1, 1, 1, 1 }, // 1
+ { 2, 2, 2, 2, 2, 2, 2, 2 }, // 2
+ { 3, 3, 3, 3, 3, 3, 3, 3 }, // 3
+ { 4, 4, 4, 4, 4, 4, 4, 4 }, // 4
+ { 5, 5, 5, 5, 5, 5, 5, 5 }, // 5
+ { 6, 6, 6, 6, 6, 6, 6, 6 }, // 6
+ { 7, 7, 7, 7, 7, 7, 7, 7 }, // 7
+};
+
+void rsp_cop2_drc::cfunc_unimplemented_opcode()
+{
+ const UINT32 ppc = m_rsp.m_ppc;
+ if ((m_machine.debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ {
+ char string[200];
+ rsp_dasm_one(string, ppc, m_op);
+ osd_printf_debug("%08X: %s\n", ppc, string);
+ }
+ fatalerror("RSP: unknown opcode %02X (%08X) at %08X\n", m_op >> 26, m_op, ppc);
+}
+
+static void unimplemented_opcode(void *param)
+{
+ ((rsp_cop2 *)param)->cfunc_unimplemented_opcode();
+}
+
+void rsp_cop2_drc::state_string_export(const int index, astring &string)
+{
+ switch (index)
+ {
+ case RSP_V0:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 0, 0), (UINT16)VREG_S( 0, 1), (UINT16)VREG_S( 0, 2), (UINT16)VREG_S( 0, 3), (UINT16)VREG_S( 0, 4), (UINT16)VREG_S( 0, 5), (UINT16)VREG_S( 0, 6), (UINT16)VREG_S( 0, 7));
+ break;
+ case RSP_V1:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 1, 0), (UINT16)VREG_S( 1, 1), (UINT16)VREG_S( 1, 2), (UINT16)VREG_S( 1, 3), (UINT16)VREG_S( 1, 4), (UINT16)VREG_S( 1, 5), (UINT16)VREG_S( 1, 6), (UINT16)VREG_S( 1, 7));
+ break;
+ case RSP_V2:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 2, 0), (UINT16)VREG_S( 2, 1), (UINT16)VREG_S( 2, 2), (UINT16)VREG_S( 2, 3), (UINT16)VREG_S( 2, 4), (UINT16)VREG_S( 2, 5), (UINT16)VREG_S( 2, 6), (UINT16)VREG_S( 2, 7));
+ break;
+ case RSP_V3:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 3, 0), (UINT16)VREG_S( 3, 1), (UINT16)VREG_S( 3, 2), (UINT16)VREG_S( 3, 3), (UINT16)VREG_S( 3, 4), (UINT16)VREG_S( 3, 5), (UINT16)VREG_S( 3, 6), (UINT16)VREG_S( 3, 7));
+ break;
+ case RSP_V4:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 4, 0), (UINT16)VREG_S( 4, 1), (UINT16)VREG_S( 4, 2), (UINT16)VREG_S( 4, 3), (UINT16)VREG_S( 4, 4), (UINT16)VREG_S( 4, 5), (UINT16)VREG_S( 4, 6), (UINT16)VREG_S( 4, 7));
+ break;
+ case RSP_V5:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 5, 0), (UINT16)VREG_S( 5, 1), (UINT16)VREG_S( 5, 2), (UINT16)VREG_S( 5, 3), (UINT16)VREG_S( 5, 4), (UINT16)VREG_S( 5, 5), (UINT16)VREG_S( 5, 6), (UINT16)VREG_S( 5, 7));
+ break;
+ case RSP_V6:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 6, 0), (UINT16)VREG_S( 6, 1), (UINT16)VREG_S( 6, 2), (UINT16)VREG_S( 6, 3), (UINT16)VREG_S( 6, 4), (UINT16)VREG_S( 6, 5), (UINT16)VREG_S( 6, 6), (UINT16)VREG_S( 6, 7));
+ break;
+ case RSP_V7:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 7, 0), (UINT16)VREG_S( 7, 1), (UINT16)VREG_S( 7, 2), (UINT16)VREG_S( 7, 3), (UINT16)VREG_S( 7, 4), (UINT16)VREG_S( 7, 5), (UINT16)VREG_S( 7, 6), (UINT16)VREG_S( 7, 7));
+ break;
+ case RSP_V8:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 8, 0), (UINT16)VREG_S( 8, 1), (UINT16)VREG_S( 8, 2), (UINT16)VREG_S( 8, 3), (UINT16)VREG_S( 8, 4), (UINT16)VREG_S( 8, 5), (UINT16)VREG_S( 8, 6), (UINT16)VREG_S( 8, 7));
+ break;
+ case RSP_V9:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S( 9, 0), (UINT16)VREG_S( 9, 1), (UINT16)VREG_S( 9, 2), (UINT16)VREG_S( 9, 3), (UINT16)VREG_S( 9, 4), (UINT16)VREG_S( 9, 5), (UINT16)VREG_S( 9, 6), (UINT16)VREG_S( 9, 7));
+ break;
+ case RSP_V10:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(10, 0), (UINT16)VREG_S(10, 1), (UINT16)VREG_S(10, 2), (UINT16)VREG_S(10, 3), (UINT16)VREG_S(10, 4), (UINT16)VREG_S(10, 5), (UINT16)VREG_S(10, 6), (UINT16)VREG_S(10, 7));
+ break;
+ case RSP_V11:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(11, 0), (UINT16)VREG_S(11, 1), (UINT16)VREG_S(11, 2), (UINT16)VREG_S(11, 3), (UINT16)VREG_S(11, 4), (UINT16)VREG_S(11, 5), (UINT16)VREG_S(11, 6), (UINT16)VREG_S(11, 7));
+ break;
+ case RSP_V12:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(12, 0), (UINT16)VREG_S(12, 1), (UINT16)VREG_S(12, 2), (UINT16)VREG_S(12, 3), (UINT16)VREG_S(12, 4), (UINT16)VREG_S(12, 5), (UINT16)VREG_S(12, 6), (UINT16)VREG_S(12, 7));
+ break;
+ case RSP_V13:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(13, 0), (UINT16)VREG_S(13, 1), (UINT16)VREG_S(13, 2), (UINT16)VREG_S(13, 3), (UINT16)VREG_S(13, 4), (UINT16)VREG_S(13, 5), (UINT16)VREG_S(13, 6), (UINT16)VREG_S(13, 7));
+ break;
+ case RSP_V14:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(14, 0), (UINT16)VREG_S(14, 1), (UINT16)VREG_S(14, 2), (UINT16)VREG_S(14, 3), (UINT16)VREG_S(14, 4), (UINT16)VREG_S(14, 5), (UINT16)VREG_S(14, 6), (UINT16)VREG_S(14, 7));
+ break;
+ case RSP_V15:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(15, 0), (UINT16)VREG_S(15, 1), (UINT16)VREG_S(15, 2), (UINT16)VREG_S(15, 3), (UINT16)VREG_S(15, 4), (UINT16)VREG_S(15, 5), (UINT16)VREG_S(15, 6), (UINT16)VREG_S(15, 7));
+ break;
+ case RSP_V16:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(16, 0), (UINT16)VREG_S(16, 1), (UINT16)VREG_S(16, 2), (UINT16)VREG_S(16, 3), (UINT16)VREG_S(16, 4), (UINT16)VREG_S(16, 5), (UINT16)VREG_S(16, 6), (UINT16)VREG_S(16, 7));
+ break;
+ case RSP_V17:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(17, 0), (UINT16)VREG_S(17, 1), (UINT16)VREG_S(17, 2), (UINT16)VREG_S(17, 3), (UINT16)VREG_S(17, 4), (UINT16)VREG_S(17, 5), (UINT16)VREG_S(17, 6), (UINT16)VREG_S(17, 7));
+ break;
+ case RSP_V18:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(18, 0), (UINT16)VREG_S(18, 1), (UINT16)VREG_S(18, 2), (UINT16)VREG_S(18, 3), (UINT16)VREG_S(18, 4), (UINT16)VREG_S(18, 5), (UINT16)VREG_S(18, 6), (UINT16)VREG_S(18, 7));
+ break;
+ case RSP_V19:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(19, 0), (UINT16)VREG_S(19, 1), (UINT16)VREG_S(19, 2), (UINT16)VREG_S(19, 3), (UINT16)VREG_S(19, 4), (UINT16)VREG_S(19, 5), (UINT16)VREG_S(19, 6), (UINT16)VREG_S(19, 7));
+ break;
+ case RSP_V20:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(20, 0), (UINT16)VREG_S(20, 1), (UINT16)VREG_S(20, 2), (UINT16)VREG_S(20, 3), (UINT16)VREG_S(20, 4), (UINT16)VREG_S(20, 5), (UINT16)VREG_S(20, 6), (UINT16)VREG_S(20, 7));
+ break;
+ case RSP_V21:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(21, 0), (UINT16)VREG_S(21, 1), (UINT16)VREG_S(21, 2), (UINT16)VREG_S(21, 3), (UINT16)VREG_S(21, 4), (UINT16)VREG_S(21, 5), (UINT16)VREG_S(21, 6), (UINT16)VREG_S(21, 7));
+ break;
+ case RSP_V22:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(22, 0), (UINT16)VREG_S(22, 1), (UINT16)VREG_S(22, 2), (UINT16)VREG_S(22, 3), (UINT16)VREG_S(22, 4), (UINT16)VREG_S(22, 5), (UINT16)VREG_S(22, 6), (UINT16)VREG_S(22, 7));
+ break;
+ case RSP_V23:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(23, 0), (UINT16)VREG_S(23, 1), (UINT16)VREG_S(23, 2), (UINT16)VREG_S(23, 3), (UINT16)VREG_S(23, 4), (UINT16)VREG_S(23, 5), (UINT16)VREG_S(23, 6), (UINT16)VREG_S(23, 7));
+ break;
+ case RSP_V24:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(24, 0), (UINT16)VREG_S(24, 1), (UINT16)VREG_S(24, 2), (UINT16)VREG_S(24, 3), (UINT16)VREG_S(24, 4), (UINT16)VREG_S(24, 5), (UINT16)VREG_S(24, 6), (UINT16)VREG_S(24, 7));
+ break;
+ case RSP_V25:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(25, 0), (UINT16)VREG_S(25, 1), (UINT16)VREG_S(25, 2), (UINT16)VREG_S(25, 3), (UINT16)VREG_S(25, 4), (UINT16)VREG_S(25, 5), (UINT16)VREG_S(25, 6), (UINT16)VREG_S(25, 7));
+ break;
+ case RSP_V26:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(26, 0), (UINT16)VREG_S(26, 1), (UINT16)VREG_S(26, 2), (UINT16)VREG_S(26, 3), (UINT16)VREG_S(26, 4), (UINT16)VREG_S(26, 5), (UINT16)VREG_S(26, 6), (UINT16)VREG_S(26, 7));
+ break;
+ case RSP_V27:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(27, 0), (UINT16)VREG_S(27, 1), (UINT16)VREG_S(27, 2), (UINT16)VREG_S(27, 3), (UINT16)VREG_S(27, 4), (UINT16)VREG_S(27, 5), (UINT16)VREG_S(27, 6), (UINT16)VREG_S(27, 7));
+ break;
+ case RSP_V28:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(28, 0), (UINT16)VREG_S(28, 1), (UINT16)VREG_S(28, 2), (UINT16)VREG_S(28, 3), (UINT16)VREG_S(28, 4), (UINT16)VREG_S(28, 5), (UINT16)VREG_S(28, 6), (UINT16)VREG_S(28, 7));
+ break;
+ case RSP_V29:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(29, 0), (UINT16)VREG_S(29, 1), (UINT16)VREG_S(29, 2), (UINT16)VREG_S(29, 3), (UINT16)VREG_S(29, 4), (UINT16)VREG_S(29, 5), (UINT16)VREG_S(29, 6), (UINT16)VREG_S(29, 7));
+ break;
+ case RSP_V30:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(30, 0), (UINT16)VREG_S(30, 1), (UINT16)VREG_S(30, 2), (UINT16)VREG_S(30, 3), (UINT16)VREG_S(30, 4), (UINT16)VREG_S(30, 5), (UINT16)VREG_S(30, 6), (UINT16)VREG_S(30, 7));
+ break;
+ case RSP_V31:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)VREG_S(31, 0), (UINT16)VREG_S(31, 1), (UINT16)VREG_S(31, 2), (UINT16)VREG_S(31, 3), (UINT16)VREG_S(31, 4), (UINT16)VREG_S(31, 5), (UINT16)VREG_S(31, 6), (UINT16)VREG_S(31, 7));
+ break;
+ }
+}
+
+
+/***************************************************************************
+ Vector Load Instructions
+***************************************************************************/
+
+// LBV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00000 | IIII | Offset |
+// --------------------------------------------------
+//
+// Load 1 byte to vector byte index
+
+inline void rsp_cop2_drc::lbv()
+{
+ UINT32 op = m_op;
+
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset;
+ VREG_B(dest, index) = m_rsp.DM_READ8(ea);
+}
+
+static void cfunc_lbv(void *param)
+{
+ ((rsp_cop2 *)param)->lbv();
+}
+
+
+// LSV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00001 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads 2 bytes starting from vector byte index
+
+inline void rsp_cop2_drc::lsv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xe;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 2) : (offset * 2);
+ int end = index + 2;
+ for (int i = index; i < end; i++)
+ {
+ VREG_B(dest, i) = m_rsp.DM_READ8(ea);
+ ea++;
+ }
+}
+
+static void cfunc_lsv(void *param)
+{
+ ((rsp_cop2 *)param)->lsv();
+}
+
+
+// LLV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00010 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads 4 bytes starting from vector byte index
+
+inline void rsp_cop2_drc::llv()
+{
+ UINT32 op = m_op;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xc;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 4) : (offset * 4);
+
+ int end = index + 4;
+
+ for (int i = index; i < end; i++)
+ {
+ VREG_B(dest, i) = m_rsp.DM_READ8(ea);
+ ea++;
+ }
+}
+
+static void cfunc_llv(void *param)
+{
+ ((rsp_cop2 *)param)->llv();
+}
+
+
+// LDV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00011 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads 8 bytes starting from vector byte index
+
+inline void rsp_cop2_drc::ldv()
+{
+ UINT32 op = m_op;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0x8;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ int end = index + 8;
+
+ for (int i = index; i < end; i++)
+ {
+ VREG_B(dest, i) = m_rsp.DM_READ8(ea);
+ ea++;
+ }
+}
+
+static void cfunc_ldv(void *param)
+{
+ ((rsp_cop2 *)param)->ldv();
+}
+
+
+// LQV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00100 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads up to 16 bytes starting from vector byte index
+
+inline void rsp_cop2_drc::lqv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ int end = 16 - (ea & 0xf);
+ if (end > 16) end = 16;
+
+ for (int i = 0; i < end; i++)
+ {
+ VREG_B(dest, i) = m_rsp.DM_READ8(ea);
+ ea++;
+ }
+}
+
+static void cfunc_lqv(void *param)
+{
+ ((rsp_cop2 *)param)->lqv();
+}
+
+
+// LRV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00101 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores up to 16 bytes starting from right side until 16-byte boundary
+
+inline void rsp_cop2_drc::lrv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ index = 16 - ((ea & 0xf) - index);
+ ea &= ~0xf;
+
+ for (int i = index; i < 16; i++)
+ {
+ VREG_B(dest, i) = m_rsp.DM_READ8(ea);
+ ea++;
+ }
+}
+
+static void cfunc_lrv(void *param)
+{
+ ((rsp_cop2 *)param)->lrv();
+}
+
+
+// LPV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00110 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads a byte as the upper 8 bits of each element
+
+inline void rsp_cop2_drc::lpv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ for (int i = 0; i < 8; i++)
+ {
+ W_VREG_S(dest, i) = m_rsp.DM_READ8(ea + (((16-index) + i) & 0xf)) << 8;
+ }
+}
+
+static void cfunc_lpv(void *param)
+{
+ ((rsp_cop2 *)param)->lpv();
+}
+
+
+// LUV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00111 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads a byte as the bits 14-7 of each element
+
+inline void rsp_cop2_drc::luv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ for (int i = 0; i < 8; i++)
+ {
+ W_VREG_S(dest, i) = m_rsp.DM_READ8(ea + (((16-index) + i) & 0xf)) << 7;
+ }
+}
+
+static void cfunc_luv(void *param)
+{
+ ((rsp_cop2 *)param)->luv();
+}
+
+
+// LHV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 01000 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads a byte as the bits 14-7 of each element, with 2-byte stride
+
+inline void rsp_cop2_drc::lhv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ for (int i = 0; i < 8; i++)
+ {
+ W_VREG_S(dest, i) = m_rsp.DM_READ8(ea + (((16-index) + (i<<1)) & 0xf)) << 7;
+ }
+}
+
+static void cfunc_lhv(void *param)
+{
+ ((rsp_cop2 *)param)->lhv();
+}
+
+
+// LFV
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 01001 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride
+
+inline void rsp_cop2_drc::lfv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ // not sure what happens if 16-byte boundary is crossed...
+
+ int end = (index >> 1) + 4;
+
+ for (int i = index >> 1; i < end; i++)
+ {
+ W_VREG_S(dest, i) = m_rsp.DM_READ8(ea) << 7;
+ ea += 4;
+ }
+}
+
+static void cfunc_lfv(void *param)
+{
+ ((rsp_cop2 *)param)->lfv();
+}
+
+
+// LWV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 01010 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads the full 128-bit vector starting from vector byte index and wrapping to index 0
+// after byte index 15
+
+inline void rsp_cop2_drc::lwv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ int end = (16 - index) + 16;
+
+ for (int i = (16 - index); i < end; i++)
+ {
+ VREG_B(dest, i & 0xf) = m_rsp.DM_READ8(ea);
+ ea += 4;
+ }
+}
+
+static void cfunc_lwv(void *param)
+{
+ ((rsp_cop2 *)param)->lwv();
+}
+
+
+// LTV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads one element to maximum of 8 vectors, while incrementing element index
+
+inline void rsp_cop2_drc::ltv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+
+ // FIXME: has a small problem with odd indices
+
+ int vs = dest;
+ int ve = dest + 8;
+ if (ve > 32)
+ {
+ ve = 32;
+ }
+
+ int element = 7 - (index >> 1);
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ ea = ((ea + 8) & ~0xf) + (index & 1);
+ for (int i = vs; i < ve; i++)
+ {
+ element = (8 - (index >> 1) + (i - vs)) << 1;
+ VREG_B(i, (element & 0xf)) = m_rsp.DM_READ8(ea);
+ VREG_B(i, ((element + 1) & 0xf)) = m_rsp.DM_READ8(ea + 1);
+ ea += 2;
+ }
+}
+
+static void cfunc_ltv(void *param)
+{
+ ((rsp_cop2 *)param)->ltv();
+}
+
+
+int rsp_cop2_drc::generate_lwc2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ switch ((op >> 11) & 0x1f)
+ {
+ case 0x00: /* LBV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_lbv, this);
+ return TRUE;
+
+ case 0x01: /* LSV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_lsv, this);
+ return TRUE;
+
+ case 0x02: /* LLV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_llv, this);
+ return TRUE;
+
+ case 0x03: /* LDV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_ldv, this);
+ return TRUE;
+
+ case 0x04: /* LQV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_lqv, this);
+ return TRUE;
+
+ case 0x05: /* LRV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_lrv, this);
+ return TRUE;
+
+ case 0x06: /* LPV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_lpv, this);
+ return TRUE;
+
+ case 0x07: /* LUV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_luv, this);
+ return TRUE;
+
+ case 0x08: /* LHV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_lhv, this);
+ return TRUE;
+
+ case 0x09: /* LFV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_lfv, this);
+ return TRUE;
+
+ case 0x0a: /* LWV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_lwv, this);
+ return TRUE;
+
+ case 0x0b: /* LTV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [m_op],desc->opptr.l
+ UML_CALLC(block, cfunc_ltv, this);
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
+
+/***************************************************************************
+ Vector Store Instructions
+***************************************************************************/
+
+// SBV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores 1 byte from vector byte index
+
+inline void rsp_cop2_drc::sbv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset;
+ m_rsp.DM_WRITE8(ea, VREG_B(dest, index));
+}
+
+static void cfunc_sbv(void *param)
+{
+ ((rsp_cop2 *)param)->sbv();
+}
+
+
+// SSV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores 2 bytes starting from vector byte index
+
+inline void rsp_cop2_drc::ssv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 2) : (offset * 2);
+
+ int end = index + 2;
+ for (int i = index; i < end; i++)
+ {
+ m_rsp.DM_WRITE8(ea, VREG_B(dest, i));
+ ea++;
+ }
+}
+
+static void cfunc_ssv(void *param)
+{
+ ((rsp_cop2 *)param)->ssv();
+}
+
+
+// SLV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores 4 bytes starting from vector byte index
+
+inline void rsp_cop2_drc::slv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 4) : (offset * 4);
+
+ int end = index + 4;
+ for (int i = index; i < end; i++)
+ {
+ m_rsp.DM_WRITE8(ea, VREG_B(dest, i));
+ ea++;
+ }
+}
+
+static void cfunc_slv(void *param)
+{
+ ((rsp_cop2 *)param)->slv();
+}
+
+
+// SDV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores 8 bytes starting from vector byte index
+
+inline void rsp_cop2_drc::sdv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0x8;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ int end = index + 8;
+ for (int i = index; i < end; i++)
+ {
+ m_rsp.DM_WRITE8(ea, VREG_B(dest, i));
+ ea++;
+ }
+}
+
+static void cfunc_sdv(void *param)
+{
+ ((rsp_cop2 *)param)->sdv();
+}
+
+
+// SQV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores up to 16 bytes starting from vector byte index until 16-byte boundary
+
+inline void rsp_cop2_drc::sqv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ int end = index + (16 - (ea & 0xf));
+ for (int i=index; i < end; i++)
+ {
+ m_rsp.DM_WRITE8(ea, VREG_B(dest, i & 0xf));
+ ea++;
+ }
+}
+
+static void cfunc_sqv(void *param)
+{
+ ((rsp_cop2 *)param)->sqv();
+}
+
+
+// SRV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores up to 16 bytes starting from right side until 16-byte boundary
+
+inline void rsp_cop2_drc::srv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ int end = index + (ea & 0xf);
+ int o = (16 - (ea & 0xf)) & 0xf;
+ ea &= ~0xf;
+
+ for (int i = index; i < end; i++)
+ {
+ m_rsp.DM_WRITE8(ea, VREG_B(dest, ((i + o) & 0xf)));
+ ea++;
+ }
+}
+
+static void cfunc_srv(void *param)
+{
+ ((rsp_cop2 *)param)->srv();
+}
+
+
+// SPV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores upper 8 bits of each element
+
+inline void rsp_cop2_drc::spv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+ int end = index + 8;
+ for (int i=index; i < end; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ m_rsp.DM_WRITE8(ea, VREG_B(dest, (i & 0xf) << 1));
+ }
+ else
+ {
+ m_rsp.DM_WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7);
+ }
+ ea++;
+ }
+}
+
+static void cfunc_spv(void *param)
+{
+ ((rsp_cop2 *)param)->spv();
+}
+
+
+// SUV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores bits 14-7 of each element
+
+inline void rsp_cop2_drc::suv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+ int end = index + 8;
+ for (int i=index; i < end; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ m_rsp.DM_WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7);
+ }
+ else
+ {
+ m_rsp.DM_WRITE8(ea, VREG_B(dest, ((i & 0x7) << 1)));
+ }
+ ea++;
+ }
+}
+
+static void cfunc_suv(void *param)
+{
+ ((rsp_cop2 *)param)->suv();
+}
+
+
+// SHV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores bits 14-7 of each element, with 2-byte stride
+
+inline void rsp_cop2_drc::shv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ for (int i=0; i < 8; i++)
+ {
+ int element = index + (i << 1);
+ UINT8 d = (VREG_B(dest, (element & 0xf)) << 1) |
+ (VREG_B(dest, ((element + 1) & 0xf)) >> 7);
+ m_rsp.DM_WRITE8(ea, d);
+ ea += 2;
+ }
+}
+
+static void cfunc_shv(void *param)
+{
+ ((rsp_cop2 *)param)->shv();
+}
+
+
+// SFV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores bits 14-7 of upper or lower quad, with 4-byte stride
+
+inline void rsp_cop2_drc::sfv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ int eaoffset = ea & 0xf;
+ ea &= ~0xf;
+
+ int end = (index >> 1) + 4;
+
+ for (int i = index>>1; i < end; i++)
+ {
+ m_rsp.DM_WRITE8(ea + (eaoffset & 0xf), VREG_S(dest, i) >> 7);
+ eaoffset += 4;
+ }
+}
+
+static void cfunc_sfv(void *param)
+{
+ ((rsp_cop2 *)param)->sfv();
+}
+
+
+// SWV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores the full 128-bit vector starting from vector byte index and wrapping to index 0
+// after byte index 15
+
+inline void rsp_cop2_drc::swv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ int eaoffset = ea & 0xf;
+ ea &= ~0xf;
+
+ int end = index + 16;
+ for (int i = index; i < end; i++)
+ {
+ m_rsp.DM_WRITE8(ea + (eaoffset & 0xf), VREG_B(dest, i & 0xf));
+ eaoffset++;
+ }
+}
+
+static void cfunc_swv(void *param)
+{
+ ((rsp_cop2 *)param)->swv();
+}
+
+
+// STV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores one element from maximum of 8 vectors, while incrementing element index
+
+inline void rsp_cop2_drc::stv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ int vs = dest;
+ int ve = dest + 8;
+ if (ve > 32)
+ {
+ ve = 32;
+ }
+
+ int element = 8 - (index >> 1);
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ int eaoffset = (ea & 0xf) + (element * 2);
+ ea &= ~0xf;
+
+ for (int i = vs; i < ve; i++)
+ {
+ m_rsp.DM_WRITE16(ea + (eaoffset & 0xf), VREG_S(i, element & 0x7));
+ eaoffset += 2;
+ element++;
+ }
+}
+
+static void cfunc_stv(void *param)
+{
+ ((rsp_cop2 *)param)->stv();
+}
+
+int rsp_cop2_drc::generate_swc2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ switch ((op >> 11) & 0x1f)
+ {
+ case 0x00: /* SBV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_sbv, this);
+ return TRUE;
+
+ case 0x01: /* SSV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_ssv, this);
+ return TRUE;
+
+ case 0x02: /* SLV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_slv, this);
+ return TRUE;
+
+ case 0x03: /* SDV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_sdv, this);
+ return TRUE;
+
+ case 0x04: /* SQV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_sqv, this);
+ return TRUE;
+
+ case 0x05: /* SRV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_srv, this);
+ return TRUE;
+
+ case 0x06: /* SPV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_spv, this);
+ return TRUE;
+
+ case 0x07: /* SUV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_suv, this);
+ return TRUE;
+
+ case 0x08: /* SHV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_shv, this);
+ return TRUE;
+
+ case 0x09: /* SFV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_sfv, this);
+ return TRUE;
+
+ case 0x0a: /* SWV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_swv, this);
+ return TRUE;
+
+ case 0x0b: /* STV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_stv, this);
+ return TRUE;
+
+ default:
+ m_rsp.unimplemented_opcode(op);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/***************************************************************************
+ Vector Opcodes
+***************************************************************************/
+
+// VMULF
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000000 |
+// ------------------------------------------------------
+//
+// Multiplies signed integer by signed integer * 2
+
+inline void rsp_cop2_drc::vmulf()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ if (s1 == -32768 && s2 == -32768)
+ {
+ // overflow
+ SET_ACCUM_H(0, i);
+ SET_ACCUM_M(-32768, i);
+ SET_ACCUM_L(-32768, i);
+ m_vres[i] = 0x7fff;
+ }
+ else
+ {
+ INT64 r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+ SET_ACCUM_H((r < 0) ? 0xffff : 0, i);
+ SET_ACCUM_M((INT16)(r >> 16), i);
+ SET_ACCUM_L((UINT16)(r), i);
+ m_vres[i] = ACCUM_M(i);
+ }
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmulf(void *param)
+{
+ ((rsp_cop2 *)param)->vmulf();
+}
+
+
+// VMULU
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 |
+// ------------------------------------------------------
+//
+
+inline void rsp_cop2_drc::vmulu()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ INT64 r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+
+ SET_ACCUM_H((UINT16)(r >> 32), i);
+ SET_ACCUM_M((UINT16)(r >> 16), i);
+ SET_ACCUM_L((UINT16)(r), i);
+
+ if (r < 0)
+ {
+ m_vres[i] = 0;
+ }
+ else if (((INT16)(ACCUM_H(i)) ^ (INT16)(ACCUM_M(i))) < 0)
+ {
+ m_vres[i] = -1;
+ }
+ else
+ {
+ m_vres[i] = ACCUM_M(i);
+ }
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmulu(void *param)
+{
+ ((rsp_cop2 *)param)->vmulu();
+}
+
+
+// VMUDL
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 |
+// ------------------------------------------------------
+//
+// Multiplies signed integer by unsigned fraction
+// The result is added into accumulator
+// The middle slice of accumulator is stored into destination element
+
+inline void rsp_cop2_drc::vmudl()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ UINT32 s1 = (UINT32)(UINT16)w1;
+ UINT32 s2 = (UINT32)(UINT16)w2;
+
+ UINT32 r = s1 * s2;
+
+ SET_ACCUM_H(0, i);
+ SET_ACCUM_M(0, i);
+ SET_ACCUM_L((UINT16)(r >> 16), i);
+
+ m_vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmudl(void *param)
+{
+ ((rsp_cop2 *)param)->vmudl();
+}
+
+
+// VMUDM
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000101 |
+// ------------------------------------------------------
+//
+// Multiplies signed integer by unsigned fraction
+// The result is stored into accumulator
+// The middle slice of accumulator is stored into destination element
+
+inline void rsp_cop2_drc::vmudm()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (UINT16)w2;
+
+ INT32 r = s1 * s2;
+
+ SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit
+ SET_ACCUM_M((INT16)(r >> 16), i);
+ SET_ACCUM_L((UINT16)r, i);
+
+ m_vres[i] = ACCUM_M(i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmudm(void *param)
+{
+ ((rsp_cop2 *)param)->vmudm();
+}
+
+
+// VMUDN
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 |
+// ------------------------------------------------------
+//
+// Multiplies unsigned fraction by signed integer
+// The result is stored into accumulator
+// The low slice of accumulator is stored into destination element
+
+inline void rsp_cop2_drc::vmudn()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (UINT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ INT32 r = s1 * s2;
+
+ SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit
+ SET_ACCUM_M((INT16)(r >> 16), i);
+ SET_ACCUM_L((UINT16)(r), i);
+
+ m_vres[i] = (UINT16)(r);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmudn(void *param)
+{
+ ((rsp_cop2 *)param)->vmudn();
+}
+
+
+// VMUDH
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000111 |
+// ------------------------------------------------------
+//
+// Multiplies signed integer by signed integer
+// The result is stored into highest 32 bits of accumulator, the low slice is zero
+// The highest 32 bits of accumulator is saturated into destination element
+
+inline void rsp_cop2_drc::vmudh()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ INT32 r = s1 * s2;
+
+ SET_ACCUM_H((INT16)(r >> 16), i);
+ SET_ACCUM_M((UINT16)(r), i);
+ SET_ACCUM_L(0, i);
+
+ if (r < -32768) r = -32768;
+ if (r > 32767) r = 32767;
+ m_vres[i] = (INT16)(r);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmudh(void *param)
+{
+ ((rsp_cop2 *)param)->vmudh();
+}
+
+
+// VMACF
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001000 |
+// ------------------------------------------------------
+//
+
+inline void rsp_cop2_drc::vmacf()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ INT32 r = s1 * s2;
+
+ UINT64 q = (UINT64)(UINT16)ACCUM_LL(i);
+ q |= (((UINT64)(UINT16)ACCUM_L(i)) << 16);
+ q |= (((UINT64)(UINT16)ACCUM_M(i)) << 32);
+ q |= (((UINT64)(UINT16)ACCUM_H(i)) << 48);
+
+ q += (INT64)(r) << 17;
+ SET_ACCUM_LL((UINT16)q, i);
+ SET_ACCUM_L((UINT16)(q >> 16), i);
+ SET_ACCUM_M((UINT16)(q >> 32), i);
+ SET_ACCUM_H((UINT16)(q >> 48), i);
+
+ m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmacf(void *param)
+{
+ ((rsp_cop2 *)param)->vmacf();
+}
+
+
+// VMACU
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 |
+// ------------------------------------------------------
+//
+
+inline void rsp_cop2_drc::vmacu()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ INT32 r1 = s1 * s2;
+ UINT32 r2 = (UINT16)ACCUM_L(i) + ((UINT16)(r1) * 2);
+ UINT32 r3 = (UINT16)ACCUM_M(i) + (UINT16)((r1 >> 16) * 2) + (UINT16)(r2 >> 16);
+
+ SET_ACCUM_L((UINT16)(r2), i);
+ SET_ACCUM_M((UINT16)(r3), i);
+ SET_ACCUM_H(ACCUM_H(i) + (UINT16)(r3 >> 16) + (UINT16)(r1 >> 31), i);
+
+ if ((INT16)ACCUM_H(i) < 0)
+ {
+ m_vres[i] = 0;
+ }
+ else
+ {
+ if (ACCUM_H(i) != 0)
+ {
+ m_vres[i] = (INT16)0xffff;
+ }
+ else
+ {
+ if ((INT16)ACCUM_M(i) < 0)
+ {
+ m_vres[i] = (INT16)0xffff;
+ }
+ else
+ {
+ m_vres[i] = ACCUM_M(i);
+ }
+ }
+ }
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmacu(void *param)
+{
+ ((rsp_cop2 *)param)->vmacu();
+}
+
+
+// VMADL
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001100 |
+// ------------------------------------------------------
+//
+// Multiplies unsigned fraction by unsigned fraction
+// Adds the higher 16 bits of the 32-bit result to accumulator
+// The low slice of accumulator is stored into destination element
+
+inline void rsp_cop2_drc::vmadl()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ UINT32 s1 = w1;
+ UINT32 s2 = w2;
+
+ UINT32 r1 = s1 * s2;
+ UINT32 r2 = (UINT16)ACCUM_L(i) + (r1 >> 16);
+ UINT32 r3 = (UINT16)ACCUM_M(i) + (r2 >> 16);
+
+ SET_ACCUM_L((UINT16)r2, i);
+ SET_ACCUM_M((UINT16)r3, i);
+ SET_ACCUM_H(ACCUM_H(i) + (INT16)(r3 >> 16), i);
+
+ m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmadl(void *param)
+{
+ ((rsp_cop2 *)param)->vmadl();
+}
+
+
+// VMADM
+//
+
+inline void rsp_cop2_drc::vmadm()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ UINT32 s1 = (INT32)(INT16)w1;
+ UINT32 s2 = (UINT16)w2;
+
+ UINT32 r1 = s1 * s2;
+ UINT32 r2 = (UINT16)ACCUM_L(i) + (UINT16)(r1);
+ UINT32 r3 = (UINT16)ACCUM_M(i) + (r1 >> 16) + (r2 >> 16);
+
+ SET_ACCUM_L((UINT16)r2, i);
+ SET_ACCUM_M((UINT16)r3, i);
+ SET_ACCUM_H((UINT16)ACCUM_H(i) + (UINT16)(r3 >> 16), i);
+ if ((INT32)(r1) < 0)
+ {
+ SET_ACCUM_H((UINT16)ACCUM_H(i) - 1, i);
+ }
+
+ m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmadm(void *param)
+{
+ ((rsp_cop2 *)param)->vmadm();
+}
+
+
+// VMADN
+//
+
+inline void rsp_cop2_drc::vmadn()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (UINT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ UINT64 q = (UINT64)ACCUM_LL(i);
+ q |= (((UINT64)ACCUM_L(i)) << 16);
+ q |= (((UINT64)ACCUM_M(i)) << 32);
+ q |= (((UINT64)ACCUM_H(i)) << 48);
+ q += (INT64)(s1*s2) << 16;
+
+ SET_ACCUM_LL((UINT16)q, i);
+ SET_ACCUM_L((UINT16)(q >> 16), i);
+ SET_ACCUM_M((UINT16)(q >> 32), i);
+ SET_ACCUM_H((UINT16)(q >> 48), i);
+
+ m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmadn(void *param)
+{
+ ((rsp_cop2 *)param)->vmadn();
+}
+
+
+// VMADH
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001111 |
+// ------------------------------------------------------
+//
+// Multiplies signed integer by signed integer
+// The result is added into highest 32 bits of accumulator, the low slice is zero
+// The highest 32 bits of accumulator is saturated into destination element
+
+inline void rsp_cop2_drc::vmadh()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ INT32 accum = (UINT32)(UINT16)ACCUM_M(i);
+ accum |= ((UINT32)((UINT16)ACCUM_H(i))) << 16;
+ accum += s1 * s2;
+
+ SET_ACCUM_H((UINT16)(accum >> 16), i);
+ SET_ACCUM_M((UINT16)accum, i);
+
+ m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmadh(void *param)
+{
+ ((rsp_cop2 *)param)->vmadh();
+}
+
+
+// VADD
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010000 |
+// ------------------------------------------------------
+//
+// Adds two vector registers and carry flag, the result is saturated to 32767
+
+inline void rsp_cop2_drc::vadd()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+ INT32 r = s1 + s2 + (((CARRY_FLAG(i)) != 0) ? 1 : 0);
+
+ SET_ACCUM_L((INT16)(r), i);
+
+ if (r > 32767) r = 32767;
+ if (r < -32768) r = -32768;
+ m_vres[i] = (INT16)(r);
+ }
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vadd(void *param)
+{
+ ((rsp_cop2 *)param)->vadd();
+}
+
+
+// VSUB
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010001 |
+// ------------------------------------------------------
+//
+// Subtracts two vector registers and carry flag, the result is saturated to -32768
+// TODO: check VS2REG == VDREG
+
+inline void rsp_cop2_drc::vsub()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+ INT32 r = s1 - s2 - (((CARRY_FLAG(i)) != 0) ? 1 : 0);
+
+ SET_ACCUM_L((INT16)(r), i);
+
+ if (r > 32767) r = 32767;
+ if (r < -32768) r = -32768;
+
+ m_vres[i] = (INT16)(r);
+ }
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vsub(void *param)
+{
+ ((rsp_cop2 *)param)->vsub();
+}
+
+
+// VABS
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010011 |
+// ------------------------------------------------------
+//
+// Changes the sign of source register 2 if source register 1 is negative and stores the result to destination register
+
+inline void rsp_cop2_drc::vabs()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+
+ if (s1 < 0)
+ {
+ if (s2 == -32768)
+ {
+ m_vres[i] = 32767;
+ }
+ else
+ {
+ m_vres[i] = -s2;
+ }
+ }
+ else if (s1 > 0)
+ {
+ m_vres[i] = s2;
+ }
+ else
+ {
+ m_vres[i] = 0;
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vabs(void *param)
+{
+ ((rsp_cop2 *)param)->vabs();
+}
+
+
+// VADDC
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010100 |
+// ------------------------------------------------------
+//
+// Adds two vector registers, the carry out is stored into carry register
+// TODO: check VS2REG = VDREG
+
+inline void rsp_cop2_drc::vaddc()
+{
+ int op = m_op;
+
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (UINT32)(UINT16)w1;
+ INT32 s2 = (UINT32)(UINT16)w2;
+ INT32 r = s1 + s2;
+
+ m_vres[i] = (INT16)(r);
+ SET_ACCUM_L((INT16)r, i);
+
+ if (r & 0xffff0000)
+ {
+ SET_CARRY_FLAG(i);
+ }
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vaddc(void *param)
+{
+ ((rsp_cop2 *)param)->vaddc();
+}
+
+
+// VSUBC
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010101 |
+// ------------------------------------------------------
+//
+// Subtracts two vector registers, the carry out is stored into carry register
+// TODO: check VS2REG = VDREG
+
+inline void rsp_cop2_drc::vsubc()
+{
+ int op = m_op;
+
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (UINT32)(UINT16)w1;
+ INT32 s2 = (UINT32)(UINT16)w2;
+ INT32 r = s1 - s2;
+
+ m_vres[i] = (INT16)(r);
+ SET_ACCUM_L((UINT16)r, i);
+
+ if ((UINT16)(r) != 0)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ if (r & 0xffff0000)
+ {
+ SET_CARRY_FLAG(i);
+ }
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vsubc(void *param)
+{
+ ((rsp_cop2 *)param)->vsubc();
+}
+
+
+// VADDB
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010110 |
+// ------------------------------------------------------
+//
+// Adds two vector registers bytewise with rounding
+
+inline void rsp_cop2_drc::vaddb()
+{
+ const int op = m_op;
+ const int round = (EL == 0) ? 0 : (1 << (EL - 1));
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+
+ UINT8 hb1 = w1 >> 8;
+ UINT8 lb1 = w1 & 0xff;
+ UINT8 hb2 = w2 >> 8;
+ UINT8 lb2 = w2 & 0xff;
+
+ UINT16 hs = hb1 + hb2 + round;
+ UINT16 ls = lb1 + lb2 + round;
+
+ SET_ACCUM_L((hs << 8) | ls, i);
+
+ hs >>= EL;
+ if (hs > 255)
+ {
+ hs = 255;
+ }
+
+ ls >>= EL;
+ if (ls > 255)
+ {
+ ls = 255;
+ }
+
+ m_vres[i] = 0; // VD writeback disabled on production hardware
+ // m_vres[i] = (hs << 8) | ls;
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vaddb(void *param)
+{
+ ((rsp_cop2 *)param)->vaddb();
+}
+
+
+// VSAW
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 011101 |
+// ------------------------------------------------------
+//
+// Stores high, middle or low slice of accumulator to destination vector
+
+inline void rsp_cop2_drc::vsaw()
+{
+ int op = m_op;
+
+ switch (EL)
+ {
+ case 0x08: // VSAWH
+ for (int i = 0; i < 8; i++)
+ {
+ W_VREG_S(VDREG, i) = ACCUM_H(i);
+ }
+ break;
+ case 0x09: // VSAWM
+ for (int i = 0; i < 8; i++)
+ {
+ W_VREG_S(VDREG, i) = ACCUM_M(i);
+ }
+ break;
+ case 0x0a: // VSAWL
+ for (int i = 0; i < 8; i++)
+ {
+ W_VREG_S(VDREG, i) = ACCUM_L(i);
+ }
+ break;
+ default: // Unsupported
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ W_VREG_S(VDREG, i) = 0;
+ }
+ }
+ }
+}
+
+static void cfunc_vsaw(void *param)
+{
+ ((rsp_cop2 *)param)->vsaw();
+}
+
+
+// VLT
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100000 |
+// ------------------------------------------------------
+//
+// Sets compare flags if elements in VS1 are less than VS2
+// Moves the element in VS2 to destination vector
+
+inline void rsp_cop2_drc::vlt()
+{
+ int op = m_op;
+
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+
+ if (s1 < s2)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ else if (s1 == s2)
+ {
+ if (ZERO_FLAG(i) != 0 && CARRY_FLAG(i) != 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ }
+
+ if (COMPARE_FLAG(i) != 0)
+ {
+ m_vres[i] = s1;
+ }
+ else
+ {
+ m_vres[i] = s2;
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vlt(void *param)
+{
+ ((rsp_cop2 *)param)->vlt();
+}
+
+
+// VEQ
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100001 |
+// ------------------------------------------------------
+//
+// Sets compare flags if elements in VS1 are equal with VS2
+// Moves the element in VS2 to destination vector
+
+inline void rsp_cop2_drc::veq()
+{
+ int op = m_op;
+
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+
+ if ((s1 == s2) && ZERO_FLAG(i) == 0)
+ {
+ SET_COMPARE_FLAG(i);
+ m_vres[i] = s1;
+ }
+ else
+ {
+ m_vres[i] = s2;
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_veq(void *param)
+{
+ ((rsp_cop2 *)param)->veq();
+}
+
+
+// VNE
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100010 |
+// ------------------------------------------------------
+//
+// Sets compare flags if elements in VS1 are not equal with VS2
+// Moves the element in VS2 to destination vector
+
+inline void rsp_cop2_drc::vne()
+{
+ int op = m_op;
+
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+
+ if (s1 != s2 || ZERO_FLAG(i) != 0)
+ {
+ SET_COMPARE_FLAG(i);
+ m_vres[i] = s1;
+ }
+ else
+ {
+ m_vres[i] = s2;
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vne(void *param)
+{
+ ((rsp_cop2 *)param)->vne();
+}
+
+
+// VGE
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100011 |
+// ------------------------------------------------------
+//
+// Sets compare flags if elements in VS1 are greater or equal with VS2
+// Moves the element in VS2 to destination vector
+
+inline void rsp_cop2_drc::vge()
+{
+ int op = m_op;
+
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+ if ((s1 == s2 && (ZERO_FLAG(i) == 0 || CARRY_FLAG(i) == 0)) || s1 > s2)
+ {
+ SET_COMPARE_FLAG(i);
+ m_vres[i] = s1;
+ }
+ else
+ {
+ m_vres[i] = s2;
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vge(void *param)
+{
+ ((rsp_cop2 *)param)->vge();
+}
+
+
+// VCL
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 |
+// ------------------------------------------------------
+//
+// Vector clip low
+
+inline void rsp_cop2_drc::vcl()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+
+ if (CARRY_FLAG(i) != 0)
+ {
+ if (ZERO_FLAG(i) != 0)
+ {
+ if (COMPARE_FLAG(i) != 0)
+ {
+ SET_ACCUM_L(-(UINT16)s2, i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+ else
+ {
+ if (CLIP1_FLAG(i) != 0)
+ {
+ if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) > 0x10000)
+ {
+ SET_ACCUM_L(s1, i);
+ CLEAR_COMPARE_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(-((UINT16)s2), i);
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ else
+ {
+ if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0)
+ {
+ SET_ACCUM_L(s1, i);
+ CLEAR_COMPARE_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(-((UINT16)s2), i);
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (ZERO_FLAG(i) != 0)
+ {
+ if (CLIP2_FLAG(i) != 0)
+ {
+ SET_ACCUM_L(s2, i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+ else
+ {
+ if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0)
+ {
+ SET_ACCUM_L(s2, i);
+ SET_CLIP2_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ CLEAR_CLIP2_FLAG(i);
+ }
+ }
+ }
+ m_vres[i] = ACCUM_L(i);
+ }
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ CLEAR_CLIP1_FLAGS();
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vcl(void *param)
+{
+ ((rsp_cop2 *)param)->vcl();
+}
+
+
+// VCH
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 |
+// ------------------------------------------------------
+//
+// Vector clip high
+
+inline void rsp_cop2_drc::vch()
+{
+ int op = m_op;
+
+ CLEAR_CARRY_FLAGS();
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP1_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ UINT32 vce = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+
+ if ((s1 ^ s2) < 0)
+ {
+ vce = (s1 + s2 == -1);
+ SET_CARRY_FLAG(i);
+ if (s2 < 0)
+ {
+ SET_CLIP2_FLAG(i);
+ }
+
+ if ((s1 + s2) <= 0)
+ {
+ SET_COMPARE_FLAG(i);
+ m_vres[i] = -((UINT16)s2);
+ }
+ else
+ {
+ m_vres[i] = s1;
+ }
+
+ if ((s1 + s2) != 0 && s1 != ~s2)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ }//sign
+ else
+ {
+ vce = 0;
+ if (s2 < 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ if ((s1 - s2) >= 0)
+ {
+ SET_CLIP2_FLAG(i);
+ m_vres[i] = s2;
+ }
+ else
+ {
+ m_vres[i] = s1;
+ }
+
+ if ((s1 - s2) != 0 && s1 != ~s2)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ }
+ if (vce)
+ {
+ SET_CLIP1_FLAG(i);
+ }
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vch(void *param)
+{
+ ((rsp_cop2 *)param)->vch();
+}
+
+
+// VCR
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 |
+// ------------------------------------------------------
+//
+// Vector clip reverse
+
+inline void rsp_cop2_drc::vcr()
+{
+ int op = m_op;
+
+ CLEAR_CARRY_FLAGS();
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP1_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+
+ if ((INT16)(s1 ^ s2) < 0)
+ {
+ if (s2 < 0)
+ {
+ SET_CLIP2_FLAG(i);
+ }
+ if ((s1 + s2) <= 0)
+ {
+ SET_ACCUM_L(~((UINT16)s2), i);
+ SET_COMPARE_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+ else
+ {
+ if (s2 < 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ if ((s1 - s2) >= 0)
+ {
+ SET_ACCUM_L(s2, i);
+ SET_CLIP2_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+
+ m_vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vcr(void *param)
+{
+ ((rsp_cop2 *)param)->vcr();
+}
+
+
+// VMRG
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100111 |
+// ------------------------------------------------------
+//
+// Merges two vectors according to compare flags
+
+inline void rsp_cop2_drc::vmrg()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+ if (COMPARE_FLAG(i) != 0)
+ {
+ m_vres[i] = s1;
+ }
+ else
+ {
+ m_vres[i] = s2;
+ }
+
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmrg(void *param)
+{
+ ((rsp_cop2 *)param)->vmrg();
+}
+
+
+// VAND
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 |
+// ------------------------------------------------------
+//
+// Bitwise AND of two vector registers
+
+inline void rsp_cop2_drc::vand()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+ m_vres[i] = s1 & s2;
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vand(void *param)
+{
+ ((rsp_cop2 *)param)->vand();
+}
+
+
+// VNAND
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101001 |
+// ------------------------------------------------------
+//
+// Bitwise NOT AND of two vector registers
+
+inline void rsp_cop2_drc::vnand()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+ m_vres[i] = ~((s1 & s2));
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vnand(void *param)
+{
+ ((rsp_cop2 *)param)->vnand();
+}
+
+
+// VOR
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101010 |
+// ------------------------------------------------------
+//
+// Bitwise OR of two vector registers
+
+inline void rsp_cop2_drc::vor()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+ m_vres[i] = s1 | s2;
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vor(void *param)
+{
+ ((rsp_cop2 *)param)->vor();
+}
+
+
+// VNOR
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101011 |
+// ------------------------------------------------------
+//
+// Bitwise NOT OR of two vector registers
+
+inline void rsp_cop2_drc::vnor()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+ m_vres[i] = ~(s1 | s2);
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vnor(void *param)
+{
+ ((rsp_cop2 *)param)->vnor();
+}
+
+
+// VXOR
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101100 |
+// ------------------------------------------------------
+//
+// Bitwise XOR of two vector registers
+
+inline void rsp_cop2_drc::vxor()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+ m_vres[i] = s1 ^ s2;
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vxor(void *param)
+{
+ ((rsp_cop2 *)param)->vxor();
+}
+
+
+// VNXOR
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 |
+// ------------------------------------------------------
+//
+// Bitwise NOT XOR of two vector registers
+
+inline void rsp_cop2_drc::vnxor()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+ m_vres[i] = ~(s1 ^ s2);
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vnxor(void *param)
+{
+ ((rsp_cop2 *)param)->vnxor();
+}
+
+
+// VRCP
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal
+
+inline void rsp_cop2_drc::vrcp()
+{
+ int op = m_op;
+
+ INT32 shifter = 0;
+ INT32 rec = (INT16)(VREG_S(VS2REG, EL & 7));
+ INT32 datainput = (rec < 0) ? (-rec) : rec;
+ if (datainput)
+ {
+ for (int i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ shifter = 0x10;
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ m_reciprocal_res = rec;
+ m_dp_allowed = 0;
+
+ 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_vrcp(void *param)
+{
+ ((rsp_cop2 *)param)->vrcp();
+}
+
+
+// VRCPL
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal low part
+
+inline void rsp_cop2_drc::vrcpl()
+{
+ int op = m_op;
+
+ INT32 shifter = 0;
+ INT32 rec = (INT16)VREG_S(VS2REG, EL & 7);
+ INT32 datainput = rec;
+
+ if (m_dp_allowed)
+ {
+ rec = (rec & 0x0000ffff) | m_reciprocal_high;
+ datainput = rec;
+
+ if (rec < 0)
+ {
+ if (rec < -32768)
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+ }
+ else if (datainput < 0)
+ {
+ datainput = -datainput;
+
+ shifter = 0x10;
+ }
+
+ if (datainput)
+ {
+ for (int i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+
+ UINT32 address = (datainput << shifter) >> 22;
+ INT32 fetchval = rsp_divtable[address & 0x1ff];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
+ temp ^= rec >> 31;
+
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ m_reciprocal_res = rec;
+ m_dp_allowed = 0;
+
+ 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_vrcpl(void *param)
+{
+ ((rsp_cop2 *)param)->vrcpl();
+}
+
+
+// VRCPH
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal high part
+
+inline void rsp_cop2_drc::vrcph()
+{
+ int op = m_op;
+
+ m_reciprocal_high = (VREG_S(VS2REG, EL & 7)) << 16;
+ m_dp_allowed = 1;
+
+ for (int i = 0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+
+ W_VREG_S(VDREG, VS1REG & 7) = (INT16)(m_reciprocal_res >> 16);
+}
+
+static void cfunc_vrcph(void *param)
+{
+ ((rsp_cop2 *)param)->vrcph();
+}
+
+
+// VMOV
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110011 |
+// ------------------------------------------------------
+//
+// Moves element from vector to destination vector
+
+inline void rsp_cop2_drc::vmov()
+{
+ int op = m_op;
+
+ W_VREG_S(VDREG, VS1REG & 7) = VREG_S(VS2REG, EL & 7);
+ for (int i = 0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+}
+
+static void cfunc_vmov(void *param)
+{
+ ((rsp_cop2 *)param)->vmov();
+}
+
+
+// VRSQ
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal square-root
+
+inline void rsp_cop2_drc::vrsq()
+{
+ int op = m_op;
+
+ 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_vrsq(void *param)
+{
+ ((rsp_cop2 *)param)->vrsq();
+}
+
+
+// VRSQL
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal square-root low part
+
+inline void rsp_cop2_drc::vrsql()
+{
+ int op = m_op;
+
+ INT32 shifter = 0;
+ INT32 rec = (INT16)VREG_S(VS2REG, EL & 7);
+ INT32 datainput = rec;
+
+ if (m_dp_allowed)
+ {
+ rec = (rec & 0x0000ffff) | m_reciprocal_high;
+ datainput = rec;
+
+ if (rec < 0)
+ {
+ if (rec < -32768)
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+ }
+ else if (datainput < 0)
+ {
+ datainput = -datainput;
+
+ shifter = 0x10;
+ }
+
+ if (datainput)
+ {
+ for (int i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+
+ 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);
+ temp ^= rec >> 31;
+
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ m_reciprocal_res = rec;
+ m_dp_allowed = 0;
+
+ W_VREG_S(VDREG, VS1REG & 7) = (UINT16)(rec & 0xffff);
+ for (int i = 0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+}
+
+static void cfunc_vrsql(void *param)
+{
+ ((rsp_cop2 *)param)->vrsql();
+}
+
+
+// VRSQH
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110110 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal square-root high part
+
+inline void rsp_cop2_drc::vrsqh()
+{
+ int op = m_op;
+
+ m_reciprocal_high = (VREG_S(VS2REG, EL & 7)) << 16;
+ m_dp_allowed = 1;
+
+ for (int i = 0; i < 8; i++)
+ {
+ SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
+ }
+
+ W_VREG_S(VDREG, VS1REG & 7) = (INT16)(m_reciprocal_res >> 16); // store high part
+}
+
+static void cfunc_vrsqh(void *param)
+{
+ ((rsp_cop2 *)param)->vrsqh();
+}
+
+
+/*-------------------------------------------------
+ generate_vector_opcode - generate code for a
+ vector opcode
+-------------------------------------------------*/
+
+int rsp_cop2_drc::generate_vector_opcode(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ // Opcode legend:
+ // E = VS2 element type
+ // S = VS1, Source vector 1
+ // T = VS2, Source vector 2
+ // D = Destination vector
+
+ switch (op & 0x3f)
+ {
+ case 0x00: /* VMULF */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmulf, this);
+ return TRUE;
+
+ case 0x01: /* VMULU */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmulu, this);
+ return TRUE;
+
+ case 0x04: /* VMUDL */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmudl, this);
+ return TRUE;
+
+ case 0x05: /* VMUDM */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmudm, this);
+ return TRUE;
+
+ case 0x06: /* VMUDN */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmudn, this);
+ return TRUE;
+
+ case 0x07: /* VMUDH */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmudh, this);
+ return TRUE;
+
+ case 0x08: /* VMACF */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmacf, this);
+ return TRUE;
+
+ case 0x09: /* VMACU */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmacu, this);
+ return TRUE;
+
+ case 0x0c: /* VMADL */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmadl, this);
+ return TRUE;
+
+ case 0x0d: /* VMADM */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmadm, this);
+ return TRUE;
+
+ case 0x0e: /* VMADN */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmadn, this);
+ return TRUE;
+
+ case 0x0f: /* VMADH */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmadh, this);
+ return TRUE;
+
+ case 0x10: /* VADD */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vadd, this);
+ return TRUE;
+
+ case 0x11: /* VSUB */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vsub, this);
+ return TRUE;
+
+ case 0x13: /* VABS */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vabs, this);
+ return TRUE;
+
+ case 0x14: /* VADDC */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vaddc, this);
+ return TRUE;
+
+ case 0x15: /* VSUBC */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vsubc, this);
+ return TRUE;
+
+ case 0x16: /* VADDB */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vaddb, this);
+ return TRUE;
+
+ case 0x17: /* VSUBB (reserved, functionally identical to VADDB) */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vaddb, this);
+ return TRUE;
+
+ case 0x18: /* VACCB (reserved, functionally identical to VADDB) */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vaddb, this);
+ return TRUE;
+
+ case 0x19: /* VSUCB (reserved, functionally identical to VADDB) */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vaddb, this);
+ return TRUE;
+
+ case 0x1d: /* VSAW */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vsaw, this);
+ return TRUE;
+
+ case 0x20: /* VLT */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vlt, this);
+ return TRUE;
+
+ case 0x21: /* VEQ */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_veq, this);
+ return TRUE;
+
+ case 0x22: /* VNE */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vne, this);
+ return TRUE;
+
+ case 0x23: /* VGE */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vge, this);
+ return TRUE;
+
+ case 0x24: /* VCL */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vcl, this);
+ return TRUE;
+
+ case 0x25: /* VCH */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vch, this);
+ return TRUE;
+
+ case 0x26: /* VCR */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vcr, this);
+ return TRUE;
+
+ case 0x27: /* VMRG */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmrg, this);
+ return TRUE;
+
+ case 0x28: /* VAND */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vand, this);
+ return TRUE;
+
+ case 0x29: /* VNAND */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vnand, this);
+ return TRUE;
+
+ case 0x2a: /* VOR */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vor, this);
+ return TRUE;
+
+ case 0x2b: /* VNOR */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vnor, this);
+ return TRUE;
+
+ case 0x2c: /* VXOR */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vxor, this);
+ return TRUE;
+
+ case 0x2d: /* VNXOR */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vnxor, this);
+ return TRUE;
+
+ case 0x30: /* VRCP */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vrcp, this);
+ return TRUE;
+
+ case 0x31: /* VRCPL */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vrcpl, this);
+ return TRUE;
+
+ case 0x32: /* VRCPH */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vrcph, this);
+ return TRUE;
+
+ case 0x33: /* VMOV */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vmov, this);
+ return TRUE;
+
+ case 0x34: /* VRSQ */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vrsq, this);
+ return TRUE;
+
+ case 0x35: /* VRSQL */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vrsql, this);
+ return TRUE;
+
+ case 0x36: /* VRSQH */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_vrsqh, this);
+ return TRUE;
+
+ case 0x37: /* VNOP */
+ case 0x3F: /* VNULL */
+ return TRUE;
+
+ default:
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, unimplemented_opcode, &m_rsp);
+ return FALSE;
+ }
+}
+
+
+/***************************************************************************
+ Vector Flag Reading/Writing
+***************************************************************************/
+
+inline void rsp_cop2_drc::mfc2()
+{
+ UINT32 op = m_op;
+ int el = (op >> 7) & 0xf;
+
+ UINT16 b1 = VREG_B(VS1REG, (el+0) & 0xf);
+ UINT16 b2 = VREG_B(VS1REG, (el+1) & 0xf);
+ if (RTREG) RTVAL = (INT32)(INT16)((b1 << 8) | (b2));
+}
+
+static void cfunc_mfc2(void *param)
+{
+ ((rsp_cop2 *)param)->mfc2();
+}
+
+inline void rsp_cop2_drc::cfc2()
+{
+ UINT32 op = m_op;
+ if (RTREG)
+ {
+ switch(RDREG)
+ {
+ case 0:
+ RTVAL = ((CARRY_FLAG(0) & 1) << 0) |
+ ((CARRY_FLAG(1) & 1) << 1) |
+ ((CARRY_FLAG(2) & 1) << 2) |
+ ((CARRY_FLAG(3) & 1) << 3) |
+ ((CARRY_FLAG(4) & 1) << 4) |
+ ((CARRY_FLAG(5) & 1) << 5) |
+ ((CARRY_FLAG(6) & 1) << 6) |
+ ((CARRY_FLAG(7) & 1) << 7) |
+ ((ZERO_FLAG(0) & 1) << 8) |
+ ((ZERO_FLAG(1) & 1) << 9) |
+ ((ZERO_FLAG(2) & 1) << 10) |
+ ((ZERO_FLAG(3) & 1) << 11) |
+ ((ZERO_FLAG(4) & 1) << 12) |
+ ((ZERO_FLAG(5) & 1) << 13) |
+ ((ZERO_FLAG(6) & 1) << 14) |
+ ((ZERO_FLAG(7) & 1) << 15);
+ if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
+ break;
+ case 1:
+ RTVAL = ((COMPARE_FLAG(0) & 1) << 0) |
+ ((COMPARE_FLAG(1) & 1) << 1) |
+ ((COMPARE_FLAG(2) & 1) << 2) |
+ ((COMPARE_FLAG(3) & 1) << 3) |
+ ((COMPARE_FLAG(4) & 1) << 4) |
+ ((COMPARE_FLAG(5) & 1) << 5) |
+ ((COMPARE_FLAG(6) & 1) << 6) |
+ ((COMPARE_FLAG(7) & 1) << 7) |
+ ((CLIP2_FLAG(0) & 1) << 8) |
+ ((CLIP2_FLAG(1) & 1) << 9) |
+ ((CLIP2_FLAG(2) & 1) << 10) |
+ ((CLIP2_FLAG(3) & 1) << 11) |
+ ((CLIP2_FLAG(4) & 1) << 12) |
+ ((CLIP2_FLAG(5) & 1) << 13) |
+ ((CLIP2_FLAG(6) & 1) << 14) |
+ ((CLIP2_FLAG(7) & 1) << 15);
+ if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
+ break;
+ case 2:
+ RTVAL = ((CLIP1_FLAG(0) & 1) << 0) |
+ ((CLIP1_FLAG(1) & 1) << 1) |
+ ((CLIP1_FLAG(2) & 1) << 2) |
+ ((CLIP1_FLAG(3) & 1) << 3) |
+ ((CLIP1_FLAG(4) & 1) << 4) |
+ ((CLIP1_FLAG(5) & 1) << 5) |
+ ((CLIP1_FLAG(6) & 1) << 6) |
+ ((CLIP1_FLAG(7) & 1) << 7);
+ break;
+ }
+ }
+}
+
+static void cfunc_cfc2(void *param)
+{
+ ((rsp_cop2 *)param)->cfc2();
+}
+
+
+inline void rsp_cop2_drc::mtc2()
+{
+ UINT32 op = m_op;
+ int el = (op >> 7) & 0xf;
+ VREG_B(VS1REG, (el+0) & 0xf) = (RTVAL >> 8) & 0xff;
+ VREG_B(VS1REG, (el+1) & 0xf) = (RTVAL >> 0) & 0xff;
+}
+
+static void cfunc_mtc2(void *param)
+{
+ ((rsp_cop2 *)param)->mtc2();
+}
+
+
+inline void rsp_cop2_drc::ctc2()
+{
+ UINT32 op = m_op;
+ switch(RDREG)
+ {
+ case 0:
+ CLEAR_CARRY_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ m_vflag[0][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
+ m_vflag[0][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
+ m_vflag[0][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
+ m_vflag[0][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
+ m_vflag[0][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
+ m_vflag[0][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
+ m_vflag[0][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
+ m_vflag[0][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 0)) { SET_CARRY_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_CARRY_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_CARRY_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_CARRY_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_CARRY_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_CARRY_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_CARRY_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_CARRY_FLAG(7); }
+ m_vflag[3][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0;
+ m_vflag[3][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0;
+ m_vflag[3][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0;
+ m_vflag[3][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0;
+ m_vflag[3][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0;
+ m_vflag[3][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0;
+ m_vflag[3][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0;
+ m_vflag[3][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 8)) { SET_ZERO_FLAG(0); }
+ if (RTVAL & (1 << 9)) { SET_ZERO_FLAG(1); }
+ if (RTVAL & (1 << 10)) { SET_ZERO_FLAG(2); }
+ if (RTVAL & (1 << 11)) { SET_ZERO_FLAG(3); }
+ if (RTVAL & (1 << 12)) { SET_ZERO_FLAG(4); }
+ if (RTVAL & (1 << 13)) { SET_ZERO_FLAG(5); }
+ if (RTVAL & (1 << 14)) { SET_ZERO_FLAG(6); }
+ if (RTVAL & (1 << 15)) { SET_ZERO_FLAG(7); }
+ break;
+ case 1:
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+ m_vflag[1][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
+ m_vflag[1][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
+ m_vflag[1][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
+ m_vflag[1][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
+ m_vflag[1][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
+ m_vflag[1][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
+ m_vflag[1][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
+ m_vflag[1][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 0)) { SET_COMPARE_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_COMPARE_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_COMPARE_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_COMPARE_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_COMPARE_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_COMPARE_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_COMPARE_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_COMPARE_FLAG(7); }
+ m_vflag[4][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0;
+ m_vflag[4][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0;
+ m_vflag[4][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0;
+ m_vflag[4][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0;
+ m_vflag[4][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0;
+ m_vflag[4][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0;
+ m_vflag[4][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0;
+ m_vflag[4][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 8)) { SET_CLIP2_FLAG(0); }
+ if (RTVAL & (1 << 9)) { SET_CLIP2_FLAG(1); }
+ if (RTVAL & (1 << 10)) { SET_CLIP2_FLAG(2); }
+ if (RTVAL & (1 << 11)) { SET_CLIP2_FLAG(3); }
+ if (RTVAL & (1 << 12)) { SET_CLIP2_FLAG(4); }
+ if (RTVAL & (1 << 13)) { SET_CLIP2_FLAG(5); }
+ if (RTVAL & (1 << 14)) { SET_CLIP2_FLAG(6); }
+ if (RTVAL & (1 << 15)) { SET_CLIP2_FLAG(7); }
+ break;
+ case 2:
+ CLEAR_CLIP1_FLAGS();
+ m_vflag[2][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
+ m_vflag[2][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
+ m_vflag[2][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
+ m_vflag[2][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
+ m_vflag[2][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
+ m_vflag[2][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
+ m_vflag[2][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
+ m_vflag[2][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 0)) { SET_CLIP1_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_CLIP1_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_CLIP1_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_CLIP1_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_CLIP1_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_CLIP1_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_CLIP1_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_CLIP1_FLAG(7); }
+ break;
+ }
+}
+
+static void cfunc_ctc2(void *param)
+{
+ ((rsp_cop2 *)param)->ctc2();
+}
+
+/***************************************************************************
+ COP2 Opcode Compilation
+***************************************************************************/
+
+int rsp_cop2_drc::generate_cop2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT8 opswitch = RSREG;
+
+ switch (opswitch)
+ {
+ case 0x00: /* MFCz */
+ if (RTREG != 0)
+ {
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_mfc2, this); // callc mfc2
+ }
+ return TRUE;
+
+ case 0x02: /* CFCz */
+ if (RTREG != 0)
+ {
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_cfc2, this); // callc cfc2
+ }
+ return TRUE;
+
+ case 0x04: /* MTCz */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_mtc2, this); // callc mtc2
+ return TRUE;
+
+ case 0x06: /* CTCz */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_ctc2, this); // callc ctc2
+ return TRUE;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ return generate_vector_opcode(block, compiler, desc);
+ }
+ return FALSE;
+} \ No newline at end of file
diff --git a/src/emu/cpu/rsp/rspcp2d.h b/src/emu/cpu/rsp/rspcp2d.h
new file mode 100644
index 00000000000..51c00dc53f3
--- /dev/null
+++ b/src/emu/cpu/rsp/rspcp2d.h
@@ -0,0 +1,110 @@
+/***************************************************************************
+
+ rspcp2d.h
+
+ Interface file for Reality Signal Processor (RSP) vector extensions
+ using Universal Machine Language (UML) dynamic recompilation.
+
+ Copyright the MESS team
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __RSPCP2D_H__
+#define __RSPCP2D_H__
+
+#include "cpu/drcuml.h"
+#include "rsp.h"
+#include "rspcp2.h"
+
+class rsp_cop2_drc : public rsp_cop2
+{
+ friend class rsp_device;
+
+ rsp_cop2_drc(rsp_device &rsp, running_machine &machine) : rsp_cop2(rsp, machine) { }
+
+ virtual int generate_cop2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc);
+ virtual int generate_lwc2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc);
+ virtual int generate_swc2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc);
+
+ virtual void state_string_export(const int index, astring &string);
+
+ void cfunc_unimplemented_opcode();
+public:
+ virtual void lbv();
+ virtual void lsv();
+ virtual void llv();
+ virtual void ldv();
+ virtual void lqv();
+ virtual void lrv();
+ virtual void lpv();
+ virtual void luv();
+ virtual void lhv();
+ virtual void lfv();
+ virtual void lwv();
+ virtual void ltv();
+ virtual void sbv();
+ virtual void ssv();
+ virtual void slv();
+ virtual void sdv();
+ virtual void sqv();
+ virtual void srv();
+ virtual void spv();
+ virtual void suv();
+ virtual void shv();
+ virtual void sfv();
+ virtual void swv();
+ virtual void stv();
+ virtual void vmulf();
+ virtual void vmulu();
+ virtual void vmudl();
+ virtual void vmudm();
+ virtual void vmudn();
+ virtual void vmudh();
+ virtual void vmacf();
+ virtual void vmacu();
+ virtual void vmadl();
+ virtual void vmadm();
+ virtual void vmadn();
+ virtual void vmadh();
+ virtual void vadd();
+ virtual void vsub();
+ virtual void vabs();
+ virtual void vaddc();
+ virtual void vsubc();
+ virtual void vaddb();
+ virtual void vsaw();
+ virtual void vlt();
+ virtual void veq();
+ virtual void vne();
+ virtual void vge();
+ virtual void vcl();
+ virtual void vch();
+ virtual void vcr();
+ virtual void vmrg();
+ virtual void vand();
+ virtual void vnand();
+ virtual void vor();
+ virtual void vnor();
+ virtual void vxor();
+ virtual void vnxor();
+ virtual void vrcp();
+ virtual void vrcpl();
+ virtual void vrcph();
+ virtual void vmov();
+ virtual void vrsql();
+ virtual void vrsqh();
+ virtual void vrsq();
+ virtual void mfc2();
+ virtual void cfc2();
+ virtual void mtc2();
+ virtual void ctc2();
+
+private:
+ virtual int generate_vector_opcode(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc);
+};
+
+#endif /* __RSPCP2D_H__ */ \ No newline at end of file
diff --git a/src/emu/cpu/rsp/rspcp2s.c b/src/emu/cpu/rsp/rspcp2s.c
new file mode 100644
index 00000000000..5f53bb927c6
--- /dev/null
+++ b/src/emu/cpu/rsp/rspcp2s.c
@@ -0,0 +1,3633 @@
+/***************************************************************************
+
+ rspcp2s.c
+
+ Universal machine language-based Nintendo/SGI RSP COP2 emulator, with
+ SSSE3 SIMD optimizations.
+ Written by Harmony of the MESS team.
+
+ Copyright the MESS team.
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "rsp.h"
+#include "rspdiv.h"
+#include "rspcp2.h"
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+
+using namespace uml;
+
+/***************************************************************************
+ Helpful Defines
+***************************************************************************/
+
+#define VDREG ((op >> 6) & 0x1f)
+#define VS1REG ((op >> 11) & 0x1f)
+#define VS2REG ((op >> 16) & 0x1f)
+#define EL ((op >> 21) & 0xf)
+
+#define RSVAL (m_rsp.m_rsp_state->r[RSREG])
+#define RTVAL (m_rsp.m_rsp_state->r[RTREG])
+#define RDVAL (m_rsp.m_rsp_state->r[RDREG])
+
+#define EXTRACT16(reg, value, element) \
+ switch((element) & 7) \
+ { \
+ case 0: value = _mm_extract_epi16(reg, 0); break; \
+ case 1: value = _mm_extract_epi16(reg, 1); break; \
+ case 2: value = _mm_extract_epi16(reg, 2); break; \
+ case 3: value = _mm_extract_epi16(reg, 3); break; \
+ case 4: value = _mm_extract_epi16(reg, 4); break; \
+ case 5: value = _mm_extract_epi16(reg, 5); break; \
+ case 6: value = _mm_extract_epi16(reg, 6); break; \
+ case 7: value = _mm_extract_epi16(reg, 7); break; \
+ }
+
+
+#define INSERT16(reg, value, element) \
+ switch((element) & 7) \
+ { \
+ case 0: reg = _mm_insert_epi16(reg, value, 0); break; \
+ case 1: reg = _mm_insert_epi16(reg, value, 1); break; \
+ case 2: reg = _mm_insert_epi16(reg, value, 2); break; \
+ case 3: reg = _mm_insert_epi16(reg, value, 3); break; \
+ case 4: reg = _mm_insert_epi16(reg, value, 4); break; \
+ case 5: reg = _mm_insert_epi16(reg, value, 5); break; \
+ case 6: reg = _mm_insert_epi16(reg, value, 6); break; \
+ case 7: reg = _mm_insert_epi16(reg, value, 7); break; \
+ }
+
+
+#define VREG_B(reg, offset) m_v[(reg)].b[(offset)^1]
+#define W_VREG_S(reg, offset) m_v[(reg)].s[(offset)]
+#define VREG_S(reg, offset) (INT16)m_v[(reg)].s[(offset)]
+
+#define VEC_EL_2(x,z) (vector_elements_2[(x)][(z)])
+
+#define ACCUM(x) m_accum[x].q
+
+#define CARRY 0
+#define COMPARE 1
+#define CLIP1 2
+#define ZERO 3
+#define CLIP2 4
+
+static void cfunc_mfc2(void *param);
+static void cfunc_cfc2(void *param);
+static void cfunc_mtc2(void *param);
+static void cfunc_ctc2(void *param);
+
+inline UINT16 rsp_cop2_simd::ACCUM_H(int x)
+{
+ UINT16 out;
+ EXTRACT16(m_accum_h, out, x);
+ return out;
+}
+
+inline UINT16 rsp_cop2_simd::ACCUM_M(int x)
+{
+ UINT16 out;
+ EXTRACT16(m_accum_m, out, x);
+ return out;
+}
+
+inline UINT16 rsp_cop2_simd::ACCUM_L(int x)
+{
+ UINT16 out;
+ EXTRACT16(m_accum_l, out, x);
+ return out;
+}
+
+inline UINT16 rsp_cop2_simd::ACCUM_LL(int x)
+{
+ UINT16 out;
+ EXTRACT16(m_accum_ll, out, x);
+ return out;
+}
+
+#define SET_ACCUM_H(v, x) INSERT16(m_accum_h, v, x);
+#define SET_ACCUM_M(v, x) INSERT16(m_>accum_m, v, x);
+#define SET_ACCUM_L(v, x) INSERT16(m_accum_l, v, x);
+#define SET_ACCUM_LL(v, x) INSERT16(m_accum_ll, v, x);
+
+#define GET_VS1(out, i) EXTRACT16(m_xv[VS1REG], out, i);
+#define GET_VS2(out, i) EXTRACT16(m_xv[VS2REG], out, VEC_EL_2(EL, i));
+
+inline UINT16 rsp_cop2_simd::CARRY_FLAG(const int x)
+{
+ UINT16 out;
+ EXTRACT16(m_xvflag[CARRY], out, x);
+ return out;
+}
+
+inline UINT16 rsp_cop2_simd::COMPARE_FLAG(const int x)
+{
+ UINT16 out;
+ EXTRACT16(m_xvflag[COMPARE], out, x);
+ return out;
+}
+
+inline UINT16 rsp_cop2_simd::CLIP1_FLAG(const int x)
+{
+ UINT16 out;
+ EXTRACT16(m_xvflag[CLIP1], out, x);
+ return out;
+}
+
+inline UINT16 rsp_cop2_simd::ZERO_FLAG(const int x)
+{
+ UINT16 out;
+ EXTRACT16(m_xvflag[ZERO], out, x);
+ return out;
+}
+
+inline UINT16 rsp_cop2_simd::CLIP2_FLAG(const int x)
+{
+ UINT16 out;
+ EXTRACT16(m_xvflag[CLIP2], out, x);
+ return out;
+}
+
+#define CLEAR_CARRY_FLAGS() { m_xvflag[CARRY] = _mm_setzero_si128(); }
+#define CLEAR_COMPARE_FLAGS() { m_xvflag[COMPARE] = _mm_setzero_si128(); }
+#define CLEAR_CLIP1_FLAGS() { m_xvflag[CLIP1] = _mm_setzero_si128(); }
+#define CLEAR_ZERO_FLAGS() { m_xvflag[ZERO] = _mm_setzero_si128(); }
+#define CLEAR_CLIP2_FLAGS() { m_xvflag[CLIP2] = _mm_setzero_si128(); }
+
+#define SET_CARRY_FLAG(x) { INSERT16(m_xvflag[CARRY], 0xffff, x); }
+#define SET_COMPARE_FLAG(x) { INSERT16(m_xvflag[COMPARE], 0xffff, x); }
+#define SET_CLIP1_FLAG(x) { INSERT16(m_xvflag[CLIP1], 0xffff, x); }
+#define SET_ZERO_FLAG(x) { INSERT16(m_xvflag[ZERO], 0xffff, x); }
+#define SET_CLIP2_FLAG(x) { INSERT16(m_xvflag[CLIP2], 0xffff, x); }
+
+#define CLEAR_CARRY_FLAG(x) { INSERT16(m_xvflag[CARRY], 0, x); }
+#define CLEAR_COMPARE_FLAG(x) { INSERT16(m_xvflag[COMPARE], 0, x); }
+#define CLEAR_CLIP1_FLAG(x) { INSERT16(m_xvflag[CLIP1], 0, x); }
+#define CLEAR_ZERO_FLAG(x) { INSERT16(m_xvflag[ZERO], 0, x); }
+#define CLEAR_CLIP2_FLAG(x) { INSERT16(m_xvflag[CLIP2], 0, x); }
+
+#define WRITEBACK_RESULT() { \
+ INSERT16(m_xv[VDREG], m_vres[0], 0); \
+ INSERT16(m_xv[VDREG], m_vres[1], 1); \
+ INSERT16(m_xv[VDREG], m_vres[2], 2); \
+ INSERT16(m_xv[VDREG], m_vres[3], 3); \
+ INSERT16(m_xv[VDREG], m_vres[4], 4); \
+ INSERT16(m_xv[VDREG], m_vres[5], 5); \
+ INSERT16(m_xv[VDREG], m_vres[6], 6); \
+ INSERT16(m_xv[VDREG], m_vres[7], 7); \
+}
+#endif
+
+static const int vector_elements_2[16][8] =
+{
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // none
+ { 0, 1, 2, 3, 4, 5, 6, 7 }, // ???
+ { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q
+ { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q
+ { 0, 0, 0, 0, 4, 4, 4, 4 }, // 0h
+ { 1, 1, 1, 1, 5, 5, 5, 5 }, // 1h
+ { 2, 2, 2, 2, 6, 6, 6, 6 }, // 2h
+ { 3, 3, 3, 3, 7, 7, 7, 7 }, // 3h
+ { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
+ { 1, 1, 1, 1, 1, 1, 1, 1 }, // 1
+ { 2, 2, 2, 2, 2, 2, 2, 2 }, // 2
+ { 3, 3, 3, 3, 3, 3, 3, 3 }, // 3
+ { 4, 4, 4, 4, 4, 4, 4, 4 }, // 4
+ { 5, 5, 5, 5, 5, 5, 5, 5 }, // 5
+ { 6, 6, 6, 6, 6, 6, 6, 6 }, // 6
+ { 7, 7, 7, 7, 7, 7, 7, 7 }, // 7
+};
+
+static __m128i vec_himask;
+static __m128i vec_lomask;
+static __m128i vec_hibit;
+static __m128i vec_lobit;
+static __m128i vec_n32768;
+static __m128i vec_32767;
+static __m128i vec_flagmask;
+static __m128i vec_shiftmask2;
+static __m128i vec_shiftmask4;
+static __m128i vec_flag_reverse;
+static __m128i vec_neg1;
+static __m128i vec_zero;
+static __m128i vec_shuf[16];
+static __m128i vec_shuf_inverse[16];
+
+rsp_cop2_simd::rsp_cop2_simd(rsp_device &rsp, running_machine &machine) : rsp_cop2(rsp, machine)
+ : m_accum_h(0)
+ , m_accum_m(0)
+ , m_accum_l(0)
+ , m_accum_ll(0)
+#if SIMUL_SIMD
+ , m_old_reciprocal_res(0)
+ , m_old_reciprocal_high(0)
+ , m_old_dp_allowed(0)
+ , m_scalar_reciprocal_res(0)
+ , m_scalar_reciprocal_high(0)
+ , m_scalar_dp_allowed(0)
+ , m_simd_reciprocal_res(0)
+ , m_simd_reciprocal_high(0)
+ , m_simd_dp_allowed(0)
+#endif
+{
+#if SIMUL_SIMD
+ memset(m_old_r, 0, sizeof(m_old_r));
+ memset(m_old_dmem, 0, sizeof(m_old_dmem));
+ memset(m_scalar_r, 0, sizeof(m_scalar_r));
+ memset(m_scalar_dmem, 0, sizeof(m_scalar_dmem));
+#endif
+ memset(m_xv, 0, sizeof(m_xv));
+ memset(m_xvflag, 0, sizeof(m_xvflag));
+
+ vec_shuf_inverse[ 0] = _mm_set_epi16(0x0f0e, 0x0d0c, 0x0b0a, 0x0908, 0x0706, 0x0504, 0x0302, 0x0100); // none
+ vec_shuf_inverse[ 1] = _mm_set_epi16(0x0f0e, 0x0d0c, 0x0b0a, 0x0908, 0x0706, 0x0504, 0x0302, 0x0100); // ???
+ vec_shuf_inverse[ 2] = _mm_set_epi16(0x0d0c, 0x0d0c, 0x0908, 0x0908, 0x0504, 0x0504, 0x0100, 0x0100); // 0q
+ vec_shuf_inverse[ 3] = _mm_set_epi16(0x0f0e, 0x0f0e, 0x0b0a, 0x0b0a, 0x0706, 0x0706, 0x0302, 0x0302); // 1q
+ vec_shuf_inverse[ 4] = _mm_set_epi16(0x0908, 0x0908, 0x0908, 0x0908, 0x0100, 0x0100, 0x0100, 0x0100); // 0h
+ vec_shuf_inverse[ 5] = _mm_set_epi16(0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0302, 0x0302, 0x0302, 0x0302); // 1h
+ vec_shuf_inverse[ 6] = _mm_set_epi16(0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0504, 0x0504, 0x0504, 0x0504); // 2h
+ vec_shuf_inverse[ 7] = _mm_set_epi16(0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0706, 0x0706, 0x0706, 0x0706); // 3h
+ vec_shuf_inverse[ 8] = _mm_set_epi16(0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100); // 0
+ vec_shuf_inverse[ 9] = _mm_set_epi16(0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302); // 1
+ vec_shuf_inverse[10] = _mm_set_epi16(0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504); // 2
+ vec_shuf_inverse[11] = _mm_set_epi16(0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706); // 3
+ vec_shuf_inverse[12] = _mm_set_epi16(0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908); // 4
+ vec_shuf_inverse[13] = _mm_set_epi16(0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a); // 5
+ vec_shuf_inverse[14] = _mm_set_epi16(0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c); // 6
+ vec_shuf_inverse[15] = _mm_set_epi16(0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e); // 7
+
+ vec_shuf[ 0] = _mm_set_epi16(0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e); // none
+ vec_shuf[ 1] = _mm_set_epi16(0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e); // ???
+ vec_shuf[ 2] = _mm_set_epi16(0x0302, 0x0302, 0x0706, 0x0706, 0x0b0a, 0x0b0a, 0x0f0e, 0x0f0e); // 0q
+ vec_shuf[ 3] = _mm_set_epi16(0x0100, 0x0100, 0x0504, 0x0706, 0x0908, 0x0908, 0x0d0c, 0x0d0c); // 1q
+ vec_shuf[ 4] = _mm_set_epi16(0x0706, 0x0706, 0x0706, 0x0706, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e); // 0q
+ vec_shuf[ 5] = _mm_set_epi16(0x0504, 0x0504, 0x0504, 0x0504, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c); // 1q
+ vec_shuf[ 6] = _mm_set_epi16(0x0302, 0x0302, 0x0302, 0x0302, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a); // 2q
+ vec_shuf[ 7] = _mm_set_epi16(0x0100, 0x0100, 0x0100, 0x0100, 0x0908, 0x0908, 0x0908, 0x0908); // 3q
+ vec_shuf[ 8] = _mm_set_epi16(0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e); // 0
+ vec_shuf[ 9] = _mm_set_epi16(0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c); // 1
+ vec_shuf[10] = _mm_set_epi16(0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a); // 2
+ vec_shuf[11] = _mm_set_epi16(0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908); // 3
+ vec_shuf[12] = _mm_set_epi16(0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706); // 4
+ vec_shuf[13] = _mm_set_epi16(0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504); // 5
+ vec_shuf[14] = _mm_set_epi16(0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302); // 6
+ vec_shuf[15] = _mm_set_epi16(0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100); // 7
+ m_accum_h = _mm_setzero_si128();
+ m_accum_m = _mm_setzero_si128();
+ m_accum_l = _mm_setzero_si128();
+ m_accum_ll = _mm_setzero_si128();
+ vec_neg1 = _mm_set_epi64x(0xffffffffffffffffL, 0xffffffffffffffffL);
+ vec_zero = _mm_setzero_si128();
+ vec_himask = _mm_set_epi64x(0xffff0000ffff0000L, 0xffff0000ffff0000L);
+ vec_lomask = _mm_set_epi64x(0x0000ffff0000ffffL, 0x0000ffff0000ffffL);
+ vec_hibit = _mm_set_epi64x(0x0001000000010000L, 0x0001000000010000L);
+ vec_lobit = _mm_set_epi64x(0x0000000100000001L, 0x0000000100000001L);
+ vec_32767 = _mm_set_epi64x(0x7fff7fff7fff7fffL, 0x7fff7fff7fff7fffL);
+ vec_n32768 = _mm_set_epi64x(0x8000800080008000L, 0x8000800080008000L);
+ vec_flagmask = _mm_set_epi64x(0x0001000100010001L, 0x0001000100010001L);
+ vec_shiftmask2 = _mm_set_epi64x(0x0000000300000003L, 0x0000000300000003L);
+ vec_shiftmask4 = _mm_set_epi64x(0x000000000000000fL, 0x000000000000000fL);
+ vec_flag_reverse = _mm_set_epi16(0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e);
+}
+
+void rsp_cop2_simd::state_string_export(const int index, astring &string)
+{
+ switch (index)
+ {
+ case RSP_V0:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 0], 7), (UINT16)_mm_extract_epi16(m_xv[ 0], 6), (UINT16)_mm_extract_epi16(m_xv[ 0], 5), (UINT16)_mm_extract_epi16(m_xv[ 0], 4), (UINT16)_mm_extract_epi16(m_xv[ 0], 3), (UINT16)_mm_extract_epi16(m_xv[ 0], 2), (UINT16)_mm_extract_epi16(m_xv[ 0], 1), (UINT16)_mm_extract_epi16(m_xv[ 0], 0));
+ break;
+ case RSP_V1:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 1], 7), (UINT16)_mm_extract_epi16(m_xv[ 1], 6), (UINT16)_mm_extract_epi16(m_xv[ 1], 5), (UINT16)_mm_extract_epi16(m_xv[ 1], 4), (UINT16)_mm_extract_epi16(m_xv[ 1], 3), (UINT16)_mm_extract_epi16(m_xv[ 1], 2), (UINT16)_mm_extract_epi16(m_xv[ 1], 1), (UINT16)_mm_extract_epi16(m_xv[ 1], 0));
+ break;
+ case RSP_V2:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 2], 7), (UINT16)_mm_extract_epi16(m_xv[ 2], 6), (UINT16)_mm_extract_epi16(m_xv[ 2], 5), (UINT16)_mm_extract_epi16(m_xv[ 2], 4), (UINT16)_mm_extract_epi16(m_xv[ 2], 3), (UINT16)_mm_extract_epi16(m_xv[ 2], 2), (UINT16)_mm_extract_epi16(m_xv[ 2], 1), (UINT16)_mm_extract_epi16(m_xv[ 2], 0));
+ break;
+ case RSP_V3:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 3], 7), (UINT16)_mm_extract_epi16(m_xv[ 3], 6), (UINT16)_mm_extract_epi16(m_xv[ 3], 5), (UINT16)_mm_extract_epi16(m_xv[ 3], 4), (UINT16)_mm_extract_epi16(m_xv[ 3], 3), (UINT16)_mm_extract_epi16(m_xv[ 3], 2), (UINT16)_mm_extract_epi16(m_xv[ 3], 1), (UINT16)_mm_extract_epi16(m_xv[ 3], 0));
+ break;
+ case RSP_V4:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 4], 7), (UINT16)_mm_extract_epi16(m_xv[ 4], 6), (UINT16)_mm_extract_epi16(m_xv[ 4], 5), (UINT16)_mm_extract_epi16(m_xv[ 4], 4), (UINT16)_mm_extract_epi16(m_xv[ 4], 3), (UINT16)_mm_extract_epi16(m_xv[ 4], 2), (UINT16)_mm_extract_epi16(m_xv[ 4], 1), (UINT16)_mm_extract_epi16(m_xv[ 4], 0));
+ break;
+ case RSP_V5:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 5], 7), (UINT16)_mm_extract_epi16(m_xv[ 5], 6), (UINT16)_mm_extract_epi16(m_xv[ 5], 5), (UINT16)_mm_extract_epi16(m_xv[ 5], 4), (UINT16)_mm_extract_epi16(m_xv[ 5], 3), (UINT16)_mm_extract_epi16(m_xv[ 5], 2), (UINT16)_mm_extract_epi16(m_xv[ 5], 1), (UINT16)_mm_extract_epi16(m_xv[ 5], 0));
+ break;
+ case RSP_V6:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 6], 7), (UINT16)_mm_extract_epi16(m_xv[ 6], 6), (UINT16)_mm_extract_epi16(m_xv[ 6], 5), (UINT16)_mm_extract_epi16(m_xv[ 6], 4), (UINT16)_mm_extract_epi16(m_xv[ 6], 3), (UINT16)_mm_extract_epi16(m_xv[ 6], 2), (UINT16)_mm_extract_epi16(m_xv[ 6], 1), (UINT16)_mm_extract_epi16(m_xv[ 6], 0));
+ break;
+ case RSP_V7:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 7], 7), (UINT16)_mm_extract_epi16(m_xv[ 7], 6), (UINT16)_mm_extract_epi16(m_xv[ 7], 5), (UINT16)_mm_extract_epi16(m_xv[ 7], 4), (UINT16)_mm_extract_epi16(m_xv[ 7], 3), (UINT16)_mm_extract_epi16(m_xv[ 7], 2), (UINT16)_mm_extract_epi16(m_xv[ 7], 1), (UINT16)_mm_extract_epi16(m_xv[ 7], 0));
+ break;
+ case RSP_V8:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 8], 7), (UINT16)_mm_extract_epi16(m_xv[ 8], 6), (UINT16)_mm_extract_epi16(m_xv[ 8], 5), (UINT16)_mm_extract_epi16(m_xv[ 8], 4), (UINT16)_mm_extract_epi16(m_xv[ 8], 3), (UINT16)_mm_extract_epi16(m_xv[ 8], 2), (UINT16)_mm_extract_epi16(m_xv[ 8], 1), (UINT16)_mm_extract_epi16(m_xv[ 8], 0));
+ break;
+ case RSP_V9:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[ 9], 7), (UINT16)_mm_extract_epi16(m_xv[ 9], 6), (UINT16)_mm_extract_epi16(m_xv[ 9], 5), (UINT16)_mm_extract_epi16(m_xv[ 9], 4), (UINT16)_mm_extract_epi16(m_xv[ 9], 3), (UINT16)_mm_extract_epi16(m_xv[ 9], 2), (UINT16)_mm_extract_epi16(m_xv[ 9], 1), (UINT16)_mm_extract_epi16(m_xv[ 9], 0));
+ break;
+ case RSP_V10:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[10], 7), (UINT16)_mm_extract_epi16(m_xv[10], 6), (UINT16)_mm_extract_epi16(m_xv[10], 5), (UINT16)_mm_extract_epi16(m_xv[10], 4), (UINT16)_mm_extract_epi16(m_xv[10], 3), (UINT16)_mm_extract_epi16(m_xv[10], 2), (UINT16)_mm_extract_epi16(m_xv[10], 1), (UINT16)_mm_extract_epi16(m_xv[10], 0));
+ break;
+ case RSP_V11:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[11], 7), (UINT16)_mm_extract_epi16(m_xv[11], 6), (UINT16)_mm_extract_epi16(m_xv[11], 5), (UINT16)_mm_extract_epi16(m_xv[11], 4), (UINT16)_mm_extract_epi16(m_xv[11], 3), (UINT16)_mm_extract_epi16(m_xv[11], 2), (UINT16)_mm_extract_epi16(m_xv[11], 1), (UINT16)_mm_extract_epi16(m_xv[11], 0));
+ break;
+ case RSP_V12:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[12], 7), (UINT16)_mm_extract_epi16(m_xv[12], 6), (UINT16)_mm_extract_epi16(m_xv[12], 5), (UINT16)_mm_extract_epi16(m_xv[12], 4), (UINT16)_mm_extract_epi16(m_xv[12], 3), (UINT16)_mm_extract_epi16(m_xv[12], 2), (UINT16)_mm_extract_epi16(m_xv[12], 1), (UINT16)_mm_extract_epi16(m_xv[12], 0));
+ break;
+ case RSP_V13:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[13], 7), (UINT16)_mm_extract_epi16(m_xv[13], 6), (UINT16)_mm_extract_epi16(m_xv[13], 5), (UINT16)_mm_extract_epi16(m_xv[13], 4), (UINT16)_mm_extract_epi16(m_xv[13], 3), (UINT16)_mm_extract_epi16(m_xv[13], 2), (UINT16)_mm_extract_epi16(m_xv[13], 1), (UINT16)_mm_extract_epi16(m_xv[13], 0));
+ break;
+ case RSP_V14:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[14], 7), (UINT16)_mm_extract_epi16(m_xv[14], 6), (UINT16)_mm_extract_epi16(m_xv[14], 5), (UINT16)_mm_extract_epi16(m_xv[14], 4), (UINT16)_mm_extract_epi16(m_xv[14], 3), (UINT16)_mm_extract_epi16(m_xv[14], 2), (UINT16)_mm_extract_epi16(m_xv[14], 1), (UINT16)_mm_extract_epi16(m_xv[14], 0));
+ break;
+ case RSP_V15:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[15], 7), (UINT16)_mm_extract_epi16(m_xv[15], 6), (UINT16)_mm_extract_epi16(m_xv[15], 5), (UINT16)_mm_extract_epi16(m_xv[15], 4), (UINT16)_mm_extract_epi16(m_xv[15], 3), (UINT16)_mm_extract_epi16(m_xv[15], 2), (UINT16)_mm_extract_epi16(m_xv[15], 1), (UINT16)_mm_extract_epi16(m_xv[15], 0));
+ break;
+ case RSP_V16:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[16], 7), (UINT16)_mm_extract_epi16(m_xv[16], 6), (UINT16)_mm_extract_epi16(m_xv[16], 5), (UINT16)_mm_extract_epi16(m_xv[16], 4), (UINT16)_mm_extract_epi16(m_xv[16], 3), (UINT16)_mm_extract_epi16(m_xv[16], 2), (UINT16)_mm_extract_epi16(m_xv[16], 1), (UINT16)_mm_extract_epi16(m_xv[16], 0));
+ break;
+ case RSP_V17:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[17], 7), (UINT16)_mm_extract_epi16(m_xv[17], 6), (UINT16)_mm_extract_epi16(m_xv[17], 5), (UINT16)_mm_extract_epi16(m_xv[17], 4), (UINT16)_mm_extract_epi16(m_xv[17], 3), (UINT16)_mm_extract_epi16(m_xv[17], 2), (UINT16)_mm_extract_epi16(m_xv[17], 1), (UINT16)_mm_extract_epi16(m_xv[17], 0));
+ break;
+ case RSP_V18:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[18], 7), (UINT16)_mm_extract_epi16(m_xv[18], 6), (UINT16)_mm_extract_epi16(m_xv[18], 5), (UINT16)_mm_extract_epi16(m_xv[18], 4), (UINT16)_mm_extract_epi16(m_xv[18], 3), (UINT16)_mm_extract_epi16(m_xv[18], 2), (UINT16)_mm_extract_epi16(m_xv[18], 1), (UINT16)_mm_extract_epi16(m_xv[18], 0));
+ break;
+ case RSP_V19:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[19], 7), (UINT16)_mm_extract_epi16(m_xv[19], 6), (UINT16)_mm_extract_epi16(m_xv[19], 5), (UINT16)_mm_extract_epi16(m_xv[19], 4), (UINT16)_mm_extract_epi16(m_xv[19], 3), (UINT16)_mm_extract_epi16(m_xv[19], 2), (UINT16)_mm_extract_epi16(m_xv[19], 1), (UINT16)_mm_extract_epi16(m_xv[19], 0));
+ break;
+ case RSP_V20:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[20], 7), (UINT16)_mm_extract_epi16(m_xv[20], 6), (UINT16)_mm_extract_epi16(m_xv[20], 5), (UINT16)_mm_extract_epi16(m_xv[20], 4), (UINT16)_mm_extract_epi16(m_xv[20], 3), (UINT16)_mm_extract_epi16(m_xv[20], 2), (UINT16)_mm_extract_epi16(m_xv[20], 1), (UINT16)_mm_extract_epi16(m_xv[20], 0));
+ break;
+ case RSP_V21:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[21], 7), (UINT16)_mm_extract_epi16(m_xv[21], 6), (UINT16)_mm_extract_epi16(m_xv[21], 5), (UINT16)_mm_extract_epi16(m_xv[21], 4), (UINT16)_mm_extract_epi16(m_xv[21], 3), (UINT16)_mm_extract_epi16(m_xv[21], 2), (UINT16)_mm_extract_epi16(m_xv[21], 1), (UINT16)_mm_extract_epi16(m_xv[21], 0));
+ break;
+ case RSP_V22:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[22], 7), (UINT16)_mm_extract_epi16(m_xv[22], 6), (UINT16)_mm_extract_epi16(m_xv[22], 5), (UINT16)_mm_extract_epi16(m_xv[22], 4), (UINT16)_mm_extract_epi16(m_xv[22], 3), (UINT16)_mm_extract_epi16(m_xv[22], 2), (UINT16)_mm_extract_epi16(m_xv[22], 1), (UINT16)_mm_extract_epi16(m_xv[22], 0));
+ break;
+ case RSP_V23:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[23], 7), (UINT16)_mm_extract_epi16(m_xv[23], 6), (UINT16)_mm_extract_epi16(m_xv[23], 5), (UINT16)_mm_extract_epi16(m_xv[23], 4), (UINT16)_mm_extract_epi16(m_xv[23], 3), (UINT16)_mm_extract_epi16(m_xv[23], 2), (UINT16)_mm_extract_epi16(m_xv[23], 1), (UINT16)_mm_extract_epi16(m_xv[23], 0));
+ break;
+ case RSP_V24:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[24], 7), (UINT16)_mm_extract_epi16(m_xv[24], 6), (UINT16)_mm_extract_epi16(m_xv[24], 5), (UINT16)_mm_extract_epi16(m_xv[24], 4), (UINT16)_mm_extract_epi16(m_xv[24], 3), (UINT16)_mm_extract_epi16(m_xv[24], 2), (UINT16)_mm_extract_epi16(m_xv[24], 1), (UINT16)_mm_extract_epi16(m_xv[24], 0));
+ break;
+ case RSP_V25:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[25], 7), (UINT16)_mm_extract_epi16(m_xv[25], 6), (UINT16)_mm_extract_epi16(m_xv[25], 5), (UINT16)_mm_extract_epi16(m_xv[25], 4), (UINT16)_mm_extract_epi16(m_xv[25], 3), (UINT16)_mm_extract_epi16(m_xv[25], 2), (UINT16)_mm_extract_epi16(m_xv[25], 1), (UINT16)_mm_extract_epi16(m_xv[25], 0));
+ break;
+ case RSP_V26:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[26], 7), (UINT16)_mm_extract_epi16(m_xv[26], 6), (UINT16)_mm_extract_epi16(m_xv[26], 5), (UINT16)_mm_extract_epi16(m_xv[26], 4), (UINT16)_mm_extract_epi16(m_xv[26], 3), (UINT16)_mm_extract_epi16(m_xv[26], 2), (UINT16)_mm_extract_epi16(m_xv[26], 1), (UINT16)_mm_extract_epi16(m_xv[26], 0));
+ break;
+ case RSP_V27:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[27], 7), (UINT16)_mm_extract_epi16(m_xv[27], 6), (UINT16)_mm_extract_epi16(m_xv[27], 5), (UINT16)_mm_extract_epi16(m_xv[27], 4), (UINT16)_mm_extract_epi16(m_xv[27], 3), (UINT16)_mm_extract_epi16(m_xv[27], 2), (UINT16)_mm_extract_epi16(m_xv[27], 1), (UINT16)_mm_extract_epi16(m_xv[27], 0));
+ break;
+ case RSP_V28:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[28], 7), (UINT16)_mm_extract_epi16(m_xv[28], 6), (UINT16)_mm_extract_epi16(m_xv[28], 5), (UINT16)_mm_extract_epi16(m_xv[28], 4), (UINT16)_mm_extract_epi16(m_xv[28], 3), (UINT16)_mm_extract_epi16(m_xv[28], 2), (UINT16)_mm_extract_epi16(m_xv[28], 1), (UINT16)_mm_extract_epi16(m_xv[28], 0));
+ break;
+ case RSP_V29:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[29], 7), (UINT16)_mm_extract_epi16(m_xv[29], 6), (UINT16)_mm_extract_epi16(m_xv[29], 5), (UINT16)_mm_extract_epi16(m_xv[29], 4), (UINT16)_mm_extract_epi16(m_xv[29], 3), (UINT16)_mm_extract_epi16(m_xv[29], 2), (UINT16)_mm_extract_epi16(m_xv[29], 1), (UINT16)_mm_extract_epi16(m_xv[29], 0));
+ break;
+ case RSP_V30:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[30], 7), (UINT16)_mm_extract_epi16(m_xv[30], 6), (UINT16)_mm_extract_epi16(m_xv[30], 5), (UINT16)_mm_extract_epi16(m_xv[30], 4), (UINT16)_mm_extract_epi16(m_xv[30], 3), (UINT16)_mm_extract_epi16(m_xv[30], 2), (UINT16)_mm_extract_epi16(m_xv[30], 1), (UINT16)_mm_extract_epi16(m_xv[30], 0));
+ break;
+ case RSP_V31:
+ string.printf("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (UINT16)_mm_extract_epi16(m_xv[31], 7), (UINT16)_mm_extract_epi16(m_xv[31], 6), (UINT16)_mm_extract_epi16(m_xv[31], 5), (UINT16)_mm_extract_epi16(m_xv[31], 4), (UINT16)_mm_extract_epi16(m_xv[31], 3), (UINT16)_mm_extract_epi16(m_xv[31], 2), (UINT16)_mm_extract_epi16(m_xv[31], 1), (UINT16)_mm_extract_epi16(m_xv[31], 0));
+ break;
+ }
+}
+
+/***************************************************************************
+ Vector Load Instructions
+***************************************************************************/
+
+// LBV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00000 | IIII | Offset |
+// --------------------------------------------------
+//
+// Load 1 byte to vector byte index
+
+inline void rsp_cop2_simd::lbv()
+{
+ UINT32 op = m_op;
+
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset;
+
+ UINT16 element;
+ EXTRACT16(m_xv[dest], element, (index >> 1));
+ element &= 0xff00 >> ((1-(index & 1)) * 8);
+ element |= m_rsp.DM_READ8(ea) << ((1-(index & 1)) * 8);
+ INSERT16(m_xv[dest], element, (index >> 1));
+}
+
+static void cfunc_lbv(void *param)
+{
+ ((rsp_cop2 *)param)->lbv();
+}
+
+
+// LSV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00001 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads 2 bytes starting from vector byte index
+
+inline void rsp_cop2_simd::lsv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xe;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 2) : (offset * 2);
+ int end = index + 2;
+ for (int i = index; i < end; i++)
+ {
+ UINT16 element;
+ EXTRACT16(m_xv[dest], element, (i >> 1));
+ element &= 0xff00 >> ((1 - (i & 1)) * 8);
+ element |= m_rsp.DM_READ8(ea) << ((1 - (i & 1)) * 8);
+ INSERT16(m_xv[dest], element, (i >> 1));
+ ea++;
+ }
+}
+
+static void cfunc_lsv(void *param)
+{
+ ((rsp_cop2 *)param)->lsv();
+}
+
+
+// LLV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00010 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads 4 bytes starting from vector byte index
+
+inline void rsp_cop2_simd::llv()
+{
+ UINT32 op = m_op;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xc;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 4) : (offset * 4);
+
+ int end = index + 4;
+
+ for (int i = index; i < end; i++)
+ {
+ UINT16 element;
+ EXTRACT16(m_xv[dest], element, (i >> 1));
+ element &= 0xff00 >> ((1 - (i & 1)) * 8);
+ element |= m_rsp.DM_READ8(ea) << ((1 - (i & 1)) * 8);
+ INSERT16(m_xv[dest], element, (i >> 1));
+ ea++;
+ }
+}
+
+static void cfunc_llv(void *param)
+{
+ ((rsp_cop2 *)param)->llv();
+}
+#endif
+
+
+// LDV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00011 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads 8 bytes starting from vector byte index
+
+inline void rsp_cop2_simd::ldv()
+{
+ UINT32 op = m_op;
+ UINT32 ea = 0;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0x8;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ int end = index + 8;
+
+ for (int i = index; i < end; i++)
+ {
+ UINT16 element;
+ EXTRACT16(m_xv[dest], element, (i >> 1));
+ element &= 0xff00 >> ((1 - (i & 1)) * 8);
+ element |= m_rsp.DM_READ8(ea) << ((1 - (i & 1)) * 8);
+ INSERT16(m_xv[dest], element, (i >> 1));
+ ea++;
+ }
+}
+
+static void cfunc_ldv(void *param)
+{
+ ((rsp_cop2 *)param)->ldv();
+}
+#endif
+
+
+// LQV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00100 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads up to 16 bytes starting from vector byte index
+
+inline void rsp_cop2_simd::lqv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ int end = 16 - (ea & 0xf);
+ if (end > 16) end = 16;
+
+ for (int i = 0; i < end; i++)
+ {
+ UINT16 element;
+ EXTRACT16(m_xv[dest], element, (i >> 1));
+ element &= 0xff00 >> ((1 - (i & 1)) * 8);
+ element |= m_rsp.DM_READ8(ea) << ((1 - (i & 1)) * 8);
+ INSERT16(m_xv[dest], element, (i >> 1));
+ ea++;
+ }
+}
+
+static void cfunc_lqv(void *param)
+{
+ ((rsp_cop2 *)param)->lqv();
+}
+
+
+// LRV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00101 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores up to 16 bytes starting from right side until 16-byte boundary
+
+inline void rsp_cop2_simd::lrv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ index = 16 - ((ea & 0xf) - index);
+ ea &= ~0xf;
+
+ for (int i = index; i < 16; i++)
+ {
+ UINT16 element;
+ EXTRACT16(m_xv[dest], element, (i >> 1));
+ element &= 0xff00 >> ((1-(i & 1)) * 8);
+ element |= m_rsp.DM_READ8(ea) << ((1-(i & 1)) * 8);
+ INSERT16(m_xv[dest], element, (i >> 1));
+ ea++;
+ }
+}
+
+static void cfunc_lrv(void *param)
+{
+ ((rsp_cop2 *)param)->lrv();
+}
+
+
+// LPV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00110 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads a byte as the upper 8 bits of each element
+
+inline void rsp_cop2_simd::lpv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ for (int i = 0; i < 8; i++)
+ {
+ INSERT16(m_xv[dest], m_rsp.DM_READ8(ea + (((16-index) + i) & 0xf)) << 8, i);
+ }
+}
+
+static void cfunc_lpv(void *param)
+{
+ ((rsp_cop2 *)param)->lpv();
+}
+
+
+// LUV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 00111 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads a byte as the bits 14-7 of each element
+
+inline void rsp_cop2_simd::luv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ for (int i = 0; i < 8; i++)
+ {
+ INSERT16(m_xv[dest], m_rsp.DM_READ8(ea + (((16-index) + i) & 0xf)) << 7, i);
+ }
+}
+
+static void cfunc_luv(void *param)
+{
+ ((rsp_cop2 *)param)->luv();
+}
+
+
+// LHV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 01000 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads a byte as the bits 14-7 of each element, with 2-byte stride
+
+inline void rsp_cop2_simd::lhv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ for (int i = 0; i < 8; i++)
+ {
+ INSERT16(m_xv[dest], m_rsp.DM_READ8(ea + (((16-index) + (i<<1)) & 0xf)) << 7, i);
+ }
+}
+
+static void cfunc_lhv(void *param)
+{
+ ((rsp_cop2 *)param)->lhv();
+}
+
+
+// LFV
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 01001 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride
+
+inline void rsp_cop2_simd::lfv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ // not sure what happens if 16-byte boundary is crossed...
+
+ int end = (index >> 1) + 4;
+
+ for (int i = index >> 1; i < end; i++)
+ {
+ INSERT16(m_xv[dest], m_rsp.DM_READ8(ea) << 7, i);
+ ea += 4;
+ }
+}
+
+static void cfunc_lfv(void *param)
+{
+ ((rsp_cop2 *)param)->lfv();
+}
+
+
+// LWV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 01010 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads the full 128-bit vector starting from vector byte index and wrapping to index 0
+// after byte index 15
+
+inline void rsp_cop2_simd::lwv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ int end = (16 - index) + 16;
+
+ UINT8 val[16];
+ for (int i = (16 - index); i < end; i++)
+ {
+ val[i & 0xf] = m_rsp.DM_READ8(ea);
+ ea += 4;
+ }
+
+ m_xv[dest] = _mm_set_epi8(val[15], val[14], val[13], val[12], val[11], val[10], val[ 9], val[ 8],
+ val[ 7], val[ 6], val[ 5], val[ 4], val[ 3], val[ 2], val[ 1], val[ 0]);
+}
+
+static void cfunc_lwv(void *param)
+{
+ ((rsp_cop2 *)param)->lwv();
+}
+
+
+// LTV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset |
+// --------------------------------------------------
+//
+// Loads one element to maximum of 8 vectors, while incrementing element index
+
+inline void rsp_cop2_simd::ltv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+
+ // FIXME: has a small problem with odd indices
+
+ int vs = dest;
+ int ve = dest + 8;
+ if (ve > 32)
+ {
+ ve = 32;
+ }
+
+ int element = 7 - (index >> 1);
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ ea = ((ea + 8) & ~0xf) + (index & 1);
+ for (int i = vs; i < ve; i++)
+ {
+ element = (8 - (index >> 1) + (i - vs)) << 1;
+ UINT16 value = (m_rsp.DM_READ8(ea) << 8) | m_rsp.DM_READ8(ea + 1);
+ INSERT16(m_xv[i], value, (element >> 1));
+ ea += 2;
+ }
+}
+
+static void cfunc_ltv(void *param)
+{
+ ((rsp_cop2 *)param)->ltv();
+}
+
+
+/***************************************************************************
+ Vector Store Instructions
+***************************************************************************/
+
+// SBV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores 1 byte from vector byte index
+
+inline void rsp_cop2_simd::sbv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset;
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, (index >> 1));
+ value >>= (1-(index & 1)) * 8;
+ m_rsp.DM_WRITE8(ea, (UINT8)value);
+}
+
+static void cfunc_sbv(void *param)
+{
+ ((rsp_cop2 *)param)->sbv();
+}
+
+
+// SSV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores 2 bytes starting from vector byte index
+
+inline void rsp_cop2_simd::ssv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 2) : (offset * 2);
+
+ int end = index + 2;
+ for (int i = index; i < end; i++)
+ {
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, (i >> 1));
+ value >>= (1 - (i & 1)) * 8;
+ m_rsp.DM_WRITE8(ea, (UINT8)value);
+ ea++;
+ }
+}
+
+static void cfunc_ssv(void *param)
+{
+ ((rsp_cop2 *)param)->ssv();
+}
+
+
+// SLV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores 4 bytes starting from vector byte index
+
+inline void rsp_cop2_simd::slv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 4) : (offset * 4);
+
+ int end = index + 4;
+ for (int i = index; i < end; i++)
+ {
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, (i >> 1));
+ value >>= (1 - (i & 1)) * 8;
+ m_rsp.DM_WRITE8(ea, (UINT8)value);
+ ea++;
+ }
+}
+
+static void cfunc_slv(void *param)
+{
+ ((rsp_cop2 *)param)->slv();
+}
+
+
+// SDV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores 8 bytes starting from vector byte index
+
+inline void rsp_cop2_simd::sdv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0x8;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+
+ int end = index + 8;
+ for (int i = index; i < end; i++)
+ {
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, (i >> 1));
+ value >>= (1 - (i & 1)) * 8;
+ m_rsp.DM_WRITE8(ea, (UINT8)value);
+ ea++;
+ }
+}
+
+static void cfunc_sdv(void *param)
+{
+ ((rsp_cop2 *)param)->sdv();
+}
+
+
+// SQV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores up to 16 bytes starting from vector byte index until 16-byte boundary
+
+inline void rsp_cop2_simd::sqv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ int end = index + (16 - (ea & 0xf));
+ for (int i=index; i < end; i++)
+ {
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, (i >> 1));
+ value >>= (1-(i & 1)) * 8;
+ m_rsp.DM_WRITE8(ea, (UINT8)value);
+ ea++;
+ }
+}
+
+static void cfunc_sqv(void *param)
+{
+ ((rsp_cop2 *)param)->sqv();
+}
+
+
+// SRV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores up to 16 bytes starting from right side until 16-byte boundary
+
+inline void rsp_cop2_simd::srv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+
+ int end = index + (ea & 0xf);
+ int o = (16 - (ea & 0xf)) & 0xf;
+ ea &= ~0xf;
+
+ for (int i = index; i < end; i++)
+ {
+ UINT32 bi = (i + o) & 0xf;
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, (bi >> 1));
+ value >>= (1-(bi & 1)) * 8;
+ m_rsp.DM_WRITE8(ea, (UINT8)value);
+ ea++;
+ }
+}
+
+static void cfunc_srv(void *param)
+{
+ ((rsp_cop2 *)param)->srv();
+}
+
+
+// SPV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores upper 8 bits of each element
+
+inline void rsp_cop2_simd::spv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+ int end = index + 8;
+ for (int i=index; i < end; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, i);
+ m_rsp.DM_WRITE8(ea, (UINT8)(value >> 8));
+ }
+ else
+ {
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, i);
+ m_rsp.DM_WRITE8(ea, (UINT8)(value >> 7));
+ }
+ ea++;
+ }
+}
+
+static void cfunc_spv(void *param)
+{
+ ((rsp_cop2 *)param)->spv();
+}
+
+
+// SUV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores bits 14-7 of each element
+
+inline void rsp_cop2_simd::suv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8);
+ int end = index + 8;
+ for (int i=index; i < end; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, i);
+ m_rsp.DM_WRITE8(ea, (UINT8)(value >> 7));
+ }
+ else
+ {
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, i);
+ m_rsp.DM_WRITE8(ea, (UINT8)(value >> 8));
+ }
+ ea++;
+ }
+}
+
+static void cfunc_suv(void *param)
+{
+ ((rsp_cop2 *)param)->suv();
+}
+
+
+// SHV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores bits 14-7 of each element, with 2-byte stride
+
+inline void rsp_cop2_simd::shv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ for (int i=0; i < 8; i++)
+ {
+ int element = index + (i << 1);
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, element >> 1);
+ m_rsp.DM_WRITE8(ea, (value >> 7) & 0x00ff);
+ ea += 2;
+ }
+}
+
+static void cfunc_shv(void *param)
+{
+ ((rsp_cop2 *)param)->shv();
+}
+
+
+// SFV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores bits 14-7 of upper or lower quad, with 4-byte stride
+
+inline void rsp_cop2_simd::sfv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ int eaoffset = ea & 0xf;
+ ea &= ~0xf;
+
+ int end = (index >> 1) + 4;
+
+ for (int i = index>>1; i < end; i++)
+ {
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, i);
+ m_rsp.DM_WRITE8(ea + (eaoffset & 0xf), (value >> 7) & 0x00ff);
+ eaoffset += 4;
+ }
+}
+
+static void cfunc_sfv(void *param)
+{
+ ((rsp_cop2 *)param)->sfv();
+}
+
+
+// SWV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores the full 128-bit vector starting from vector byte index and wrapping to index 0
+// after byte index 15
+
+inline void rsp_cop2_simd::swv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ int eaoffset = ea & 0xf;
+ ea &= ~0xf;
+
+ int end = index + 16;
+ for (int i = index; i < end; i++)
+ {
+ UINT16 value;
+ EXTRACT16(m_xv[dest], value, i >> 1);
+ m_rsp.DM_WRITE8(ea + (eaoffset & 0xf), (value >> ((1-(i & 1)) * 8)) & 0xff);
+ eaoffset++;
+ }
+}
+
+static void cfunc_swv(void *param)
+{
+ ((rsp_cop2 *)param)->swv();
+}
+
+
+// STV
+//
+// 31 25 20 15 10 6 0
+// --------------------------------------------------
+// | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset |
+// --------------------------------------------------
+//
+// Stores one element from maximum of 8 vectors, while incrementing element index
+
+inline void rsp_cop2_simd::stv()
+{
+ UINT32 op = m_op;
+ int dest = (op >> 16) & 0x1f;
+ int base = (op >> 21) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+
+ if (offset & 0x40)
+ {
+ offset |= 0xffffffc0;
+ }
+
+ int vs = dest;
+ int ve = dest + 8;
+ if (ve > 32)
+ {
+ ve = 32;
+ }
+
+ int element = 8 - (index >> 1);
+
+ UINT32 ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
+ int eaoffset = (ea & 0xf) + (element * 2);
+ ea &= ~0xf;
+
+ for (int i = vs; i < ve; i++)
+ {
+ UINT16 value;
+ EXTRACT16(m_xv[i], value, element);
+ m_rsp.DM_WRITE16(ea + (eaoffset & 0xf), value);
+ eaoffset += 2;
+ element++;
+ }
+}
+
+static void cfunc_stv(void *param)
+{
+ ((rsp_cop2 *)param)->stv();
+}
+
+
+/***************************************************************************
+ SIMD Accelerators
+***************************************************************************/
+
+/* ============================================================================
+* RSPPackLo32to16: Pack LSBs of 32-bit vectors to 16-bits without saturation.
+* TODO: 5 SSE2 operations is kind of expensive just to truncate values?
+* ========================================================================= */
+INLINE __m128i RSPPackLo32to16(__m128i vectorLow, __m128i vectorHigh)
+{
+ vectorLow = _mm_slli_epi32(vectorLow, 16);
+ vectorHigh = _mm_slli_epi32(vectorHigh, 16);
+ vectorLow = _mm_srai_epi32(vectorLow, 16);
+ vectorHigh = _mm_srai_epi32(vectorHigh, 16);
+ return _mm_packs_epi32(vectorLow, vectorHigh);
+}
+
+/* ============================================================================
+* RSPPackHi32to16: Pack MSBs of 32-bit vectors to 16-bits without saturation.
+* ========================================================================= */
+INLINE __m128i RSPPackHi32to16(__m128i vectorLow, __m128i vectorHigh)
+{
+ vectorLow = _mm_srai_epi32(vectorLow, 16);
+ vectorHigh = _mm_srai_epi32(vectorHigh, 16);
+ return _mm_packs_epi32(vectorLow, vectorHigh);
+}
+
+/* ============================================================================
+* RSPSignExtend16to32: Sign-extend 16-bit slices to 32-bit slices.
+* ========================================================================= */
+INLINE void RSPSignExtend16to32(__m128i source, __m128i *vectorLow, __m128i *vectorHigh)
+{
+ __m128i vMask = _mm_srai_epi16(source, 15);
+ *vectorHigh = _mm_unpackhi_epi16(source, vMask);
+ *vectorLow = _mm_unpacklo_epi16(source, vMask);
+}
+
+/* ============================================================================
+* RSPZeroExtend16to32: Zero-extend 16-bit slices to 32-bit slices.
+* ========================================================================= */
+INLINE void RSPZeroExtend16to32(__m128i source, __m128i *vectorLow, __m128i *vectorHigh)
+{
+ *vectorHigh = _mm_unpackhi_epi16(source, _mm_setzero_si128());
+ *vectorLow = _mm_unpacklo_epi16(source, _mm_setzero_si128());
+}
+
+/* ============================================================================
+* _mm_mullo_epi32: SSE2 lacks _mm_mullo_epi32, define it manually.
+* TODO/WARNING/DISCLAIMER: Assumes one argument is positive.
+* ========================================================================= */
+INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b)
+{
+ __m128i a4 = _mm_srli_si128(a, 4);
+ __m128i b4 = _mm_srli_si128(b, 4);
+ __m128i ba = _mm_mul_epu32(b, a);
+ __m128i b4a4 = _mm_mul_epu32(b4, a4);
+
+ __m128i mask = _mm_setr_epi32(~0, 0, ~0, 0);
+ __m128i baMask = _mm_and_si128(ba, mask);
+ __m128i b4a4Mask = _mm_and_si128(b4a4, mask);
+ __m128i b4a4MaskShift = _mm_slli_si128(b4a4Mask, 4);
+
+ return _mm_or_si128(baMask, b4a4MaskShift);
+}
+
+/* ============================================================================
+* RSPClampLowToVal: Clamps the low word of the accumulator.
+* ========================================================================= */
+INLINE __m128i RSPClampLowToVal(__m128i vaccLow, __m128i vaccMid, __m128i vaccHigh)
+{
+ __m128i setMask = _mm_cmpeq_epi16(_mm_setzero_si128(), _mm_setzero_si128());
+ __m128i negCheck, useValMask, negVal, posVal;
+
+ /* Compute some common values ahead of time. */
+ negCheck = _mm_cmplt_epi16(vaccHigh, _mm_setzero_si128());
+
+ /* If accmulator < 0, clamp to val if val != TMin. */
+ useValMask = _mm_and_si128(vaccHigh, _mm_srai_epi16(vaccMid, 15));
+ useValMask = _mm_cmpeq_epi16(useValMask, setMask);
+ negVal = _mm_and_si128(useValMask, vaccLow);
+
+ /* Otherwise, clamp to ~0 if any high bits are set. */
+ useValMask = _mm_or_si128(vaccHigh, _mm_srai_epi16(vaccMid, 15));
+ useValMask = _mm_cmpeq_epi16(useValMask, _mm_setzero_si128());
+ posVal = _mm_and_si128(useValMask, vaccLow);
+
+ negVal = _mm_and_si128(negCheck, negVal);
+ posVal = _mm_andnot_si128(negCheck, posVal);
+ return _mm_or_si128(negVal, posVal);
+}
+
+
+/***************************************************************************
+ Vector Opcodes
+***************************************************************************/
+
+// VMULF
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000000 |
+// ------------------------------------------------------
+//
+// Multiplies signed integer by signed integer * 2
+
+inline void rsp_cop2_simd::vmulf()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ if (s1 == -32768 && s2 == -32768)
+ {
+ // overflow
+ SET_ACCUM_H(0, i);
+ SET_ACCUM_M(-32768, i);
+ SET_ACCUM_L(-32768, i);
+ m_vres[i] = 0x7fff;
+ }
+ else
+ {
+ INT64 r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+ SET_ACCUM_H((r < 0) ? 0xffff : 0, i);
+ SET_ACCUM_M((INT16)(r >> 16), i);
+ SET_ACCUM_L((UINT16)(r), i);
+ m_vres[i] = ACCUM_M(i);
+ }
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmulf(void *param)
+{
+ ((rsp_cop2 *)param)->vmulf();
+}
+
+
+// VMULU
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 |
+// ------------------------------------------------------
+//
+
+inline void rsp_cop2_simd::vmulu()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ INT64 r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+
+ SET_ACCUM_H((UINT16)(r >> 32), i);
+ SET_ACCUM_M((UINT16)(r >> 16), i);
+ SET_ACCUM_L((UINT16)(r), i);
+
+ if (r < 0)
+ {
+ m_vres[i] = 0;
+ }
+ else if (((INT16)(ACCUM_H(i)) ^ (INT16)(ACCUM_M(i))) < 0)
+ {
+ m_vres[i] = -1;
+ }
+ else
+ {
+ m_vres[i] = ACCUM_M(i);
+ }
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmulu(void *param)
+{
+ ((rsp_cop2 *)param)->vmulu();
+}
+
+
+// VMUDL
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 |
+// ------------------------------------------------------
+//
+// Multiplies signed integer by unsigned fraction
+// The result is added into accumulator
+// The middle slice of accumulator is stored into destination element
+
+inline void rsp_cop2_simd::vmudl()
+{
+ int op = m_op;
+
+ __m128i vsReg = m_xv[VS1REG];
+ __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+
+ /* Unpack to obtain for 32-bit precision. */
+ __m128i unpackLo = _mm_mullo_epi16(vsReg, vtReg);
+ __m128i unpackHi = _mm_mulhi_epu16(vsReg, vtReg);
+ __m128i loProduct = _mm_unpacklo_epi16(unpackLo, unpackHi);
+ __m128i hiProduct = _mm_unpackhi_epi16(unpackLo, unpackHi);
+
+ m_xv[VDREG] = m_accum_l = RSPPackHi32to16(loProduct, hiProduct);
+
+ m_accum_m = _mm_setzero_si128();
+ m_accum_h = _mm_setzero_si128();
+}
+
+static void cfunc_vmudl(void *param)
+{
+ ((rsp_cop2 *)param)->vmudl();
+}
+
+
+// VMUDM
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000101 |
+// ------------------------------------------------------
+//
+// Multiplies signed integer by unsigned fraction
+// The result is stored into accumulator
+// The middle slice of accumulator is stored into destination element
+
+inline void rsp_cop2_simd::vmudm()
+{
+ int op = m_op;
+
+ __m128i vsRegLo, vsRegHi, vtRegLo, vtRegHi;
+
+ __m128i vsReg = m_xv[VS1REG];
+ __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+
+ /* Unpack to obtain for 32-bit precision. */
+ RSPSignExtend16to32(vsReg, &vsRegLo, &vsRegHi);
+ RSPZeroExtend16to32(vtReg, &vtRegLo, &vtRegHi);
+
+ /* Begin accumulating the products. */
+ __m128i loProduct = _mm_mullo_epi32(vsRegLo, vtRegLo);
+ __m128i hiProduct = _mm_mullo_epi32(vsRegHi, vtRegHi);
+ m_accum_l = RSPPackLo32to16(loProduct, hiProduct);
+ m_accum_m = m_xv[VDREG] = RSPPackHi32to16(loProduct, hiProduct);
+
+ loProduct = _mm_cmplt_epi32(loProduct, _mm_setzero_si128());
+ hiProduct = _mm_cmplt_epi32(hiProduct, _mm_setzero_si128());
+ m_accum_h = _mm_packs_epi32(loProduct, hiProduct);
+}
+
+static void cfunc_vmudm(void *param)
+{
+ ((rsp_cop2 *)param)->vmudm();
+}
+
+
+// VMUDN
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 |
+// ------------------------------------------------------
+//
+// Multiplies unsigned fraction by signed integer
+// The result is stored into accumulator
+// The low slice of accumulator is stored into destination element
+
+inline void rsp_cop2_simd::vmudn()
+{
+ int op = m_op;
+
+ __m128i vsRegLo, vsRegHi, vtRegLo, vtRegHi;
+
+ __m128i vsReg = m_xv[VS1REG];
+ __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+
+ /* Unpack to obtain for 32-bit precision. */
+ RSPZeroExtend16to32(vsReg, &vsRegLo, &vsRegHi);
+ RSPSignExtend16to32(vtReg, &vtRegLo, &vtRegHi);
+
+ /* Begin accumulating the products. */
+ __m128i loProduct = _mm_mullo_epi32(vsRegLo, vtRegLo);
+ __m128i hiProduct = _mm_mullo_epi32(vsRegHi, vtRegHi);
+ m_xv[VDREG] = m_accum_l = RSPPackLo32to16(loProduct, hiProduct);
+ m_accum_m = RSPPackHi32to16(loProduct, hiProduct);
+ m_accum_h = _mm_cmplt_epi16(m_accum_m, _mm_setzero_si128());
+}
+
+static void cfunc_vmudn(void *param)
+{
+ ((rsp_cop2 *)param)->vmudn();
+}
+
+
+// VMUDH
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000111 |
+// ------------------------------------------------------
+//
+// Multiplies signed integer by signed integer
+// The result is stored into highest 32 bits of accumulator, the low slice is zero
+// The highest 32 bits of accumulator is saturated into destination element
+
+inline void rsp_cop2_simd::vmudh()
+{
+ int op = m_op;
+
+ __m128i vaccLow, vaccHigh;
+ __m128i unpackLo, unpackHi;
+
+ __m128i vsReg = m_xv[VS1REG];
+ __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+
+ /* Multiply the sources, accumulate the product. */
+ unpackLo = _mm_mullo_epi16(vsReg, vtReg);
+ unpackHi = _mm_mulhi_epi16(vsReg, vtReg);
+ vaccHigh = _mm_unpackhi_epi16(unpackLo, unpackHi);
+ vaccLow = _mm_unpacklo_epi16(unpackLo, unpackHi);
+
+ /* Pack the accumulator and result back up. */
+ m_xv[VDREG] = _mm_packs_epi32(vaccLow, vaccHigh);
+ m_accum_l = _mm_setzero_si128();
+ m_accum_m = RSPPackLo32to16(vaccLow, vaccHigh);
+ m_accum_h = RSPPackHi32to16(vaccLow, vaccHigh);
+}
+
+static void cfunc_vmudh(void *param)
+{
+ ((rsp_cop2 *)param)->vmudh();
+}
+
+
+// VMACF
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001000 |
+// ------------------------------------------------------
+//
+
+inline void rsp_cop2_simd::vmacf()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (INT32)(INT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ INT32 r = s1 * s2;
+
+ UINT64 q = (UINT64)(UINT16)ACCUM_LL(i);
+ q |= (((UINT64)(UINT16)ACCUM_L(i)) << 16);
+ q |= (((UINT64)(UINT16)ACCUM_M(i)) << 32);
+ q |= (((UINT64)(UINT16)ACCUM_H(i)) << 48);
+
+ q += (INT64)(r) << 17;
+ SET_ACCUM_LL((UINT16)q, i);
+ SET_ACCUM_L((UINT16)(q >> 16), i);
+ SET_ACCUM_M((UINT16)(q >> 32), i);
+ SET_ACCUM_H((UINT16)(q >> 48), i);
+
+ m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmacf(void *param)
+{
+ ((rsp_cop2 *)param)->vmacf();
+}
+
+
+// VMACU
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 |
+// ------------------------------------------------------
+//
+
+inline void rsp_cop2_simd::vmacu()
+{
+ int op = m_op;
+
+ __m128i loProduct, hiProduct, unpackLo, unpackHi;
+ __m128i vaccHigh;
+ __m128i vdReg, vdRegLo, vdRegHi;
+
+ __m128i vsReg = m_xv[VS1REG];
+ __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+
+ __m128i vaccLow = m_accum_l;
+
+ /* Unpack to obtain for 32-bit precision. */
+ RSPZeroExtend16to32(vaccLow, &vaccLow, &vaccHigh);
+
+ /* Begin accumulating the products. */
+ unpackLo = _mm_mullo_epi16(vsReg, vtReg);
+ unpackHi = _mm_mulhi_epi16(vsReg, vtReg);
+ loProduct = _mm_unpacklo_epi16(unpackLo, unpackHi);
+ hiProduct = _mm_unpackhi_epi16(unpackLo, unpackHi);
+ loProduct = _mm_slli_epi32(loProduct, 1);
+ hiProduct = _mm_slli_epi32(hiProduct, 1);
+
+ vdRegLo = _mm_srli_epi32(loProduct, 16);
+ vdRegHi = _mm_srli_epi32(hiProduct, 16);
+ vdRegLo = _mm_slli_epi32(vdRegLo, 16);
+ vdRegHi = _mm_slli_epi32(vdRegHi, 16);
+ vdRegLo = _mm_xor_si128(vdRegLo, loProduct);
+ vdRegHi = _mm_xor_si128(vdRegHi, hiProduct);
+
+ vaccLow = _mm_add_epi32(vaccLow, vdRegLo);
+ vaccHigh = _mm_add_epi32(vaccHigh, vdRegHi);
+
+ m_accum_l = vdReg = RSPPackLo32to16(vaccLow, vaccHigh);
+
+ /* Multiply the MSB of sources, accumulate the product. */
+ vdRegLo = _mm_unpacklo_epi16(m_accum_m, m_accum_h);
+ vdRegHi = _mm_unpackhi_epi16(m_accum_m, m_accum_h);
+
+ loProduct = _mm_srai_epi32(loProduct, 16);
+ hiProduct = _mm_srai_epi32(hiProduct, 16);
+ vaccLow = _mm_srai_epi32(vaccLow, 16);
+ vaccHigh = _mm_srai_epi32(vaccHigh, 16);
+
+ vaccLow = _mm_add_epi32(loProduct, vaccLow);
+ vaccHigh = _mm_add_epi32(hiProduct, vaccHigh);
+ vaccLow = _mm_add_epi32(vdRegLo, vaccLow);
+ vaccHigh = _mm_add_epi32(vdRegHi, vaccHigh);
+
+ /* Clamp the accumulator and write it all out. */
+ m_accum_m = RSPPackLo32to16(vaccLow, vaccHigh);
+ m_accum_h = RSPPackHi32to16(vaccLow, vaccHigh);
+}
+
+static void cfunc_vmacu(void *param)
+{
+ ((rsp_cop2 *)param)->vmacu();
+}
+
+
+// VMADL
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001100 |
+// ------------------------------------------------------
+//
+// Multiplies unsigned fraction by unsigned fraction
+// Adds the higher 16 bits of the 32-bit result to accumulator
+// The low slice of accumulator is stored into destination element
+
+inline void rsp_cop2_simd::vmadl()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ UINT32 s1 = w1;
+ UINT32 s2 = w2;
+
+ UINT32 r1 = s1 * s2;
+ UINT32 r2 = (UINT16)ACCUM_L(i) + (r1 >> 16);
+ UINT32 r3 = (UINT16)ACCUM_M(i) + (r2 >> 16);
+
+ SET_ACCUM_L((UINT16)r2, i);
+ SET_ACCUM_M((UINT16)r3, i);
+ SET_ACCUM_H(ACCUM_H(i) + (INT16)(r3 >> 16), i);
+
+ m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmadl(void *param)
+{
+ ((rsp_cop2 *)param)->vmadl();
+}
+
+
+// VMADM
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 |
+// ------------------------------------------------------
+//
+// Multiplies signed fraction by unsigned fraction
+// Adds the higher 16 bits of the 32-bit result to accumulator
+// The medium slice of accumulator is stored into destination element
+
+inline void rsp_cop2_simd::vmadm()
+{
+ int op = m_op;
+
+ __m128i vaccLow, vaccHigh, loProduct, hiProduct;
+ __m128i vsRegLo, vsRegHi, vtRegLo, vtRegHi, vdRegLo, vdRegHi;
+
+ __m128i vsReg = m_xv[VS1REG];
+ __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+
+ /* Unpack to obtain for 32-bit precision. */
+ RSPSignExtend16to32(vsReg, &vsRegLo, &vsRegHi);
+ RSPZeroExtend16to32(vtReg, &vtRegLo, &vtRegHi);
+ RSPZeroExtend16to32(m_accum_l, &vaccLow, &vaccHigh);
+
+ /* Begin accumulating the products. */
+ loProduct = _mm_mullo_epi32(vsRegLo, vtRegLo);
+ hiProduct = _mm_mullo_epi32(vsRegHi, vtRegHi);
+
+ vdRegLo = _mm_srli_epi32(loProduct, 16);
+ vdRegHi = _mm_srli_epi32(hiProduct, 16);
+ vdRegLo = _mm_slli_epi32(vdRegLo, 16);
+ vdRegHi = _mm_slli_epi32(vdRegHi, 16);
+ vdRegLo = _mm_xor_si128(vdRegLo, loProduct);
+ vdRegHi = _mm_xor_si128(vdRegHi, hiProduct);
+ vaccLow = _mm_add_epi32(vaccLow, vdRegLo);
+ vaccHigh = _mm_add_epi32(vaccHigh, vdRegHi);
+
+ m_accum_l = m_xv[VDREG] = RSPPackLo32to16(vaccLow, vaccHigh);
+
+ /* Multiply the MSB of sources, accumulate the product. */
+ vdRegLo = _mm_unpacklo_epi16(m_accum_m, m_accum_h);
+ vdRegHi = _mm_unpackhi_epi16(m_accum_m, m_accum_h);
+
+ loProduct = _mm_srai_epi32(loProduct, 16);
+ hiProduct = _mm_srai_epi32(hiProduct, 16);
+ vaccLow = _mm_srai_epi32(vaccLow, 16);
+ vaccHigh = _mm_srai_epi32(vaccHigh, 16);
+
+ vaccLow = _mm_add_epi32(loProduct, vaccLow);
+ vaccHigh = _mm_add_epi32(hiProduct, vaccHigh);
+ vaccLow = _mm_add_epi32(vdRegLo, vaccLow);
+ vaccHigh = _mm_add_epi32(vdRegHi, vaccHigh);
+
+ /* Clamp the accumulator and write it all out. */
+ m_xv[VDREG] = _mm_packs_epi32(vaccLow, vaccHigh);
+ m_accum_m = RSPPackLo32to16(vaccLow, vaccHigh);
+ m_accum_h = RSPPackHi32to16(vaccLow, vaccHigh);
+}
+
+static void cfunc_vmadm(void *param)
+{
+ ((rsp_cop2 *)param)->vmadm();
+}
+
+
+// VMADN
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 |
+// ------------------------------------------------------
+//
+// Multiplies unsigned fraction by signed fraction
+// Adds the 32-bit result to the medium and high slices of the accumulator
+// The low slice of accumulator is saturated into destination element
+
+inline void rsp_cop2_simd::vmadn()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+ INT32 s1 = (UINT16)w1;
+ INT32 s2 = (INT32)(INT16)w2;
+
+ UINT64 q = (UINT64)ACCUM_LL(i);
+ q |= (((UINT64)ACCUM_L(i)) << 16);
+ q |= (((UINT64)ACCUM_M(i)) << 32);
+ q |= (((UINT64)ACCUM_H(i)) << 48);
+ q += (INT64)(s1*s2) << 16;
+
+ SET_ACCUM_LL((UINT16)q, i);
+ SET_ACCUM_L((UINT16)(q >> 16), i);
+ SET_ACCUM_M((UINT16)(q >> 32), i);
+ SET_ACCUM_H((UINT16)(q >> 48), i);
+
+ m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vmadn(void *param)
+{
+ ((rsp_cop2 *)param)->vmadn();
+}
+
+
+// VMADH
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001111 |
+// ------------------------------------------------------
+//
+// Multiplies signed integer by signed integer
+// The result is added into highest 32 bits of accumulator, the low slice is zero
+// The highest 32 bits of accumulator is saturated into destination element
+
+inline void rsp_cop2_simd::vmadh()
+{
+ int op = m_op;
+
+ __m128i vsReg = m_xv[VS1REG];
+ __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+
+ /* Unpack to obtain for 32-bit precision. */
+ __m128i vaccLow = _mm_unpacklo_epi16(m_accum_m, m_accum_h);
+ __m128i vaccHigh = _mm_unpackhi_epi16(m_accum_m, m_accum_h);
+
+ /* Multiply the sources, accumulate the product. */
+ __m128i unpackLo = _mm_mullo_epi16(vsReg, vtReg);
+ __m128i unpackHi = _mm_mulhi_epi16(vsReg, vtReg);
+ __m128i loProduct = _mm_unpacklo_epi16(unpackLo, unpackHi);
+ __m128i hiProduct = _mm_unpackhi_epi16(unpackLo, unpackHi);
+ vaccLow = _mm_add_epi32(vaccLow, loProduct);
+ vaccHigh = _mm_add_epi32(vaccHigh, hiProduct);
+
+ /* Pack the accumulator and result back up. */
+ m_xv[VDREG] = _mm_packs_epi32(vaccLow, vaccHigh);
+ m_accum_m = RSPPackLo32to16(vaccLow, vaccHigh);
+ m_accum_h = RSPPackHi32to16(vaccLow, vaccHigh);
+}
+
+static void cfunc_vmadh(void *param)
+{
+ ((rsp_cop2 *)param)->vmadh();
+}
+
+
+// VADD
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010000 |
+// ------------------------------------------------------
+//
+// Adds two vector registers and carry flag, the result is saturated to 32767
+
+inline void rsp_cop2_simd::vadd()
+{
+ int op = m_op;
+
+ __m128i shuffled = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ __m128i carry = _mm_and_si128(m_xvflag[CARRY], vec_flagmask);
+ m_accum_l = _mm_add_epi16(_mm_add_epi16(m_xv[VS1REG], shuffled), carry);
+
+ __m128i addvec = _mm_adds_epi16(m_xv[VS1REG], shuffled);
+
+ carry = _mm_and_si128(carry, _mm_xor_si128(_mm_cmpeq_epi16(addvec, vec_32767), vec_neg1));
+ carry = _mm_and_si128(carry, _mm_xor_si128(_mm_cmpeq_epi16(addvec, vec_n32768), vec_neg1));
+
+ m_xv[VDREG] = _mm_add_epi16(addvec, carry);
+
+ m_xvflag[ZERO] = vec_zero;
+ m_xvflag[CARRY] = vec_zero;
+}
+
+static void cfunc_vadd(void *param)
+{
+ ((rsp_cop2 *)param)->vadd();
+}
+
+
+// VSUB
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010001 |
+// ------------------------------------------------------
+//
+// Subtracts two vector registers and carry flag, the result is saturated to -32768
+// TODO: check VS2REG == VDREG
+
+inline void rsp_cop2_simd::vsub()
+{
+ int op = m_op;
+
+ __m128i shuffled = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ __m128i carry = _mm_and_si128(m_xvflag[CARRY], vec_flagmask);
+ __m128i unsat = _mm_sub_epi16(m_xv[VS1REG], shuffled);
+
+ __m128i vs2neg = _mm_cmplt_epi16(shuffled, vec_zero);
+ __m128i vs2pos = _mm_cmpeq_epi16(vs2neg, vec_zero);
+
+ __m128i saturated = _mm_subs_epi16(m_xv[VS1REG], shuffled);
+ __m128i carry_mask = _mm_cmpeq_epi16(unsat, saturated);
+ carry_mask = _mm_and_si128(vs2neg, carry_mask);
+
+ vs2neg = _mm_and_si128(carry_mask, carry);
+ vs2pos = _mm_and_si128(vs2pos, carry);
+ __m128i dest_carry = _mm_or_si128(vs2neg, vs2pos);
+ m_xv[VDREG] = _mm_subs_epi16(saturated, dest_carry);
+
+ m_accum_l = _mm_sub_epi16(unsat, carry);
+
+ m_xvflag[ZERO] = _mm_setzero_si128();
+ m_xvflag[CARRY] = _mm_setzero_si128();
+}
+
+static void cfunc_vsub(void *param)
+{
+ ((rsp_cop2 *)param)->vsub();
+}
+
+
+// VABS
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010011 |
+// ------------------------------------------------------
+//
+// Changes the sign of source register 2 if source register 1 is negative and stores the result to destination register
+
+inline void rsp_cop2_simd::vabs()
+{
+ int op = m_op;
+
+ __m128i shuf2 = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ __m128i negs2 = _mm_sub_epi16(_mm_setzero_si128(), shuf2);
+ __m128i s2_n32768 = _mm_cmpeq_epi16(shuf2, vec_n32768);
+ __m128i s1_lz = _mm_cmplt_epi16(m_xv[VS1REG], _mm_setzero_si128());
+
+ __m128i result_gz = _mm_and_si128(shuf2, _mm_cmpgt_epi16(m_xv[VS1REG], _mm_setzero_si128()));
+ __m128i result_n32768 = _mm_and_si128(s1_lz, _mm_and_si128(vec_32767, s2_n32768));
+ __m128i result_negs2 = _mm_and_si128(s1_lz, _mm_and_si128(negs2, _mm_xor_si128(s2_n32768, vec_neg1)));
+ m_xv[VDREG] = m_accum_l = _mm_or_si128(result_gz, _mm_or_si128(result_n32768, result_negs2));
+}
+
+static void cfunc_vabs(void *param)
+{
+ ((rsp_cop2 *)param)->vabs();
+}
+
+
+// VADDC
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010100 |
+// ------------------------------------------------------
+//
+// Adds two vector registers, the carry out is stored into carry register
+// TODO: check VS2REG = VDREG
+
+inline void rsp_cop2_simd::vaddc()
+{
+ int op = m_op;
+
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+
+ __m128i shuf2 = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ __m128i vec7531 = _mm_and_si128(m_xv[VS1REG], vec_lomask);
+ __m128i vec6420 = _mm_srli_epi32(m_xv[VS1REG], 16);
+ __m128i shuf7531 = _mm_and_si128(shuf2, vec_lomask);
+ __m128i shuf6420 = _mm_srli_epi32(shuf2, 16);
+ __m128i sum7531 = _mm_add_epi32(vec7531, shuf7531);
+ __m128i sum6420 = _mm_add_epi32(vec6420, shuf6420);
+
+ __m128i over7531 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum7531, _mm_setzero_si128()), vec_neg1), vec_himask);
+ __m128i over6420 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum6420, _mm_setzero_si128()), vec_neg1), vec_himask);
+
+ sum7531 = _mm_and_si128(sum7531, vec_lomask);
+ sum6420 = _mm_and_si128(sum6420, vec_lomask);
+
+ m_xvflag[CARRY] = _mm_or_si128(over6420, _mm_srli_epi32(over7531, 16));
+ m_accum_l = m_xv[VDREG] = _mm_or_si128(_mm_slli_epi32(sum6420, 16), sum7531);
+}
+
+static void cfunc_vaddc(void *param)
+{
+ ((rsp_cop2 *)param)->vaddc();
+}
+
+
+// VSUBC
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010101 |
+// ------------------------------------------------------
+//
+// Subtracts two vector registers, the carry out is stored into carry register
+// TODO: check VS2REG = VDREG
+
+inline void rsp_cop2_simd::vsubc()
+{
+ int op = m_op;
+
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+
+ __m128i shuf2 = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ __m128i vec7531 = _mm_and_si128(m_xv[VS1REG], vec_lomask);
+ __m128i vec6420 = _mm_srli_epi32(m_xv[VS1REG], 16);
+ __m128i shuf7531 = _mm_and_si128(shuf2, vec_lomask);
+ __m128i shuf6420 = _mm_srli_epi32(shuf2, 16);
+ __m128i sum7531 = _mm_sub_epi32(vec7531, shuf7531);
+ __m128i sum6420 = _mm_sub_epi32(vec6420, shuf6420);
+
+ __m128i over7531 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum7531, _mm_setzero_si128()), vec_neg1), vec_himask);
+ __m128i over6420 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum6420, _mm_setzero_si128()), vec_neg1), vec_himask);
+ sum7531 = _mm_and_si128(sum7531, vec_lomask);
+ sum6420 = _mm_and_si128(sum6420, vec_lomask);
+ __m128i zero7531 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum7531, _mm_setzero_si128()), vec_neg1), vec_lomask);
+ __m128i zero6420 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum6420, _mm_setzero_si128()), vec_neg1), vec_lomask);
+
+ m_xvflag[CARRY] = _mm_or_si128(over6420, _mm_srli_epi32(over7531, 16));
+ m_xvflag[ZERO] = _mm_or_si128(_mm_slli_epi32(zero6420, 16), zero7531);
+
+ m_accum_l = m_xv[VDREG] = _mm_or_si128(_mm_slli_epi32(sum6420, 16), sum7531);
+}
+
+static void cfunc_vsubc(void *param)
+{
+ ((rsp_cop2 *)param)->vsubc();
+}
+
+
+// VADDB
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010110 |
+// ------------------------------------------------------
+//
+// Adds two vector registers bytewise with rounding
+inline void rsp_cop2_simd::vaddb()
+{
+ const int op = m_op;
+ const int round = (EL == 0) ? 0 : (1 << (EL - 1));
+
+ for (int i = 0; i < 8; i++)
+ {
+ UINT16 w1, w2;
+ GET_VS1(w1, i);
+ GET_VS2(w2, i);
+
+ UINT8 hb1 = w1 >> 8;
+ UINT8 lb1 = w1 & 0xff;
+ UINT8 hb2 = w2 >> 8;
+ UINT8 lb2 = w2 & 0xff;
+
+ UINT16 hs = hb1 + hb2 + round;
+ UINT16 ls = lb1 + lb2 + round;
+
+ SET_ACCUM_L((hs << 8) | ls, i);
+
+ hs >>= EL;
+ if (hs > 255)
+ {
+ hs = 255;
+ }
+
+ ls >>= EL;
+ if (ls > 255)
+ {
+ ls = 255;
+ }
+
+ m_vres[i] = 0; // VD writeback disabled on production hardware
+ // m_vres[i] = (hs << 8) | ls;
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vaddb(void *param)
+{
+ ((rsp_cop2 *)param)->vaddb();
+}
+
+
+// VSAW
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 011101 |
+// ------------------------------------------------------
+//
+// Stores high, middle or low slice of accumulator to destination vector
+
+inline void rsp_cop2_simd::vsaw()
+{
+ int op = m_op;
+
+ switch (EL)
+ {
+ case 0x08: // VSAWH
+ {
+ m_xv[VDREG] = m_accum_h;
+ break;
+ }
+ case 0x09: // VSAWM
+ {
+ m_xv[VDREG] = m_accum_m;
+ break;
+ }
+ case 0x0a: // VSAWL
+ {
+ m_xv[VDREG] = m_accum_l;
+ break;
+ }
+ default: // Unsupported, writes 0 to VD
+ {
+
+ }
+ }
+}
+
+static void cfunc_vsaw(void *param)
+{
+ ((rsp_cop2 *)param)->vsaw();
+}
+
+
+// VLT
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100000 |
+// ------------------------------------------------------
+//
+// Sets compare flags if elements in VS1 are less than VS2
+// Moves the element in VS2 to destination vector
+
+inline void rsp_cop2_simd::vlt()
+{
+ int op = m_op;
+
+ m_xvflag[COMPARE] = m_xvflag[CLIP2] = _mm_setzero_si128();
+
+ __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ __m128i zc_mask = _mm_and_si128(m_xvflag[ZERO], m_xvflag[CARRY]);
+ __m128i lt_mask = _mm_cmplt_epi16(m_xv[VS1REG], shuf);
+ __m128i eq_mask = _mm_and_si128(_mm_cmpeq_epi16(m_xv[VS1REG], shuf), zc_mask);
+
+ m_xvflag[COMPARE] = _mm_or_si128(lt_mask, eq_mask);
+
+ __m128i result = _mm_and_si128(m_xv[VS1REG], m_xvflag[COMPARE]);
+ m_accum_l = m_xv[VDREG] = _mm_or_si128(result, _mm_and_si128(shuf, _mm_xor_si128(m_xvflag[COMPARE], vec_neg1)));
+
+ m_xvflag[ZERO] = m_xvflag[CARRY] = _mm_setzero_si128();
+}
+
+static void cfunc_void vlt(void *param)
+{
+ ((rsp_cop2 *)param)->vlt();
+}
+
+
+// VEQ
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100001 |
+// ------------------------------------------------------
+//
+// Sets compare flags if elements in VS1 are equal with VS2
+// Moves the element in VS2 to destination vector
+
+inline void rsp_cop2_simd::veq()
+{
+ int op = m_op;
+
+ m_xvflag[COMPARE] = m_xvflag[CLIP2] = _mm_setzero_si128();
+
+ __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ __m128i zero_mask = _mm_cmpeq_epi16(m_xvflag[ZERO], _mm_setzero_si128());
+ __m128i eq_mask = _mm_cmpeq_epi16(m_xv[VS1REG], shuf);
+
+ m_xvflag[COMPARE] = _mm_and_si128(zero_mask, eq_mask);
+
+ __m128i result = _mm_and_si128(m_xv[VS1REG], m_xvflag[COMPARE]);
+ m_accum_l = m_xv[VDREG] = _mm_or_si128(result, _mm_and_si128(shuf, _mm_xor_si128(m_xvflag[COMPARE], vec_neg1)));
+
+ m_xvflag[ZERO] = m_xvflag[CARRY] = _mm_setzero_si128();
+}
+
+static void cfunc_veq(void *param)
+{
+ ((rsp_cop2 *)param)->veq();
+}
+
+
+// VNE
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100010 |
+// ------------------------------------------------------
+//
+// Sets compare flags if elements in VS1 are not equal with VS2
+// Moves the element in VS2 to destination vector
+
+inline void rsp_cop2_simd::vne()
+{
+ int op = m_op;
+
+ m_xvflag[COMPARE] = m_xvflag[CLIP2] = _mm_setzero_si128();
+
+ __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ __m128i neq_mask = _mm_xor_si128(_mm_cmpeq_epi16(m_xv[VS1REG], shuf), vec_neg1);
+
+ m_xvflag[COMPARE] = _mm_or_si128(m_xvflag[ZERO], neq_mask);
+
+ __m128i result = _mm_and_si128(m_xv[VS1REG], m_xvflag[COMPARE]);
+ m_accum_l = m_xv[VDREG] = _mm_or_si128(result, _mm_and_si128(shuf, _mm_xor_si128(m_xvflag[COMPARE], vec_neg1)));
+
+ m_xvflag[ZERO] = m_xvflag[CARRY] = _mm_setzero_si128();
+}
+
+static void cfunc_vne(void *param)
+{
+ ((rsp_cop2 *)param)->vne();
+}
+
+
+// VGE
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100011 |
+// ------------------------------------------------------
+//
+// Sets compare flags if elements in VS1 are greater or equal with VS2
+// Moves the element in VS2 to destination vector
+
+inline void rsp_cop2_simd::vge()
+{
+ int op = m_op;
+
+ m_xvflag[COMPARE] = m_xvflag[CLIP2] = _mm_setzero_si128();
+
+ __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ __m128i zero_mask = _mm_cmpeq_epi16(m_xvflag[ZERO], _mm_setzero_si128());
+ __m128i carry_mask = _mm_cmpeq_epi16(m_xvflag[CARRY], _mm_setzero_si128());
+ __m128i flag_mask = _mm_or_si128(zero_mask, carry_mask);
+ __m128i eq_mask = _mm_and_si128(_mm_cmpeq_epi16(m_xv[VS1REG], shuf), flag_mask);
+ __m128i gt_mask = _mm_cmpgt_epi16(m_xv[VS1REG], shuf);
+ m_xvflag[COMPARE] = _mm_or_si128(eq_mask, gt_mask);
+
+ __m128i result = _mm_and_si128(m_xv[VS1REG], m_xvflag[COMPARE]);
+ m_accum_l = m_xv[VDREG] = _mm_or_si128(result, _mm_and_si128(shuf, _mm_xor_si128(m_xvflag[COMPARE], vec_neg1)));
+
+ m_xvflag[ZERO] = m_xvflag[CARRY] = _mm_setzero_si128();
+}
+
+static void cfunc_vge(void *param)
+{
+ ((rsp_cop2 *)param)->vge();
+}
+
+
+// VCL
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 |
+// ------------------------------------------------------
+//
+// Vector clip low
+
+inline void rsp_cop2_simd::vcl()
+{
+ int op = m_op;
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+
+ if (CARRY_FLAG(i) != 0)
+ {
+ if (ZERO_FLAG(i) != 0)
+ {
+ if (COMPARE_FLAG(i) != 0)
+ {
+ SET_ACCUM_L(-(UINT16)s2, i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+ else
+ {
+ if (CLIP1_FLAG(i) != 0)
+ {
+ if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) > 0x10000)
+ {
+ SET_ACCUM_L(s1, i);
+ CLEAR_COMPARE_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(-((UINT16)s2), i);
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ else
+ {
+ if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0)
+ {
+ SET_ACCUM_L(s1, i);
+ CLEAR_COMPARE_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(-((UINT16)s2), i);
+ SET_COMPARE_FLAG(i);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (ZERO_FLAG(i) != 0)
+ {
+ if (CLIP2_FLAG(i) != 0)
+ {
+ SET_ACCUM_L(s2, i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+ else
+ {
+ if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0)
+ {
+ SET_ACCUM_L(s2, i);
+ SET_CLIP2_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ CLEAR_CLIP2_FLAG(i);
+ }
+ }
+ }
+ m_vres[i] = ACCUM_L(i);
+ }
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CARRY_FLAGS();
+ CLEAR_CLIP1_FLAGS();
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vcl(void *param)
+{
+ ((rsp_cop2 *)param)->vcl();
+}
+
+
+// VCH
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 |
+// ------------------------------------------------------
+//
+// Vector clip high
+
+inline void rsp_cop2_simd::vch()
+{
+ int op = m_op;
+
+ CLEAR_CARRY_FLAGS();
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP1_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ UINT32 vce = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+
+ if ((s1 ^ s2) < 0)
+ {
+ vce = (s1 + s2 == -1);
+ SET_CARRY_FLAG(i);
+ if (s2 < 0)
+ {
+ SET_CLIP2_FLAG(i);
+ }
+
+ if ((s1 + s2) <= 0)
+ {
+ SET_COMPARE_FLAG(i);
+ m_vres[i] = -((UINT16)s2);
+ }
+ else
+ {
+ m_vres[i] = s1;
+ }
+
+ if ((s1 + s2) != 0 && s1 != ~s2)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ }//sign
+ else
+ {
+ vce = 0;
+ if (s2 < 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ if ((s1 - s2) >= 0)
+ {
+ SET_CLIP2_FLAG(i);
+ m_vres[i] = s2;
+ }
+ else
+ {
+ m_vres[i] = s1;
+ }
+
+ if ((s1 - s2) != 0 && s1 != ~s2)
+ {
+ SET_ZERO_FLAG(i);
+ }
+ }
+ if (vce)
+ {
+ SET_CLIP1_FLAG(i);
+ }
+ SET_ACCUM_L(m_vres[i], i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vch(void *param)
+{
+ ((rsp_cop2 *)param)->vch();
+}
+
+
+// VCR
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 |
+// ------------------------------------------------------
+//
+// Vector clip reverse
+
+inline void rsp_cop2_simd::vcr()
+{
+ int op = m_op;
+
+ CLEAR_CARRY_FLAGS();
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP1_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 s1, s2;
+ GET_VS1(s1, i);
+ GET_VS2(s2, i);
+
+ if ((INT16)(s1 ^ s2) < 0)
+ {
+ if (s2 < 0)
+ {
+ SET_CLIP2_FLAG(i);
+ }
+ if ((s1 + s2) <= 0)
+ {
+ SET_ACCUM_L(~((UINT16)s2), i);
+ SET_COMPARE_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+ else
+ {
+ if (s2 < 0)
+ {
+ SET_COMPARE_FLAG(i);
+ }
+ if ((s1 - s2) >= 0)
+ {
+ SET_ACCUM_L(s2, i);
+ SET_CLIP2_FLAG(i);
+ }
+ else
+ {
+ SET_ACCUM_L(s1, i);
+ }
+ }
+
+ m_vres[i] = ACCUM_L(i);
+ }
+ WRITEBACK_RESULT();
+}
+
+static void cfunc_vcr(void *param)
+{
+ ((rsp_cop2 *)param)->vcr();
+}
+
+
+// VMRG
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100111 |
+// ------------------------------------------------------
+//
+// Merges two vectors according to compare flags
+
+inline void rsp_cop2_simd::vmrg()
+{
+ int op = m_op;
+
+ __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ __m128i s2mask = _mm_cmpeq_epi16(m_xvflag[COMPARE], _mm_setzero_si128());
+ __m128i s1mask = _mm_xor_si128(s2mask, vec_neg1);
+ __m128i result = _mm_and_si128(m_xv[VS1REG], s1mask);
+ m_xv[VDREG] = _mm_or_si128(result, _mm_and_si128(shuf, s2mask));
+ m_accum_l = m_xv[VDREG];
+}
+
+static void cfunc_vmrg(void *param)
+{
+ ((rsp_cop2 *)param)->vmrg();
+}
+
+
+// VAND
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 |
+// ------------------------------------------------------
+//
+// Bitwise AND of two vector registers
+
+inline void rsp_cop2_simd::vand()
+{
+ int op = m_op;
+
+ __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ m_accum_l = m_xv[VDREG] = _mm_and_si128(m_xv[VS1REG], shuf);
+}
+
+static void cfunc_vand(void *param)
+{
+ ((rsp_cop2 *)param)->vand();
+}
+
+
+// VNAND
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101001 |
+// ------------------------------------------------------
+//
+// Bitwise NOT AND of two vector registers
+
+inline void rsp_cop2_simd::vnand()
+{
+ int op = m_op;
+
+ __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ m_accum_l = m_xv[VDREG] = _mm_xor_si128(_mm_and_si128(m_xv[VS1REG], shuf), vec_neg1);
+}
+
+static void cfunc_vnand(void *param)
+{
+ ((rsp_cop2 *)param)->vnand();
+}
+
+
+// VOR
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101010 |
+// ------------------------------------------------------
+//
+// Bitwise OR of two vector registers
+
+inline void rsp_cop2_simd::vor()
+{
+ int op = m_op;
+
+ __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ m_accum_l = m_xv[VDREG] = _mm_or_si128(m_xv[VS1REG], shuf);
+}
+
+static void cfunc_vor_simd(void *param)
+{
+ ((rsp_cop2 *)param)->vor();
+}
+
+
+// VNOR
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101011 |
+// ------------------------------------------------------
+//
+// Bitwise NOT OR of two vector registers
+
+inline void rsp_cop2_simd::vnor()
+{
+ int op = m_op;
+
+ __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ m_accum_l = m_xv[VDREG] = _mm_xor_si128(_mm_or_si128(m_xv[VS1REG], shuf), vec_neg1);
+}
+
+static void cfunc_vnor(void *param)
+{
+ ((rsp_cop2 *)param)->vnor();
+}
+
+
+// VXOR
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101100 |
+// ------------------------------------------------------
+//
+// Bitwise XOR of two vector registers
+
+inline void rsp_cop2_simd::vxor()
+{
+ int op = m_op;
+
+ __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ m_accum_l = m_xv[VDREG] = _mm_xor_si128(m_xv[VS1REG], shuf);
+}
+
+static void cfunc_vxor(void *param)
+{
+ ((rsp_cop2 *)param)->vxor();
+}
+
+
+// VNXOR
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 |
+// ------------------------------------------------------
+//
+// Bitwise NOT XOR of two vector registers
+
+inline void rsp_cop2_simd::vnxor()
+{
+ int op = m_op;
+
+ __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+ m_accum_l = m_xv[VDREG] = _mm_xor_si128(_mm_xor_si128(m_xv[VS1REG], shuf), vec_neg1);
+}
+
+static void cfunc_vnxor(void *param)
+{
+ ((rsp_cop2 *)param)->vnxor();
+}
+
+
+// VRCP
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal
+
+inline void rsp_cop2_simd::vrcp()
+{
+ int op = m_op;
+
+ INT32 shifter = 0;
+ UINT16 urec;
+ INT32 rec;
+ EXTRACT16(m_xv[VS2REG], urec, EL);
+ rec = (INT16)urec;
+ INT32 datainput = (rec < 0) ? (-rec) : rec;
+ if (datainput)
+ {
+ for (int i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+ else
+ {
+ shifter = 0x10;
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
+ if (rec < 0)
+ {
+ temp = ~temp;
+ }
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ m_reciprocal_res = rec;
+ m_dp_allowed = 0;
+
+ INSERT16(m_xv[VDREG], (UINT16)rec, VS1REG);
+ m_accum_l = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+}
+
+static void cfunc_vrcp(void *param)
+{
+ ((rsp_cop2 *)param)->vrcp();
+}
+
+
+// VRCPL
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal low part
+
+inline void rsp_cop2_simd::vrcpl()
+{
+ int op = m_op;
+
+#if SIMUL_SIMD
+ m_old_reciprocal_res = m_reciprocal_res;
+ m_old_reciprocal_high = m_reciprocal_high;
+ m_old_dp_allowed = m_dp_allowed;
+#endif
+
+ INT32 shifter = 0;
+
+ UINT16 urec;
+ EXTRACT16(m_xv[VS2REG], urec, EL);
+ INT32 rec = (INT16)urec;
+ INT32 datainput = rec;
+
+ if (m_dp_allowed)
+ {
+ rec = (rec & 0x0000ffff) | m_reciprocal_high;
+ datainput = rec;
+
+ if (rec < 0)
+ {
+ if (rec < -32768)
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+ }
+ else if (datainput < 0)
+ {
+ datainput = -datainput;
+
+ shifter = 0x10;
+ }
+
+ if (datainput)
+ {
+ for (int i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+
+ INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ INT32 fetchval = rsp_divtable[address];
+ INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
+ temp ^= rec >> 31;
+
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ m_reciprocal_res = rec;
+ m_dp_allowed = 0;
+
+ INSERT16(m_xv[VDREG], (UINT16)rec, VS1REG);
+
+ for (int i = 0; i < 8; i++)
+ {
+ INT16 val;
+ EXTRACT16(m_xv[VS2REG], val, VEC_EL_2(EL, i));
+ SET_ACCUM_L(val, i);
+ }
+}
+
+static void cfunc_vrcpl(void *param)
+{
+ ((rsp_cop2 *)param)->vrcpl();
+}
+
+
+// VRCPH
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal high part
+
+inline void rsp_cop2_simd::vrcph()
+{
+ int op = m_op;
+
+#if SIMUL_SIMD
+ m_old_reciprocal_res = m_reciprocal_res;
+ m_old_reciprocal_high = m_reciprocal_high;
+ m_old_dp_allowed = m_dp_allowed;
+#endif
+
+ UINT16 rcph;
+ EXTRACT16(m_xv[VS2REG], rcph, EL);
+ m_reciprocal_high = rcph << 16;
+ m_dp_allowed = 1;
+
+ m_accum_l = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+
+ INSERT16(m_xv[VDREG], (INT16)(m_reciprocal_res >> 16), VS1REG);
+}
+
+static void cfunc_vrcph(void *param)
+{
+ ((rsp_cop2 *)param)->vrcph();
+}
+
+
+// VMOV
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110011 |
+// ------------------------------------------------------
+//
+// Moves element from vector to destination vector
+
+inline void rsp_cop2_simd::vmov()
+{
+ int op = m_op;
+
+ INT16 val;
+ EXTRACT16(m_xv[VS2REG], val, EL);
+ INSERT16(m_xv[VDREG], val, VS1REG);
+ m_accum_l = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+}
+
+static void cfunc_vmov(void *param)
+{
+ ((rsp_cop2 *)param)->vmov();
+}
+
+
+// VRSQ
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal square-root
+
+inline void rsp_cop2_simd::vrsq()
+{
+ int op = m_op;
+
+ 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_vrsq(void *param)
+{
+ ((rsp_cop2 *)param)->vrsq();
+}
+
+
+// VRSQL
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal square-root low part
+
+inline void rsp_cop2_simd::vrsql()
+{
+ int op = m_op;
+
+#if SIMUL_SIMD
+ m_old_reciprocal_res = m_reciprocal_res;
+ m_old_reciprocal_high = m_reciprocal_high;
+ m_old_dp_allowed = m_dp_allowed;
+#endif
+
+ INT32 shifter = 0;
+ UINT16 val;
+ EXTRACT16(m_xv[VS2REG], val, EL);
+ INT32 rec = (INT16)val;
+ INT32 datainput = rec;
+
+ if (m_dp_allowed)
+ {
+ rec = (rec & 0x0000ffff) | m_reciprocal_high;
+ datainput = rec;
+
+ if (rec < 0)
+ {
+ if (rec < -32768)
+ {
+ datainput = ~datainput;
+ }
+ else
+ {
+ datainput = -datainput;
+ }
+ }
+ }
+ else if (datainput < 0)
+ {
+ datainput = -datainput;
+
+ shifter = 0x10;
+ }
+
+ if (datainput)
+ {
+ for (int i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+ }
+
+ 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);
+ temp ^= rec >> 31;
+
+ if (!rec)
+ {
+ temp = 0x7fffffff;
+ }
+ else if (rec == 0xffff8000)
+ {
+ temp = 0xffff0000;
+ }
+ rec = temp;
+
+ m_reciprocal_res = rec;
+ m_dp_allowed = 0;
+
+ INSERT16(m_xv[VDREG], (UINT16)rec, VS1REG);
+ m_accum_l = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+}
+
+static void cfunc_vrsql(void *param)
+{
+ ((rsp_cop2 *)param)->vrsql();
+}
+
+
+// VRSQH
+//
+// 31 25 24 20 15 10 5 0
+// ------------------------------------------------------
+// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110110 |
+// ------------------------------------------------------
+//
+// Calculates reciprocal square-root high part
+
+inline void rsp_cop2_simd::vrsqh()
+{
+ int op = m_op;
+
+#if SIMUL_SIMD
+ m_old_reciprocal_res = m_reciprocal_res;
+ m_old_reciprocal_high = m_reciprocal_high;
+ m_old_dp_allowed = m_dp_allowed;
+#endif
+
+ UINT16 val;
+ EXTRACT16(m_xv[VS2REG], val, EL);
+ m_reciprocal_high = val << 16;
+ m_dp_allowed = 1;
+
+ m_accum_l = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
+
+ INSERT16(m_xv[VDREG], (INT16)(m_reciprocal_res >> 16), VS1REG); // store high part
+}
+
+static void cfunc_vrsqh(void *param)
+{
+ ((rsp_cop2 *)param)->vrsqh();
+}
+
+
+/***************************************************************************
+ Vector Flag Reading/Writing
+***************************************************************************/
+
+inline void rsp_cop2_simd::mfc2()
+{
+ UINT32 op = m_op;
+ int el = (op >> 7) & 0xf;
+
+ UINT16 out;
+ EXTRACT16(m_xv[VS1REG], out, (el >> 1));
+ out >>= (1 - (el & 1)) * 8;
+ out &= 0x00ff;
+
+ el++;
+
+ UINT16 temp;
+ EXTRACT16(m_xv[VS1REG], temp, (el >> 1));
+ temp >>= (1 - (el & 1)) * 8;
+ temp &= 0x00ff;
+
+ m_rsp.m_rsp_state->r[RTREG] = (INT32)(INT16)((out << 8) | temp);
+}
+
+static void cfunc_mfc2(void *param)
+{
+ ((rsp_cop2 *)param)->mfc2();
+}
+
+
+inline void rsp_cop2_simd::cfc2()
+{
+ UINT32 op = m_op;
+ if (RTREG)
+ {
+ switch(RDREG)
+ {
+ case 0:
+ RTVAL = ((CARRY_FLAG(0) & 1) << 0) |
+ ((CARRY_FLAG(1) & 1) << 1) |
+ ((CARRY_FLAG(2) & 1) << 2) |
+ ((CARRY_FLAG(3) & 1) << 3) |
+ ((CARRY_FLAG(4) & 1) << 4) |
+ ((CARRY_FLAG(5) & 1) << 5) |
+ ((CARRY_FLAG(6) & 1) << 6) |
+ ((CARRY_FLAG(7) & 1) << 7) |
+ ((ZERO_FLAG(0) & 1) << 8) |
+ ((ZERO_FLAG(1) & 1) << 9) |
+ ((ZERO_FLAG(2) & 1) << 10) |
+ ((ZERO_FLAG(3) & 1) << 11) |
+ ((ZERO_FLAG(4) & 1) << 12) |
+ ((ZERO_FLAG(5) & 1) << 13) |
+ ((ZERO_FLAG(6) & 1) << 14) |
+ ((ZERO_FLAG(7) & 1) << 15);
+ if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
+ break;
+ case 1:
+ RTVAL = ((COMPARE_FLAG(0) & 1) << 0) |
+ ((COMPARE_FLAG(1) & 1) << 1) |
+ ((COMPARE_FLAG(2) & 1) << 2) |
+ ((COMPARE_FLAG(3) & 1) << 3) |
+ ((COMPARE_FLAG(4) & 1) << 4) |
+ ((COMPARE_FLAG(5) & 1) << 5) |
+ ((COMPARE_FLAG(6) & 1) << 6) |
+ ((COMPARE_FLAG(7) & 1) << 7) |
+ ((CLIP2_FLAG(0) & 1) << 8) |
+ ((CLIP2_FLAG(1) & 1) << 9) |
+ ((CLIP2_FLAG(2) & 1) << 10) |
+ ((CLIP2_FLAG(3) & 1) << 11) |
+ ((CLIP2_FLAG(4) & 1) << 12) |
+ ((CLIP2_FLAG(5) & 1) << 13) |
+ ((CLIP2_FLAG(6) & 1) << 14) |
+ ((CLIP2_FLAG(7) & 1) << 15);
+ if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
+ break;
+ case 2:
+ RTVAL = ((CLIP1_FLAG(0) & 1) << 0) |
+ ((CLIP1_FLAG(1) & 1) << 1) |
+ ((CLIP1_FLAG(2) & 1) << 2) |
+ ((CLIP1_FLAG(3) & 1) << 3) |
+ ((CLIP1_FLAG(4) & 1) << 4) |
+ ((CLIP1_FLAG(5) & 1) << 5) |
+ ((CLIP1_FLAG(6) & 1) << 6) |
+ ((CLIP1_FLAG(7) & 1) << 7);
+ break;
+ }
+ }
+}
+
+static void cfunc_cfc2(void *param)
+{
+ ((rsp_cop2 *)param)->cfc2();
+}
+
+
+inline void rsp_cop2_simd::mtc2()
+{
+ UINT32 op = m_op;
+ int el = (op >> 7) & 0xf;
+ INSERT16(m_xv[VS1REG], RTVAL, el >> 1);
+}
+
+static void cfunc_mtc2(void *param)
+{
+ ((rsp_cop2 *)param)->mtc2();
+}
+
+
+inline void rsp_cop2_simd::ctc2()
+{
+ UINT32 op = m_op;
+ switch(RDREG)
+ {
+ case 0:
+ CLEAR_CARRY_FLAGS();
+ CLEAR_ZERO_FLAGS();
+ m_vflag[0][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
+ m_vflag[0][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
+ m_vflag[0][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
+ m_vflag[0][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
+ m_vflag[0][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
+ m_vflag[0][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
+ m_vflag[0][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
+ m_vflag[0][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 0)) { SET_CARRY_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_CARRY_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_CARRY_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_CARRY_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_CARRY_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_CARRY_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_CARRY_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_CARRY_FLAG(7); }
+ m_vflag[3][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0;
+ m_vflag[3][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0;
+ m_vflag[3][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0;
+ m_vflag[3][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0;
+ m_vflag[3][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0;
+ m_vflag[3][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0;
+ m_vflag[3][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0;
+ m_vflag[3][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 8)) { SET_ZERO_FLAG(0); }
+ if (RTVAL & (1 << 9)) { SET_ZERO_FLAG(1); }
+ if (RTVAL & (1 << 10)) { SET_ZERO_FLAG(2); }
+ if (RTVAL & (1 << 11)) { SET_ZERO_FLAG(3); }
+ if (RTVAL & (1 << 12)) { SET_ZERO_FLAG(4); }
+ if (RTVAL & (1 << 13)) { SET_ZERO_FLAG(5); }
+ if (RTVAL & (1 << 14)) { SET_ZERO_FLAG(6); }
+ if (RTVAL & (1 << 15)) { SET_ZERO_FLAG(7); }
+ break;
+ case 1:
+ CLEAR_COMPARE_FLAGS();
+ CLEAR_CLIP2_FLAGS();
+ m_vflag[1][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
+ m_vflag[1][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
+ m_vflag[1][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
+ m_vflag[1][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
+ m_vflag[1][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
+ m_vflag[1][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
+ m_vflag[1][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
+ m_vflag[1][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 0)) { SET_COMPARE_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_COMPARE_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_COMPARE_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_COMPARE_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_COMPARE_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_COMPARE_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_COMPARE_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_COMPARE_FLAG(7); }
+ m_vflag[4][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0;
+ m_vflag[4][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0;
+ m_vflag[4][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0;
+ m_vflag[4][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0;
+ m_vflag[4][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0;
+ m_vflag[4][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0;
+ m_vflag[4][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0;
+ m_vflag[4][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 8)) { SET_CLIP2_FLAG(0); }
+ if (RTVAL & (1 << 9)) { SET_CLIP2_FLAG(1); }
+ if (RTVAL & (1 << 10)) { SET_CLIP2_FLAG(2); }
+ if (RTVAL & (1 << 11)) { SET_CLIP2_FLAG(3); }
+ if (RTVAL & (1 << 12)) { SET_CLIP2_FLAG(4); }
+ if (RTVAL & (1 << 13)) { SET_CLIP2_FLAG(5); }
+ if (RTVAL & (1 << 14)) { SET_CLIP2_FLAG(6); }
+ if (RTVAL & (1 << 15)) { SET_CLIP2_FLAG(7); }
+ break;
+ case 2:
+ CLEAR_CLIP1_FLAGS();
+ m_vflag[2][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
+ m_vflag[2][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
+ m_vflag[2][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
+ m_vflag[2][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
+ m_vflag[2][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
+ m_vflag[2][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
+ m_vflag[2][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
+ m_vflag[2][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
+ if (RTVAL & (1 << 0)) { SET_CLIP1_FLAG(0); }
+ if (RTVAL & (1 << 1)) { SET_CLIP1_FLAG(1); }
+ if (RTVAL & (1 << 2)) { SET_CLIP1_FLAG(2); }
+ if (RTVAL & (1 << 3)) { SET_CLIP1_FLAG(3); }
+ if (RTVAL & (1 << 4)) { SET_CLIP1_FLAG(4); }
+ if (RTVAL & (1 << 5)) { SET_CLIP1_FLAG(5); }
+ if (RTVAL & (1 << 6)) { SET_CLIP1_FLAG(6); }
+ if (RTVAL & (1 << 7)) { SET_CLIP1_FLAG(7); }
+ break;
+ }
+}
+
+static void cfunc_ctc2(void *param)
+{
+ ((rsp_cop2 *)param)->ctc2();
+}
+
+
+/***************************************************************************
+ COP2 Opcode Compilation
+***************************************************************************/
+
+int rsp_cop2_simd::generate_cop2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = desc->opptr.l[0];
+ UINT8 opswitch = RSREG;
+
+ switch (opswitch)
+ {
+ case 0x00: /* MFCz */
+ if (RTREG != 0)
+ {
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_mfc2, this); // callc mfc2
+ }
+ return TRUE;
+
+ case 0x02: /* CFCz */
+ if (RTREG != 0)
+ {
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_cfc2, this); // callc cfc2
+ }
+ return TRUE;
+
+ case 0x04: /* MTCz */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_mtc2, this); // callc mtc2
+ return TRUE;
+
+ case 0x06: /* CTCz */
+ UML_MOV(block, mem(&m_op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
+ UML_CALLC(block, cfunc_ctc2, this); // callc ctc2
+ return TRUE;
+
+ case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ return generate_vector_opcode(block, compiler, desc);
+ }
+ return FALSE;
+}
diff --git a/src/emu/cpu/rsp/rspcp2s.h b/src/emu/cpu/rsp/rspcp2s.h
new file mode 100644
index 00000000000..4c0e5d9a557
--- /dev/null
+++ b/src/emu/cpu/rsp/rspcp2s.h
@@ -0,0 +1,158 @@
+/***************************************************************************
+
+ rspcp2s.h
+
+ Interface file for Reality Signal Processor (RSP) vector extensions
+ using SSSE3 SIMD acceleration.
+
+ Copyright the MESS team
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __RSPCP2S_H__
+#define __RSPCP2S_H__
+
+#include "cpu/drcuml.h"
+#include "rsp.h"
+#include "rspcp2.h"
+
+#include <tmmintrin.h>
+
+class rsp_cop2_simd : public rsp_cop2_drc
+{
+ friend class rsp_device;
+
+ rsp_cop2_simd(rsp_device &rsp, running_machine &machine);
+
+ virtual int generate_cop2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc);
+ virtual int generate_lwc2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc);
+ virtual int generate_swc2(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc);
+
+ virtual void state_string_export(const int index, astring &string);
+
+public:
+ virtual void lbv();
+ virtual void lsv();
+ virtual void llv();
+ virtual void ldv();
+ virtual void lqv();
+ virtual void lrv();
+ virtual void lpv();
+ virtual void luv();
+ virtual void lhv();
+ virtual void lfv();
+ virtual void lwv();
+ virtual void ltv();
+ virtual void sbv();
+ virtual void ssv();
+ virtual void slv();
+ virtual void sdv();
+ virtual void sqv();
+ virtual void srv();
+ virtual void spv();
+ virtual void suv();
+ virtual void shv();
+ virtual void sfv();
+ virtual void swv();
+ virtual void stv();
+ virtual void vmulf();
+ virtual void vmulu();
+ virtual void vmudl();
+ virtual void vmudm();
+ virtual void vmudn();
+ virtual void vmudh();
+ virtual void vmacf();
+ virtual void vmacu();
+ virtual void vmadl();
+ virtual void vmadm();
+ virtual void vmadn();
+ virtual void vmadh();
+ virtual void vadd();
+ virtual void vsub();
+ virtual void vabs();
+ virtual void vaddc();
+ virtual void vsubc();
+ virtual void vaddb();
+ virtual void vsaw();
+ virtual void vlt();
+ virtual void veq();
+ virtual void vne();
+ virtual void vge();
+ virtual void vcl();
+ virtual void vch();
+ virtual void vcr();
+ virtual void vmrg();
+ virtual void vand();
+ virtual void vnand();
+ virtual void vor();
+ virtual void vnor();
+ virtual void vxor();
+ virtual void vnxor();
+ virtual void vrcp();
+ virtual void vrcpl();
+ virtual void vrcph();
+ virtual void vmov();
+ virtual void vrsql();
+ virtual void vrsqh();
+ virtual void vrsq();
+ virtual void mfc2();
+ virtual void cfc2();
+ virtual void mtc2();
+ virtual void ctc2();
+
+#if SIMUL_SIMD
+ void backup_regs();
+ void restore_regs();
+ void verify_regs();
+#endif
+
+private:
+ virtual int generate_vector_opcode(drcuml_block *block, rsp_device::compiler_state *compiler, const opcode_desc *desc);
+
+ UINT16 ACCUM_H(int x);
+ UINT16 ACCUM_M(int x);
+ UINT16 ACCUM_L(int x);
+ UINT16 ACCUM_LL(int x);
+ UINT16 CARRY_FLAG(const int x);
+ UINT16 COMPARE_FLAG(const int x);
+ UINT16 CLIP1_FLAG(const int x);
+ UINT16 ZERO_FLAG(const int x);
+ UINT16 CLIP2_FLAG(const int x);
+ UINT16 SATURATE_ACCUM(int accum, int slice, UINT16 negative, UINT16 positive);
+
+ __m128i m_accum_h;
+ __m128i m_accum_m;
+ __m128i m_accum_l;
+ __m128i m_accum_ll;
+
+ // Mirror of v[] for now, to be used in parallel as
+ // more vector ops are transitioned over
+ __m128i m_xv[32];
+ __m128i m_xvflag[6];
+
+#if SIMUL_SIMD
+ UINT32 m_old_r[35];
+ UINT8 m_old_dmem[4096];
+
+ UINT32 m_scalar_r[35];
+ UINT8 m_scalar_dmem[4096];
+
+ INT32 m_old_reciprocal_res;
+ UINT32 m_old_reciprocal_high;
+ INT32 m_old_dp_allowed;
+
+ INT32 m_scalar_reciprocal_res;
+ UINT32 m_scalar_reciprocal_high;
+ INT32 m_scalar_dp_allowed;
+
+ INT32 m_simd_reciprocal_res;
+ UINT32 m_simd_reciprocal_high;
+ INT32 m_simd_dp_allowed;
+#endif
+};
+
+#endif /* __RSPCP2S_H__ */ \ No newline at end of file
diff --git a/src/emu/cpu/rsp/rspdrc.c b/src/emu/cpu/rsp/rspdrc.c
index 95d71ce48a5..fb999a809a7 100644
--- a/src/emu/cpu/rsp/rspdrc.c
+++ b/src/emu/cpu/rsp/rspdrc.c
@@ -25,6 +25,7 @@
#include "rsp.h"
#include "rspdiv.h"
#include "rspfe.h"
+#include "rspcp2.h"
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
#include "cpu/drcumlsh.h"
@@ -52,213 +53,13 @@ extern offs_t rsp_dasm_one(char *buffer, offs_t pc, UINT32 op);
/***************************************************************************
- MACROS
+ Macros
***************************************************************************/
#define R32(reg) m_regmap[reg]
/***************************************************************************
- HELPFUL DEFINES
-***************************************************************************/
-
-#define VDREG ((op >> 6) & 0x1f)
-#define VS1REG ((op >> 11) & 0x1f)
-#define VS2REG ((op >> 16) & 0x1f)
-#define EL ((op >> 21) & 0xf)
-
-#define SIMD_EXTRACT16(reg, value, element) \
- switch((element) & 7) \
- { \
- case 0: value = _mm_extract_epi16(reg, 0); break; \
- case 1: value = _mm_extract_epi16(reg, 1); break; \
- case 2: value = _mm_extract_epi16(reg, 2); break; \
- case 3: value = _mm_extract_epi16(reg, 3); break; \
- case 4: value = _mm_extract_epi16(reg, 4); break; \
- case 5: value = _mm_extract_epi16(reg, 5); break; \
- case 6: value = _mm_extract_epi16(reg, 6); break; \
- case 7: value = _mm_extract_epi16(reg, 7); break; \
- }
-
-
-#define SIMD_INSERT16(reg, value, element) \
- switch((element) & 7) \
- { \
- case 0: reg = _mm_insert_epi16(reg, value, 0); break; \
- case 1: reg = _mm_insert_epi16(reg, value, 1); break; \
- case 2: reg = _mm_insert_epi16(reg, value, 2); break; \
- case 3: reg = _mm_insert_epi16(reg, value, 3); break; \
- case 4: reg = _mm_insert_epi16(reg, value, 4); break; \
- case 5: reg = _mm_insert_epi16(reg, value, 5); break; \
- case 6: reg = _mm_insert_epi16(reg, value, 6); break; \
- case 7: reg = _mm_insert_epi16(reg, value, 7); break; \
- }
-
-
-#define SIMD_EXTRACT16C(reg, value, element) value = _mm_extract_epi16(reg, element);
-#define SIMD_INSERT16C(reg, value, element) reg = _mm_insert_epi16(reg, value, element);
-
-#define VREG_B(reg, offset) m_v[(reg)].b[(offset)^1]
-#define W_VREG_S(reg, offset) m_v[(reg)].s[(offset)]
-#define VREG_S(reg, offset) (INT16)m_v[(reg)].s[(offset)]
-
-#define VEC_EL_2(x,z) (vector_elements_2[(x)][(z)])
-
-#define ACCUM(x) m_accum[x].q
-
-#define CARRY 0
-#define COMPARE 1
-#define CLIP1 2
-#define ZERO 3
-#define CLIP2 4
-
-
-#if USE_SIMD
-static void cfunc_mfc2_simd(void *param);
-static void cfunc_cfc2_simd(void *param);
-static void cfunc_mtc2_simd(void *param);
-static void cfunc_ctc2_simd(void *param);
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-static void cfunc_mfc2_scalar(void *param);
-static void cfunc_cfc2_scalar(void *param);
-static void cfunc_mtc2_scalar(void *param);
-static void cfunc_ctc2_scalar(void *param);
-#endif
-
-
-#if USE_SIMD
-inline UINT16 rsp_device::VEC_ACCUM_H(int x)
-{
- UINT16 out;
- SIMD_EXTRACT16(m_accum_h, out, x);
- return out;
-}
-
-inline UINT16 rsp_device::VEC_ACCUM_M(int x)
-{
- UINT16 out;
- SIMD_EXTRACT16(m_accum_m, out, x);
- return out;
-}
-
-inline UINT16 rsp_device::VEC_ACCUM_L(int x)
-{
- UINT16 out;
- SIMD_EXTRACT16(m_accum_l, out, x);
- return out;
-}
-
-inline UINT16 rsp_device::VEC_ACCUM_LL(int x)
-{
- UINT16 out;
- SIMD_EXTRACT16(m_accum_ll, out, x);
- return out;
-}
-
-#define VEC_SET_ACCUM_H(v, x) SIMD_INSERT16(m_accum_h, v, x);
-#define VEC_SET_ACCUM_M(v, x) SIMD_INSERT16(m_>accum_m, v, x);
-#define VEC_SET_ACCUM_L(v, x) SIMD_INSERT16(m_accum_l, v, x);
-#define VEC_SET_ACCUM_LL(v, x) SIMD_INSERT16(m_accum_ll, v, x);
-
-#define VEC_GET_SCALAR_VS1(out, i) SIMD_EXTRACT16(m_xv[VS1REG], out, i);
-#define VEC_GET_SCALAR_VS2(out, i) SIMD_EXTRACT16(m_xv[VS2REG], out, VEC_EL_2(EL, i));
-
-inline UINT16 rsp_device::VEC_CARRY_FLAG(const int x)
-{
- UINT16 out;
- SIMD_EXTRACT16(m_xvflag[CARRY], out, x);
- return out;
-}
-
-inline UINT16 rsp_device::VEC_COMPARE_FLAG(const int x)
-{
- UINT16 out;
- SIMD_EXTRACT16(m_xvflag[COMPARE], out, x);
- return out;
-}
-
-inline UINT16 rsp_device::VEC_CLIP1_FLAG(const int x)
-{
- UINT16 out;
- SIMD_EXTRACT16(m_xvflag[CLIP1], out, x);
- return out;
-}
-
-inline UINT16 rsp_device::VEC_ZERO_FLAG(const int x)
-{
- UINT16 out;
- SIMD_EXTRACT16(m_xvflag[ZERO], out, x);
- return out;
-}
-
-inline UINT16 rsp_device::VEC_CLIP2_FLAG(const int x)
-{
- UINT16 out;
- SIMD_EXTRACT16(m_xvflag[CLIP2], out, x);
- return out;
-}
-
-#define VEC_CLEAR_CARRY_FLAGS() { m_xvflag[CARRY] = _mm_setzero_si128(); }
-#define VEC_CLEAR_COMPARE_FLAGS() { m_xvflag[COMPARE] = _mm_setzero_si128(); }
-#define VEC_CLEAR_CLIP1_FLAGS() { m_xvflag[CLIP1] = _mm_setzero_si128(); }
-#define VEC_CLEAR_ZERO_FLAGS() { m_xvflag[ZERO] = _mm_setzero_si128(); }
-#define VEC_CLEAR_CLIP2_FLAGS() { m_xvflag[CLIP2] = _mm_setzero_si128(); }
-
-#define VEC_SET_CARRY_FLAG(x) { SIMD_INSERT16(m_xvflag[CARRY], 0xffff, x); }
-#define VEC_SET_COMPARE_FLAG(x) { SIMD_INSERT16(m_xvflag[COMPARE], 0xffff, x); }
-#define VEC_SET_CLIP1_FLAG(x) { SIMD_INSERT16(m_xvflag[CLIP1], 0xffff, x); }
-#define VEC_SET_ZERO_FLAG(x) { SIMD_INSERT16(m_xvflag[ZERO], 0xffff, x); }
-#define VEC_SET_CLIP2_FLAG(x) { SIMD_INSERT16(m_xvflag[CLIP2], 0xffff, x); }
-
-#define VEC_CLEAR_CARRY_FLAG(x) { SIMD_INSERT16(m_xvflag[CARRY], 0, x); }
-#define VEC_CLEAR_COMPARE_FLAG(x) { SIMD_INSERT16(m_xvflag[COMPARE], 0, x); }
-#define VEC_CLEAR_CLIP1_FLAG(x) { SIMD_INSERT16(m_xvflag[CLIP1], 0, x); }
-#define VEC_CLEAR_ZERO_FLAG(x) { SIMD_INSERT16(m_xvflag[ZERO], 0, x); }
-#define VEC_CLEAR_CLIP2_FLAG(x) { SIMD_INSERT16(m_xvflag[CLIP2], 0, x); }
-
-#endif
-
-#define ACCUM_H(x) (UINT16)m_accum[x].w[3]
-#define ACCUM_M(x) (UINT16)m_accum[x].w[2]
-#define ACCUM_L(x) (UINT16)m_accum[x].w[1]
-#define ACCUM_LL(x) (UINT16)m_accum[x].w[0]
-
-#define SET_ACCUM_H(v, x) m_accum[x].w[3] = v;
-#define SET_ACCUM_M(v, x) m_accum[x].w[2] = v;
-#define SET_ACCUM_L(v, x) m_accum[x].w[1] = v;
-#define SET_ACCUM_LL(v, x) m_accum[x].w[0] = v;
-
-#define SCALAR_GET_VS1(out, i) out = VREG_S(VS1REG, i)
-#define SCALAR_GET_VS2(out, i) out = VREG_S(VS2REG, VEC_EL_2(EL, i))
-
-#define CARRY_FLAG(x) (m_vflag[CARRY][x & 7] != 0 ? 0xffff : 0)
-#define COMPARE_FLAG(x) (m_vflag[COMPARE][x & 7] != 0 ? 0xffff : 0)
-#define CLIP1_FLAG(x) (m_vflag[CLIP1][x & 7] != 0 ? 0xffff : 0)
-#define ZERO_FLAG(x) (m_vflag[ZERO][x & 7] != 0 ? 0xffff : 0)
-#define CLIP2_FLAG(x) (m_vflag[CLIP2][x & 7] != 0 ? 0xffff : 0)
-
-#define CLEAR_CARRY_FLAGS() { memset(m_vflag[CARRY], 0, 16); }
-#define CLEAR_COMPARE_FLAGS() { memset(m_vflag[COMPARE], 0, 16); }
-#define CLEAR_CLIP1_FLAGS() { memset(m_vflag[CLIP1], 0, 16); }
-#define CLEAR_ZERO_FLAGS() { memset(m_vflag[ZERO], 0, 16); }
-#define CLEAR_CLIP2_FLAGS() { memset(m_vflag[CLIP2], 0, 16); }
-
-#define SET_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0xffff; }
-#define SET_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0xffff; }
-#define SET_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0xffff; }
-#define SET_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0xffff; }
-#define SET_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0xffff; }
-
-#define CLEAR_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0; }
-#define CLEAR_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0; }
-#define CLEAR_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0; }
-#define CLEAR_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0; }
-#define CLEAR_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0; }
-
-
-/***************************************************************************
- INLINE FUNCTIONS
+ Inline Functions
***************************************************************************/
/*-------------------------------------------------
@@ -331,9 +132,10 @@ void rsp_device::rspdrc_add_dmem(UINT32 *base)
m_dmem8 = (UINT8*)base;
}
-inline UINT8 rsp_device::DM_READ8(UINT32 address)
+UINT8 rsp_device::DM_READ8(UINT32 address)
{
UINT8 ret = m_dmem8[BYTE4_XOR_BE(address & 0xfff)];
+ //printf("R8:%08x=%02x\n", address, ret);
return ret;
}
@@ -347,12 +149,13 @@ static void cfunc_read8(void *param)
((rsp_device *)param)->ccfunc_read8();
}
-inline UINT16 rsp_device::DM_READ16(UINT32 address)
+UINT16 rsp_device::DM_READ16(UINT32 address)
{
UINT16 ret;
address &= 0xfff;
ret = m_dmem8[BYTE4_XOR_BE(address)] << 8;
ret |= m_dmem8[BYTE4_XOR_BE(address + 1)];
+ //printf("R16:%08x=%04x\n", address, ret);
return ret;
}
@@ -366,7 +169,7 @@ static void cfunc_read16(void *param)
((rsp_device *)param)->ccfunc_read16();
}
-inline UINT32 rsp_device::DM_READ32(UINT32 address)
+UINT32 rsp_device::DM_READ32(UINT32 address)
{
UINT32 ret;
address &= 0xfff;
@@ -374,6 +177,7 @@ inline UINT32 rsp_device::DM_READ32(UINT32 address)
ret |= m_dmem8[BYTE4_XOR_BE(address + 1)] << 16;
ret |= m_dmem8[BYTE4_XOR_BE(address + 2)] << 8;
ret |= m_dmem8[BYTE4_XOR_BE(address + 3)];
+ //printf("R32:%08x=%08x\n", address, ret);
return ret;
}
@@ -387,10 +191,11 @@ static void cfunc_read32(void *param)
((rsp_device *)param)->ccfunc_read32();;
}
-inline void rsp_device::DM_WRITE8(UINT32 address, UINT8 data)
+void rsp_device::DM_WRITE8(UINT32 address, UINT8 data)
{
address &= 0xfff;
m_dmem8[BYTE4_XOR_BE(address)] = data;
+ //printf("W8:%08x=%02x\n", address, data);
}
inline void rsp_device::ccfunc_write8()
@@ -403,11 +208,12 @@ static void cfunc_write8(void *param)
((rsp_device *)param)->ccfunc_write8();;
}
-inline void rsp_device::DM_WRITE16(UINT32 address, UINT16 data)
+void rsp_device::DM_WRITE16(UINT32 address, UINT16 data)
{
address &= 0xfff;
m_dmem8[BYTE4_XOR_BE(address)] = data >> 8;
m_dmem8[BYTE4_XOR_BE(address + 1)] = data & 0xff;
+ //printf("W16:%08x=%04x\n", address, data);
}
inline void rsp_device::ccfunc_write16()
@@ -420,13 +226,14 @@ static void cfunc_write16(void *param)
((rsp_device *)param)->ccfunc_write16();;
}
-inline void rsp_device::DM_WRITE32(UINT32 address, UINT32 data)
+void rsp_device::DM_WRITE32(UINT32 address, UINT32 data)
{
address &= 0xfff;
m_dmem8[BYTE4_XOR_BE(address)] = data >> 24;
m_dmem8[BYTE4_XOR_BE(address + 1)] = (data >> 16) & 0xff;
m_dmem8[BYTE4_XOR_BE(address + 2)] = (data >> 8) & 0xff;
m_dmem8[BYTE4_XOR_BE(address + 3)] = data & 0xff;
+ //printf("W32:%08x=%08x\n", address, data);
}
inline void rsp_device::ccfunc_write32()
@@ -452,52 +259,6 @@ void rsp_device::rspdrc_set_options(UINT32 options)
}
-/*-------------------------------------------------
- cfunc_printf_debug - generic printf for
- debugging
--------------------------------------------------*/
-
-#ifdef UNUSED_CODE
-inline void rs_device::cfunc_printf_debug()
-{
- switch(m_arg2)
- {
- case 0: // WRITE8
- printf("%04x:%02x\n", m_rsp_state->arg0 & 0xffff, (UINT8)m_rsp_state->arg1);
- break;
- case 1: // WRITE16
- printf("%04x:%04x\n", m_rsp_state->arg0 & 0xffff, (UINT16)m_rsp_state->arg1);
- break;
- case 2: // WRITE32
- printf("%04x:%08x\n", m_rsp_state->arg0 & 0xffff, m_rsp_state->arg1);
- break;
- case 3: // READ8
- printf("%04xr%02x\n", m_rsp_state->arg0 & 0xffff, (UINT8)m_rsp_state->arg1);
- break;
- case 4: // READ16
- printf("%04xr%04x\n", m_rsp_state->arg0 & 0xffff, (UINT16)m_rsp_state->arg1);
- break;
- case 5: // READ32
- printf("%04xr%08x\n", m_rsp_state->arg0 & 0xffff, m_rsp_state->arg1);
- break;
- case 6: // Checksum
- printf("Sum: %08x\n", m_rsp_state->arg0);
- break;
- case 7: // Checksum
- printf("Correct Sum: %08x\n", m_rsp_state->arg0);
- break;
- default: // ???
- printf("%08x %08x\n", m_rsp_state->arg0 & 0xffff, m_rsp_state->arg1);
- break;
- }
-}
-
-static void cfunc_printf_debug(void *param)
-{
- ((rsp_device *)param)->ccfunc_printf_debug();
-}
-#endif
-
inline void rsp_device::ccfunc_get_cop0_reg()
{
int reg = m_rsp_state->arg0;
@@ -552,6451 +313,12 @@ static void cfunc_set_cop0_reg(void *param)
((rsp_device *)param)->ccfunc_set_cop0_reg();
}
-inline void rsp_device::ccfunc_unimplemented_opcode()
-{
- int op = m_rsp_state->arg0;
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
- {
- char string[200];
- rsp_dasm_one(string, m_ppc, op);
- osd_printf_debug("%08X: %s\n", m_ppc, string);
- }
-
- fatalerror("RSP: unknown opcode %02X (%08X) at %08X\n", op >> 26, op, m_ppc);
-}
-
-static void cfunc_unimplemented_opcode(void *param)
-{
- ((rsp_device *)param)->ccfunc_unimplemented_opcode();
-}
-
/*****************************************************************************/
-/* Legacy. Going forward, this will be transitioned into unrolled opcode decodes. */
-static const int vector_elements_2[16][8] =
-{
- { 0, 1, 2, 3, 4, 5, 6, 7 }, // none
- { 0, 1, 2, 3, 4, 5, 6, 7 }, // ???
- { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q
- { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q
- { 0, 0, 0, 0, 4, 4, 4, 4 }, // 0h
- { 1, 1, 1, 1, 5, 5, 5, 5 }, // 1h
- { 2, 2, 2, 2, 6, 6, 6, 6 }, // 2h
- { 3, 3, 3, 3, 7, 7, 7, 7 }, // 3h
- { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
- { 1, 1, 1, 1, 1, 1, 1, 1 }, // 1
- { 2, 2, 2, 2, 2, 2, 2, 2 }, // 2
- { 3, 3, 3, 3, 3, 3, 3, 3 }, // 3
- { 4, 4, 4, 4, 4, 4, 4, 4 }, // 4
- { 5, 5, 5, 5, 5, 5, 5, 5 }, // 5
- { 6, 6, 6, 6, 6, 6, 6, 6 }, // 6
- { 7, 7, 7, 7, 7, 7, 7, 7 }, // 7
-};
-
-#if USE_SIMD
-static __m128i vec_himask;
-static __m128i vec_lomask;
-static __m128i vec_hibit;
-static __m128i vec_lobit;
-static __m128i vec_n32768;
-static __m128i vec_32767;
-static __m128i vec_flagmask;
-static __m128i vec_shiftmask2;
-static __m128i vec_shiftmask4;
-static __m128i vec_flag_reverse;
-static __m128i vec_neg1;
-static __m128i vec_zero;
-static __m128i vec_shuf[16];
-static __m128i vec_shuf_inverse[16];
-#endif
-
void rsp_device::rspcom_init()
{
-#if USE_SIMD
- VEC_CLEAR_CARRY_FLAGS();
- VEC_CLEAR_COMPARE_FLAGS();
- VEC_CLEAR_CLIP1_FLAGS();
- VEC_CLEAR_ZERO_FLAGS();
- VEC_CLEAR_CLIP2_FLAGS();
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
- CLEAR_CARRY_FLAGS();
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP1_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP2_FLAGS();
-#endif
-
-#if USE_SIMD
- vec_shuf_inverse[ 0] = _mm_set_epi16(0x0f0e, 0x0d0c, 0x0b0a, 0x0908, 0x0706, 0x0504, 0x0302, 0x0100); // none
- vec_shuf_inverse[ 1] = _mm_set_epi16(0x0f0e, 0x0d0c, 0x0b0a, 0x0908, 0x0706, 0x0504, 0x0302, 0x0100); // ???
- vec_shuf_inverse[ 2] = _mm_set_epi16(0x0d0c, 0x0d0c, 0x0908, 0x0908, 0x0504, 0x0504, 0x0100, 0x0100); // 0q
- vec_shuf_inverse[ 3] = _mm_set_epi16(0x0f0e, 0x0f0e, 0x0b0a, 0x0b0a, 0x0706, 0x0706, 0x0302, 0x0302); // 1q
- vec_shuf_inverse[ 4] = _mm_set_epi16(0x0908, 0x0908, 0x0908, 0x0908, 0x0100, 0x0100, 0x0100, 0x0100); // 0h
- vec_shuf_inverse[ 5] = _mm_set_epi16(0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0302, 0x0302, 0x0302, 0x0302); // 1h
- vec_shuf_inverse[ 6] = _mm_set_epi16(0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0504, 0x0504, 0x0504, 0x0504); // 2h
- vec_shuf_inverse[ 7] = _mm_set_epi16(0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0706, 0x0706, 0x0706, 0x0706); // 3h
- vec_shuf_inverse[ 8] = _mm_set_epi16(0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100); // 0
- vec_shuf_inverse[ 9] = _mm_set_epi16(0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302); // 1
- vec_shuf_inverse[10] = _mm_set_epi16(0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504); // 2
- vec_shuf_inverse[11] = _mm_set_epi16(0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706); // 3
- vec_shuf_inverse[12] = _mm_set_epi16(0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908); // 4
- vec_shuf_inverse[13] = _mm_set_epi16(0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a); // 5
- vec_shuf_inverse[14] = _mm_set_epi16(0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c); // 6
- vec_shuf_inverse[15] = _mm_set_epi16(0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e); // 7
-
- vec_shuf[ 0] = _mm_set_epi16(0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e); // none
- vec_shuf[ 1] = _mm_set_epi16(0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e); // ???
- vec_shuf[ 2] = _mm_set_epi16(0x0302, 0x0302, 0x0706, 0x0706, 0x0b0a, 0x0b0a, 0x0f0e, 0x0f0e); // 0q
- vec_shuf[ 3] = _mm_set_epi16(0x0100, 0x0100, 0x0504, 0x0706, 0x0908, 0x0908, 0x0d0c, 0x0d0c); // 1q
- vec_shuf[ 4] = _mm_set_epi16(0x0706, 0x0706, 0x0706, 0x0706, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e); // 0q
- vec_shuf[ 5] = _mm_set_epi16(0x0504, 0x0504, 0x0504, 0x0504, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c); // 1q
- vec_shuf[ 6] = _mm_set_epi16(0x0302, 0x0302, 0x0302, 0x0302, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a); // 2q
- vec_shuf[ 7] = _mm_set_epi16(0x0100, 0x0100, 0x0100, 0x0100, 0x0908, 0x0908, 0x0908, 0x0908); // 3q
- vec_shuf[ 8] = _mm_set_epi16(0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e); // 0
- vec_shuf[ 9] = _mm_set_epi16(0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c); // 1
- vec_shuf[10] = _mm_set_epi16(0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a); // 2
- vec_shuf[11] = _mm_set_epi16(0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908); // 3
- vec_shuf[12] = _mm_set_epi16(0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706); // 4
- vec_shuf[13] = _mm_set_epi16(0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504); // 5
- vec_shuf[14] = _mm_set_epi16(0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302); // 6
- vec_shuf[15] = _mm_set_epi16(0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100); // 7
- m_accum_h = _mm_setzero_si128();
- m_accum_m = _mm_setzero_si128();
- m_accum_l = _mm_setzero_si128();
- m_accum_ll = _mm_setzero_si128();
- vec_neg1 = _mm_set_epi64x(0xffffffffffffffffL, 0xffffffffffffffffL);
- vec_zero = _mm_setzero_si128();
- vec_himask = _mm_set_epi64x(0xffff0000ffff0000L, 0xffff0000ffff0000L);
- vec_lomask = _mm_set_epi64x(0x0000ffff0000ffffL, 0x0000ffff0000ffffL);
- vec_hibit = _mm_set_epi64x(0x0001000000010000L, 0x0001000000010000L);
- vec_lobit = _mm_set_epi64x(0x0000000100000001L, 0x0000000100000001L);
- vec_32767 = _mm_set_epi64x(0x7fff7fff7fff7fffL, 0x7fff7fff7fff7fffL);
- vec_n32768 = _mm_set_epi64x(0x8000800080008000L, 0x8000800080008000L);
- vec_flagmask = _mm_set_epi64x(0x0001000100010001L, 0x0001000100010001L);
- vec_shiftmask2 = _mm_set_epi64x(0x0000000300000003L, 0x0000000300000003L);
- vec_shiftmask4 = _mm_set_epi64x(0x000000000000000fL, 0x000000000000000fL);
- vec_flag_reverse = _mm_set_epi16(0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e);
-#endif
-}
-
-
-#if USE_SIMD
-// LBV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00000 | IIII | Offset |
-// --------------------------------------------------
-//
-// Load 1 byte to vector byte index
-
-inline void rsp_device::ccfunc_rsp_lbv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
-
- UINT32 ea = 0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- ea = (base) ? m_rsp_state->r[base] + offset : offset;
-
- UINT16 element;
- SIMD_EXTRACT16(m_xv[dest], element, (index >> 1));
- element &= 0xff00 >> ((1-(index & 1)) * 8);
- element |= DM_READ8(ea) << ((1-(index & 1)) * 8);
- SIMD_INSERT16(m_xv[dest], element, (index >> 1));
-}
-
-static void cfunc_rsp_lbv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lbv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-inline void rsp_device::ccfunc_rsp_lbv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
-
- UINT32 ea = 0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- ea = (base) ? m_rsp_state->r[base] + offset : offset;
- VREG_B(dest, index) = DM_READ8(ea);
-}
-
-static void cfunc_rsp_lbv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lbv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// LSV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00001 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads 2 bytes starting from vector byte index
-
-inline void rsp_device::ccfunc_rsp_lsv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xe;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 2) : (offset * 2);
- int end = index + 2;
- for (int i = index; i < end; i++)
- {
- UINT16 element;
- SIMD_EXTRACT16(m_xv[dest], element, (i >> 1));
- element &= 0xff00 >> ((1 - (i & 1)) * 8);
- element |= DM_READ8(ea) << ((1 - (i & 1)) * 8);
- SIMD_INSERT16(m_xv[dest], element, (i >> 1));
- ea++;
- }
-}
-
-static void cfunc_rsp_lsv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lsv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-inline void rsp_device::ccfunc_rsp_lsv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xe;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 2) : (offset * 2);
- int end = index + 2;
- for (int i = index; i < end; i++)
- {
- VREG_B(dest, i) = DM_READ8(ea);
- ea++;
- }
-}
-
-static void cfunc_rsp_lsv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lsv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// LLV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00010 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads 4 bytes starting from vector byte index
-
-inline void rsp_device::ccfunc_rsp_llv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- UINT32 ea = 0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xc;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 4) : (offset * 4);
-
- int end = index + 4;
-
- for (int i = index; i < end; i++)
- {
- UINT16 element;
- SIMD_EXTRACT16(m_xv[dest], element, (i >> 1));
- element &= 0xff00 >> ((1 - (i & 1)) * 8);
- element |= DM_READ8(ea) << ((1 - (i & 1)) * 8);
- SIMD_INSERT16(m_xv[dest], element, (i >> 1));
- ea++;
- }
-}
-
-static void cfunc_rsp_llv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_llv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_llv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- UINT32 ea = 0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xc;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 4) : (offset * 4);
-
- int end = index + 4;
-
- for (int i = index; i < end; i++)
- {
- VREG_B(dest, i) = DM_READ8(ea);
- ea++;
- }
-}
-
-static void cfunc_rsp_llv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_llv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// LDV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00011 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads 8 bytes starting from vector byte index
-
-inline void rsp_device::ccfunc_rsp_ldv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- UINT32 ea = 0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0x8;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- int end = index + 8;
-
- for (int i = index; i < end; i++)
- {
- UINT16 element;
- SIMD_EXTRACT16(m_xv[dest], element, (i >> 1));
- element &= 0xff00 >> ((1 - (i & 1)) * 8);
- element |= DM_READ8(ea) << ((1 - (i & 1)) * 8);
- SIMD_INSERT16(m_xv[dest], element, (i >> 1));
- ea++;
- }
-}
-
-static void cfunc_rsp_ldv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_ldv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_ldv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- UINT32 ea = 0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0x8;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- int end = index + 8;
-
- for (int i = index; i < end; i++)
- {
- VREG_B(dest, i) = DM_READ8(ea);
- ea++;
- }
-}
-
-static void cfunc_rsp_ldv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_ldv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// LQV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00100 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads up to 16 bytes starting from vector byte index
-
-inline void rsp_device::ccfunc_rsp_lqv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- int end = 16 - (ea & 0xf);
- if (end > 16) end = 16;
-
- for (int i = 0; i < end; i++)
- {
- UINT16 element;
- SIMD_EXTRACT16(m_xv[dest], element, (i >> 1));
- element &= 0xff00 >> ((1 - (i & 1)) * 8);
- element |= DM_READ8(ea) << ((1 - (i & 1)) * 8);
- SIMD_INSERT16(m_xv[dest], element, (i >> 1));
- ea++;
- }
-}
-
-static void cfunc_rsp_lqv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lqv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_lqv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- int end = 16 - (ea & 0xf);
- if (end > 16) end = 16;
-
- for (int i = 0; i < end; i++)
- {
- VREG_B(dest, i) = DM_READ8(ea);
- ea++;
- }
-}
-
-static void cfunc_rsp_lqv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lqv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// LRV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00101 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores up to 16 bytes starting from right side until 16-byte boundary
-
-inline void rsp_device::ccfunc_rsp_lrv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- index = 16 - ((ea & 0xf) - index);
- ea &= ~0xf;
-
- for (int i = index; i < 16; i++)
- {
- UINT16 element;
- SIMD_EXTRACT16(m_xv[dest], element, (i >> 1));
- element &= 0xff00 >> ((1-(i & 1)) * 8);
- element |= DM_READ8(ea) << ((1-(i & 1)) * 8);
- SIMD_INSERT16(m_xv[dest], element, (i >> 1));
- ea++;
- }
-}
-
-static void cfunc_rsp_lrv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lrv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_lrv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- index = 16 - ((ea & 0xf) - index);
- ea &= ~0xf;
-
- for (int i = index; i < 16; i++)
- {
- VREG_B(dest, i) = DM_READ8(ea);
- ea++;
- }
-}
-
-static void cfunc_rsp_lrv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lrv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// LPV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00110 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads a byte as the upper 8 bits of each element
-
-inline void rsp_device::ccfunc_rsp_lpv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- for (int i = 0; i < 8; i++)
- {
- SIMD_INSERT16(m_xv[dest], DM_READ8(ea + (((16-index) + i) & 0xf)) << 8, i);
- }
-}
-
-static void cfunc_rsp_lpv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lpv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_lpv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- for (int i = 0; i < 8; i++)
- {
- W_VREG_S(dest, i) = DM_READ8(ea + (((16-index) + i) & 0xf)) << 8;
- }
-}
-
-static void cfunc_rsp_lpv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lpv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// LUV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00111 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads a byte as the bits 14-7 of each element
-
-inline void rsp_device::ccfunc_rsp_luv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- for (int i = 0; i < 8; i++)
- {
- SIMD_INSERT16(m_xv[dest], DM_READ8(ea + (((16-index) + i) & 0xf)) << 7, i);
- }
-}
-
-static void cfunc_rsp_luv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_luv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_luv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- for (int i = 0; i < 8; i++)
- {
- W_VREG_S(dest, i) = DM_READ8(ea + (((16-index) + i) & 0xf)) << 7;
- }
-}
-
-static void cfunc_rsp_luv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_luv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// LHV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 01000 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads a byte as the bits 14-7 of each element, with 2-byte stride
-
-inline void rsp_device::ccfunc_rsp_lhv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- for (int i = 0; i < 8; i++)
- {
- SIMD_INSERT16(m_xv[dest], DM_READ8(ea + (((16-index) + (i<<1)) & 0xf)) << 7, i);
- }
-}
-
-static void cfunc_rsp_lhv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lhv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_lhv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- for (int i = 0; i < 8; i++)
- {
- W_VREG_S(dest, i) = DM_READ8(ea + (((16-index) + (i<<1)) & 0xf)) << 7;
- }
-}
-
-static void cfunc_rsp_lhv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lhv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// LFV
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 01001 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride
-
-inline void rsp_device::ccfunc_rsp_lfv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- // not sure what happens if 16-byte boundary is crossed...
-
- int end = (index >> 1) + 4;
-
- for (int i = index >> 1; i < end; i++)
- {
- SIMD_INSERT16(m_xv[dest], DM_READ8(ea) << 7, i);
- ea += 4;
- }
-}
-
-static void cfunc_rsp_lfv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lfv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_lfv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- // not sure what happens if 16-byte boundary is crossed...
-
- int end = (index >> 1) + 4;
-
- for (int i = index >> 1; i < end; i++)
- {
- W_VREG_S(dest, i) = DM_READ8(ea) << 7;
- ea += 4;
- }
-}
-
-static void cfunc_rsp_lfv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lfv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// LWV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 01010 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads the full 128-bit vector starting from vector byte index and wrapping to index 0
-// after byte index 15
-
-inline void rsp_device::ccfunc_rsp_lwv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- int end = (16 - index) + 16;
-
- UINT8 val[16];
- for (int i = (16 - index); i < end; i++)
- {
- val[i & 0xf] = DM_READ8(ea);
- ea += 4;
- }
-
- m_xv[dest] = _mm_set_epi8(val[15], val[14], val[13], val[12], val[11], val[10], val[ 9], val[ 8],
- val[ 7], val[ 6], val[ 5], val[ 4], val[ 3], val[ 2], val[ 1], val[ 0]);
-}
-
-static void cfunc_rsp_lwv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lwv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_lwv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- int end = (16 - index) + 16;
-
- for (int i = (16 - index); i < end; i++)
- {
- VREG_B(dest, i & 0xf) = DM_READ8(ea);
- ea += 4;
- }
-}
-
-static void cfunc_rsp_lwv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_lwv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// LTV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads one element to maximum of 8 vectors, while incrementing element index
-
-inline void rsp_device::ccfunc_rsp_ltv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
-
- // FIXME: has a small problem with odd indices
-
- int vs = dest;
- int ve = dest + 8;
- if (ve > 32)
- {
- ve = 32;
- }
-
- int element = 7 - (index >> 1);
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- ea = ((ea + 8) & ~0xf) + (index & 1);
- for (int i = vs; i < ve; i++)
- {
- element = (8 - (index >> 1) + (i - vs)) << 1;
- UINT16 value = (DM_READ8(ea) << 8) | DM_READ8(ea + 1);
- SIMD_INSERT16(m_xv[i], value, (element >> 1));
- ea += 2;
- }
-}
-
-static void cfunc_rsp_ltv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_ltv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_ltv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
-
- // FIXME: has a small problem with odd indices
-
- int vs = dest;
- int ve = dest + 8;
- if (ve > 32)
- {
- ve = 32;
- }
-
- int element = 7 - (index >> 1);
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- ea = ((ea + 8) & ~0xf) + (index & 1);
- for (int i = vs; i < ve; i++)
- {
- element = (8 - (index >> 1) + (i - vs)) << 1;
- VREG_B(i, (element & 0xf)) = DM_READ8(ea);
- VREG_B(i, ((element + 1) & 0xf)) = DM_READ8(ea + 1);
- ea += 2;
- }
-}
-
-static void cfunc_rsp_ltv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_ltv_scalar();
-}
-#endif
-
-#if USE_SIMD && SIMUL_SIMD
-inline void rsp_device::ccfunc_backup_regs()
-{
- memcpy(m_old_dmem, m_dmem8, sizeof(m_old_dmem));
- memcpy(m_old_r, m_r, sizeof(m_r));
-
- m_simd_reciprocal_res = m_reciprocal_res;
- m_simd_reciprocal_high = m_reciprocal_high;
- m_simd_dp_allowed = m_dp_allowed;
-
- m_reciprocal_res = m_old_reciprocal_res;
- m_reciprocal_high = m_old_reciprocal_high;
- m_dp_allowed = m_old_dp_allowed;
-}
-
-static void cfunc_backup_regs(void *param)
-{
- ((rsp_device *)param)->ccfunc_backup_regs();
-}
-
-inline void rsp_device::ccfunc_restore_regs()
-{
- memcpy(m_scalar_r, m_r, sizeof(m_r));
- memcpy(m_r, m_old_r, sizeof(m_r));
- memcpy(m_scalar_dmem, m_dmem8, sizeof(m_scalar_dmem));
- memcpy(m_dmem8, m_old_dmem, sizeof(m_old_dmem));
-
- m_scalar_reciprocal_res = m_reciprocal_res;
- m_scalar_reciprocal_high = m_reciprocal_high;
- m_scalar_dp_allowed = m_dp_allowed;
-
- m_reciprocal_res = m_simd_reciprocal_res;
- m_reciprocal_high = m_simd_reciprocal_high;
- m_dp_allowed = m_simd_dp_allowed;
-}
-
-static void cfunc_restore_regs(void *param)
-{
- ((rsp_device *)param)->ccfunc_restore_regs();
-}
-
-inline void rsp_device::ccfunc_verify_regs()
-{
- int op = m_rsp_state->arg0;
- if (VEC_ACCUM_H(0) != ACCUM_H(0)) fatalerror("ACCUM_H element 0 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_H(0), ACCUM_H(0), op);
- if (VEC_ACCUM_H(1) != ACCUM_H(1)) fatalerror("ACCUM_H element 1 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_H(1), ACCUM_H(1), op);
- if (VEC_ACCUM_H(2) != ACCUM_H(2)) fatalerror("ACCUM_H element 2 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_H(2), ACCUM_H(2), op);
- if (VEC_ACCUM_H(3) != ACCUM_H(3)) fatalerror("ACCUM_H element 3 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_H(3), ACCUM_H(3), op);
- if (VEC_ACCUM_H(4) != ACCUM_H(4)) fatalerror("ACCUM_H element 4 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_H(4), ACCUM_H(4), op);
- if (VEC_ACCUM_H(5) != ACCUM_H(5)) fatalerror("ACCUM_H element 5 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_H(5), ACCUM_H(5), op);
- if (VEC_ACCUM_H(6) != ACCUM_H(6)) fatalerror("ACCUM_H element 6 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_H(6), ACCUM_H(6), op);
- if (VEC_ACCUM_H(7) != ACCUM_H(7)) fatalerror("ACCUM_H element 7 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_H(7), ACCUM_H(7), op);
- if (VEC_ACCUM_M(0) != ACCUM_M(0)) fatalerror("ACCUM_M element 0 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_M(0), ACCUM_M(0), op);
- if (VEC_ACCUM_M(1) != ACCUM_M(1)) fatalerror("ACCUM_M element 1 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_M(1), ACCUM_M(1), op);
- if (VEC_ACCUM_M(2) != ACCUM_M(2)) fatalerror("ACCUM_M element 2 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_M(2), ACCUM_M(2), op);
- if (VEC_ACCUM_M(3) != ACCUM_M(3)) fatalerror("ACCUM_M element 3 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_M(3), ACCUM_M(3), op);
- if (VEC_ACCUM_M(4) != ACCUM_M(4)) fatalerror("ACCUM_M element 4 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_M(4), ACCUM_M(4), op);
- if (VEC_ACCUM_M(5) != ACCUM_M(5)) fatalerror("ACCUM_M element 5 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_M(5), ACCUM_M(5), op);
- if (VEC_ACCUM_M(6) != ACCUM_M(6)) fatalerror("ACCUM_M element 6 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_M(6), ACCUM_M(6), op);
- if (VEC_ACCUM_M(7) != ACCUM_M(7)) fatalerror("ACCUM_M element 7 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_M(7), ACCUM_M(7), op);
- if (VEC_ACCUM_L(0) != ACCUM_L(0)) fatalerror("ACCUM_L element 0 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_L(0), ACCUM_L(0), op);
- if (VEC_ACCUM_L(1) != ACCUM_L(1)) fatalerror("ACCUM_L element 1 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_L(1), ACCUM_L(1), op);
- if (VEC_ACCUM_L(2) != ACCUM_L(2)) fatalerror("ACCUM_L element 2 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_L(2), ACCUM_L(2), op);
- if (VEC_ACCUM_L(3) != ACCUM_L(3)) fatalerror("ACCUM_L element 3 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_L(3), ACCUM_L(3), op);
- if (VEC_ACCUM_L(4) != ACCUM_L(4)) fatalerror("ACCUM_L element 4 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_L(4), ACCUM_L(4), op);
- if (VEC_ACCUM_L(5) != ACCUM_L(5)) fatalerror("ACCUM_L element 5 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_L(5), ACCUM_L(5), op);
- if (VEC_ACCUM_L(6) != ACCUM_L(6)) fatalerror("ACCUM_L element 6 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_L(6), ACCUM_L(6), op);
- if (VEC_ACCUM_L(7) != ACCUM_L(7)) fatalerror("ACCUM_L element 7 mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", VEC_ACCUM_L(7), ACCUM_L(7), op);
- for (int i = 0; i < 32; i++)
- {
- if (m_rsp_state->r[i] != m_scalar_r[i]) fatalerror("r[%d] mismatch (SIMD %08x vs. Scalar %08x) after op: %08x\n", i, m_rsp_state->r[i], m_scalar_r[i], op);
- for (int el = 0; el < 8; el++)
- {
- UINT16 out;
- SIMD_EXTRACT16(m_xv[i], out, el);
- if ((UINT16)VREG_S(i, el) != out) fatalerror("Vector %d element %d mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", i, el, out, (UINT16)VREG_S(i, el), op);
- }
- }
- for (int i = 0; i < 4096; i++)
- {
- if (m_dmem8[i] != m_scalar_dmem[i]) fatalerror("dmem[%d] mismatch (SIMD %02x vs. Scalar %02x) after op: %08x\n", i, m_dmem8[i], m_scalar_dmem[i], op);
- }
- for (int i = 0; i < 5; i++)
- {
- for (int el = 0; el < 8; el++)
- {
- UINT16 out;
- SIMD_EXTRACT16(m_xvflag[i], out, el);
- if (m_vflag[i][el] != out) fatalerror("flag[%d][%d] mismatch (SIMD %04x vs. Scalar %04x) after op: %08x\n", i, el, out, m_vflag[i][el], op);
- }
- }
-}
-
-static void cfunc_verify_regs(void *param)
-{
- ((rsp_device *)param)->ccfunc_verify_regs();
-}
-#endif
-
-#if USE_SIMD
-int rsp_device::generate_lwc2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
-{
- //int loopdest;
- UINT32 op = desc->opptr.l[0];
- //int dest = (op >> 16) & 0x1f;
- //int base = (op >> 21) & 0x1f;
- //int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- //int skip;
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- switch ((op >> 11) & 0x1f)
- {
- case 0x00: /* LBV */
- //UML_ADD(block, I0, R32(RSREG), offset);
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lbv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_lbv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x01: /* LSV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lsv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_lsv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x02: /* LLV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_llv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_llv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x03: /* LDV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_ldv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_ldv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x04: /* LQV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lqv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_lqv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x05: /* LRV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lrv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_lrv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x06: /* LPV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lpv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_lpv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x07: /* LUV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_luv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_luv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x08: /* LHV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lhv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_lhv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x09: /* LFV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lfv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_lfv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x0a: /* LWV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lwv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_lwv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x0b: /* LTV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_ltv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_ltv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- default:
- return FALSE;
- }
-}
-
-#else
-
-int rsp_device::generate_lwc2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
-{
- //int loopdest;
- UINT32 op = desc->opptr.l[0];
- //int dest = (op >> 16) & 0x1f;
- //int base = (op >> 21) & 0x1f;
- //int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- //int skip;
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- switch ((op >> 11) & 0x1f)
- {
- case 0x00: /* LBV */
- //UML_ADD(block, I0, R32(RSREG), offset);
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lbv_scalar, this);
- return TRUE;
- case 0x01: /* LSV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lsv_scalar, this);
- return TRUE;
- case 0x02: /* LLV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_llv_scalar, this);
- return TRUE;
- case 0x03: /* LDV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_ldv_scalar, this);
- return TRUE;
- case 0x04: /* LQV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lqv_scalar, this);
- return TRUE;
- case 0x05: /* LRV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lrv_scalar, this);
- return TRUE;
- case 0x06: /* LPV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lpv_scalar, this);
- return TRUE;
- case 0x07: /* LUV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_luv_scalar, this);
- return TRUE;
- case 0x08: /* LHV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lhv_scalar, this);
- return TRUE;
- case 0x09: /* LFV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lfv_scalar, this);
- return TRUE;
- case 0x0a: /* LWV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_lwv_scalar, this);
- return TRUE;
- case 0x0b: /* LTV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_ltv_scalar, this);
- return TRUE;
-
- default:
- return FALSE;
- }
-}
-#endif
-
-#if USE_SIMD
-// SBV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores 1 byte from vector byte index
-
-inline void rsp_device::ccfunc_rsp_sbv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + offset : offset;
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, (index >> 1));
- value >>= (1-(index & 1)) * 8;
- DM_WRITE8(ea, (UINT8)value);
-}
-
-static void cfunc_rsp_sbv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_sbv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_sbv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + offset : offset;
- DM_WRITE8(ea, VREG_B(dest, index));
-}
-
-static void cfunc_rsp_sbv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_sbv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// SSV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores 2 bytes starting from vector byte index
-
-inline void rsp_device::ccfunc_rsp_ssv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 2) : (offset * 2);
-
- int end = index + 2;
- for (int i = index; i < end; i++)
- {
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, (i >> 1));
- value >>= (1 - (i & 1)) * 8;
- DM_WRITE8(ea, (UINT8)value);
- ea++;
- }
-}
-
-static void cfunc_rsp_ssv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_ssv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_ssv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 2) : (offset * 2);
-
- int end = index + 2;
- for (int i = index; i < end; i++)
- {
- DM_WRITE8(ea, VREG_B(dest, i));
- ea++;
- }
-}
-
-static void cfunc_rsp_ssv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_ssv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// SLV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores 4 bytes starting from vector byte index
-
-inline void rsp_device::ccfunc_rsp_slv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 4) : (offset * 4);
-
- int end = index + 4;
- for (int i = index; i < end; i++)
- {
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, (i >> 1));
- value >>= (1 - (i & 1)) * 8;
- DM_WRITE8(ea, (UINT8)value);
- ea++;
- }
-}
-
-static void cfunc_rsp_slv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_slv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_slv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 4) : (offset * 4);
-
- int end = index + 4;
- for (int i = index; i < end; i++)
- {
- DM_WRITE8(ea, VREG_B(dest, i));
- ea++;
- }
-}
-
-static void cfunc_rsp_slv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_slv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// SDV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores 8 bytes starting from vector byte index
-
-inline void rsp_device::ccfunc_rsp_sdv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0x8;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- int end = index + 8;
- for (int i = index; i < end; i++)
- {
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, (i >> 1));
- value >>= (1 - (i & 1)) * 8;
- DM_WRITE8(ea, (UINT8)value);
- ea++;
- }
-}
-
-static void cfunc_rsp_sdv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_sdv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_sdv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0x8;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
-
- int end = index + 8;
- for (int i = index; i < end; i++)
- {
- DM_WRITE8(ea, VREG_B(dest, i));
- ea++;
- }
-}
-
-static void cfunc_rsp_sdv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_sdv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// SQV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores up to 16 bytes starting from vector byte index until 16-byte boundary
-
-inline void rsp_device::ccfunc_rsp_sqv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- int end = index + (16 - (ea & 0xf));
- for (int i=index; i < end; i++)
- {
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, (i >> 1));
- value >>= (1-(i & 1)) * 8;
- DM_WRITE8(ea, (UINT8)value);
- ea++;
- }
-}
-
-static void cfunc_rsp_sqv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_sqv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_sqv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- int end = index + (16 - (ea & 0xf));
- for (int i=index; i < end; i++)
- {
- DM_WRITE8(ea, VREG_B(dest, i & 0xf));
- ea++;
- }
-}
-
-static void cfunc_rsp_sqv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_sqv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// SRV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores up to 16 bytes starting from right side until 16-byte boundary
-
-inline void rsp_device::ccfunc_rsp_srv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- int end = index + (ea & 0xf);
- int o = (16 - (ea & 0xf)) & 0xf;
- ea &= ~0xf;
-
- for (int i = index; i < end; i++)
- {
- UINT32 bi = (i + o) & 0xf;
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, (bi >> 1));
- value >>= (1-(bi & 1)) * 8;
- DM_WRITE8(ea, (UINT8)value);
- ea++;
- }
-}
-
-static void cfunc_rsp_srv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_srv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_srv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- int end = index + (ea & 0xf);
- int o = (16 - (ea & 0xf)) & 0xf;
- ea &= ~0xf;
-
- for (int i = index; i < end; i++)
- {
- DM_WRITE8(ea, VREG_B(dest, ((i + o) & 0xf)));
- ea++;
- }
-}
-
-static void cfunc_rsp_srv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_srv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// SPV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores upper 8 bits of each element
-
-inline void rsp_device::ccfunc_rsp_spv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
- int end = index + 8;
- for (int i=index; i < end; i++)
- {
- if ((i & 0xf) < 8)
- {
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, i);
- DM_WRITE8(ea, (UINT8)(value >> 8));
- }
- else
- {
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, i);
- DM_WRITE8(ea, (UINT8)(value >> 7));
- }
- ea++;
- }
-}
-
-static void cfunc_rsp_spv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_spv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_spv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
- int end = index + 8;
- for (int i=index; i < end; i++)
- {
- if ((i & 0xf) < 8)
- {
- DM_WRITE8(ea, VREG_B(dest, (i & 0xf) << 1));
- }
- else
- {
- DM_WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7);
- }
- ea++;
- }
-}
-
-static void cfunc_rsp_spv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_spv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// SUV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores bits 14-7 of each element
-
-inline void rsp_device::ccfunc_rsp_suv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
- int end = index + 8;
- for (int i=index; i < end; i++)
- {
- if ((i & 0xf) < 8)
- {
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, i);
- DM_WRITE8(ea, (UINT8)(value >> 7));
- }
- else
- {
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, i);
- DM_WRITE8(ea, (UINT8)(value >> 8));
- }
- ea++;
- }
-}
-
-static void cfunc_rsp_suv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_suv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_suv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 8) : (offset * 8);
- int end = index + 8;
- for (int i=index; i < end; i++)
- {
- if ((i & 0xf) < 8)
- {
- DM_WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7);
- }
- else
- {
- DM_WRITE8(ea, VREG_B(dest, ((i & 0x7) << 1)));
- }
- ea++;
- }
-}
-
-static void cfunc_rsp_suv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_suv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// SHV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores bits 14-7 of each element, with 2-byte stride
-
-inline void rsp_device::ccfunc_rsp_shv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- for (int i=0; i < 8; i++)
- {
- int element = index + (i << 1);
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, element >> 1);
- DM_WRITE8(ea, (value >> 7) & 0x00ff);
- ea += 2;
- }
-}
-
-static void cfunc_rsp_shv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_shv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_shv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- for (int i=0; i < 8; i++)
- {
- int element = index + (i << 1);
- UINT8 d = (VREG_B(dest, (element & 0xf)) << 1) |
- (VREG_B(dest, ((element + 1) & 0xf)) >> 7);
- DM_WRITE8(ea, d);
- ea += 2;
- }
-}
-
-static void cfunc_rsp_shv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_shv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// SFV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores bits 14-7 of upper or lower quad, with 4-byte stride
-
-inline void rsp_device::ccfunc_rsp_sfv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- int eaoffset = ea & 0xf;
- ea &= ~0xf;
-
- int end = (index >> 1) + 4;
-
- for (int i = index>>1; i < end; i++)
- {
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, i);
- DM_WRITE8(ea + (eaoffset & 0xf), (value >> 7) & 0x00ff);
- eaoffset += 4;
- }
-}
-
-static void cfunc_rsp_sfv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_sfv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_sfv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- int eaoffset = ea & 0xf;
- ea &= ~0xf;
-
- int end = (index >> 1) + 4;
-
- for (int i = index>>1; i < end; i++)
- {
- DM_WRITE8(ea + (eaoffset & 0xf), VREG_S(dest, i) >> 7);
- eaoffset += 4;
- }
-}
-
-static void cfunc_rsp_sfv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_sfv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// SWV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores the full 128-bit vector starting from vector byte index and wrapping to index 0
-// after byte index 15
-
-inline void rsp_device::ccfunc_rsp_swv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- int eaoffset = ea & 0xf;
- ea &= ~0xf;
-
- int end = index + 16;
- for (int i = index; i < end; i++)
- {
- UINT16 value;
- SIMD_EXTRACT16(m_xv[dest], value, i >> 1);
- DM_WRITE8(ea + (eaoffset & 0xf), (value >> ((1-(i & 1)) * 8)) & 0xff);
- eaoffset++;
- }
-}
-
-static void cfunc_rsp_swv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_swv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_swv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- int eaoffset = ea & 0xf;
- ea &= ~0xf;
-
- int end = index + 16;
- for (int i = index; i < end; i++)
- {
- DM_WRITE8(ea + (eaoffset & 0xf), VREG_B(dest, i & 0xf));
- eaoffset++;
- }
-}
-
-static void cfunc_rsp_swv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_swv_scalar();
-}
-#endif
-
-#if USE_SIMD
-// STV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores one element from maximum of 8 vectors, while incrementing element index
-
-inline void rsp_device::ccfunc_rsp_stv_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
-
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- int vs = dest;
- int ve = dest + 8;
- if (ve > 32)
- {
- ve = 32;
- }
-
- int element = 8 - (index >> 1);
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- int eaoffset = (ea & 0xf) + (element * 2);
- ea &= ~0xf;
-
- for (int i = vs; i < ve; i++)
- {
- UINT16 value;
- SIMD_EXTRACT16(m_xv[i], value, element);
- DM_WRITE16(ea + (eaoffset & 0xf), value);
- eaoffset += 2;
- element++;
- }
-}
-
-static void cfunc_rsp_stv_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_stv_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_stv_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
-
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- int vs = dest;
- int ve = dest + 8;
- if (ve > 32)
- {
- ve = 32;
- }
-
- int element = 8 - (index >> 1);
-
- UINT32 ea = (base) ? m_rsp_state->r[base] + (offset * 16) : (offset * 16);
- int eaoffset = (ea & 0xf) + (element * 2);
- ea &= ~0xf;
-
- for (int i = vs; i < ve; i++)
- {
- DM_WRITE16(ea + (eaoffset & 0xf), VREG_S(i, element & 0x7));
- eaoffset += 2;
- element++;
- }
-}
-
-static void cfunc_rsp_stv_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_stv_scalar();
-}
-#endif
-
-#if USE_SIMD
-int rsp_device::generate_swc2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
-{
-// int loopdest;
- UINT32 op = desc->opptr.l[0];
- //int dest = (op >> 16) & 0x1f;
- //int base = (op >> 21) & 0x1f;
- //int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- //int skip;
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- switch ((op >> 11) & 0x1f)
- {
- case 0x00: /* SBV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_sbv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_sbv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x01: /* SSV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_ssv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_ssv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x02: /* SLV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_slv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_slv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x03: /* SDV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_sdv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_sdv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x04: /* SQV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_sqv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_sqv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x05: /* SRV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_srv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_srv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x06: /* SPV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_spv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_spv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x07: /* SUV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_suv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_suv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x08: /* SHV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_shv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_shv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x09: /* SFV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_sfv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_sfv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x0a: /* SWV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_swv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_swv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
- case 0x0b: /* STV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_stv_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_stv_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- default:
- unimplemented_opcode(op);
- return FALSE;
- }
-
- return TRUE;
-}
-
-#else
-
-int rsp_device::generate_swc2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
-{
-// int loopdest;
- UINT32 op = desc->opptr.l[0];
- //int dest = (op >> 16) & 0x1f;
- //int base = (op >> 21) & 0x1f;
- //int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- //int skip;
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- switch ((op >> 11) & 0x1f)
- {
- case 0x00: /* SBV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_sbv_scalar, this);
- return TRUE;
- case 0x01: /* SSV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_ssv_scalar, this);
- return TRUE;
- case 0x02: /* SLV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_slv_scalar, this);
- return TRUE;
- case 0x03: /* SDV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_sdv_scalar, this);
- return TRUE;
- case 0x04: /* SQV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_sqv_scalar, this);
- return TRUE;
- case 0x05: /* SRV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_srv_scalar, this);
- return TRUE;
- case 0x06: /* SPV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_spv_scalar, this);
- return TRUE;
- case 0x07: /* SUV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_suv_scalar, this);
- return TRUE;
- case 0x08: /* SHV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_shv_scalar, this);
- return TRUE;
- case 0x09: /* SFV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_sfv_scalar, this);
- return TRUE;
- case 0x0a: /* SWV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_swv_scalar, this);
- return TRUE;
- case 0x0b: /* STV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_stv_scalar, this);
- return TRUE;
-
- default:
- unimplemented_opcode(op);
- return FALSE;
- }
-
- return TRUE;
-}
-#endif
-
-#if USE_SIMD
-inline UINT16 rsp_device::VEC_SATURATE_ACCUM(int accum, int slice, UINT16 negative, UINT16 positive)
-{
- if ((INT16)VEC_ACCUM_H(accum) < 0)
- {
- if ((UINT16)(VEC_ACCUM_H(accum)) != 0xffff)
- {
- return negative;
- }
- else
- {
- if ((INT16)VEC_ACCUM_M(accum) >= 0)
- {
- return negative;
- }
- else
- {
- if (slice == 0)
- {
- return VEC_ACCUM_L(accum);
- }
- else if (slice == 1)
- {
- return VEC_ACCUM_M(accum);
- }
- }
- }
- }
- else
- {
- if ((UINT16)(VEC_ACCUM_H(accum)) != 0)
- {
- return positive;
- }
- else
- {
- if ((INT16)VEC_ACCUM_M(accum) < 0)
- {
- return positive;
- }
- else
- {
- if (slice == 0)
- {
- return VEC_ACCUM_L(accum);
- }
- else
- {
- return VEC_ACCUM_M(accum);
- }
- }
- }
- }
- return 0;
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-inline UINT16 rsp_device::SATURATE_ACCUM(int accum, int slice, UINT16 negative, UINT16 positive)
-{
- if ((INT16)ACCUM_H(accum) < 0)
- {
- if ((UINT16)(ACCUM_H(accum)) != 0xffff)
- {
- return negative;
- }
- else
- {
- if ((INT16)ACCUM_M(accum) >= 0)
- {
- return negative;
- }
- else
- {
- if (slice == 0)
- {
- return ACCUM_L(accum);
- }
- else if (slice == 1)
- {
- return ACCUM_M(accum);
- }
- }
- }
- }
- else
- {
- if ((UINT16)(ACCUM_H(accum)) != 0)
- {
- return positive;
- }
- else
- {
- if ((INT16)ACCUM_M(accum) < 0)
- {
- return positive;
- }
- else
- {
- if (slice == 0)
- {
- return ACCUM_L(accum);
- }
- else
- {
- return ACCUM_M(accum);
- }
- }
- }
- }
- return 0;
-}
-#endif
-
-inline UINT16 rsp_device::SATURATE_ACCUM1(int accum, UINT16 negative, UINT16 positive)
-{
- // Return negative if H<0 && (H!=0xffff || M >= 0)
- // Return positive if H>0 || (H==0 && M<0)
- // Return medium slice if H==0xffff && M<0
- // Return medium slice if H==0 && M>=0
- if ((INT16)ACCUM_H(accum) < 0)
- {
- if ((UINT16)(ACCUM_H(accum)) != 0xffff)
- {
- return negative;
- }
- else
- {
- if ((INT16)ACCUM_M(accum) >= 0)
- {
- return negative;
- }
- else
- {
- return ACCUM_M(accum);
- }
- }
- }
- else
- {
- if ((UINT16)(ACCUM_H(accum)) != 0)
- {
- return positive;
- }
- else
- {
- if ((INT16)ACCUM_M(accum) < 0)
- {
- return positive;
- }
- else
- {
- return ACCUM_M(accum);
- }
- }
- }
- // never executed
- //return 0;
-}
-
-#if USE_SIMD
-#define VEC_WRITEBACK_RESULT() { \
- SIMD_INSERT16(m_xv[VDREG], vres[0], 0); \
- SIMD_INSERT16(m_xv[VDREG], vres[1], 1); \
- SIMD_INSERT16(m_xv[VDREG], vres[2], 2); \
- SIMD_INSERT16(m_xv[VDREG], vres[3], 3); \
- SIMD_INSERT16(m_xv[VDREG], vres[4], 4); \
- SIMD_INSERT16(m_xv[VDREG], vres[5], 5); \
- SIMD_INSERT16(m_xv[VDREG], vres[6], 6); \
- SIMD_INSERT16(m_xv[VDREG], vres[7], 7); \
-}
-#endif
-
-#define WRITEBACK_RESULT() { \
- W_VREG_S(VDREG, 0) = vres[0]; \
- W_VREG_S(VDREG, 1) = vres[1]; \
- W_VREG_S(VDREG, 2) = vres[2]; \
- W_VREG_S(VDREG, 3) = vres[3]; \
- W_VREG_S(VDREG, 4) = vres[4]; \
- W_VREG_S(VDREG, 5) = vres[5]; \
- W_VREG_S(VDREG, 6) = vres[6]; \
- W_VREG_S(VDREG, 7) = vres[7]; \
-}
-
-#if USE_SIMD
-/* ============================================================================
-* RSPPackLo32to16: Pack LSBs of 32-bit vectors to 16-bits without saturation.
-* TODO: 5 SSE2 operations is kind of expensive just to truncate values?
-* ========================================================================= */
-INLINE __m128i RSPPackLo32to16(__m128i vectorLow, __m128i vectorHigh)
-{
- vectorLow = _mm_slli_epi32(vectorLow, 16);
- vectorHigh = _mm_slli_epi32(vectorHigh, 16);
- vectorLow = _mm_srai_epi32(vectorLow, 16);
- vectorHigh = _mm_srai_epi32(vectorHigh, 16);
- return _mm_packs_epi32(vectorLow, vectorHigh);
-}
-
-/* ============================================================================
-* RSPPackHi32to16: Pack MSBs of 32-bit vectors to 16-bits without saturation.
-* ========================================================================= */
-INLINE __m128i RSPPackHi32to16(__m128i vectorLow, __m128i vectorHigh)
-{
- vectorLow = _mm_srai_epi32(vectorLow, 16);
- vectorHigh = _mm_srai_epi32(vectorHigh, 16);
- return _mm_packs_epi32(vectorLow, vectorHigh);
-}
-
-/* ============================================================================
-* RSPSignExtend16to32: Sign-extend 16-bit slices to 32-bit slices.
-* ========================================================================= */
-INLINE void RSPSignExtend16to32(__m128i source, __m128i *vectorLow, __m128i *vectorHigh)
-{
- __m128i vMask = _mm_srai_epi16(source, 15);
- *vectorHigh = _mm_unpackhi_epi16(source, vMask);
- *vectorLow = _mm_unpacklo_epi16(source, vMask);
-}
-
-/* ============================================================================
-* RSPZeroExtend16to32: Zero-extend 16-bit slices to 32-bit slices.
-* ========================================================================= */
-INLINE void RSPZeroExtend16to32(__m128i source, __m128i *vectorLow, __m128i *vectorHigh)
-{
- *vectorHigh = _mm_unpackhi_epi16(source, _mm_setzero_si128());
- *vectorLow = _mm_unpacklo_epi16(source, _mm_setzero_si128());
-}
-
-/* ============================================================================
-* _mm_mullo_epi32: SSE2 lacks _mm_mullo_epi32, define it manually.
-* TODO/WARNING/DISCLAIMER: Assumes one argument is positive.
-* ========================================================================= */
-INLINE __m128i _mm_mullo_epi32(__m128i a, __m128i b)
-{
- __m128i a4 = _mm_srli_si128(a, 4);
- __m128i b4 = _mm_srli_si128(b, 4);
- __m128i ba = _mm_mul_epu32(b, a);
- __m128i b4a4 = _mm_mul_epu32(b4, a4);
-
- __m128i mask = _mm_setr_epi32(~0, 0, ~0, 0);
- __m128i baMask = _mm_and_si128(ba, mask);
- __m128i b4a4Mask = _mm_and_si128(b4a4, mask);
- __m128i b4a4MaskShift = _mm_slli_si128(b4a4Mask, 4);
-
- return _mm_or_si128(baMask, b4a4MaskShift);
-}
-
-/* ============================================================================
-* RSPClampLowToVal: Clamps the low word of the accumulator.
-* ========================================================================= */
-INLINE __m128i RSPClampLowToVal(__m128i vaccLow, __m128i vaccMid, __m128i vaccHigh)
-{
- __m128i setMask = _mm_cmpeq_epi16(_mm_setzero_si128(), _mm_setzero_si128());
- __m128i negCheck, useValMask, negVal, posVal;
-
- /* Compute some common values ahead of time. */
- negCheck = _mm_cmplt_epi16(vaccHigh, _mm_setzero_si128());
-
- /* If accmulator < 0, clamp to val if val != TMin. */
- useValMask = _mm_and_si128(vaccHigh, _mm_srai_epi16(vaccMid, 15));
- useValMask = _mm_cmpeq_epi16(useValMask, setMask);
- negVal = _mm_and_si128(useValMask, vaccLow);
-
- /* Otherwise, clamp to ~0 if any high bits are set. */
- useValMask = _mm_or_si128(vaccHigh, _mm_srai_epi16(vaccMid, 15));
- useValMask = _mm_cmpeq_epi16(useValMask, _mm_setzero_si128());
- posVal = _mm_and_si128(useValMask, vaccLow);
-
- negVal = _mm_and_si128(negCheck, negVal);
- posVal = _mm_andnot_si128(negCheck, posVal);
- return _mm_or_si128(negVal, posVal);
-}
-#endif
-
-#if USE_SIMD
-// VMULF
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000000 |
-// ------------------------------------------------------
-//
-// Multiplies signed integer by signed integer * 2
-
-inline void rsp_device::ccfunc_rsp_vmulf_simd()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- VEC_GET_SCALAR_VS1(w1, i);
- VEC_GET_SCALAR_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- if (s1 == -32768 && s2 == -32768)
- {
- // overflow
- VEC_SET_ACCUM_H(0, i);
- VEC_SET_ACCUM_M(-32768, i);
- VEC_SET_ACCUM_L(-32768, i);
- vres[i] = 0x7fff;
- }
- else
- {
- INT64 r = s1 * s2 * 2;
- r += 0x8000; // rounding ?
- VEC_SET_ACCUM_H((r < 0) ? 0xffff : 0, i);
- VEC_SET_ACCUM_M((INT16)(r >> 16), i);
- VEC_SET_ACCUM_L((UINT16)(r), i);
- vres[i] = VEC_ACCUM_M(i);
- }
- }
- VEC_WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmulf_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmulf_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmulf_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- if (s1 == -32768 && s2 == -32768)
- {
- // overflow
- SET_ACCUM_H(0, i);
- SET_ACCUM_M(-32768, i);
- SET_ACCUM_L(-32768, i);
- vres[i] = 0x7fff;
- }
- else
- {
- INT64 r = s1 * s2 * 2;
- r += 0x8000; // rounding ?
- SET_ACCUM_H((r < 0) ? 0xffff : 0, i);
- SET_ACCUM_M((INT16)(r >> 16), i);
- SET_ACCUM_L((UINT16)(r), i);
- vres[i] = ACCUM_M(i);
- }
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmulf_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmulf_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMULU
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 |
-// ------------------------------------------------------
-//
-
-inline void rsp_device::ccfunc_rsp_vmulu_simd()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- VEC_GET_SCALAR_VS1(w1, i);
- VEC_GET_SCALAR_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- INT64 r = s1 * s2 * 2;
- r += 0x8000; // rounding ?
-
- VEC_SET_ACCUM_H((UINT16)(r >> 32), i);
- VEC_SET_ACCUM_M((UINT16)(r >> 16), i);
- VEC_SET_ACCUM_L((UINT16)(r), i);
-
- if (r < 0)
- {
- vres[i] = 0;
- }
- else if (((INT16)(VEC_ACCUM_H(i)) ^ (INT16)(VEC_ACCUM_M(i))) < 0)
- {
- vres[i] = -1;
- }
- else
- {
- vres[i] = VEC_ACCUM_M(i);
- }
- }
- VEC_WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmulu_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmulu_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmulu_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- INT64 r = s1 * s2 * 2;
- r += 0x8000; // rounding ?
-
- SET_ACCUM_H((UINT16)(r >> 32), i);
- SET_ACCUM_M((UINT16)(r >> 16), i);
- SET_ACCUM_L((UINT16)(r), i);
-
- if (r < 0)
- {
- vres[i] = 0;
- }
- else if (((INT16)(ACCUM_H(i)) ^ (INT16)(ACCUM_M(i))) < 0)
- {
- vres[i] = -1;
- }
- else
- {
- vres[i] = ACCUM_M(i);
- }
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmulu_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmulu_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMUDL
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 |
-// ------------------------------------------------------
-//
-// Multiplies signed integer by unsigned fraction
-// The result is added into accumulator
-// The middle slice of accumulator is stored into destination element
-
-inline void rsp_device::ccfunc_rsp_vmudl_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i vsReg = m_xv[VS1REG];
- __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- /* Unpack to obtain for 32-bit precision. */
- __m128i unpackLo = _mm_mullo_epi16(vsReg, vtReg);
- __m128i unpackHi = _mm_mulhi_epu16(vsReg, vtReg);
- __m128i loProduct = _mm_unpacklo_epi16(unpackLo, unpackHi);
- __m128i hiProduct = _mm_unpackhi_epi16(unpackLo, unpackHi);
-
- m_xv[VDREG] = m_accum_l = RSPPackHi32to16(loProduct, hiProduct);
-
- m_accum_m = _mm_setzero_si128();
- m_accum_h = _mm_setzero_si128();
-}
-
-static void cfunc_rsp_vmudl_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmudl_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmudl_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- UINT32 s1 = (UINT32)(UINT16)w1;
- UINT32 s2 = (UINT32)(UINT16)w2;
-
- UINT32 r = s1 * s2;
-
- SET_ACCUM_H(0, i);
- SET_ACCUM_M(0, i);
- SET_ACCUM_L((UINT16)(r >> 16), i);
-
- vres[i] = ACCUM_L(i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmudl_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmudl_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMUDM
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000101 |
-// ------------------------------------------------------
-//
-// Multiplies signed integer by unsigned fraction
-// The result is stored into accumulator
-// The middle slice of accumulator is stored into destination element
-
-inline void rsp_device::ccfunc_rsp_vmudm_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i vsRegLo, vsRegHi, vtRegLo, vtRegHi;
-
- __m128i vsReg = m_xv[VS1REG];
- __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- /* Unpack to obtain for 32-bit precision. */
- RSPSignExtend16to32(vsReg, &vsRegLo, &vsRegHi);
- RSPZeroExtend16to32(vtReg, &vtRegLo, &vtRegHi);
-
- /* Begin accumulating the products. */
- __m128i loProduct = _mm_mullo_epi32(vsRegLo, vtRegLo);
- __m128i hiProduct = _mm_mullo_epi32(vsRegHi, vtRegHi);
- m_accum_l = RSPPackLo32to16(loProduct, hiProduct);
- m_accum_m = m_xv[VDREG] = RSPPackHi32to16(loProduct, hiProduct);
-
- loProduct = _mm_cmplt_epi32(loProduct, _mm_setzero_si128());
- hiProduct = _mm_cmplt_epi32(hiProduct, _mm_setzero_si128());
- m_accum_h = _mm_packs_epi32(loProduct, hiProduct);
-}
-
-static void cfunc_rsp_vmudm_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmudm_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmudm_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (UINT16)w2;
-
- INT32 r = s1 * s2;
-
- SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit
- SET_ACCUM_M((INT16)(r >> 16), i);
- SET_ACCUM_L((UINT16)r, i);
-
- vres[i] = ACCUM_M(i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmudm_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmudm_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMUDN
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 |
-// ------------------------------------------------------
-//
-// Multiplies unsigned fraction by signed integer
-// The result is stored into accumulator
-// The low slice of accumulator is stored into destination element
-
-inline void rsp_device::ccfunc_rsp_vmudn_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i vsRegLo, vsRegHi, vtRegLo, vtRegHi;
-
- __m128i vsReg = m_xv[VS1REG];
- __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- /* Unpack to obtain for 32-bit precision. */
- RSPZeroExtend16to32(vsReg, &vsRegLo, &vsRegHi);
- RSPSignExtend16to32(vtReg, &vtRegLo, &vtRegHi);
-
- /* Begin accumulating the products. */
- __m128i loProduct = _mm_mullo_epi32(vsRegLo, vtRegLo);
- __m128i hiProduct = _mm_mullo_epi32(vsRegHi, vtRegHi);
- m_xv[VDREG] = m_accum_l = RSPPackLo32to16(loProduct, hiProduct);
- m_accum_m = RSPPackHi32to16(loProduct, hiProduct);
- m_accum_h = _mm_cmplt_epi16(m_accum_m, _mm_setzero_si128());
-}
-
-static void cfunc_rsp_vmudn_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmudn_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmudn_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8] = { 0 };
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (UINT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- INT32 r = s1 * s2;
-
- SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit
- SET_ACCUM_M((INT16)(r >> 16), i);
- SET_ACCUM_L((UINT16)(r), i);
-
- vres[i] = (UINT16)(r);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmudn_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmudn_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMUDH
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000111 |
-// ------------------------------------------------------
-//
-// Multiplies signed integer by signed integer
-// The result is stored into highest 32 bits of accumulator, the low slice is zero
-// The highest 32 bits of accumulator is saturated into destination element
-
-inline void rsp_device::ccfunc_rsp_vmudh_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i vaccLow, vaccHigh;
- __m128i unpackLo, unpackHi;
-
- __m128i vsReg = m_xv[VS1REG];
- __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- /* Multiply the sources, accumulate the product. */
- unpackLo = _mm_mullo_epi16(vsReg, vtReg);
- unpackHi = _mm_mulhi_epi16(vsReg, vtReg);
- vaccHigh = _mm_unpackhi_epi16(unpackLo, unpackHi);
- vaccLow = _mm_unpacklo_epi16(unpackLo, unpackHi);
-
- /* Pack the accumulator and result back up. */
- m_xv[VDREG] = _mm_packs_epi32(vaccLow, vaccHigh);
- m_accum_l = _mm_setzero_si128();
- m_accum_m = RSPPackLo32to16(vaccLow, vaccHigh);
- m_accum_h = RSPPackHi32to16(vaccLow, vaccHigh);
-}
-
-static void cfunc_rsp_vmudh_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmudh_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmudh_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- INT32 r = s1 * s2;
-
- SET_ACCUM_H((INT16)(r >> 16), i);
- SET_ACCUM_M((UINT16)(r), i);
- SET_ACCUM_L(0, i);
-
- if (r < -32768) r = -32768;
- if (r > 32767) r = 32767;
- vres[i] = (INT16)(r);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmudh_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmudh_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMACF
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001000 |
-// ------------------------------------------------------
-//
-
-inline void rsp_device::ccfunc_rsp_vmacf_simd()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- VEC_GET_SCALAR_VS1(w1, i);
- VEC_GET_SCALAR_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- INT32 r = s1 * s2;
-
- UINT64 q = (UINT64)(UINT16)VEC_ACCUM_LL(i);
- q |= (((UINT64)(UINT16)VEC_ACCUM_L(i)) << 16);
- q |= (((UINT64)(UINT16)VEC_ACCUM_M(i)) << 32);
- q |= (((UINT64)(UINT16)VEC_ACCUM_H(i)) << 48);
-
- q += (INT64)(r) << 17;
- VEC_SET_ACCUM_LL((UINT16)q, i);
- VEC_SET_ACCUM_L((UINT16)(q >> 16), i);
- VEC_SET_ACCUM_M((UINT16)(q >> 32), i);
- VEC_SET_ACCUM_H((UINT16)(q >> 48), i);
-
- vres[i] = VEC_SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
- }
- VEC_WRITEBACK_RESULT();
-/*
- __m128i loProduct, hiProduct, unpackLo, unpackHi;
- __m128i vaccHigh;
- __m128i vdReg, vdRegLo, vdRegHi;
-
- __m128i vsReg = m_xv[VS1REG];
- __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- __m128i vaccLow = m_accum_l;
-
- // Unpack to obtain for 32-bit precision.
- RSPZeroExtend16to32(vaccLow, &vaccLow, &vaccHigh);
-
- // Begin accumulating the products.
- unpackLo = _mm_mullo_epi16(vsReg, vtReg);
- unpackHi = _mm_mulhi_epi16(vsReg, vtReg);
- loProduct = _mm_unpacklo_epi16(unpackLo, unpackHi);
- hiProduct = _mm_unpackhi_epi16(unpackLo, unpackHi);
- loProduct = _mm_slli_epi32(loProduct, 1);
- hiProduct = _mm_slli_epi32(hiProduct, 1);
-
- vdRegLo = _mm_srli_epi32(loProduct, 16);
- vdRegHi = _mm_srli_epi32(hiProduct, 16);
- vdRegLo = _mm_slli_epi32(vdRegLo, 16);
- vdRegHi = _mm_slli_epi32(vdRegHi, 16);
- vdRegLo = _mm_xor_si128(vdRegLo, loProduct);
- vdRegHi = _mm_xor_si128(vdRegHi, hiProduct);
-
- vaccLow = _mm_add_epi32(vaccLow, vdRegLo);
- vaccHigh = _mm_add_epi32(vaccHigh, vdRegHi);
-
- m_accum_l = vdReg = RSPPackLo32to16(vaccLow, vaccHigh);
-
- // Multiply the MSB of sources, accumulate the product.
- vdRegLo = _mm_unpacklo_epi16(m_accum_m, m_accum_h);
- vdRegHi = _mm_unpackhi_epi16(m_accum_m, m_accum_h);
-
- loProduct = _mm_srai_epi32(loProduct, 16);
- hiProduct = _mm_srai_epi32(hiProduct, 16);
- vaccLow = _mm_srai_epi32(vaccLow, 16);
- vaccHigh = _mm_srai_epi32(vaccHigh, 16);
-
- vaccLow = _mm_add_epi32(loProduct, vaccLow);
- vaccHigh = _mm_add_epi32(hiProduct, vaccHigh);
- vaccLow = _mm_add_epi32(vdRegLo, vaccLow);
- vaccHigh = _mm_add_epi32(vdRegHi, vaccHigh);
-
- // Clamp the accumulator and write it all out.
- m_xv[VDREG] = _mm_packs_epi32(vaccLow, vaccHigh);
- m_accum_m = RSPPackLo32to16(vaccLow, vaccHigh);
- m_accum_h = RSPPackHi32to16(vaccLow, vaccHigh);
-*/
-}
-
-static void cfunc_rsp_vmacf_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmacf_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmacf_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- INT32 r = s1 * s2;
-
- UINT64 q = (UINT64)(UINT16)ACCUM_LL(i);
- q |= (((UINT64)(UINT16)ACCUM_L(i)) << 16);
- q |= (((UINT64)(UINT16)ACCUM_M(i)) << 32);
- q |= (((UINT64)(UINT16)ACCUM_H(i)) << 48);
-
- q += (INT64)(r) << 17;
- SET_ACCUM_LL((UINT16)q, i);
- SET_ACCUM_L((UINT16)(q >> 16), i);
- SET_ACCUM_M((UINT16)(q >> 32), i);
- SET_ACCUM_H((UINT16)(q >> 48), i);
-
- vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmacf_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmacf_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMACU
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 |
-// ------------------------------------------------------
-//
-
-inline void rsp_device::ccfunc_rsp_vmacu_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i loProduct, hiProduct, unpackLo, unpackHi;
- __m128i vaccHigh;
- __m128i vdReg, vdRegLo, vdRegHi;
-
- __m128i vsReg = m_xv[VS1REG];
- __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- __m128i vaccLow = m_accum_l;
-
- /* Unpack to obtain for 32-bit precision. */
- RSPZeroExtend16to32(vaccLow, &vaccLow, &vaccHigh);
-
- /* Begin accumulating the products. */
- unpackLo = _mm_mullo_epi16(vsReg, vtReg);
- unpackHi = _mm_mulhi_epi16(vsReg, vtReg);
- loProduct = _mm_unpacklo_epi16(unpackLo, unpackHi);
- hiProduct = _mm_unpackhi_epi16(unpackLo, unpackHi);
- loProduct = _mm_slli_epi32(loProduct, 1);
- hiProduct = _mm_slli_epi32(hiProduct, 1);
-
- vdRegLo = _mm_srli_epi32(loProduct, 16);
- vdRegHi = _mm_srli_epi32(hiProduct, 16);
- vdRegLo = _mm_slli_epi32(vdRegLo, 16);
- vdRegHi = _mm_slli_epi32(vdRegHi, 16);
- vdRegLo = _mm_xor_si128(vdRegLo, loProduct);
- vdRegHi = _mm_xor_si128(vdRegHi, hiProduct);
-
- vaccLow = _mm_add_epi32(vaccLow, vdRegLo);
- vaccHigh = _mm_add_epi32(vaccHigh, vdRegHi);
-
- m_accum_l = vdReg = RSPPackLo32to16(vaccLow, vaccHigh);
-
- /* Multiply the MSB of sources, accumulate the product. */
- vdRegLo = _mm_unpacklo_epi16(m_accum_m, m_accum_h);
- vdRegHi = _mm_unpackhi_epi16(m_accum_m, m_accum_h);
-
- loProduct = _mm_srai_epi32(loProduct, 16);
- hiProduct = _mm_srai_epi32(hiProduct, 16);
- vaccLow = _mm_srai_epi32(vaccLow, 16);
- vaccHigh = _mm_srai_epi32(vaccHigh, 16);
-
- vaccLow = _mm_add_epi32(loProduct, vaccLow);
- vaccHigh = _mm_add_epi32(hiProduct, vaccHigh);
- vaccLow = _mm_add_epi32(vdRegLo, vaccLow);
- vaccHigh = _mm_add_epi32(vdRegHi, vaccHigh);
-
- /* Clamp the accumulator and write it all out. */
- m_accum_m = RSPPackLo32to16(vaccLow, vaccHigh);
- m_accum_h = RSPPackHi32to16(vaccLow, vaccHigh);
-}
-
-static void cfunc_rsp_vmacu_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmacu_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmacu_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- INT32 r1 = s1 * s2;
- UINT32 r2 = (UINT16)ACCUM_L(i) + ((UINT16)(r1) * 2);
- UINT32 r3 = (UINT16)ACCUM_M(i) + (UINT16)((r1 >> 16) * 2) + (UINT16)(r2 >> 16);
-
- SET_ACCUM_L((UINT16)(r2), i);
- SET_ACCUM_M((UINT16)(r3), i);
- SET_ACCUM_H(ACCUM_H(i) + (UINT16)(r3 >> 16) + (UINT16)(r1 >> 31), i);
-
- if ((INT16)ACCUM_H(i) < 0)
- {
- vres[i] = 0;
- }
- else
- {
- if (ACCUM_H(i) != 0)
- {
- vres[i] = (INT16)0xffff;
- }
- else
- {
- if ((INT16)ACCUM_M(i) < 0)
- {
- vres[i] = (INT16)0xffff;
- }
- else
- {
- vres[i] = ACCUM_M(i);
- }
- }
- }
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmacu_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmacu_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMADL
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001100 |
-// ------------------------------------------------------
-//
-// Multiplies unsigned fraction by unsigned fraction
-// Adds the higher 16 bits of the 32-bit result to accumulator
-// The low slice of accumulator is stored into destination element
-
-inline void rsp_device::ccfunc_rsp_vmadl_simd()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- VEC_GET_SCALAR_VS1(w1, i);
- VEC_GET_SCALAR_VS2(w2, i);
- UINT32 s1 = w1;
- UINT32 s2 = w2;
-
- UINT32 r1 = s1 * s2;
- UINT32 r2 = (UINT16)VEC_ACCUM_L(i) + (r1 >> 16);
- UINT32 r3 = (UINT16)VEC_ACCUM_M(i) + (r2 >> 16);
-
- VEC_SET_ACCUM_L((UINT16)r2, i);
- VEC_SET_ACCUM_M((UINT16)r3, i);
- VEC_SET_ACCUM_H(VEC_ACCUM_H(i) + (INT16)(r3 >> 16), i);
-
- vres[i] = VEC_SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
- }
- VEC_WRITEBACK_RESULT();
-
- /*__m128i vaccHigh;
- __m128i unpackHi, loProduct, hiProduct;
- __m128i vdReg, vdRegLo, vdRegHi;
-
- __m128i vsReg = m_xv[VS1REG];
- __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- __m128i vaccLow = m_accum_l;
-
- // Unpack to obtain for 32-bit precision.
- RSPZeroExtend16to32(vaccLow, &vaccLow, &vaccHigh);
-
- // Begin accumulating the products.
- unpackHi = _mm_mulhi_epu16(vsReg, vtReg);
- loProduct = _mm_unpacklo_epi16(unpackHi, _mm_setzero_si128());
- hiProduct = _mm_unpackhi_epi16(unpackHi, _mm_setzero_si128());
-
- vaccLow = _mm_add_epi32(vaccLow, loProduct);
- vaccHigh = _mm_add_epi32(vaccHigh, hiProduct);
- m_accum_l = vdReg = RSPPackLo32to16(vaccLow, vaccHigh);
-
- // Finish accumulating whatever is left.
- vdRegLo = _mm_unpacklo_epi16(m_accum_m, m_accum_h);
- vdRegHi = _mm_unpackhi_epi16(m_accum_m, m_accum_h);
-
- vaccLow = _mm_srai_epi32(vaccLow, 16);
- vaccHigh = _mm_srai_epi32(vaccHigh, 16);
- vaccLow = _mm_add_epi32(vdRegLo, vaccLow);
- vaccHigh = _mm_add_epi32(vdRegHi, vaccHigh);
-
- // Clamp the accumulator and write it all out.
- m_accum_m = RSPPackLo32to16(vaccLow, vaccHigh);
- m_accum_h = RSPPackHi32to16(vaccLow, vaccHigh);
- m_xv[VDREG] = RSPClampLowToVal(vdReg, m_accum_m, m_accum_h);*/
-}
-
-static void cfunc_rsp_vmadl_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmadl_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmadl_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- UINT32 s1 = w1;
- UINT32 s2 = w2;
-
- UINT32 r1 = s1 * s2;
- UINT32 r2 = (UINT16)ACCUM_L(i) + (r1 >> 16);
- UINT32 r3 = (UINT16)ACCUM_M(i) + (r2 >> 16);
-
- SET_ACCUM_L((UINT16)r2, i);
- SET_ACCUM_M((UINT16)r3, i);
- SET_ACCUM_H(ACCUM_H(i) + (INT16)(r3 >> 16), i);
-
- vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmadl_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmadl_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMADM
-//
-
-inline void rsp_device::ccfunc_rsp_vmadm_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i vaccLow, vaccHigh, loProduct, hiProduct;
- __m128i vsRegLo, vsRegHi, vtRegLo, vtRegHi, vdRegLo, vdRegHi;
-
- __m128i vsReg = m_xv[VS1REG];
- __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- /* Unpack to obtain for 32-bit precision. */
- RSPSignExtend16to32(vsReg, &vsRegLo, &vsRegHi);
- RSPZeroExtend16to32(vtReg, &vtRegLo, &vtRegHi);
- RSPZeroExtend16to32(m_accum_l, &vaccLow, &vaccHigh);
-
- /* Begin accumulating the products. */
- loProduct = _mm_mullo_epi32(vsRegLo, vtRegLo);
- hiProduct = _mm_mullo_epi32(vsRegHi, vtRegHi);
-
- vdRegLo = _mm_srli_epi32(loProduct, 16);
- vdRegHi = _mm_srli_epi32(hiProduct, 16);
- vdRegLo = _mm_slli_epi32(vdRegLo, 16);
- vdRegHi = _mm_slli_epi32(vdRegHi, 16);
- vdRegLo = _mm_xor_si128(vdRegLo, loProduct);
- vdRegHi = _mm_xor_si128(vdRegHi, hiProduct);
- vaccLow = _mm_add_epi32(vaccLow, vdRegLo);
- vaccHigh = _mm_add_epi32(vaccHigh, vdRegHi);
-
- m_accum_l = m_xv[VDREG] = RSPPackLo32to16(vaccLow, vaccHigh);
-
- /* Multiply the MSB of sources, accumulate the product. */
- vdRegLo = _mm_unpacklo_epi16(m_accum_m, m_accum_h);
- vdRegHi = _mm_unpackhi_epi16(m_accum_m, m_accum_h);
-
- loProduct = _mm_srai_epi32(loProduct, 16);
- hiProduct = _mm_srai_epi32(hiProduct, 16);
- vaccLow = _mm_srai_epi32(vaccLow, 16);
- vaccHigh = _mm_srai_epi32(vaccHigh, 16);
-
- vaccLow = _mm_add_epi32(loProduct, vaccLow);
- vaccHigh = _mm_add_epi32(hiProduct, vaccHigh);
- vaccLow = _mm_add_epi32(vdRegLo, vaccLow);
- vaccHigh = _mm_add_epi32(vdRegHi, vaccHigh);
-
- /* Clamp the accumulator and write it all out. */
- m_xv[VDREG] = _mm_packs_epi32(vaccLow, vaccHigh);
- m_accum_m = RSPPackLo32to16(vaccLow, vaccHigh);
- m_accum_h = RSPPackHi32to16(vaccLow, vaccHigh);
-}
-
-static void cfunc_rsp_vmadm_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmadm_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmadm_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- UINT32 s1 = (INT32)(INT16)w1;
- UINT32 s2 = (UINT16)w2;
-
- UINT32 r1 = s1 * s2;
- UINT32 r2 = (UINT16)ACCUM_L(i) + (UINT16)(r1);
- UINT32 r3 = (UINT16)ACCUM_M(i) + (r1 >> 16) + (r2 >> 16);
-
- SET_ACCUM_L((UINT16)r2, i);
- SET_ACCUM_M((UINT16)r3, i);
- SET_ACCUM_H((UINT16)ACCUM_H(i) + (UINT16)(r3 >> 16), i);
- if ((INT32)(r1) < 0)
- {
- SET_ACCUM_H((UINT16)ACCUM_H(i) - 1, i);
- }
-
- vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmadm_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmadm_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMADN
-//
-
-inline void rsp_device::ccfunc_rsp_vmadn_simd()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- VEC_GET_SCALAR_VS1(w1, i);
- VEC_GET_SCALAR_VS2(w2, i);
- INT32 s1 = (UINT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- UINT64 q = (UINT64)VEC_ACCUM_LL(i);
- q |= (((UINT64)VEC_ACCUM_L(i)) << 16);
- q |= (((UINT64)VEC_ACCUM_M(i)) << 32);
- q |= (((UINT64)VEC_ACCUM_H(i)) << 48);
- q += (INT64)(s1*s2) << 16;
-
- VEC_SET_ACCUM_LL((UINT16)q, i);
- VEC_SET_ACCUM_L((UINT16)(q >> 16), i);
- VEC_SET_ACCUM_M((UINT16)(q >> 32), i);
- VEC_SET_ACCUM_H((UINT16)(q >> 48), i);
-
- vres[i] = VEC_SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
- }
- VEC_WRITEBACK_RESULT();
-}
-/*INLINE void cfunc_rsp_vmadn_simd(void *param)
-{
- rsp_state *rsp = (rsp_state*)param;
- int op = m_rsp_state->arg0;
-
- __m128i vaccLow, vaccHigh, loProduct, hiProduct;
- __m128i vsRegLo, vsRegHi, vtRegLo, vtRegHi, vdRegLo, vdRegHi;
-
- __m128i vsReg = m_xv[VS1REG];
- __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- vaccLow = m_accum_l;
-
- RSPZeroExtend16to32(vsReg, &vsRegLo, &vsRegHi);
- RSPSignExtend16to32(vtReg, &vtRegLo, &vtRegHi);
- RSPZeroExtend16to32(vaccLow, &vaccLow, &vaccHigh);
-
- // Begin accumulating the products.
- loProduct = _mm_mullo_epi32(vsRegLo, vtRegLo);
- hiProduct = _mm_mullo_epi32(vsRegHi, vtRegHi);
-
- vdRegLo = _mm_srli_epi32(loProduct, 16);
- vdRegHi = _mm_srli_epi32(hiProduct, 16);
- vdRegLo = _mm_slli_epi32(vdRegLo, 16);
- vdRegHi = _mm_slli_epi32(vdRegHi, 16);
- vdRegLo = _mm_xor_si128(vdRegLo, loProduct);
- vdRegHi = _mm_xor_si128(vdRegHi, hiProduct);
-
- vaccLow = _mm_add_epi32(vaccLow, vdRegLo);
- vaccHigh = _mm_add_epi32(vaccHigh, vdRegHi);
-
- m_accum_l = RSPPackLo32to16(vaccLow, vaccHigh);
-
- // Multiply the MSB of sources, accumulate the product.
- vdRegLo = _mm_unpacklo_epi16(m_accum_m, m_accum_h);
- vdRegHi = _mm_unpackhi_epi16(m_accum_m, m_accum_h);
-
- loProduct = _mm_srai_epi32(loProduct, 16);
- hiProduct = _mm_srai_epi32(hiProduct, 16);
- vaccLow = _mm_srai_epi32(vaccLow, 16);
- vaccHigh = _mm_srai_epi32(vaccHigh, 16);
-
- vaccLow = _mm_add_epi32(loProduct, vaccLow);
- vaccHigh = _mm_add_epi32(hiProduct, vaccHigh);
- vaccLow = _mm_add_epi32(vdRegLo, vaccLow);
- vaccHigh = _mm_add_epi32(vdRegHi, vaccHigh);
-
- // Clamp the accumulator and write it all out.
- m_accum_m = RSPPackLo32to16(vaccLow, vaccHigh);
- m_accum_h = RSPPackHi32to16(vaccLow, vaccHigh);
- m_xv[VDREG] = RSPClampLowToVal(m_accum_l, m_accum_m, m_accum_h);
-}*/
-
-static void cfunc_rsp_vmadn_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmadn_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmadn_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (UINT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- UINT64 q = (UINT64)ACCUM_LL(i);
- q |= (((UINT64)ACCUM_L(i)) << 16);
- q |= (((UINT64)ACCUM_M(i)) << 32);
- q |= (((UINT64)ACCUM_H(i)) << 48);
- q += (INT64)(s1*s2) << 16;
-
- SET_ACCUM_LL((UINT16)q, i);
- SET_ACCUM_L((UINT16)(q >> 16), i);
- SET_ACCUM_M((UINT16)(q >> 32), i);
- SET_ACCUM_H((UINT16)(q >> 48), i);
-
- vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmadn_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmadn_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMADH
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001111 |
-// ------------------------------------------------------
-//
-// Multiplies signed integer by signed integer
-// The result is added into highest 32 bits of accumulator, the low slice is zero
-// The highest 32 bits of accumulator is saturated into destination element
-
-inline void rsp_device::ccfunc_rsp_vmadh_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i vsReg = m_xv[VS1REG];
- __m128i vtReg = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- /* Unpack to obtain for 32-bit precision. */
- __m128i vaccLow = _mm_unpacklo_epi16(m_accum_m, m_accum_h);
- __m128i vaccHigh = _mm_unpackhi_epi16(m_accum_m, m_accum_h);
-
- /* Multiply the sources, accumulate the product. */
- __m128i unpackLo = _mm_mullo_epi16(vsReg, vtReg);
- __m128i unpackHi = _mm_mulhi_epi16(vsReg, vtReg);
- __m128i loProduct = _mm_unpacklo_epi16(unpackLo, unpackHi);
- __m128i hiProduct = _mm_unpackhi_epi16(unpackLo, unpackHi);
- vaccLow = _mm_add_epi32(vaccLow, loProduct);
- vaccHigh = _mm_add_epi32(vaccHigh, hiProduct);
-
- /* Pack the accumulator and result back up. */
- m_xv[VDREG] = _mm_packs_epi32(vaccLow, vaccHigh);
- m_accum_m = RSPPackLo32to16(vaccLow, vaccHigh);
- m_accum_h = RSPPackHi32to16(vaccLow, vaccHigh);
-}
-
-static void cfunc_rsp_vmadh_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmadh_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmadh_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- INT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
-
- INT32 accum = (UINT32)(UINT16)ACCUM_M(i);
- accum |= ((UINT32)((UINT16)ACCUM_H(i))) << 16;
- accum += s1 * s2;
-
- SET_ACCUM_H((UINT16)(accum >> 16), i);
- SET_ACCUM_M((UINT16)accum, i);
-
- vres[i] = SATURATE_ACCUM1(i, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmadh_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmadh_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VADD
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010000 |
-// ------------------------------------------------------
-//
-// Adds two vector registers and carry flag, the result is saturated to 32767
-
-inline void rsp_device::ccfunc_rsp_vadd_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i shuffled = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i carry = _mm_and_si128(m_xvflag[CARRY], vec_flagmask);
- m_accum_l = _mm_add_epi16(_mm_add_epi16(m_xv[VS1REG], shuffled), carry);
-
- __m128i addvec = _mm_adds_epi16(m_xv[VS1REG], shuffled);
-
- carry = _mm_and_si128(carry, _mm_xor_si128(_mm_cmpeq_epi16(addvec, vec_32767), vec_neg1));
- carry = _mm_and_si128(carry, _mm_xor_si128(_mm_cmpeq_epi16(addvec, vec_n32768), vec_neg1));
-
- m_xv[VDREG] = _mm_add_epi16(addvec, carry);
-
- m_xvflag[ZERO] = vec_zero;
- m_xvflag[CARRY] = vec_zero;
-}
-
-static void cfunc_rsp_vadd_simd(void *param)
-{
- ((rsp_Device *)param)->ccfunc_rsp_vadd_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vadd_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8] = { 0 };
- for (int i = 0; i < 8; i++)
- {
- INT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
- INT32 r = s1 + s2 + (((CARRY_FLAG(i)) != 0) ? 1 : 0);
-
- SET_ACCUM_L((INT16)(r), i);
-
- if (r > 32767) r = 32767;
- if (r < -32768) r = -32768;
- vres[i] = (INT16)(r);
- }
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vadd_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vadd_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VSUB
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010001 |
-// ------------------------------------------------------
-//
-// Subtracts two vector registers and carry flag, the result is saturated to -32768
-// TODO: check VS2REG == VDREG
-
-inline void rsp_device::ccfunc_rsp_vsub_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i shuffled = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i carry = _mm_and_si128(m_xvflag[CARRY], vec_flagmask);
- __m128i unsat = _mm_sub_epi16(m_xv[VS1REG], shuffled);
-
- __m128i vs2neg = _mm_cmplt_epi16(shuffled, vec_zero);
- __m128i vs2pos = _mm_cmpeq_epi16(vs2neg, vec_zero);
-
- __m128i saturated = _mm_subs_epi16(m_xv[VS1REG], shuffled);
- __m128i carry_mask = _mm_cmpeq_epi16(unsat, saturated);
- carry_mask = _mm_and_si128(vs2neg, carry_mask);
-
- vs2neg = _mm_and_si128(carry_mask, carry);
- vs2pos = _mm_and_si128(vs2pos, carry);
- __m128i dest_carry = _mm_or_si128(vs2neg, vs2pos);
- m_xv[VDREG] = _mm_subs_epi16(saturated, dest_carry);
-
- m_accum_l = _mm_sub_epi16(unsat, carry);
-
- m_xvflag[ZERO] = _mm_setzero_si128();
- m_xvflag[CARRY] = _mm_setzero_si128();
-}
-
-static void cfunc_rsp_vsub_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vsub_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vsub_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- INT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (INT32)(INT16)w1;
- INT32 s2 = (INT32)(INT16)w2;
- INT32 r = s1 - s2 - (((CARRY_FLAG(i)) != 0) ? 1 : 0);
-
- SET_ACCUM_L((INT16)(r), i);
-
- if (r > 32767) r = 32767;
- if (r < -32768) r = -32768;
-
- vres[i] = (INT16)(r);
- }
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vsub_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vsub_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VABS
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010011 |
-// ------------------------------------------------------
-//
-// Changes the sign of source register 2 if source register 1 is negative and stores the result to destination register
-
-inline void rsp_device::ccfunc_rsp_vabs_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i shuf2 = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i negs2 = _mm_sub_epi16(_mm_setzero_si128(), shuf2);
- __m128i s2_n32768 = _mm_cmpeq_epi16(shuf2, vec_n32768);
- __m128i s1_lz = _mm_cmplt_epi16(m_xv[VS1REG], _mm_setzero_si128());
-
- __m128i result_gz = _mm_and_si128(shuf2, _mm_cmpgt_epi16(m_xv[VS1REG], _mm_setzero_si128()));
- __m128i result_n32768 = _mm_and_si128(s1_lz, _mm_and_si128(vec_32767, s2_n32768));
- __m128i result_negs2 = _mm_and_si128(s1_lz, _mm_and_si128(negs2, _mm_xor_si128(s2_n32768, vec_neg1)));
- m_xv[VDREG] = m_accum_l = _mm_or_si128(result_gz, _mm_or_si128(result_n32768, result_negs2));
-}
-
-static void cfunc_rsp_vabs_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vabs_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vabs_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
-
- if (s1 < 0)
- {
- if (s2 == -32768)
- {
- vres[i] = 32767;
- }
- else
- {
- vres[i] = -s2;
- }
- }
- else if (s1 > 0)
- {
- vres[i] = s2;
- }
- else
- {
- vres[i] = 0;
- }
-
- SET_ACCUM_L(vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vabs_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vabs_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VADDC
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010100 |
-// ------------------------------------------------------
-//
-// Adds two vector registers, the carry out is stored into carry register
-// TODO: check VS2REG = VDREG
-
-inline void rsp_device::ccfunc_rsp_vaddc_simd()
-{
- int op = m_rsp_state->arg0;
-
- VEC_CLEAR_ZERO_FLAGS();
- VEC_CLEAR_CARRY_FLAGS();
-
- __m128i shuf2 = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i vec7531 = _mm_and_si128(m_xv[VS1REG], vec_lomask);
- __m128i vec6420 = _mm_srli_epi32(m_xv[VS1REG], 16);
- __m128i shuf7531 = _mm_and_si128(shuf2, vec_lomask);
- __m128i shuf6420 = _mm_srli_epi32(shuf2, 16);
- __m128i sum7531 = _mm_add_epi32(vec7531, shuf7531);
- __m128i sum6420 = _mm_add_epi32(vec6420, shuf6420);
-
- __m128i over7531 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum7531, _mm_setzero_si128()), vec_neg1), vec_himask);
- __m128i over6420 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum6420, _mm_setzero_si128()), vec_neg1), vec_himask);
-
- sum7531 = _mm_and_si128(sum7531, vec_lomask);
- sum6420 = _mm_and_si128(sum6420, vec_lomask);
-
- m_xvflag[CARRY] = _mm_or_si128(over6420, _mm_srli_epi32(over7531, 16));
- m_accum_l = m_xv[VDREG] = _mm_or_si128(_mm_slli_epi32(sum6420, 16), sum7531);
-}
-
-static void cfunc_rsp_vaddc_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vaddc_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vaddc_scalar()
-{
- int op = m_rsp_state->arg0;
-
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
-
- INT16 vres[8] = { 0 };
- for (int i = 0; i < 8; i++)
- {
- INT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (UINT32)(UINT16)w1;
- INT32 s2 = (UINT32)(UINT16)w2;
- INT32 r = s1 + s2;
-
- vres[i] = (INT16)(r);
- SET_ACCUM_L((INT16)r, i);
-
- if (r & 0xffff0000)
- {
- SET_CARRY_FLAG(i);
- }
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vaddc_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vaddc_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VSUBC
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010101 |
-// ------------------------------------------------------
-//
-// Subtracts two vector registers, the carry out is stored into carry register
-// TODO: check VS2REG = VDREG
-
-inline void rsp_device::ccfunc_rsp_vsubc_simd()
-{
- int op = m_rsp_state->arg0;
-
- VEC_CLEAR_ZERO_FLAGS();
- VEC_CLEAR_CARRY_FLAGS();
-
- __m128i shuf2 = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i vec7531 = _mm_and_si128(m_xv[VS1REG], vec_lomask);
- __m128i vec6420 = _mm_srli_epi32(m_xv[VS1REG], 16);
- __m128i shuf7531 = _mm_and_si128(shuf2, vec_lomask);
- __m128i shuf6420 = _mm_srli_epi32(shuf2, 16);
- __m128i sum7531 = _mm_sub_epi32(vec7531, shuf7531);
- __m128i sum6420 = _mm_sub_epi32(vec6420, shuf6420);
-
- __m128i over7531 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum7531, _mm_setzero_si128()), vec_neg1), vec_himask);
- __m128i over6420 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum6420, _mm_setzero_si128()), vec_neg1), vec_himask);
- sum7531 = _mm_and_si128(sum7531, vec_lomask);
- sum6420 = _mm_and_si128(sum6420, vec_lomask);
- __m128i zero7531 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum7531, _mm_setzero_si128()), vec_neg1), vec_lomask);
- __m128i zero6420 = _mm_and_si128(_mm_xor_si128(_mm_cmpeq_epi16(sum6420, _mm_setzero_si128()), vec_neg1), vec_lomask);
-
- m_xvflag[CARRY] = _mm_or_si128(over6420, _mm_srli_epi32(over7531, 16));
- m_xvflag[ZERO] = _mm_or_si128(_mm_slli_epi32(zero6420, 16), zero7531);
-
- m_accum_l = m_xv[VDREG] = _mm_or_si128(_mm_slli_epi32(sum6420, 16), sum7531);
-}
-
-static void cfunc_rsp_vsubc_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vsubc_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vsubc_scalar()
-{
- int op = m_rsp_state->arg0;
-
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- INT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
- INT32 s1 = (UINT32)(UINT16)w1;
- INT32 s2 = (UINT32)(UINT16)w2;
- INT32 r = s1 - s2;
-
- vres[i] = (INT16)(r);
- SET_ACCUM_L((UINT16)r, i);
-
- if ((UINT16)(r) != 0)
- {
- SET_ZERO_FLAG(i);
- }
- if (r & 0xffff0000)
- {
- SET_CARRY_FLAG(i);
- }
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vsubc_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vsubc_scalar();
-}
-#endif
-
-// VADDB
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010110 |
-// ------------------------------------------------------
-//
-// Adds two vector registers bytewise with rounding
-inline void rsp_device::ccfunc_rsp_vaddb_scalar()
-{
- const int op = m_rsp_state->arg0;
- const int round = (EL == 0) ? 0 : (1 << (EL - 1));
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 w1, w2;
- SCALAR_GET_VS1(w1, i);
- SCALAR_GET_VS2(w2, i);
-
- UINT8 hb1 = w1 >> 8;
- UINT8 lb1 = w1 & 0xff;
- UINT8 hb2 = w2 >> 8;
- UINT8 lb2 = w2 & 0xff;
-
- UINT16 hs = hb1 + hb2 + round;
- UINT16 ls = lb1 + lb2 + round;
-
- SET_ACCUM_L((hs << 8) | ls, i);
-
- hs >>= EL;
- if (hs > 255)
- {
- hs = 255;
- }
- /*else if (hs < 0)
- {
- hs = 0;
- }*/
-
- ls >>= EL;
- if (ls > 255)
- {
- ls = 255;
- }
- /*else if (ls < 0)
- {
- ls = 0;
- }*/
-
- vres[i] = 0; // VD writeback disabled on production hardware
- // vres[i] = (hs << 8) | ls;
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vaddb_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vaddb_scalar();
-}
-
-#if USE_SIMD
-// VSAW
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 011101 |
-// ------------------------------------------------------
-//
-// Stores high, middle or low slice of accumulator to destination vector
-
-inline void rsp_device::ccfunc_rsp_vsaw_simd()
-{
- int op = m_rsp_state->arg0;
-
- switch (EL)
- {
- case 0x08: // VSAWH
- {
- m_xv[VDREG] = m_accum_h;
- break;
- }
- case 0x09: // VSAWM
- {
- m_xv[VDREG] = m_accum_m;
- break;
- }
- case 0x0a: // VSAWL
- {
- m_xv[VDREG] = m_accum_l;
- break;
- }
- default: // Unsupported, writes 0 to VD
- {
-
- }
- }
-}
-
-static void cfunc_rsp_vsaw_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vsaw_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vsaw_scalar()
-{
- int op = m_rsp_state->arg0;
-
- switch (EL)
- {
- case 0x08: // VSAWH
- for (int i = 0; i < 8; i++)
- {
- W_VREG_S(VDREG, i) = ACCUM_H(i);
- }
- break;
- case 0x09: // VSAWM
- for (int i = 0; i < 8; i++)
- {
- W_VREG_S(VDREG, i) = ACCUM_M(i);
- }
- break;
- case 0x0a: // VSAWL
- for (int i = 0; i < 8; i++)
- {
- W_VREG_S(VDREG, i) = ACCUM_L(i);
- }
- break;
- default: // Unsupported
- {
- for (int i = 0; i < 8; i++)
- {
- W_VREG_S(VDREG, i) = 0;
- }
- }
- }
-}
-
-static void cfunc_rsp_vsaw_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vsaw_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VLT
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100000 |
-// ------------------------------------------------------
-//
-// Sets compare flags if elements in VS1 are less than VS2
-// Moves the element in VS2 to destination vector
-
-inline void rsp_device::ccfunc_rsp_vlt_simd()
-{
- int op = m_rsp_state->arg0;
-
- m_xvflag[COMPARE] = m_xvflag[CLIP2] = _mm_setzero_si128();
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i zc_mask = _mm_and_si128(m_xvflag[ZERO], m_xvflag[CARRY]);
- __m128i lt_mask = _mm_cmplt_epi16(m_xv[VS1REG], shuf);
- __m128i eq_mask = _mm_and_si128(_mm_cmpeq_epi16(m_xv[VS1REG], shuf), zc_mask);
-
- m_xvflag[COMPARE] = _mm_or_si128(lt_mask, eq_mask);
-
- __m128i result = _mm_and_si128(m_xv[VS1REG], m_xvflag[COMPARE]);
- m_accum_l = m_xv[VDREG] = _mm_or_si128(result, _mm_and_si128(shuf, _mm_xor_si128(m_xvflag[COMPARE], vec_neg1)));
-
- m_xvflag[ZERO] = m_xvflag[CARRY] = _mm_setzero_si128();
-}
-
-static void void cfunc_rsp_vlt_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vlt_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vlt_scalar()
-{
- int op = m_rsp_state->arg0;
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
-
- if (s1 < s2)
- {
- SET_COMPARE_FLAG(i);
- }
- else if (s1 == s2)
- {
- if (ZERO_FLAG(i) != 0 && CARRY_FLAG(i) != 0)
- {
- SET_COMPARE_FLAG(i);
- }
- }
-
- if (COMPARE_FLAG(i) != 0)
- {
- vres[i] = s1;
- }
- else
- {
- vres[i] = s2;
- }
-
- SET_ACCUM_L(vres[i], i);
- }
-
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vlt_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vlt_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VEQ
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100001 |
-// ------------------------------------------------------
-//
-// Sets compare flags if elements in VS1 are equal with VS2
-// Moves the element in VS2 to destination vector
-
-inline void rsp_device::ccfunc_rsp_veq_simd()
-{
- int op = m_rsp_state->arg0;
-
- m_xvflag[COMPARE] = m_xvflag[CLIP2] = _mm_setzero_si128();
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i zero_mask = _mm_cmpeq_epi16(m_xvflag[ZERO], _mm_setzero_si128());
- __m128i eq_mask = _mm_cmpeq_epi16(m_xv[VS1REG], shuf);
-
- m_xvflag[COMPARE] = _mm_and_si128(zero_mask, eq_mask);
-
- __m128i result = _mm_and_si128(m_xv[VS1REG], m_xvflag[COMPARE]);
- m_accum_l = m_xv[VDREG] = _mm_or_si128(result, _mm_and_si128(shuf, _mm_xor_si128(m_xvflag[COMPARE], vec_neg1)));
-
- m_xvflag[ZERO] = m_xvflag[CARRY] = _mm_setzero_si128();
-}
-
-static void cfunc_rsp_veq_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_veq_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_veq_scalar()
-{
- int op = m_rsp_state->arg0;
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
-
- if ((s1 == s2) && ZERO_FLAG(i) == 0)
- {
- SET_COMPARE_FLAG(i);
- vres[i] = s1;
- }
- else
- {
- vres[i] = s2;
- }
-
- SET_ACCUM_L(vres[i], i);
- }
-
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_veq_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_veq_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VNE
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100010 |
-// ------------------------------------------------------
-//
-// Sets compare flags if elements in VS1 are not equal with VS2
-// Moves the element in VS2 to destination vector
-
-inline void rsp_device::ccfunc_rsp_vne_simd()
-{
- int op = m_rsp_state->arg0;
-
- m_xvflag[COMPARE] = m_xvflag[CLIP2] = _mm_setzero_si128();
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i neq_mask = _mm_xor_si128(_mm_cmpeq_epi16(m_xv[VS1REG], shuf), vec_neg1);
-
- m_xvflag[COMPARE] = _mm_or_si128(m_xvflag[ZERO], neq_mask);
-
- __m128i result = _mm_and_si128(m_xv[VS1REG], m_xvflag[COMPARE]);
- m_accum_l = m_xv[VDREG] = _mm_or_si128(result, _mm_and_si128(shuf, _mm_xor_si128(m_xvflag[COMPARE], vec_neg1)));
-
- m_xvflag[ZERO] = m_xvflag[CARRY] = _mm_setzero_si128();
-}
-
-static void cfunc_rsp_vne_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vne_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vne_scalar()
-{
- int op = m_rsp_state->arg0;
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
-
- if (s1 != s2 || ZERO_FLAG(i) != 0)
- {
- SET_COMPARE_FLAG(i);
- vres[i] = s1;
- }
- else
- {
- vres[i] = s2;
- }
-
- SET_ACCUM_L(vres[i], i);
- }
-
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vne_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vne_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VGE
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100011 |
-// ------------------------------------------------------
-//
-// Sets compare flags if elements in VS1 are greater or equal with VS2
-// Moves the element in VS2 to destination vector
-
-inline void rsp_device::ccfunc_rsp_vge_simd()
-{
- int op = m_rsp_state->arg0;
-
- m_xvflag[COMPARE] = m_xvflag[CLIP2] = _mm_setzero_si128();
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i zero_mask = _mm_cmpeq_epi16(m_xvflag[ZERO], _mm_setzero_si128());
- __m128i carry_mask = _mm_cmpeq_epi16(m_xvflag[CARRY], _mm_setzero_si128());
- __m128i flag_mask = _mm_or_si128(zero_mask, carry_mask);
- __m128i eq_mask = _mm_and_si128(_mm_cmpeq_epi16(m_xv[VS1REG], shuf), flag_mask);
- __m128i gt_mask = _mm_cmpgt_epi16(m_xv[VS1REG], shuf);
- m_xvflag[COMPARE] = _mm_or_si128(eq_mask, gt_mask);
-
- __m128i result = _mm_and_si128(m_xv[VS1REG], m_xvflag[COMPARE]);
- m_accum_l = m_xv[VDREG] = _mm_or_si128(result, _mm_and_si128(shuf, _mm_xor_si128(m_xvflag[COMPARE], vec_neg1)));
-
- m_xvflag[ZERO] = m_xvflag[CARRY] = _mm_setzero_si128();
-}
-
-static void cfunc_rsp_vge_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vge_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vge_scalar()
-{
- int op = m_rsp_state->arg0;
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
- if ((s1 == s2 && (ZERO_FLAG(i) == 0 || CARRY_FLAG(i) == 0)) || s1 > s2)
- {
- SET_COMPARE_FLAG(i);
- vres[i] = s1;
- }
- else
- {
- vres[i] = s2;
- }
-
- SET_ACCUM_L(vres[i], i);
- }
-
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vge_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vge_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VCL
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 |
-// ------------------------------------------------------
-//
-// Vector clip low
-
-inline void rsp_device::ccfunc_rsp_vcl_simd()
-{
- int op = m_rsp_state->arg0;
- INT16 vres[8];
-
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- VEC_GET_SCALAR_VS1(s1, i);
- VEC_GET_SCALAR_VS2(s2, i);
-
- if (VEC_CARRY_FLAG(i) != 0)
- {
- if (VEC_ZERO_FLAG(i) != 0)
- {
- if (VEC_COMPARE_FLAG(i) != 0)
- {
- VEC_SET_ACCUM_L(-(UINT16)s2, i);
- }
- else
- {
- VEC_SET_ACCUM_L(s1, i);
- }
- }
- else
- {
- if (VEC_CLIP1_FLAG(i) != 0)
- {
- if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) > 0x10000)
- {
- VEC_SET_ACCUM_L(s1, i);
- VEC_CLEAR_COMPARE_FLAG(i);
- }
- else
- {
- VEC_SET_ACCUM_L(-((UINT16)s2), i);
- VEC_SET_COMPARE_FLAG(i);
- }
- }
- else
- {
- if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0)
- {
- VEC_SET_ACCUM_L(s1, i);
- VEC_CLEAR_COMPARE_FLAG(i);
- }
- else
- {
- VEC_SET_ACCUM_L(-((UINT16)s2), i);
- VEC_SET_COMPARE_FLAG(i);
- }
- }
- }
- }
- else
- {
- if (VEC_ZERO_FLAG(i) != 0)
- {
- if (VEC_CLIP2_FLAG(i) != 0)
- {
- VEC_SET_ACCUM_L(s2, i);
- }
- else
- {
- VEC_SET_ACCUM_L(s1, i);
- }
- }
- else
- {
- if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0)
- {
- VEC_SET_ACCUM_L(s2, i);
- VEC_SET_CLIP2_FLAG(i);
- }
- else
- {
- VEC_SET_ACCUM_L(s1, i);
- VEC_CLEAR_CLIP2_FLAG(i);
- }
- }
- }
- vres[i] = VEC_ACCUM_L(i);
- }
- VEC_CLEAR_ZERO_FLAGS();
- VEC_CLEAR_CARRY_FLAGS();
- VEC_CLEAR_CLIP1_FLAGS();
- VEC_WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vcl_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vcl_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vcl_scalar()
-{
- int op = m_rsp_state->arg0;
- INT16 vres[8];
-
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
-
- if (CARRY_FLAG(i) != 0)
- {
- if (ZERO_FLAG(i) != 0)
- {
- if (COMPARE_FLAG(i) != 0)
- {
- SET_ACCUM_L(-(UINT16)s2, i);
- }
- else
- {
- SET_ACCUM_L(s1, i);
- }
- }
- else
- {
- if (CLIP1_FLAG(i) != 0)
- {
- if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) > 0x10000)
- {
- SET_ACCUM_L(s1, i);
- CLEAR_COMPARE_FLAG(i);
- }
- else
- {
- SET_ACCUM_L(-((UINT16)s2), i);
- SET_COMPARE_FLAG(i);
- }
- }
- else
- {
- if (((UINT32)(UINT16)(s1) + (UINT32)(UINT16)(s2)) != 0)
- {
- SET_ACCUM_L(s1, i);
- CLEAR_COMPARE_FLAG(i);
- }
- else
- {
- SET_ACCUM_L(-((UINT16)s2), i);
- SET_COMPARE_FLAG(i);
- }
- }
- }
- }
- else
- {
- if (ZERO_FLAG(i) != 0)
- {
- if (CLIP2_FLAG(i) != 0)
- {
- SET_ACCUM_L(s2, i);
- }
- else
- {
- SET_ACCUM_L(s1, i);
- }
- }
- else
- {
- if (((INT32)(UINT16)s1 - (INT32)(UINT16)s2) >= 0)
- {
- SET_ACCUM_L(s2, i);
- SET_CLIP2_FLAG(i);
- }
- else
- {
- SET_ACCUM_L(s1, i);
- CLEAR_CLIP2_FLAG(i);
- }
- }
- }
- vres[i] = ACCUM_L(i);
- }
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- CLEAR_CLIP1_FLAGS();
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vcl_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vcl_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VCH
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 |
-// ------------------------------------------------------
-//
-// Vector clip high
-
-inline void rsp_device::ccfunc_rsp_vch_simd()
-{
- int op = m_rsp_state->arg0;
-
- VEC_CLEAR_CARRY_FLAGS();
- VEC_CLEAR_COMPARE_FLAGS();
- VEC_CLEAR_CLIP1_FLAGS();
- VEC_CLEAR_ZERO_FLAGS();
- VEC_CLEAR_CLIP2_FLAGS();
-
-#if 0
- // Compare flag
- // flag[1] bit [0- 7] set if (s1 ^ s2) < 0 && (s1 + s2) <= 0)
- // flag[1] bit [0- 7] set if (s1 ^ s2) >= 0 && (s2 < 0)
-
- // flag[1] bit [8-15] set if (s1 ^ s2) < 0 && (s2 < 0)
- // flag[1] bit [8-15] set if (s1 ^ s2) >= 0 && (s1 - s2) >= 0
-
- // Carry flag
- // flag[0] bit [0- 7] set if (s1 ^ s2) < 0
-
- // Zero flag
- // flag[0] bit [8-15] set if (s1 ^ s2) < 0 && (s1 + s2) != 0 && (s1 != ~s2)
- // flag[0] bit [8-15] set if (s1 ^ s2) >= 0 && (s1 - s2) != 0 && (s1 != ~s2)
-
- // flag[2] bit [0- 7] set if (s1 ^ s2) < 0 && (s1 + s2) == -1
-
- // accum set to -s2 if (s1 ^ s2) < 0 && (s1 + s2) <= 0)
- // accum set to -s2 if (s1 ^ s2) >= 0 && (s1 - s2) >= 0
-
- // accum set to s1 if (s1 ^ s2) < 0 && (s1 + s2) > 0)
- // accum set to s1 if (s1 ^ s2) >= 0 && (s1 - s2) < 0
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i s1_xor_s2 = _mm_xor_si128(m_xv[VS1REG], shuf);
- __m128i s1_plus_s2 = _mm_add_epi16(m_xv[VS1REG], shuf);
- __m128i s1_sub_s2 = _mm_sub_epi16(m_xv[VS1REG], shuf);
- __m128i s2_neg = _mm_xor_si128(shuf, vec_neg1);
-
- __m128i s2_lz = _mm_cmplt_epi16(shuf, _mm_setzero_si128());
- __m128i s1s2_xor_lz = _mm_cmplt_epi16(s1_xor_s2, _mm_setzero_si128());
- __m128i s1s2_xor_gez = _mm_xor_si128(s1s2_xor_lz, vec_neg1);
- __m128i s1s2_plus_nz = _mm_xor_si128(_mm_cmpeq_epi16(s1_plus_s2, _mm_setzero_si128()), vec_neg1);
- __m128i s1s2_plus_gz = _mm_cmpgt_epi16(s1_plus_s2, _mm_setzero_si128());
- __m128i s1s2_plus_lez = _mm_xor_si128(s1s2_plus_gz, vec_neg1);
- __m128i s1s2_plus_n1 = _mm_cmpeq_epi16(s1_plus_s2, vec_neg1);
- __m128i s1s2_sub_nz = _mm_xor_si128(_mm_cmpeq_epi16(s1_sub_s2, _mm_setzero_si128()), vec_neg1);
- __m128i s1s2_sub_lz = _mm_cmplt_epi16(s1_sub_s2, _mm_setzero_si128());
- __m128i s1s2_sub_gez = _mm_xor_si128(s1s2_sub_lz, vec_neg1);
- __m128i s1_nens2 = _mm_xor_si128(_mm_cmpeq_epi16(m_xv[VS1REG], s2_neg), vec_neg1);
-
- __m128i ext_mask = _mm_and_si128(_mm_and_si128(s1s2_xor_lz, s1s2_plus_n1), vec_flagmask);
- m_flag[2] |= _mm_extract_epi16(ext_mask, 0) << 0;
- m_flag[2] |= _mm_extract_epi16(ext_mask, 1) << 1;
- m_flag[2] |= _mm_extract_epi16(ext_mask, 2) << 2;
- m_flag[2] |= _mm_extract_epi16(ext_mask, 3) << 3;
- m_flag[2] |= _mm_extract_epi16(ext_mask, 4) << 4;
- m_flag[2] |= _mm_extract_epi16(ext_mask, 5) << 5;
- m_flag[2] |= _mm_extract_epi16(ext_mask, 6) << 6;
- m_flag[2] |= _mm_extract_epi16(ext_mask, 7) << 7;
-
- __m128i carry_mask = _mm_and_si128(s1s2_xor_lz, vec_flagmask);
- m_flag[0] |= _mm_extract_epi16(carry_mask, 0) << 0;
- m_flag[0] |= _mm_extract_epi16(carry_mask, 1) << 1;
- m_flag[0] |= _mm_extract_epi16(carry_mask, 2) << 2;
- m_flag[0] |= _mm_extract_epi16(carry_mask, 3) << 3;
- m_flag[0] |= _mm_extract_epi16(carry_mask, 4) << 4;
- m_flag[0] |= _mm_extract_epi16(carry_mask, 5) << 5;
- m_flag[0] |= _mm_extract_epi16(carry_mask, 6) << 6;
- m_flag[0] |= _mm_extract_epi16(carry_mask, 7) << 7;
-
- __m128i z0_mask = _mm_and_si128(_mm_and_si128(s1s2_xor_gez, s1s2_sub_nz), s1_nens2);
- __m128i z1_mask = _mm_and_si128(_mm_and_si128(s1s2_xor_lz, s1s2_plus_nz), s1_nens2);
- __m128i z_mask = _mm_and_si128(_mm_or_si128(z0_mask, z1_mask), vec_flagmask);
- z_mask = _mm_and_si128(_mm_or_si128(z_mask, _mm_srli_epi32(z_mask, 15)), vec_shiftmask2);
- z_mask = _mm_and_si128(_mm_or_si128(z_mask, _mm_srli_epi64(z_mask, 30)), vec_shiftmask4);
- z_mask = _mm_or_si128(z_mask, _mm_srli_si128(z_mask, 7));
- z_mask = _mm_or_si128(z_mask, _mm_srli_epi16(z_mask, 4));
- m_flag[0] |= (_mm_extract_epi16(z_mask, 0) << 8) & 0x00ff00;
-
- __m128i f0_mask = _mm_and_si128(_mm_or_si128(_mm_and_si128(s1s2_xor_gez, s2_lz), _mm_and_si128(s1s2_xor_lz, s1s2_plus_lez)), vec_flagmask);
- __m128i f8_mask = _mm_and_si128(_mm_or_si128(_mm_and_si128(s1s2_xor_gez, s1s2_sub_gez), _mm_and_si128(s1s2_xor_lz, s2_lz)), vec_flagmask);
- f0_mask = _mm_and_si128(f0_mask, vec_flagmask);
- f8_mask = _mm_and_si128(f8_mask, vec_flagmask);
- m_flag[1] |= _mm_extract_epi16(f0_mask, 0) << 0;
- m_flag[1] |= _mm_extract_epi16(f0_mask, 1) << 1;
- m_flag[1] |= _mm_extract_epi16(f0_mask, 2) << 2;
- m_flag[1] |= _mm_extract_epi16(f0_mask, 3) << 3;
- m_flag[1] |= _mm_extract_epi16(f0_mask, 4) << 4;
- m_flag[1] |= _mm_extract_epi16(f0_mask, 5) << 5;
- m_flag[1] |= _mm_extract_epi16(f0_mask, 6) << 6;
- m_flag[1] |= _mm_extract_epi16(f0_mask, 7) << 7;
-
- m_flag[1] |= _mm_extract_epi16(f8_mask, 0) << 8;
- m_flag[1] |= _mm_extract_epi16(f8_mask, 1) << 9;
- m_flag[1] |= _mm_extract_epi16(f8_mask, 2) << 10;
- m_flag[1] |= _mm_extract_epi16(f8_mask, 3) << 11;
- m_flag[1] |= _mm_extract_epi16(f8_mask, 4) << 12;
- m_flag[1] |= _mm_extract_epi16(f8_mask, 5) << 13;
- m_flag[1] |= _mm_extract_epi16(f8_mask, 6) << 14;
- m_flag[1] |= _mm_extract_epi16(f8_mask, 7) << 15;
-#endif
- INT16 vres[8];
- UINT32 vce = 0;
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- VEC_GET_SCALAR_VS1(s1, i);
- VEC_GET_SCALAR_VS2(s2, i);
-
- if ((s1 ^ s2) < 0)
- {
- vce = (s1 + s2 == -1);
- VEC_SET_CARRY_FLAG(i);
- if (s2 < 0)
- {
- VEC_SET_CLIP2_FLAG(i);
- }
-
- if ((s1 + s2) <= 0)
- {
- VEC_SET_COMPARE_FLAG(i);
- vres[i] = -((UINT16)s2);
- }
- else
- {
- vres[i] = s1;
- }
-
- if ((s1 + s2) != 0 && s1 != ~s2)
- {
- VEC_SET_ZERO_FLAG(i);
- }
- }//sign
- else
- {
- vce = 0;
- if (s2 < 0)
- {
- VEC_SET_COMPARE_FLAG(i);
- }
- if ((s1 - s2) >= 0)
- {
- VEC_SET_CLIP2_FLAG(i);
- vres[i] = s2;
- }
- else
- {
- vres[i] = s1;
- }
-
- if ((s1 - s2) != 0 && s1 != ~s2)
- {
- VEC_SET_ZERO_FLAG(i);
- }
- }
- if (vce)
- {
- VEC_SET_CLIP1_FLAG(i);
- }
- VEC_SET_ACCUM_L(vres[i], i);
- }
- VEC_WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vch_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vch_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vch_scalar()
-{
- int op = m_rsp_state->arg0;
-
- CLEAR_CARRY_FLAGS();
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP1_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- INT16 vres[8];
- UINT32 vce = 0;
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
-
- if ((s1 ^ s2) < 0)
- {
- vce = (s1 + s2 == -1);
- SET_CARRY_FLAG(i);
- if (s2 < 0)
- {
- SET_CLIP2_FLAG(i);
- }
-
- if ((s1 + s2) <= 0)
- {
- SET_COMPARE_FLAG(i);
- vres[i] = -((UINT16)s2);
- }
- else
- {
- vres[i] = s1;
- }
-
- if ((s1 + s2) != 0 && s1 != ~s2)
- {
- SET_ZERO_FLAG(i);
- }
- }//sign
- else
- {
- vce = 0;
- if (s2 < 0)
- {
- SET_COMPARE_FLAG(i);
- }
- if ((s1 - s2) >= 0)
- {
- SET_CLIP2_FLAG(i);
- vres[i] = s2;
- }
- else
- {
- vres[i] = s1;
- }
-
- if ((s1 - s2) != 0 && s1 != ~s2)
- {
- SET_ZERO_FLAG(i);
- }
- }
- if (vce)
- {
- SET_CLIP1_FLAG(i);
- }
- SET_ACCUM_L(vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vch_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vch_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VCR
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 |
-// ------------------------------------------------------
-//
-// Vector clip reverse
-
-inline void rsp_device::ccfunc_rsp_vcr_simd()
-{
- int op = m_rsp_state->arg0;
-
- VEC_CLEAR_CARRY_FLAGS();
- VEC_CLEAR_COMPARE_FLAGS();
- VEC_CLEAR_CLIP1_FLAGS();
- VEC_CLEAR_ZERO_FLAGS();
- VEC_CLEAR_CLIP2_FLAGS();
-
-#if 0
- // flag[1] bit [0- 7] set if (s1 ^ s2) < 0 && (s1 + s2) <= 0)
- // flag[1] bit [0- 7] set if (s1 ^ s2) >= 0 && (s2 < 0)
-
- // flag[1] bit [8-15] set if (s1 ^ s2) < 0 && (s2 < 0)
- // flag[1] bit [8-15] set if (s1 ^ s2) >= 0 && (s1 - s2) >= 0
-
- // accum set to ~s2 if (s1 ^ s2) < 0 && (s1 + s2) <= 0)
- // accum set to ~s2 if (s1 ^ s2) >= 0 && (s1 - s2) >= 0
-
- // accum set to s1 if (s1 ^ s2) < 0 && (s1 + s2) > 0)
- // accum set to s1 if (s1 ^ s2) >= 0 && (s1 - s2) < 0
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i s1_xor_s2 = _mm_xor_si128(m_xv[VS1REG], shuf);
- __m128i s1_plus_s2 = _mm_add_epi16(m_xv[VS1REG], shuf);
- __m128i s1_sub_s2 = _mm_sub_epi16(m_xv[VS1REG], shuf);
- __m128i s2_neg = _mm_xor_si128(shuf, vec_neg1);
-
- __m128i s2_lz = _mm_cmplt_epi16(shuf, _mm_setzero_si128());
- __m128i s1s2_xor_lz = _mm_cmplt_epi16(s1_xor_s2, _mm_setzero_si128());
- __m128i s1s2_xor_gez = _mm_xor_si128(s1s2_xor_lz, vec_neg1);
- __m128i s1s2_plus_gz = _mm_cmpgt_epi16(s1_plus_s2, _mm_setzero_si128());
- __m128i s1s2_plus_lez = _mm_xor_si128(s1s2_plus_gz, vec_neg1);
- __m128i s1s2_sub_lz = _mm_cmplt_epi16(s1_sub_s2, _mm_setzero_si128());
- __m128i s1s2_sub_gez = _mm_xor_si128(s1s2_sub_lz, vec_neg1);
-
- __m128i s1_mask = _mm_or_si128(_mm_and_si128(s1s2_xor_gez, s1s2_sub_lz), _mm_and_si128(s1s2_xor_lz, s1s2_plus_gz));
- __m128i s2_mask = _mm_or_si128(_mm_and_si128(s1s2_xor_gez, s1s2_sub_gez), _mm_and_si128(s1s2_xor_lz, s1s2_plus_lez));
- m_accum_l = _mm_or_si128(_mm_and_si128(m_xv[VS1REG], s1_mask), _mm_and_si128(s2_neg, s2_mask));
- m_xv[VDREG] = m_accum_l;
-
- m_xvflag[COMPARE] = _mm_or_si128(_mm_and_si128(s1s2_xor_gez, s2_lz), _mm_and_si128(s1s2_xor_lz, s1s2_plus_lez));
- m_xvflag[CLIP2] = _mm_or_si128(_mm_and_si128(s1s2_xor_gez, s1s2_sub_gez), _mm_and_si128(s1s2_xor_lz, s2_lz));
-#endif
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- VEC_GET_SCALAR_VS1(s1, i);
- VEC_GET_SCALAR_VS2(s2, i);
-
- if ((INT16)(s1 ^ s2) < 0)
- {
- if (s2 < 0)
- {
- VEC_SET_CLIP2_FLAG(i);
- }
- if ((s1 + s2) <= 0)
- {
- VEC_SET_ACCUM_L(~((UINT16)s2), i);
- VEC_SET_COMPARE_FLAG(i);
- }
- else
- {
- VEC_SET_ACCUM_L(s1, i);
- }
- }
- else
- {
- if (s2 < 0)
- {
- VEC_SET_COMPARE_FLAG(i);
- }
- if ((s1 - s2) >= 0)
- {
- VEC_SET_ACCUM_L(s2, i);
- VEC_SET_CLIP2_FLAG(i);
- }
- else
- {
- VEC_SET_ACCUM_L(s1, i);
- }
- }
-
- vres[i] = VEC_ACCUM_L(i);
- }
- VEC_WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vcr_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vcr_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vcr_scalar()
-{
- int op = m_rsp_state->arg0;
-
- CLEAR_CARRY_FLAGS();
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP1_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
-
- if ((INT16)(s1 ^ s2) < 0)
- {
- if (s2 < 0)
- {
- SET_CLIP2_FLAG(i);
- }
- if ((s1 + s2) <= 0)
- {
- SET_ACCUM_L(~((UINT16)s2), i);
- SET_COMPARE_FLAG(i);
- }
- else
- {
- SET_ACCUM_L(s1, i);
- }
- }
- else
- {
- if (s2 < 0)
- {
- SET_COMPARE_FLAG(i);
- }
- if ((s1 - s2) >= 0)
- {
- SET_ACCUM_L(s2, i);
- SET_CLIP2_FLAG(i);
- }
- else
- {
- SET_ACCUM_L(s1, i);
- }
- }
-
- vres[i] = ACCUM_L(i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vcr_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vcr_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMRG
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100111 |
-// ------------------------------------------------------
-//
-// Merges two vectors according to compare flags
-
-inline void rsp_device::ccfunc_rsp_vmrg_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- __m128i s2mask = _mm_cmpeq_epi16(m_xvflag[COMPARE], _mm_setzero_si128());
- __m128i s1mask = _mm_xor_si128(s2mask, vec_neg1);
- __m128i result = _mm_and_si128(m_xv[VS1REG], s1mask);
- m_xv[VDREG] = _mm_or_si128(result, _mm_and_si128(shuf, s2mask));
- m_accum_l = m_xv[VDREG];
-}
-
-static void cfunc_rsp_vmrg_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmrg_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmrg_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- INT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
- if (COMPARE_FLAG(i) != 0)
- {
- vres[i] = s1;
- }
- else
- {
- vres[i] = s2;
- }
-
- SET_ACCUM_L(vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vmrg_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmrg_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VAND
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 |
-// ------------------------------------------------------
-//
-// Bitwise AND of two vector registers
-
-inline void rsp_device::ccfunc_rsp_vand_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- m_xv[VDREG] = _mm_and_si128(m_xv[VS1REG], shuf);
- m_accum_l = m_xv[VDREG];
-}
-
-static void cfunc_rsp_vand_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vand_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vand_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
- vres[i] = s1 & s2;
- SET_ACCUM_L(vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vand_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vand_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VNAND
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101001 |
-// ------------------------------------------------------
-//
-// Bitwise NOT AND of two vector registers
-
-inline void rsp_device::ccfunc_rsp_vnand_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- m_xv[VDREG] = _mm_xor_si128(_mm_and_si128(m_xv[VS1REG], shuf), vec_neg1);
- m_accum_l = m_xv[VDREG];
-}
-
-static void cfunc_rsp_vnand_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vnand_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vnand_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
- vres[i] = ~((s1 & s2));
- SET_ACCUM_L(vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vnand_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vnand_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VOR
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101010 |
-// ------------------------------------------------------
-//
-// Bitwise OR of two vector registers
-
-inline void rsp_device::ccfunc_rsp_vor_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- m_xv[VDREG] = _mm_or_si128(m_xv[VS1REG], shuf);
- m_accum_l = m_xv[VDREG];
-}
-
-static void cfunc_rsp_vor_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vor_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vor_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
- vres[i] = s1 | s2;
- SET_ACCUM_L(vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vor_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vor_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VNOR
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101011 |
-// ------------------------------------------------------
-//
-// Bitwise NOT OR of two vector registers
-
-inline void rsp_device::ccfunc_rsp_vnor_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- m_xv[VDREG] = _mm_xor_si128(_mm_or_si128(m_xv[VS1REG], shuf), vec_neg1);
- m_accum_l = m_xv[VDREG];
-}
-
-static void cfunc_rsp_vnor_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vnor_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vnor_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
- vres[i] = ~(s1 | s2);
- SET_ACCUM_L(vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vnor_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vnor_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VXOR
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101100 |
-// ------------------------------------------------------
-//
-// Bitwise XOR of two vector registers
-
-inline void rsp_device::ccfunc_rsp_vxor_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- m_xv[VDREG] = _mm_xor_si128(m_xv[VS1REG], shuf);
- m_accum_l = m_xv[VDREG];
-}
-
-static void cfunc_rsp_vxor_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vxor_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vxor_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
- vres[i] = s1 ^ s2;
- SET_ACCUM_L(vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vxor_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vxor_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VNXOR
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 |
-// ------------------------------------------------------
-//
-// Bitwise NOT XOR of two vector registers
-
-inline void rsp_device::ccfunc_rsp_vnxor_simd()
-{
- int op = m_rsp_state->arg0;
-
- __m128i shuf = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
- m_xv[VDREG] = _mm_xor_si128(_mm_xor_si128(m_xv[VS1REG], shuf), vec_neg1);
- m_accum_l = m_xv[VDREG];
-}
-
-static void cfunc_rsp_vnxor_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vnxor_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vnxor_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT16 vres[8];
- for (int i = 0; i < 8; i++)
- {
- UINT16 s1, s2;
- SCALAR_GET_VS1(s1, i);
- SCALAR_GET_VS2(s2, i);
- vres[i] = ~(s1 ^ s2);
- SET_ACCUM_L(vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-static void cfunc_rsp_vnxor_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vnxor_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VRCP
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 |
-// ------------------------------------------------------
-//
-// Calculates reciprocal
-
-inline void rsp_device::ccfunc_rsp_vrcp_simd()
-{
- int op = m_rsp_state->arg0;
-
- INT32 shifter = 0;
- UINT16 urec;
- INT32 rec;
- SIMD_EXTRACT16(m_xv[VS2REG], urec, EL);
- rec = (INT16)urec;
- INT32 datainput = (rec < 0) ? (-rec) : rec;
- if (datainput)
- {
- for (int i = 0; i < 32; i++)
- {
- if (datainput & (1 << ((~i) & 0x1f)))
- {
- shifter = i;
- break;
- }
- }
- }
- else
- {
- shifter = 0x10;
- }
-
- INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
- INT32 fetchval = rsp_divtable[address];
- INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
- if (rec < 0)
- {
- temp = ~temp;
- }
- if (!rec)
- {
- temp = 0x7fffffff;
- }
- else if (rec == 0xffff8000)
- {
- temp = 0xffff0000;
- }
- rec = temp;
-
- m_reciprocal_res = rec;
- m_dp_allowed = 0;
-
- SIMD_INSERT16(m_xv[VDREG], (UINT16)rec, VS1REG);
- m_accum_l = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-}
-
-static void cfunc_rsp_vrcp_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vrcp_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vrcp_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 (datainput)
- {
- for (int i = 0; i < 32; i++)
- {
- if (datainput & (1 << ((~i) & 0x1f)))
- {
- shifter = i;
- break;
- }
- }
- }
- else
- {
- shifter = 0x10;
- }
-
- INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
- INT32 fetchval = rsp_divtable[address];
- INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
- if (rec < 0)
- {
- temp = ~temp;
- }
- if (!rec)
- {
- temp = 0x7fffffff;
- }
- else if (rec == 0xffff8000)
- {
- temp = 0xffff0000;
- }
- rec = temp;
-
- m_reciprocal_res = rec;
- m_dp_allowed = 0;
-
- 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_vrcp_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vrcp_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VRCPL
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 |
-// ------------------------------------------------------
-//
-// Calculates reciprocal low part
-
-inline void rsp_device::ccfunc_rsp_vrcpl_simd()
-{
- int op = m_rsp_state->arg0;
-
-#if SIMUL_SIMD
- m_old_reciprocal_res = m_reciprocal_res;
- m_old_reciprocal_high = m_reciprocal_high;
- m_old_dp_allowed = m_dp_allowed;
-#endif
-
- INT32 shifter = 0;
-
- UINT16 urec;
- SIMD_EXTRACT16(m_xv[VS2REG], urec, EL);
- INT32 rec = (INT16)urec;
- INT32 datainput = rec;
-
- if (m_dp_allowed)
- {
- rec = (rec & 0x0000ffff) | m_reciprocal_high;
- datainput = rec;
-
- if (rec < 0)
- {
- if (rec < -32768)
- {
- datainput = ~datainput;
- }
- else
- {
- datainput = -datainput;
- }
- }
- }
- else if (datainput < 0)
- {
- datainput = -datainput;
-
- shifter = 0x10;
- }
-
- if (datainput)
- {
- for (int i = 0; i < 32; i++)
- {
- if (datainput & (1 << ((~i) & 0x1f)))
- {
- shifter = i;
- break;
- }
- }
- }
-
- INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22;
- INT32 fetchval = rsp_divtable[address];
- INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
- temp ^= rec >> 31;
-
- if (!rec)
- {
- temp = 0x7fffffff;
- }
- else if (rec == 0xffff8000)
- {
- temp = 0xffff0000;
- }
- rec = temp;
-
- m_reciprocal_res = rec;
- m_dp_allowed = 0;
-
- SIMD_INSERT16(m_xv[VDREG], (UINT16)rec, VS1REG);
-
- for (int i = 0; i < 8; i++)
- {
- INT16 val;
- SIMD_EXTRACT16(m_xv[VS2REG], val, VEC_EL_2(EL, i));
- VEC_SET_ACCUM_L(val, i);
- }
-}
-
-static void cfunc_rsp_vrcpl_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vrcpl_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vrcpl_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT32 shifter = 0;
- INT32 rec = (INT16)VREG_S(VS2REG, EL & 7);
- INT32 datainput = rec;
-
- if (m_dp_allowed)
- {
- rec = (rec & 0x0000ffff) | m_reciprocal_high;
- datainput = rec;
-
- if (rec < 0)
- {
- if (rec < -32768)
- {
- datainput = ~datainput;
- }
- else
- {
- datainput = -datainput;
- }
- }
- }
- else if (datainput < 0)
- {
- datainput = -datainput;
-
- shifter = 0x10;
- }
-
- if (datainput)
- {
- for (int i = 0; i < 32; i++)
- {
- if (datainput & (1 << ((~i) & 0x1f)))
- {
- shifter = i;
- break;
- }
- }
- }
-
- UINT32 address = (datainput << shifter) >> 22;
- INT32 fetchval = rsp_divtable[address & 0x1ff];
- INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f);
- temp ^= rec >> 31;
-
- if (!rec)
- {
- temp = 0x7fffffff;
- }
- else if (rec == 0xffff8000)
- {
- temp = 0xffff0000;
- }
- rec = temp;
-
- m_reciprocal_res = rec;
- m_dp_allowed = 0;
-
- 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_vrcpl_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vrcpl_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VRCPH
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 |
-// ------------------------------------------------------
-//
-// Calculates reciprocal high part
-
-inline void rsp_device::ccfunc_rsp_vrcph_simd()
-{
- int op = m_rsp_state->arg0;
-
-#if SIMUL_SIMD
- m_old_reciprocal_res = m_reciprocal_res;
- m_old_reciprocal_high = m_reciprocal_high;
- m_old_dp_allowed = m_dp_allowed;
-#endif
-
- UINT16 rcph;
- SIMD_EXTRACT16(m_xv[VS2REG], rcph, EL);
- m_reciprocal_high = rcph << 16;
- m_dp_allowed = 1;
-
- m_accum_l = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- SIMD_INSERT16(m_xv[VDREG], (INT16)(m_reciprocal_res >> 16), VS1REG);
-}
-
-static void cfunc_rsp_vrcph_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vrcph_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vrcph_scalar()
-{
- int op = m_rsp_state->arg0;
-
- m_reciprocal_high = (VREG_S(VS2REG, EL & 7)) << 16;
- m_dp_allowed = 1;
-
- for (int i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
- }
-
- W_VREG_S(VDREG, VS1REG & 7) = (INT16)(m_reciprocal_res >> 16);
-}
-
-static void cfunc_rsp_vrcph_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vrcph_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VMOV
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110011 |
-// ------------------------------------------------------
-//
-// Moves element from vector to destination vector
-
-inline void rsp_device::ccfunc_rsp_vmov_simd()
-{
- int op = m_rsp_state->arg0;
-
- INT16 val;
- SIMD_EXTRACT16(m_xv[VS2REG], val, EL);
- SIMD_INSERT16(m_xv[VDREG], val, VS1REG);
- m_accum_l = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-}
-
-static void cfunc_rsp_vmov_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmov_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vmov_scalar()
-{
- int op = m_rsp_state->arg0;
-
- W_VREG_S(VDREG, VS1REG & 7) = VREG_S(VS2REG, EL & 7);
- for (int i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
- }
-}
-
-static void cfunc_rsp_vmov_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vmov_scalar();
-}
-#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
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 |
-// ------------------------------------------------------
-//
-// Calculates reciprocal square-root low part
-
-inline void rsp_device::ccfunc_rsp_vrsql_simd()
-{
- int op = m_rsp_state->arg0;
-
-#if SIMUL_SIMD
- m_old_reciprocal_res = m_reciprocal_res;
- m_old_reciprocal_high = m_reciprocal_high;
- m_old_dp_allowed = m_dp_allowed;
-#endif
-
- INT32 shifter = 0;
- UINT16 val;
- SIMD_EXTRACT16(m_xv[VS2REG], val, EL);
- INT32 rec = (INT16)val;
- INT32 datainput = rec;
-
- if (m_dp_allowed)
- {
- rec = (rec & 0x0000ffff) | m_reciprocal_high;
- datainput = rec;
-
- if (rec < 0)
- {
- if (rec < -32768)
- {
- datainput = ~datainput;
- }
- else
- {
- datainput = -datainput;
- }
- }
- }
- else if (datainput < 0)
- {
- datainput = -datainput;
-
- shifter = 0x10;
- }
-
- if (datainput)
- {
- for (int i = 0; i < 32; i++)
- {
- if (datainput & (1 << ((~i) & 0x1f)))
- {
- shifter = i;
- break;
- }
- }
- }
-
- 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);
- temp ^= rec >> 31;
-
- if (!rec)
- {
- temp = 0x7fffffff;
- }
- else if (rec == 0xffff8000)
- {
- temp = 0xffff0000;
- }
- rec = temp;
-
- m_reciprocal_res = rec;
- m_dp_allowed = 0;
-
- SIMD_INSERT16(m_xv[VDREG], (UINT16)rec, VS1REG);
- m_accum_l = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-}
-
-static void cfunc_rsp_vrsql_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vrsql_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vrsql_scalar()
-{
- int op = m_rsp_state->arg0;
-
- INT32 shifter = 0;
- INT32 rec = (INT16)VREG_S(VS2REG, EL & 7);
- INT32 datainput = rec;
-
- if (m_dp_allowed)
- {
- rec = (rec & 0x0000ffff) | m_reciprocal_high;
- datainput = rec;
-
- if (rec < 0)
- {
- if (rec < -32768)
- {
- datainput = ~datainput;
- }
- else
- {
- datainput = -datainput;
- }
- }
- }
- else if (datainput < 0)
- {
- datainput = -datainput;
-
- shifter = 0x10;
- }
-
- if (datainput)
- {
- for (int i = 0; i < 32; i++)
- {
- if (datainput & (1 << ((~i) & 0x1f)))
- {
- shifter = i;
- break;
- }
- }
- }
-
- 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);
- temp ^= rec >> 31;
-
- if (!rec)
- {
- temp = 0x7fffffff;
- }
- else if (rec == 0xffff8000)
- {
- temp = 0xffff0000;
- }
- rec = temp;
-
- m_reciprocal_res = rec;
- m_dp_allowed = 0;
-
- W_VREG_S(VDREG, VS1REG & 7) = (UINT16)(rec & 0xffff);
- for (int i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
- }
-}
-
-static void cfunc_rsp_vrsql_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vrsql_scalar();
-}
-#endif
-
-#if USE_SIMD
-// VRSQH
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110110 |
-// ------------------------------------------------------
-//
-// Calculates reciprocal square-root high part
-
-inline void rsp_device::ccfunc_rsp_vrsqh_simd()
-{
- int op = m_rsp_state->arg0;
-
-#if SIMUL_SIMD
- m_old_reciprocal_res = m_reciprocal_res;
- m_old_reciprocal_high = m_reciprocal_high;
- m_old_dp_allowed = m_dp_allowed;
-#endif
-
- UINT16 val;
- SIMD_EXTRACT16(m_xv[VS2REG], val, EL);
- m_reciprocal_high = val << 16;
- m_dp_allowed = 1;
-
- m_accum_l = _mm_shuffle_epi8(m_xv[VS2REG], vec_shuf_inverse[EL]);
-
- SIMD_INSERT16(m_xv[VDREG], (INT16)(m_reciprocal_res >> 16), VS1REG); // store high part
-}
-
-static void cfunc_rsp_vrsqh_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vrsqh_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-
-inline void rsp_device::ccfunc_rsp_vrsqh_scalar()
-{
- int op = m_rsp_state->arg0;
-
- m_reciprocal_high = (VREG_S(VS2REG, EL & 7)) << 16;
- m_dp_allowed = 1;
-
- for (int i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
- }
-
- W_VREG_S(VDREG, VS1REG & 7) = (INT16)(m_reciprocal_res >> 16); // store high part
-}
-
-static void cfunc_rsp_vrsqh_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_rsp_vrsqh_scalar();
-}
-#endif
-
-
inline void rsp_device::ccfunc_sp_set_status_cb()
{
m_sp_set_status_func(0, m_rsp_state->arg0, 0xffffffff);
@@ -7355,7 +677,7 @@ void rsp_device::static_generate_memory_accessor(int size, int iswrite, const ch
if (size == 1)
{
UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address
- UML_CALLC(block, cfunc_read8, this); // callc cfunc_printf_debug
+ UML_CALLC(block, cfunc_read8, this); // callc read8
UML_MOV(block, I0, mem(&m_rsp_state->arg0)); // mov i0,[arg0],i0 ; result
}
else if (size == 2)
@@ -7581,719 +903,6 @@ void rsp_device::generate_delay_slot_and_branch(drcuml_block *block, compiler_st
UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles
}
-
-/*-------------------------------------------------
- generate_vector_opcode - generate code for a
- vector opcode
--------------------------------------------------*/
-
-#if USE_SIMD
-
-int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
-{
- UINT32 op = desc->opptr.l[0];
- // Opcode legend:
- // E = VS2 element type
- // S = VS1, Source vector 1
- // T = VS2, Source vector 2
- // D = Destination vector
-
- switch (op & 0x3f)
- {
- case 0x00: /* VMULF */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmulf_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmulf_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x01: /* VMULU */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmulu_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmulu_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x04: /* VMUDL */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmudl_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmudl_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x05: /* VMUDM */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmudm_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmudm_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x06: /* VMUDN */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmudn_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmudn_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x07: /* VMUDH */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmudh_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmudh_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x08: /* VMACF */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmacf_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmacf_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x09: /* VMACU */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmacu_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmacu_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x0c: /* VMADL */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmadl_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmadl_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x0d: /* VMADM */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmadm_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmadm_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x0e: /* VMADN */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmadn_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmadn_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x0f: /* VMADH */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmadh_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmadh_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x10: /* VADD */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vadd_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vadd_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x11: /* VSUB */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vsub_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vsub_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x13: /* VABS */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vabs_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vabs_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x14: /* VADDC */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vaddc_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vaddc_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x15: /* VSUBC */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vsubc_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vsubc_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x16: /* VADDB */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vaddb_scalar, this);
- return TRUE;
-
- case 0x17: /* VSUBB (reserved, functionally identical to VADDB) */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vaddb_scalar, this);
- return TRUE;
-
- case 0x18: /* VACCB (reserved, functionally identical to VADDB) */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vaddb_scalar, this);
- return TRUE;
-
- case 0x19: /* VSUCB (reserved, functionally identical to VADDB) */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vaddb_scalar, this);
- return TRUE;
-
- case 0x1d: /* VSAW */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vsaw_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vsaw_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x20: /* VLT */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vlt_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vlt_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x21: /* VEQ */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_veq_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_veq_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x22: /* VNE */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vne_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vne_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x23: /* VGE */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vge_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vge_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x24: /* VCL */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vcl_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vcl_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x25: /* VCH */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vch_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vch_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x26: /* VCR */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vcr_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vcr_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x27: /* VMRG */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmrg_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmrg_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x28: /* VAND */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vand_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vand_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x29: /* VNAND */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vnand_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vnand_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x2a: /* VOR */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vor_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vor_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x2b: /* VNOR */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vnor_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vnor_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x2c: /* VXOR */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vxor_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vxor_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x2d: /* VNXOR */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vnxor_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vnxor_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x30: /* VRCP */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vrcp_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vrcp_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x31: /* VRCPL */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vrcpl_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vrcpl_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x32: /* VRCPH */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vrcph_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vrcph_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x33: /* VMOV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmov_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vmov_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#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);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vrsql_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
- return TRUE;
-
- case 0x36: /* VRSQH */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vrsqh_simd, this);
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_rsp_vrsqh_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#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);
- return FALSE;
- }
-}
-
-#else
-
-int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
-{
- UINT32 op = desc->opptr.l[0];
- // Opcode legend:
- // E = VS2 element type
- // S = VS1, Source vector 1
- // T = VS2, Source vector 2
- // D = Destination vector
-
- switch (op & 0x3f)
- {
- case 0x00: /* VMULF */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmulf_scalar, this);
- return TRUE;
-
- case 0x01: /* VMULU */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmulu_scalar, this);
- return TRUE;
-
- case 0x04: /* VMUDL */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmudl_scalar, this);
- return TRUE;
-
- case 0x05: /* VMUDM */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmudm_scalar, this);
- return TRUE;
-
- case 0x06: /* VMUDN */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmudn_scalar, this);
- return TRUE;
-
- case 0x07: /* VMUDH */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmudh_scalar, this);
- return TRUE;
-
- case 0x08: /* VMACF */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmacf_scalar, this);
- return TRUE;
-
- case 0x09: /* VMACU */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmacu_scalar, this);
- return TRUE;
-
- case 0x0c: /* VMADL */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmadl_scalar, this);
- return TRUE;
-
- case 0x0d: /* VMADM */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmadm_scalar, this);
- return TRUE;
-
- case 0x0e: /* VMADN */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmadn_scalar, this);
- return TRUE;
-
- case 0x0f: /* VMADH */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmadh_scalar, this);
- return TRUE;
-
- case 0x10: /* VADD */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vadd_scalar, this);
- return TRUE;
-
- case 0x11: /* VSUB */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vsub_scalar, this);
- return TRUE;
-
- case 0x13: /* VABS */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vabs_scalar, this);
- return TRUE;
-
- case 0x14: /* VADDC */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vaddc_scalar, this);
- return TRUE;
-
- case 0x15: /* VSUBC */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vsubc_scalar, this);
- return TRUE;
-
- case 0x16: /* VADDB */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vaddb_scalar, this);
- return TRUE;
-
- case 0x17: /* VSUBB (reserved, functionally identical to VADDB) */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vaddb_scalar, this);
- return TRUE;
-
- case 0x18: /* VACCB (reserved, functionally identical to VADDB) */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vaddb_scalar, this);
- return TRUE;
-
- case 0x19: /* VSUCB (reserved, functionally identical to VADDB) */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vaddb_scalar, this);
- return TRUE;
-
- case 0x1d: /* VSAW */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vsaw_scalar, this);
- return TRUE;
-
- case 0x20: /* VLT */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vlt_scalar, this);
- return TRUE;
-
- case 0x21: /* VEQ */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_veq_scalar, this);
- return TRUE;
-
- case 0x22: /* VNE */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vne_scalar, this);
- return TRUE;
-
- case 0x23: /* VGE */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vge_scalar, this);
- return TRUE;
-
- case 0x24: /* VCL */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vcl_scalar, this);
- return TRUE;
-
- case 0x25: /* VCH */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vch_scalar, this);
- return TRUE;
-
- case 0x26: /* VCR */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vcr_scalar, this);
- return TRUE;
-
- case 0x27: /* VMRG */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vmrg_scalar, this);
- return TRUE;
-
- case 0x28: /* VAND */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vand_scalar, this);
- return TRUE;
-
- case 0x29: /* VNAND */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vnand_scalar, this);
- return TRUE;
-
- case 0x2a: /* VOR */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vor_scalar, this);
- return TRUE;
-
- case 0x2b: /* VNOR */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vnor_scalar, this);
- return TRUE;
-
- case 0x2c: /* VXOR */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vxor_scalar, this);
- return TRUE;
-
- case 0x2d: /* VNXOR */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vnxor_scalar, this);
- return TRUE;
-
- case 0x30: /* VRCP */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vrcp_scalar, this);
- return TRUE;
-
- case 0x31: /* VRCPL */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vrcpl_scalar, this);
- return TRUE;
-
- case 0x32: /* VRCPH */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_rsp_vrcph_scalar, this);
- return TRUE;
-
- case 0x33: /* VMOV */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- 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);
- return TRUE;
-
- case 0x36: /* VRSQH */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- 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);
- return FALSE;
- }
-}
-#endif
-
int rsp_device::generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
{
int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0);
@@ -8450,7 +1059,7 @@ int rsp_device::generate_opcode(drcuml_block *block, compiler_state *compiler, c
return TRUE;
case 0x32: /* LWC2 - MIPS I */
- return generate_lwc2(block, compiler, desc);
+ return m_cop2->generate_lwc2(block, compiler, desc);
/* ----- memory store operations ----- */
@@ -8480,10 +1089,7 @@ int rsp_device::generate_opcode(drcuml_block *block, compiler_state *compiler, c
return TRUE;
case 0x3a: /* SWC2 - MIPS I */
- return generate_swc2(block, compiler, desc);
- //UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- //UML_CALLC(block, cfunc_swc2, this); // callc cfunc_mfc2
- //return TRUE;
+ return m_cop2->generate_swc2(block, compiler, desc);
/* ----- coprocessor instructions ----- */
@@ -8491,9 +1097,7 @@ int rsp_device::generate_opcode(drcuml_block *block, compiler_state *compiler, c
return generate_cop0(block, compiler, desc);
case 0x12: /* COP2 - MIPS I */
- return generate_cop2(block, compiler, desc);
- //UML_EXH(block, m_exception[EXCEPTION_INVALIDOP], 0);// exh invalidop,0
- //return TRUE;
+ return m_cop2->generate_cop2(block, compiler, desc);
/* ----- unimplemented/illegal instructions ----- */
@@ -8705,92 +1309,6 @@ int rsp_device::generate_regimm(drcuml_block *block, compiler_state *compiler, c
/*-------------------------------------------------
- generate_cop2 - compile COP2 opcodes
--------------------------------------------------*/
-
-int rsp_device::generate_cop2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
-{
- UINT32 op = desc->opptr.l[0];
- UINT8 opswitch = RSREG;
-
- switch (opswitch)
- {
- case 0x00: /* MFCz */
- if (RTREG != 0)
- {
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
-#if USE_SIMD
- UML_CALLC(block, cfunc_mfc2_simd, this); // callc cfunc_ctc2
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_mfc2_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
-#else
- UML_CALLC(block, cfunc_mfc2_scalar, this);
-#endif
- //UML_SEXT(block, R32(RTREG), I0, DWORD); // dsext <rtreg>,i0,dword
- }
- return TRUE;
-
- case 0x02: /* CFCz */
- if (RTREG != 0)
- {
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
-#if USE_SIMD
- UML_CALLC(block, cfunc_cfc2_simd, this); // callc cfunc_ctc2
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_cfc2_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
-#else
- UML_CALLC(block, cfunc_cfc2_scalar, this);
-#endif
- //UML_SEXT(block, R32(RTREG), I0, DWORD); // dsext <rtreg>,i0,dword
- }
- return TRUE;
-
- case 0x04: /* MTCz */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
-#if USE_SIMD
- UML_CALLC(block, cfunc_mtc2_simd, this); // callc cfunc_ctc2
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_mtc2_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
-#else
- UML_CALLC(block, cfunc_mtc2_scalar, this);
-#endif
- return TRUE;
-
- case 0x06: /* CTCz */
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
-#if USE_SIMD
- UML_CALLC(block, cfunc_ctc2_simd, this); // callc cfunc_ctc2
-#if SIMUL_SIMD
- UML_CALLC(block, cfunc_backup_regs, this);
- UML_CALLC(block, cfunc_ctc2_scalar, this);
- UML_CALLC(block, cfunc_restore_regs, this);
- UML_CALLC(block, cfunc_verify_regs, this);
-#endif
-#else
- UML_CALLC(block, cfunc_ctc2_scalar, this);
-#endif
- return TRUE;
-
- case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
- case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
- return generate_vector_opcode(block, compiler, desc);
- }
- return FALSE;
-}
-
-/*-------------------------------------------------
generate_cop0 - compile COP0 opcodes
-------------------------------------------------*/
@@ -8825,423 +1343,6 @@ int rsp_device::generate_cop0(drcuml_block *block, compiler_state *compiler, con
return FALSE;
}
-#if USE_SIMD
-inline void rsp_device::ccfunc_mfc2_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int el = (op >> 7) & 0xf;
-
- UINT16 out;
- SIMD_EXTRACT16(m_xv[VS1REG], out, (el >> 1));
- out >>= (1 - (el & 1)) * 8;
- out &= 0x00ff;
-
- el++;
-
- UINT16 temp;
- SIMD_EXTRACT16(m_xv[VS1REG], temp, (el >> 1));
- temp >>= (1 - (el & 1)) * 8;
- temp &= 0x00ff;
-
- m_rsp_state->r[RTREG] = (INT32)(INT16)((out << 8) | temp);
-}
-
-static void cfunc_mfc2_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_mfc2_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-inline void rsp_device::ccfunc_mfc2_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int el = (op >> 7) & 0xf;
-
- UINT16 b1 = VREG_B(VS1REG, (el+0) & 0xf);
- UINT16 b2 = VREG_B(VS1REG, (el+1) & 0xf);
- if (RTREG) RTVAL = (INT32)(INT16)((b1 << 8) | (b2));
-}
-
-static void cfunc_mfc2_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_mfc2_scalar();
-}
-#endif
-
-#if USE_SIMD
-inline void rsp_device::ccfunc_cfc2_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- if (RTREG)
- {
- switch(RDREG)
- {
- case 0:
- RTVAL = ((VEC_CARRY_FLAG(0) & 1) << 0) |
- ((VEC_CARRY_FLAG(1) & 1) << 1) |
- ((VEC_CARRY_FLAG(2) & 1) << 2) |
- ((VEC_CARRY_FLAG(3) & 1) << 3) |
- ((VEC_CARRY_FLAG(4) & 1) << 4) |
- ((VEC_CARRY_FLAG(5) & 1) << 5) |
- ((VEC_CARRY_FLAG(6) & 1) << 6) |
- ((VEC_CARRY_FLAG(7) & 1) << 7) |
- ((VEC_ZERO_FLAG(0) & 1) << 8) |
- ((VEC_ZERO_FLAG(1) & 1) << 9) |
- ((VEC_ZERO_FLAG(2) & 1) << 10) |
- ((VEC_ZERO_FLAG(3) & 1) << 11) |
- ((VEC_ZERO_FLAG(4) & 1) << 12) |
- ((VEC_ZERO_FLAG(5) & 1) << 13) |
- ((VEC_ZERO_FLAG(6) & 1) << 14) |
- ((VEC_ZERO_FLAG(7) & 1) << 15);
- if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
- break;
- case 1:
- RTVAL = ((VEC_COMPARE_FLAG(0) & 1) << 0) |
- ((VEC_COMPARE_FLAG(1) & 1) << 1) |
- ((VEC_COMPARE_FLAG(2) & 1) << 2) |
- ((VEC_COMPARE_FLAG(3) & 1) << 3) |
- ((VEC_COMPARE_FLAG(4) & 1) << 4) |
- ((VEC_COMPARE_FLAG(5) & 1) << 5) |
- ((VEC_COMPARE_FLAG(6) & 1) << 6) |
- ((VEC_COMPARE_FLAG(7) & 1) << 7) |
- ((VEC_CLIP2_FLAG(0) & 1) << 8) |
- ((VEC_CLIP2_FLAG(1) & 1) << 9) |
- ((VEC_CLIP2_FLAG(2) & 1) << 10) |
- ((VEC_CLIP2_FLAG(3) & 1) << 11) |
- ((VEC_CLIP2_FLAG(4) & 1) << 12) |
- ((VEC_CLIP2_FLAG(5) & 1) << 13) |
- ((VEC_CLIP2_FLAG(6) & 1) << 14) |
- ((VEC_CLIP2_FLAG(7) & 1) << 15);
- if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
- break;
- case 2:
- RTVAL = ((VEC_CLIP1_FLAG(0) & 1) << 0) |
- ((VEC_CLIP1_FLAG(1) & 1) << 1) |
- ((VEC_CLIP1_FLAG(2) & 1) << 2) |
- ((VEC_CLIP1_FLAG(3) & 1) << 3) |
- ((VEC_CLIP1_FLAG(4) & 1) << 4) |
- ((VEC_CLIP1_FLAG(5) & 1) << 5) |
- ((VEC_CLIP1_FLAG(6) & 1) << 6) |
- ((VEC_CLIP1_FLAG(7) & 1) << 7);
- break;
- }
- }
-}
-
-static void cfunc_cfc2_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_cfc2_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-inline void rsp_device::ccfunc_cfc2_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- if (RTREG)
- {
- switch(RDREG)
- {
- case 0:
- RTVAL = ((CARRY_FLAG(0) & 1) << 0) |
- ((CARRY_FLAG(1) & 1) << 1) |
- ((CARRY_FLAG(2) & 1) << 2) |
- ((CARRY_FLAG(3) & 1) << 3) |
- ((CARRY_FLAG(4) & 1) << 4) |
- ((CARRY_FLAG(5) & 1) << 5) |
- ((CARRY_FLAG(6) & 1) << 6) |
- ((CARRY_FLAG(7) & 1) << 7) |
- ((ZERO_FLAG(0) & 1) << 8) |
- ((ZERO_FLAG(1) & 1) << 9) |
- ((ZERO_FLAG(2) & 1) << 10) |
- ((ZERO_FLAG(3) & 1) << 11) |
- ((ZERO_FLAG(4) & 1) << 12) |
- ((ZERO_FLAG(5) & 1) << 13) |
- ((ZERO_FLAG(6) & 1) << 14) |
- ((ZERO_FLAG(7) & 1) << 15);
- if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
- break;
- case 1:
- RTVAL = ((COMPARE_FLAG(0) & 1) << 0) |
- ((COMPARE_FLAG(1) & 1) << 1) |
- ((COMPARE_FLAG(2) & 1) << 2) |
- ((COMPARE_FLAG(3) & 1) << 3) |
- ((COMPARE_FLAG(4) & 1) << 4) |
- ((COMPARE_FLAG(5) & 1) << 5) |
- ((COMPARE_FLAG(6) & 1) << 6) |
- ((COMPARE_FLAG(7) & 1) << 7) |
- ((CLIP2_FLAG(0) & 1) << 8) |
- ((CLIP2_FLAG(1) & 1) << 9) |
- ((CLIP2_FLAG(2) & 1) << 10) |
- ((CLIP2_FLAG(3) & 1) << 11) |
- ((CLIP2_FLAG(4) & 1) << 12) |
- ((CLIP2_FLAG(5) & 1) << 13) |
- ((CLIP2_FLAG(6) & 1) << 14) |
- ((CLIP2_FLAG(7) & 1) << 15);
- if (RTVAL & 0x8000) RTVAL |= 0xffff0000;
- break;
- case 2:
- RTVAL = ((CLIP1_FLAG(0) & 1) << 0) |
- ((CLIP1_FLAG(1) & 1) << 1) |
- ((CLIP1_FLAG(2) & 1) << 2) |
- ((CLIP1_FLAG(3) & 1) << 3) |
- ((CLIP1_FLAG(4) & 1) << 4) |
- ((CLIP1_FLAG(5) & 1) << 5) |
- ((CLIP1_FLAG(6) & 1) << 6) |
- ((CLIP1_FLAG(7) & 1) << 7);
- break;
- }
- }
-}
-
-static void cfunc_cfc2_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_cfc2_scalar();
-}
-#endif
-
-#if USE_SIMD
-inline void rsp_device::ccfunc_mtc2_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- int el = (op >> 7) & 0xf;
- SIMD_INSERT16(m_xv[VS1REG], RTVAL, el >> 1);
-}
-
-static void cfunc_mtc2_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_mtc2_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-inline void rsp_device::ccfunc_mtc2_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- int el = (op >> 7) & 0xf;
- VREG_B(VS1REG, (el+0) & 0xf) = (RTVAL >> 8) & 0xff;
- VREG_B(VS1REG, (el+1) & 0xf) = (RTVAL >> 0) & 0xff;
-}
-
-static void cfunc_mtc2_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_mtc2_scalar();
-}
-#endif
-
-#if USE_SIMD
-inline void rsp_device::ccfunc_ctc2_simd()
-{
- UINT32 op = m_rsp_state->arg0;
- switch(RDREG)
- {
- case 0:
- VEC_CLEAR_CARRY_FLAGS();
- VEC_CLEAR_ZERO_FLAGS();
- m_vflag[0][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
- m_vflag[0][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
- m_vflag[0][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
- m_vflag[0][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
- m_vflag[0][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
- m_vflag[0][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
- m_vflag[0][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
- m_vflag[0][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
- if (RTVAL & (1 << 0)) { VEC_SET_CARRY_FLAG(0); }
- if (RTVAL & (1 << 1)) { VEC_SET_CARRY_FLAG(1); }
- if (RTVAL & (1 << 2)) { VEC_SET_CARRY_FLAG(2); }
- if (RTVAL & (1 << 3)) { VEC_SET_CARRY_FLAG(3); }
- if (RTVAL & (1 << 4)) { VEC_SET_CARRY_FLAG(4); }
- if (RTVAL & (1 << 5)) { VEC_SET_CARRY_FLAG(5); }
- if (RTVAL & (1 << 6)) { VEC_SET_CARRY_FLAG(6); }
- if (RTVAL & (1 << 7)) { VEC_SET_CARRY_FLAG(7); }
- m_vflag[3][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0;
- m_vflag[3][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0;
- m_vflag[3][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0;
- m_vflag[3][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0;
- m_vflag[3][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0;
- m_vflag[3][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0;
- m_vflag[3][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0;
- m_vflag[3][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0;
- if (RTVAL & (1 << 8)) { VEC_SET_ZERO_FLAG(0); }
- if (RTVAL & (1 << 9)) { VEC_SET_ZERO_FLAG(1); }
- if (RTVAL & (1 << 10)) { VEC_SET_ZERO_FLAG(2); }
- if (RTVAL & (1 << 11)) { VEC_SET_ZERO_FLAG(3); }
- if (RTVAL & (1 << 12)) { VEC_SET_ZERO_FLAG(4); }
- if (RTVAL & (1 << 13)) { VEC_SET_ZERO_FLAG(5); }
- if (RTVAL & (1 << 14)) { VEC_SET_ZERO_FLAG(6); }
- if (RTVAL & (1 << 15)) { VEC_SET_ZERO_FLAG(7); }
- break;
- case 1:
- VEC_CLEAR_COMPARE_FLAGS();
- VEC_CLEAR_CLIP2_FLAGS();
- m_vflag[1][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
- m_vflag[1][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
- m_vflag[1][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
- m_vflag[1][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
- m_vflag[1][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
- m_vflag[1][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
- m_vflag[1][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
- m_vflag[1][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
- if (RTVAL & (1 << 0)) { VEC_SET_COMPARE_FLAG(0); }
- if (RTVAL & (1 << 1)) { VEC_SET_COMPARE_FLAG(1); }
- if (RTVAL & (1 << 2)) { VEC_SET_COMPARE_FLAG(2); }
- if (RTVAL & (1 << 3)) { VEC_SET_COMPARE_FLAG(3); }
- if (RTVAL & (1 << 4)) { VEC_SET_COMPARE_FLAG(4); }
- if (RTVAL & (1 << 5)) { VEC_SET_COMPARE_FLAG(5); }
- if (RTVAL & (1 << 6)) { VEC_SET_COMPARE_FLAG(6); }
- if (RTVAL & (1 << 7)) { VEC_SET_COMPARE_FLAG(7); }
- m_vflag[4][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0;
- m_vflag[4][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0;
- m_vflag[4][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0;
- m_vflag[4][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0;
- m_vflag[4][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0;
- m_vflag[4][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0;
- m_vflag[4][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0;
- m_vflag[4][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0;
- if (RTVAL & (1 << 8)) { VEC_SET_CLIP2_FLAG(0); }
- if (RTVAL & (1 << 9)) { VEC_SET_CLIP2_FLAG(1); }
- if (RTVAL & (1 << 10)) { VEC_SET_CLIP2_FLAG(2); }
- if (RTVAL & (1 << 11)) { VEC_SET_CLIP2_FLAG(3); }
- if (RTVAL & (1 << 12)) { VEC_SET_CLIP2_FLAG(4); }
- if (RTVAL & (1 << 13)) { VEC_SET_CLIP2_FLAG(5); }
- if (RTVAL & (1 << 14)) { VEC_SET_CLIP2_FLAG(6); }
- if (RTVAL & (1 << 15)) { VEC_SET_CLIP2_FLAG(7); }
- break;
- case 2:
- VEC_CLEAR_CLIP1_FLAGS();
- m_vflag[2][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
- m_vflag[2][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
- m_vflag[2][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
- m_vflag[2][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
- m_vflag[2][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
- m_vflag[2][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
- m_vflag[2][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
- m_vflag[2][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
- if (RTVAL & (1 << 0)) { VEC_SET_CLIP1_FLAG(0); }
- if (RTVAL & (1 << 1)) { VEC_SET_CLIP1_FLAG(1); }
- if (RTVAL & (1 << 2)) { VEC_SET_CLIP1_FLAG(2); }
- if (RTVAL & (1 << 3)) { VEC_SET_CLIP1_FLAG(3); }
- if (RTVAL & (1 << 4)) { VEC_SET_CLIP1_FLAG(4); }
- if (RTVAL & (1 << 5)) { VEC_SET_CLIP1_FLAG(5); }
- if (RTVAL & (1 << 6)) { VEC_SET_CLIP1_FLAG(6); }
- if (RTVAL & (1 << 7)) { VEC_SET_CLIP1_FLAG(7); }
- break;
- }
-}
-
-static void cfunc_ctc2_simd(void *param)
-{
- ((rsp_device *)param)->ccfunc_ctc2_simd();
-}
-#endif
-
-#if (!USE_SIMD || SIMUL_SIMD)
-inline void rsp_device::ccfunc_ctc2_scalar()
-{
- UINT32 op = m_rsp_state->arg0;
- switch(RDREG)
- {
- case 0:
- CLEAR_CARRY_FLAGS();
- CLEAR_ZERO_FLAGS();
- m_vflag[0][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
- m_vflag[0][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
- m_vflag[0][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
- m_vflag[0][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
- m_vflag[0][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
- m_vflag[0][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
- m_vflag[0][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
- m_vflag[0][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
- if (RTVAL & (1 << 0)) { SET_CARRY_FLAG(0); }
- if (RTVAL & (1 << 1)) { SET_CARRY_FLAG(1); }
- if (RTVAL & (1 << 2)) { SET_CARRY_FLAG(2); }
- if (RTVAL & (1 << 3)) { SET_CARRY_FLAG(3); }
- if (RTVAL & (1 << 4)) { SET_CARRY_FLAG(4); }
- if (RTVAL & (1 << 5)) { SET_CARRY_FLAG(5); }
- if (RTVAL & (1 << 6)) { SET_CARRY_FLAG(6); }
- if (RTVAL & (1 << 7)) { SET_CARRY_FLAG(7); }
- m_vflag[3][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0;
- m_vflag[3][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0;
- m_vflag[3][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0;
- m_vflag[3][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0;
- m_vflag[3][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0;
- m_vflag[3][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0;
- m_vflag[3][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0;
- m_vflag[3][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0;
- if (RTVAL & (1 << 8)) { SET_ZERO_FLAG(0); }
- if (RTVAL & (1 << 9)) { SET_ZERO_FLAG(1); }
- if (RTVAL & (1 << 10)) { SET_ZERO_FLAG(2); }
- if (RTVAL & (1 << 11)) { SET_ZERO_FLAG(3); }
- if (RTVAL & (1 << 12)) { SET_ZERO_FLAG(4); }
- if (RTVAL & (1 << 13)) { SET_ZERO_FLAG(5); }
- if (RTVAL & (1 << 14)) { SET_ZERO_FLAG(6); }
- if (RTVAL & (1 << 15)) { SET_ZERO_FLAG(7); }
- break;
- case 1:
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
- m_vflag[1][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
- m_vflag[1][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
- m_vflag[1][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
- m_vflag[1][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
- m_vflag[1][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
- m_vflag[1][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
- m_vflag[1][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
- m_vflag[1][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
- if (RTVAL & (1 << 0)) { SET_COMPARE_FLAG(0); }
- if (RTVAL & (1 << 1)) { SET_COMPARE_FLAG(1); }
- if (RTVAL & (1 << 2)) { SET_COMPARE_FLAG(2); }
- if (RTVAL & (1 << 3)) { SET_COMPARE_FLAG(3); }
- if (RTVAL & (1 << 4)) { SET_COMPARE_FLAG(4); }
- if (RTVAL & (1 << 5)) { SET_COMPARE_FLAG(5); }
- if (RTVAL & (1 << 6)) { SET_COMPARE_FLAG(6); }
- if (RTVAL & (1 << 7)) { SET_COMPARE_FLAG(7); }
- m_vflag[4][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0;
- m_vflag[4][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0;
- m_vflag[4][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0;
- m_vflag[4][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0;
- m_vflag[4][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0;
- m_vflag[4][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0;
- m_vflag[4][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0;
- m_vflag[4][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0;
- if (RTVAL & (1 << 8)) { SET_CLIP2_FLAG(0); }
- if (RTVAL & (1 << 9)) { SET_CLIP2_FLAG(1); }
- if (RTVAL & (1 << 10)) { SET_CLIP2_FLAG(2); }
- if (RTVAL & (1 << 11)) { SET_CLIP2_FLAG(3); }
- if (RTVAL & (1 << 12)) { SET_CLIP2_FLAG(4); }
- if (RTVAL & (1 << 13)) { SET_CLIP2_FLAG(5); }
- if (RTVAL & (1 << 14)) { SET_CLIP2_FLAG(6); }
- if (RTVAL & (1 << 15)) { SET_CLIP2_FLAG(7); }
- break;
- case 2:
- CLEAR_CLIP1_FLAGS();
- m_vflag[2][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0;
- m_vflag[2][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0;
- m_vflag[2][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0;
- m_vflag[2][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0;
- m_vflag[2][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0;
- m_vflag[2][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0;
- m_vflag[2][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0;
- m_vflag[2][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0;
- if (RTVAL & (1 << 0)) { SET_CLIP1_FLAG(0); }
- if (RTVAL & (1 << 1)) { SET_CLIP1_FLAG(1); }
- if (RTVAL & (1 << 2)) { SET_CLIP1_FLAG(2); }
- if (RTVAL & (1 << 3)) { SET_CLIP1_FLAG(3); }
- if (RTVAL & (1 << 4)) { SET_CLIP1_FLAG(4); }
- if (RTVAL & (1 << 5)) { SET_CLIP1_FLAG(5); }
- if (RTVAL & (1 << 6)) { SET_CLIP1_FLAG(6); }
- if (RTVAL & (1 << 7)) { SET_CLIP1_FLAG(7); }
- break;
- }
-}
-
-static void cfunc_ctc2_scalar(void *param)
-{
- ((rsp_device *)param)->ccfunc_ctc2_scalar();
-}
-#endif
-
/***************************************************************************
CODE LOGGING HELPERS
***************************************************************************/
diff --git a/src/mame/drivers/sauro.c b/src/mame/drivers/sauro.c
index 7e304f04e47..389a9f2f90b 100644
--- a/src/mame/drivers/sauro.c
+++ b/src/mame/drivers/sauro.c
@@ -491,6 +491,39 @@ ROM_START( saurop )
ROM_LOAD( "sp0256-al2.bin", 0x1000, 0x0800, CRC(b504ac15) SHA1(e60fcb5fa16ff3f3b69d36c7a6e955744d3feafc) )
ROM_END
+ROM_START( saurorr ) // all roms have original Tecfri stickers
+ ROM_REGION( 0x10000, "maincpu", 0 )
+ ROM_LOAD( "27256-2.bin", 0x00000, 0x8000, CRC(b0d80eab) SHA1(60cbe16d6c87d4681155814a5034b7e9d10bbd81) )
+ ROM_LOAD( "27256-1.bin", 0x08000, 0x8000, CRC(cbb5f06e) SHA1(f93c01006d308e0b6950d720b6fe4409728c79e2) )
+
+ ROM_REGION( 0x10000, "audiocpu", 0 )
+ ROM_LOAD( "sauro-3.bin", 0x00000, 0x8000, CRC(0d501e1b) SHA1(20a56ff30d4fa5d2f483a449703b49153839f6bc) )
+
+ ROM_REGION( 0x10000, "gfx1", 0 )
+ ROM_LOAD( "sauro-6.bin", 0x00000, 0x8000, CRC(4b77cb0f) SHA1(7b9cb2dca561d81390106c1a5c0533dcecaf6f1a) )
+ ROM_LOAD( "sauro-7.bin", 0x08000, 0x8000, CRC(187da060) SHA1(1df156e58379bb39acade02aabab6ff1cb7cc288) )
+
+ ROM_REGION( 0x10000, "gfx2", 0 )
+ ROM_LOAD( "sauro-4.bin", 0x00000, 0x8000, CRC(9b617cda) SHA1(ce26b84ad5ecd6185ae218520e9972645bbf09ad) )
+ ROM_LOAD( "27256-5.bin", 0x08000, 0x8000, CRC(9aabdbe5) SHA1(ef008e368024f9377a8d2bc5863b01c63bc8f55b) ) // contains the changed license logo
+
+ ROM_REGION( 0x20000, "gfx3", 0 )
+ ROM_LOAD( "sauro-8.bin", 0x00000, 0x8000, CRC(e08b5d5e) SHA1(eaaeaa08b19c034ab2a2140f887edffca5f441b9) )
+ ROM_LOAD( "sauro-9.bin", 0x08000, 0x8000, CRC(7c707195) SHA1(0529f6808b0cec3e12ca51bee189841d21577786) )
+ ROM_LOAD( "sauro-10.bin", 0x10000, 0x8000, CRC(c93380d1) SHA1(fc9655cc94c2d2058f83eb341be7e7856a08194f) )
+ ROM_LOAD( "sauro-11.bin", 0x18000, 0x8000, CRC(f47982a8) SHA1(cbaeac272c015d9439f151cfb3449082f11a57a1) )
+
+ ROM_REGION( 0x0c00, "proms", 0 )
+ ROM_LOAD( "82s137-3.bin", 0x0000, 0x0400, CRC(d52c4cd0) SHA1(27d6126b46616c06b55d8018c97f6c3d7805ae9e) ) /* Red component */
+ ROM_LOAD( "82s137-2.bin", 0x0400, 0x0400, CRC(c3e96d5d) SHA1(3f6f21526a4357e4a9a9d56a6f4ef5911af2d120) ) /* Green component */
+ ROM_LOAD( "82s137-1.bin", 0x0800, 0x0400, CRC(bdfcf00c) SHA1(9faf4d7f8959b64faa535c9945eec59c774a3760) ) /* Blue component */
+
+ ROM_REGION( 0x10000, "speech", 0 )
+ /* SP0256 mask rom */
+ ROM_LOAD( "sp0256-al2.bin", 0x1000, 0x0800, CRC(b504ac15) SHA1(e60fcb5fa16ff3f3b69d36c7a6e955744d3feafc) )
+ROM_END
+
+
ROM_START( trckydoc )
ROM_REGION( 0x10000, "maincpu", 0 )
ROM_LOAD( "trckydoc.d9", 0x0000, 0x8000, CRC(c6242fc3) SHA1(c8a6f6abe8b51061a113ed75fead0479df68ec40) )
@@ -550,7 +583,9 @@ DRIVER_INIT_MEMBER(sauro_state,tecfri)
RAM[0xe000] = 1;
}
-GAME( 1987, sauro, 0, sauro, tecfri, sauro_state, tecfri, ROT0, "Tecfri", "Sauro", 0 )
-GAME( 1987, saurop, sauro, sauro, tecfri, sauro_state, tecfri, ROT0, "Tecfri (Philko license)", "Sauro (Philko license)", 0 )
+GAME( 1987, sauro, 0, sauro, tecfri, sauro_state, tecfri, ROT0, "Tecfri", "Sauro", 0 )
+GAME( 1987, saurop, sauro, sauro, tecfri, sauro_state, tecfri, ROT0, "Tecfri (Philko license)", "Sauro (Philko license)", 0 )
+GAME( 1987, saurorr, sauro, sauro, tecfri, sauro_state, tecfri, ROT0, "Tecfri (Recreativo Real S.A. license)", "Sauro (Recreativo Real S.A. license)", 0 )
+
GAME( 1987, trckydoc, 0, trckydoc, tecfri, sauro_state, tecfri, ROT0, "Tecfri", "Tricky Doc (set 1)", 0 )
GAME( 1987, trckydoca,trckydoc, trckydoc, trckydoca, sauro_state, tecfri, ROT0, "Tecfri", "Tricky Doc (set 2)", 0 )
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 9e9cafacb8f..ac73ac51ef2 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -9310,6 +9310,7 @@ speedbal // (c) 1987
musicbal // (c) 1987
sauro // (c) 1987
saurop // (c) 1987
+saurorr // (c) 1987
trckydoc // (c) 1987
trckydoca // (c) 1987