summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/rsp
diff options
context:
space:
mode:
author MooglyGuy <MooglyGuy@users.noreply.github.com>2021-08-10 03:06:08 +0200
committer GitHub <noreply@github.com>2021-08-09 21:06:08 -0400
commit7fe8f9f74c8a8aca5e0ca949dafcac13504c3013 (patch)
tree3cd6d926ab025b2b965c01ff02dbfee69488abec /src/devices/cpu/rsp
parent1fc8bf7fcd88b672f1c9ab7427d80f0356358d85 (diff)
Assorted N64 fixes (#8415)
* -rdp: Fixed incorrect channel swapping on 32-bit resampled framebuffers. [Ryan Holtz] * -rsp: Fixed LWV and VMOV behavior. Added reserved instructions V056, V057, V073, and VNULL. [Ryan Holtz, krom] * -rdp: Temporarily adjusted framebuffer resampling to not exceed screen bounds in some games. [Ryan Holtz] * -n64: Fixed SP DMA behavior based on hardware tests. [Ryan Holtz] * -rsp: Removed unused DRC and SIMD support. General code cleanup. [Ryan Holtz] * -n64: Pass K4 and K5 factors to threaded drawing code. Fixes black geometry in Conker's Bad Fur Day. [Ryan Holtz] * -aleck64: Fixed compile issue with previous commits. [Ryan Holtz]
Diffstat (limited to 'src/devices/cpu/rsp')
-rw-r--r--src/devices/cpu/rsp/clamp.h37
-rw-r--r--src/devices/cpu/rsp/rsp.cpp3010
-rw-r--r--src/devices/cpu/rsp/rsp.h195
-rw-r--r--src/devices/cpu/rsp/rsp_dasm.cpp4
-rw-r--r--src/devices/cpu/rsp/rspcp2.cpp4223
-rw-r--r--src/devices/cpu/rsp/rspcp2.h395
-rw-r--r--src/devices/cpu/rsp/rspcp2d.cpp3388
-rw-r--r--src/devices/cpu/rsp/rspcp2d.h179
-rw-r--r--src/devices/cpu/rsp/rspdrc.cpp1279
-rw-r--r--src/devices/cpu/rsp/rspfe.cpp307
-rw-r--r--src/devices/cpu/rsp/rspfe.h55
-rw-r--r--src/devices/cpu/rsp/vabs.h15
-rw-r--r--src/devices/cpu/rsp/vadd.h16
-rw-r--r--src/devices/cpu/rsp/vaddc.h13
-rw-r--r--src/devices/cpu/rsp/vand.h9
-rw-r--r--src/devices/cpu/rsp/vch.h57
-rw-r--r--src/devices/cpu/rsp/vcl.h65
-rw-r--r--src/devices/cpu/rsp/vcmp.h49
-rw-r--r--src/devices/cpu/rsp/vcr.h35
-rw-r--r--src/devices/cpu/rsp/vdivh.h12
-rw-r--r--src/devices/cpu/rsp/vldst.h69
-rw-r--r--src/devices/cpu/rsp/vmac.h57
-rw-r--r--src/devices/cpu/rsp/vmov.h9
-rw-r--r--src/devices/cpu/rsp/vmrg.h13
-rw-r--r--src/devices/cpu/rsp/vmudh.h10
-rw-r--r--src/devices/cpu/rsp/vmul.h39
-rw-r--r--src/devices/cpu/rsp/vmulh.h30
-rw-r--r--src/devices/cpu/rsp/vmull.h44
-rw-r--r--src/devices/cpu/rsp/vmulm.h56
-rw-r--r--src/devices/cpu/rsp/vmuln.h55
-rw-r--r--src/devices/cpu/rsp/vor.h10
-rw-r--r--src/devices/cpu/rsp/vrcpsq.h58
-rw-r--r--src/devices/cpu/rsp/vrsq.h66
-rw-r--r--src/devices/cpu/rsp/vsub.h17
-rw-r--r--src/devices/cpu/rsp/vsubc.h14
-rw-r--r--src/devices/cpu/rsp/vxor.h10
36 files changed, 2699 insertions, 11201 deletions
diff --git a/src/devices/cpu/rsp/clamp.h b/src/devices/cpu/rsp/clamp.h
deleted file mode 100644
index 5b69b746a7d..00000000000
--- a/src/devices/cpu/rsp/clamp.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-static inline rsp_vec_t sclamp_acc_to_mid(rsp_vec_t acc_mid, rsp_vec_t acc_hi)
-{
- return _mm_packs_epi32(
- _mm_unpacklo_epi16(acc_mid, acc_hi),
- _mm_unpackhi_epi16(acc_mid, acc_hi)
- );
-}
-
-static inline rsp_vec_t uclamp_acc(rsp_vec_t val, rsp_vec_t acc_mid, rsp_vec_t acc_hi, rsp_vec_t zero)
-{
- rsp_vec_t hi_negative = _mm_srai_epi16(acc_hi, 15); // 0x0000
- rsp_vec_t mid_negative = _mm_srai_epi16(acc_mid, 15); // 0xffff
-
- // We don't have to clamp if the HI part of the
- // accumulator is sign-extended down to the MD part.
- rsp_vec_t hi_sign_check = _mm_cmpeq_epi16(hi_negative, acc_hi); // 0x0000
- rsp_vec_t mid_sign_check = _mm_cmpeq_epi16(hi_negative, mid_negative); // 0x0000
- rsp_vec_t clamp_mask = _mm_and_si128(mid_sign_check, hi_sign_check); // 0x0000
-
- // Generate the value in the event we need to clamp.
- // * hi_negative, mid_sign => xxxx
- // * hi_negative, !mid_sign => 0000
- // * !hi_negative, mid_sign => FFFF
- // * !hi_negative, !mid_sign => xxxx
- rsp_vec_t clamped_val = _mm_cmpeq_epi16(hi_negative, zero); // 0xffff
-
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- return _mm_blendv_epi8(clamped_val, val, clamp_mask);
-#else
- clamped_val = _mm_and_si128(clamp_mask, val);
- val = _mm_andnot_si128(clamp_mask, clamped_val);
- return _mm_or_si128(val, clamped_val);
-#endif
-}
diff --git a/src/devices/cpu/rsp/rsp.cpp b/src/devices/cpu/rsp/rsp.cpp
index 07deffc6e10..5d8cccff5af 100644
--- a/src/devices/cpu/rsp/rsp.cpp
+++ b/src/devices/cpu/rsp/rsp.cpp
@@ -9,13 +9,10 @@
#include "emu.h"
#include "rsp.h"
-#include "rspfe.h"
-#include "rspcp2.h"
-#include "rspcp2d.h"
-
#include "debugger.h"
#include "rspdefs.h"
+#include "rspdiv.h"
#include "rsp_dasm.h"
@@ -27,59 +24,72 @@ DEFINE_DEVICE_TYPE(RSP, rsp_device, "rsp", "Nintendo & SGI Reality Signal Proces
#define SAVE_DMEM 0
#define RSP_TEST_SYNC 0
-#define PRINT_VECREG(x) osd_printf_debug("V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X\n", (x), \
- (uint16_t)VREG_S((x),0), (uint16_t)VREG_S((x),1), \
- (uint16_t)VREG_S((x),2), (uint16_t)VREG_S((x),3), \
- (uint16_t)VREG_S((x),4), (uint16_t)VREG_S((x),5), \
- (uint16_t)VREG_S((x),6), (uint16_t)VREG_S((x),7))
+#define PRINT_VECREG(x) osd_printf_debug("V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X\n", x, \
+ m_v[x].w[0], m_v[x].w[1], m_v[x].w[2], m_v[x].w[3], \
+ m_v[x].w[4], m_v[x].w[5], m_v[x].w[6], m_v[x].w[7])
-#define PRINT_ACCUM(x) osd_printf_debug("A%d: %08X|%08X\n", (x), \
- (uint32_t)( ( ACCUM(x) >> 32 ) & 0x00000000ffffffff ), \
- (uint32_t)( ACCUM(x) & 0x00000000ffffffff ))
+#define PRINT_ACCUM(x) osd_printf_debug("A%d: %08X|%08X\n", x, (uint32_t)(m_accum[x].q >> 32), (uint32_t)m_accum[x].q);
#define SIMM16 ((int32_t)(int16_t)(op))
#define UIMM16 ((uint16_t)(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); }
-#define JUMP_REL_L(offset,l) { m_nextpc = 0x04001000 | ((m_rsp_state->pc + ((offset) << 2)) & 0xfff); m_rsp_state->r[l] = m_rsp_state->pc + 4; }
-#define JUMP_PC(addr) { m_nextpc = 0x04001000 | ((addr) & 0xfff); }
-#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 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 ROPCODE(pc) m_pcache.read_dword(pc)
+#define JUMP_ABS(addr) { m_nextpc = (addr) << 2; }
+#define JUMP_ABS_L(addr,l) { m_nextpc = (addr) << 2; m_r[l] = m_pc + 4; }
+#define JUMP_REL(offset) { m_nextpc = m_pc + ((offset) << 2); }
+#define JUMP_REL_L(offset,l) { m_nextpc = m_pc + ((offset) << 2); m_r[l] = m_pc + 4; }
+#define JUMP_PC(addr) { m_nextpc = addr; }
+#define JUMP_PC_L(addr,l) { m_nextpc = addr; m_r[l] = m_pc + 4; }
+#define ROPCODE(pc) m_icache.read_dword(pc & 0xfff)
+
+/***************************************************************************
+ Helpful Vector Defines
+***************************************************************************/
+
+#define VDREG ((op >> 6) & 0x1f)
+#define VS1REG ((op >> 11) & 0x1f)
+#define VS2REG ((op >> 16) & 0x1f)
+#define EL ((op >> 21) & 0xf)
+
+#define VREG_B(reg, offset) m_v[(reg)].b[(offset)^1]
+#define W_VREG_B(reg, offset, val) (m_v[(reg)].b[(offset)^1] = 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 SLICE_H 3
+#define SLICE_M 2
+#define SLICE_L 1
+#define SLICE_LL 0
+
+#define WRITEBACK_RESULT() memcpy(m_v[VDREG].s, vres, sizeof(uint16_t) * 8);
+
+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
+};
/***************************************************************************
DEBUGGING
@@ -103,39 +113,17 @@ DEFINE_DEVICE_TYPE(RSP, rsp_device, "rsp", "Nintendo & SGI Reality Signal Proces
rsp_device::rsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, RSP, tag, owner, clock)
- , m_program_config("program", ENDIANNESS_BIG, 32, 32)
- , m_cache(CACHE_SIZE + sizeof(internal_rsp_state))
- , m_drcuml(nullptr)
-// , m_drcuml(*this, m_cache, 0, 8, 32, 2)
- , m_drcfe(nullptr)
- , m_drcoptions(0)
- , m_cache_dirty(true)
- , m_numcycles(0)
- , m_format(nullptr)
- , m_arg2(0)
- , m_arg3(0)
- , m_entry(nullptr)
- , m_nocode(nullptr)
- , m_out_of_cycles(nullptr)
- , m_read8(nullptr)
- , m_write8(nullptr)
- , m_read16(nullptr)
- , m_write16(nullptr)
- , m_read32(nullptr)
- , m_write32(nullptr)
- , m_rsp_state(nullptr)
+ , m_imem_config("imem", ENDIANNESS_BIG, 32, 12)
+ , m_dmem_config("dmem", ENDIANNESS_BIG, 32, 12)
, m_exec_output(nullptr)
, m_sr(0)
, m_step_count(0)
, m_ppc(0)
- , m_nextpc(0)
- , m_dmem32(nullptr)
- , m_dmem16(nullptr)
- , m_dmem8(nullptr)
- , m_imem32(nullptr)
- , m_imem16(nullptr)
- , m_imem8(nullptr)
+ , m_nextpc(0xffff)
, m_debugger_temp(0)
+ , m_pc_temp(0)
+ , m_ppc_temp(0)
+ , m_nextpc_temp(0xffff)
, m_dp_reg_r_func(*this)
, m_dp_reg_w_func(*this)
, m_sp_reg_r_func(*this)
@@ -151,7 +139,8 @@ rsp_device::~rsp_device()
device_memory_interface::space_config_vector rsp_device::memory_space_config() const
{
return space_config_vector {
- std::make_pair(AS_PROGRAM, &m_program_config)
+ std::make_pair(AS_PROGRAM, &m_imem_config),
+ std::make_pair(AS_DATA, &m_dmem_config)
};
}
@@ -160,133 +149,34 @@ std::unique_ptr<util::disasm_interface> rsp_device::create_disassembler()
return std::make_unique<rsp_disassembler>();
}
-void rsp_device::rsp_add_imem(uint32_t *base)
-{
- m_imem32 = base;
- m_imem16 = (uint16_t*)base;
- m_imem8 = (uint8_t*)base;
-}
-
-void rsp_device::rsp_add_dmem(uint32_t *base)
-{
- m_dmem32 = base;
- m_dmem16 = (uint16_t*)base;
- m_dmem8 = (uint8_t*)base;
-}
-
-uint8_t rsp_device::DM_READ8(uint32_t address)
-{
- uint8_t ret = m_dmem8[BYTE4_XOR_BE(address & 0xfff)];
- //printf("R8:%08x=%02x\n", address, ret);
- return ret;
-}
-
-uint16_t rsp_device::DM_READ16(uint32_t address)
-{
- uint16_t 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;
-}
-
-uint32_t rsp_device::DM_READ32(uint32_t address)
-{
- uint32_t ret;
- address &= 0xfff;
- ret = m_dmem8[BYTE4_XOR_BE(address)] << 24;
- 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;
-}
-
-void rsp_device::DM_WRITE8(uint32_t address, uint8_t data)
-{
- address &= 0xfff;
- m_dmem8[BYTE4_XOR_BE(address)] = data;
- //printf("W8:%08x=%02x\n", address, data);
-}
-
-void rsp_device::DM_WRITE16(uint32_t address, uint16_t data)
+uint8_t rsp_device::read_dmem_byte(uint32_t address)
{
- 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);
+ return m_dcache.read_byte(address);
}
-void rsp_device::DM_WRITE32(uint32_t address, uint32_t data)
+uint16_t rsp_device::read_dmem_word(uint32_t address)
{
- 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);
+ return m_dcache.read_word_unaligned(address);
}
-uint8_t rsp_device::READ8(uint32_t address)
+uint32_t rsp_device::read_dmem_dword(uint32_t address)
{
- uint8_t ret;
- address &= 0xfff;
- ret = m_program.read_byte(address);
- //printf("R8:%08x=%02x\n", address, ret);
- return ret;
+ return m_dcache.read_dword_unaligned(address);
}
-uint16_t rsp_device::READ16(uint32_t address)
+void rsp_device::write_dmem_byte(uint32_t address, uint8_t data)
{
- uint16_t 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;
-}
-
-uint32_t rsp_device::READ32(uint32_t address)
-{
- uint32_t ret;
- address &= 0xfff;
-
- ret = (m_program.read_byte(address) << 24) |
- (m_program.read_byte(address + 1) << 16) |
- (m_program.read_byte(address + 2) << 8) |
- (m_program.read_byte(address + 3) << 0);
-
- //printf("R32:%08x=%08x\n", address, ret);
- return ret;
+ m_dcache.write_byte(address, data);
}
-void rsp_device::WRITE8(uint32_t address, uint8_t data)
+void rsp_device::write_dmem_word(uint32_t address, uint16_t data)
{
- address &= 0xfff;
- m_program.write_byte(address, data);
- //printf("W8:%08x=%02x\n", address, data);
+ m_dcache.write_word_unaligned(address, data);
}
-void rsp_device::WRITE16(uint32_t address, uint16_t data)
+void rsp_device::write_dmem_dword(uint32_t address, uint32_t data)
{
- address &= 0xfff;
-
- 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_t address, uint32_t data)
-{
- address &= 0xfff;
-
- m_program.write_byte(address, data >> 24);
- 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);
+ m_dcache.write_dword_unaligned(address, data);
}
/*****************************************************************************/
@@ -353,7 +243,7 @@ void rsp_device::unimplemented_opcode(uint32_t op)
for (i=0; i < 0x1000; i++)
{
- fputc(READ8(rsp, 0x04000000 + i), dmem);
+ fputc(read_dmem_byte(i), dmem);
}
fclose(dmem);
}
@@ -375,97 +265,82 @@ void rsp_device::resolve_cb()
void rsp_device::device_start()
{
- m_isdrc = allow_drc();
- m_rsp_state = (internal_rsp_state *)m_cache.alloc_near(sizeof(internal_rsp_state));
-
if (LOG_INSTRUCTION_EXECUTION)
m_exec_output = fopen("rsp_execute.txt", "wt");
- space(AS_PROGRAM).cache(m_pcache);
- space(AS_PROGRAM).specific(m_program);
+ space(AS_PROGRAM).cache(m_icache);
+ space(AS_PROGRAM).specific(m_imem);
+ space(AS_DATA).cache(m_dcache);
+ space(AS_DATA).specific(m_dmem);
resolve_cb();
- if (m_isdrc)
- m_cop2 = std::make_unique<cop2_drc>(*this, machine());
- else
- m_cop2 = std::make_unique<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_sr = RSP_STATUS_HALT;
- m_step_count = 0;
+ m_r[regIdx] = 0;
- /* initialize the UML generator */
- uint32_t drc_flags = 0;
- m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, drc_flags, 8, 32, 2);
-
- /* add symbols for our stuff */
- m_drcuml->symbol_add(&m_rsp_state->pc, sizeof(m_rsp_state->pc), "pc");
- m_drcuml->symbol_add(&m_rsp_state->icount, sizeof(m_rsp_state->icount), "icount");
- for (int regnum = 0; regnum < 32; regnum++)
+ for(auto & elem : m_v)
{
- char buf[10];
- sprintf(buf, "r%d", regnum);
- m_drcuml->symbol_add(&m_rsp_state->r[regnum], sizeof(m_rsp_state->r[regnum]), buf);
+ elem.d[0] = 0;
+ elem.d[1] = 0;
}
- m_drcuml->symbol_add(&m_rsp_state->arg0, sizeof(m_rsp_state->arg0), "arg0");
- m_drcuml->symbol_add(&m_rsp_state->arg1, sizeof(m_rsp_state->arg1), "arg1");
- m_drcuml->symbol_add(&m_arg2, sizeof(m_arg2), "arg2");
- m_drcuml->symbol_add(&m_arg3, sizeof(m_arg3), "arg3");
- m_drcuml->symbol_add(&m_numcycles, sizeof(m_numcycles), "numcycles");
- /* initialize the front-end helper */
- m_drcfe = std::make_unique<frontend>(*this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
+ m_vcarry = 0;
+ m_vcompare = 0;
+ m_vclip1 = 0;
+ m_vzero = 0;
+ m_vclip2 = 0;
+
+ m_reciprocal_res = 0;
+ m_reciprocal_high = 0;
+ m_ideduct = 0;
+ m_scalar_busy = false;
+ m_vector_busy = false;
+ m_paired_busy = false;
- /* compute the register parameters */
- for (int regnum = 0; regnum < 32; regnum++)
+ for(auto & elem : m_accum)
{
- m_regmap[regnum] = (regnum == 0) ? uml::parameter(0) : uml::parameter::make_memory(&m_rsp_state->r[regnum]);
+ elem.q = 0;
}
- /* mark the cache dirty so it is updated on next execute */
- m_cache_dirty = true;
-
- state_add( RSP_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%08X");
- state_add( RSP_R0, "R0", m_rsp_state->r[0]).formatstr("%08X");
- state_add( RSP_R1, "R1", m_rsp_state->r[1]).formatstr("%08X");
- state_add( RSP_R2, "R2", m_rsp_state->r[2]).formatstr("%08X");
- state_add( RSP_R3, "R3", m_rsp_state->r[3]).formatstr("%08X");
- state_add( RSP_R4, "R4", m_rsp_state->r[4]).formatstr("%08X");
- state_add( RSP_R5, "R5", m_rsp_state->r[5]).formatstr("%08X");
- state_add( RSP_R6, "R6", m_rsp_state->r[6]).formatstr("%08X");
- state_add( RSP_R7, "R7", m_rsp_state->r[7]).formatstr("%08X");
- state_add( RSP_R8, "R8", m_rsp_state->r[8]).formatstr("%08X");
- state_add( RSP_R9, "R9", m_rsp_state->r[9]).formatstr("%08X");
- state_add( RSP_R10, "R10", m_rsp_state->r[10]).formatstr("%08X");
- state_add( RSP_R11, "R11", m_rsp_state->r[11]).formatstr("%08X");
- state_add( RSP_R12, "R12", m_rsp_state->r[12]).formatstr("%08X");
- state_add( RSP_R13, "R13", m_rsp_state->r[13]).formatstr("%08X");
- state_add( RSP_R14, "R14", m_rsp_state->r[14]).formatstr("%08X");
- state_add( RSP_R15, "R15", m_rsp_state->r[15]).formatstr("%08X");
- state_add( RSP_R16, "R16", m_rsp_state->r[16]).formatstr("%08X");
- state_add( RSP_R17, "R17", m_rsp_state->r[17]).formatstr("%08X");
- state_add( RSP_R18, "R18", m_rsp_state->r[18]).formatstr("%08X");
- state_add( RSP_R19, "R19", m_rsp_state->r[19]).formatstr("%08X");
- state_add( RSP_R20, "R20", m_rsp_state->r[20]).formatstr("%08X");
- state_add( RSP_R21, "R21", m_rsp_state->r[21]).formatstr("%08X");
- state_add( RSP_R22, "R22", m_rsp_state->r[22]).formatstr("%08X");
- state_add( RSP_R23, "R23", m_rsp_state->r[23]).formatstr("%08X");
- state_add( RSP_R24, "R24", m_rsp_state->r[24]).formatstr("%08X");
- state_add( RSP_R25, "R25", m_rsp_state->r[25]).formatstr("%08X");
- state_add( RSP_R26, "R26", m_rsp_state->r[26]).formatstr("%08X");
- state_add( RSP_R27, "R27", m_rsp_state->r[27]).formatstr("%08X");
- state_add( RSP_R28, "R28", m_rsp_state->r[28]).formatstr("%08X");
- state_add( RSP_R29, "R29", m_rsp_state->r[29]).formatstr("%08X");
- state_add( RSP_R30, "R30", m_rsp_state->r[30]).formatstr("%08X");
- state_add( RSP_R31, "R31", m_rsp_state->r[31]).formatstr("%08X");
+ m_pc = 0;
+ m_nextpc = 0xffff;
+ m_sr = RSP_STATUS_HALT;
+ m_step_count = 0;
+
+ state_add( RSP_PC, "PC", m_pc).callimport().callexport().formatstr("%08X");
+ state_add( RSP_R0, "R0", m_r[0]).formatstr("%08X");
+ state_add( RSP_R1, "R1", m_r[1]).formatstr("%08X");
+ state_add( RSP_R2, "R2", m_r[2]).formatstr("%08X");
+ state_add( RSP_R3, "R3", m_r[3]).formatstr("%08X");
+ state_add( RSP_R4, "R4", m_r[4]).formatstr("%08X");
+ state_add( RSP_R5, "R5", m_r[5]).formatstr("%08X");
+ state_add( RSP_R6, "R6", m_r[6]).formatstr("%08X");
+ state_add( RSP_R7, "R7", m_r[7]).formatstr("%08X");
+ state_add( RSP_R8, "R8", m_r[8]).formatstr("%08X");
+ state_add( RSP_R9, "R9", m_r[9]).formatstr("%08X");
+ state_add( RSP_R10, "R10", m_r[10]).formatstr("%08X");
+ state_add( RSP_R11, "R11", m_r[11]).formatstr("%08X");
+ state_add( RSP_R12, "R12", m_r[12]).formatstr("%08X");
+ state_add( RSP_R13, "R13", m_r[13]).formatstr("%08X");
+ state_add( RSP_R14, "R14", m_r[14]).formatstr("%08X");
+ state_add( RSP_R15, "R15", m_r[15]).formatstr("%08X");
+ state_add( RSP_R16, "R16", m_r[16]).formatstr("%08X");
+ state_add( RSP_R17, "R17", m_r[17]).formatstr("%08X");
+ state_add( RSP_R18, "R18", m_r[18]).formatstr("%08X");
+ state_add( RSP_R19, "R19", m_r[19]).formatstr("%08X");
+ state_add( RSP_R20, "R20", m_r[20]).formatstr("%08X");
+ state_add( RSP_R21, "R21", m_r[21]).formatstr("%08X");
+ state_add( RSP_R22, "R22", m_r[22]).formatstr("%08X");
+ state_add( RSP_R23, "R23", m_r[23]).formatstr("%08X");
+ state_add( RSP_R24, "R24", m_r[24]).formatstr("%08X");
+ state_add( RSP_R25, "R25", m_r[25]).formatstr("%08X");
+ state_add( RSP_R26, "R26", m_r[26]).formatstr("%08X");
+ state_add( RSP_R27, "R27", m_r[27]).formatstr("%08X");
+ state_add( RSP_R28, "R28", m_r[28]).formatstr("%08X");
+ state_add( RSP_R29, "R29", m_r[29]).formatstr("%08X");
+ state_add( RSP_R30, "R30", m_r[30]).formatstr("%08X");
+ state_add( RSP_R31, "R31", m_r[31]).formatstr("%08X");
state_add( RSP_SR, "SR", m_sr).formatstr("%08X");
- state_add( RSP_NEXTPC, "NPC", m_debugger_temp).callimport().callexport().formatstr("%08X");
+ state_add( RSP_NEXTPC, "NPC", m_nextpc).callimport().callexport().formatstr("%04X");
state_add( RSP_STEPCNT, "STEP", m_step_count).formatstr("%08X");
state_add( RSP_V0, "V0", m_debugger_temp).formatstr("%39s");
@@ -501,12 +376,12 @@ void rsp_device::device_start()
state_add( RSP_V30, "V30", m_debugger_temp).formatstr("%39s");
state_add( RSP_V31, "V31", m_debugger_temp).formatstr("%39s");
- state_add( STATE_GENPC, "GENPC", m_debugger_temp).callimport().callexport().noshow();
- state_add( STATE_GENPCBASE, "CURPC", m_rsp_state->pc).noshow();
- state_add( STATE_GENFLAGS, "GENFLAGS", m_debugger_temp).formatstr("%1s").noshow();
- state_add( STATE_GENSP, "GENSP", m_rsp_state->r[31]).noshow();
+ state_add( STATE_GENPC, "GENPC", m_pc).noshow();
+ state_add( STATE_GENPCBASE, "CURPC", m_pc).noshow();
+ state_add( STATE_GENFLAGS, "GENFLAGS", m_r[31]).formatstr("%1s").noshow();
+ state_add( STATE_GENSP, "GENSP", m_r[31]).noshow();
- set_icountptr(m_rsp_state->icount);
+ set_icountptr(m_icount);
}
void rsp_device::state_import(const device_state_entry &entry)
@@ -515,15 +390,15 @@ void rsp_device::state_import(const device_state_entry &entry)
{
case STATE_GENPC:
case RSP_PC:
- m_rsp_state->pc = m_debugger_temp;
+ m_pc = (uint16_t)m_pc_temp;
break;
case STATE_GENPCBASE:
- m_ppc = m_debugger_temp;
+ m_ppc = (uint16_t)m_ppc_temp;
break;
case RSP_NEXTPC:
- m_nextpc = m_debugger_temp;
+ m_nextpc = (uint16_t)m_nextpc_temp;
break;
}
}
@@ -535,15 +410,15 @@ void rsp_device::state_export(const device_state_entry &entry)
{
case STATE_GENPC:
case RSP_PC:
- m_debugger_temp = m_rsp_state->pc | 0x04000000;
+ m_pc_temp = m_pc;
break;
case STATE_GENPCBASE:
- m_debugger_temp = m_ppc | 0x04000000;
+ m_ppc_temp = m_ppc;
break;
case RSP_NEXTPC:
- m_debugger_temp = m_nextpc | 0x04000000;
+ m_nextpc_temp = m_nextpc;
break;
}
}
@@ -551,13 +426,75 @@ void rsp_device::state_export(const device_state_entry &entry)
void rsp_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
const int index = entry.index();
- if (index >= RSP_V0 && index <= RSP_V31)
- {
- m_cop2->state_string_export(index, str);
- }
- else if (index == STATE_GENFLAGS)
+ switch (index)
{
- str = "";
+ case RSP_V0:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 0].w[0], m_v[ 0].w[1], m_v[ 0].w[2], m_v[ 0].w[3], m_v[ 0].w[4], m_v[ 0].w[5], m_v[ 0].w[6], m_v[ 0].w[7]); break;
+ case RSP_V1:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 1].w[0], m_v[ 1].w[1], m_v[ 1].w[2], m_v[ 1].w[3], m_v[ 1].w[4], m_v[ 1].w[5], m_v[ 1].w[6], m_v[ 1].w[7]); break;
+ case RSP_V2:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 2].w[0], m_v[ 2].w[1], m_v[ 2].w[2], m_v[ 2].w[3], m_v[ 2].w[4], m_v[ 2].w[5], m_v[ 2].w[6], m_v[ 2].w[7]); break;
+ case RSP_V3:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 3].w[0], m_v[ 3].w[1], m_v[ 3].w[2], m_v[ 3].w[3], m_v[ 3].w[4], m_v[ 3].w[5], m_v[ 3].w[6], m_v[ 3].w[7]); break;
+ case RSP_V4:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 4].w[0], m_v[ 4].w[1], m_v[ 4].w[2], m_v[ 4].w[3], m_v[ 4].w[4], m_v[ 4].w[5], m_v[ 4].w[6], m_v[ 4].w[7]); break;
+ case RSP_V5:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 5].w[0], m_v[ 5].w[1], m_v[ 5].w[2], m_v[ 5].w[3], m_v[ 5].w[4], m_v[ 5].w[5], m_v[ 5].w[6], m_v[ 5].w[7]); break;
+ case RSP_V6:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 6].w[0], m_v[ 6].w[1], m_v[ 6].w[2], m_v[ 6].w[3], m_v[ 6].w[4], m_v[ 6].w[5], m_v[ 6].w[6], m_v[ 6].w[7]); break;
+ case RSP_V7:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 7].w[0], m_v[ 7].w[1], m_v[ 7].w[2], m_v[ 7].w[3], m_v[ 7].w[4], m_v[ 7].w[5], m_v[ 7].w[6], m_v[ 7].w[7]); break;
+ case RSP_V8:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 8].w[0], m_v[ 8].w[1], m_v[ 8].w[2], m_v[ 8].w[3], m_v[ 8].w[4], m_v[ 8].w[5], m_v[ 8].w[6], m_v[ 8].w[7]); break;
+ case RSP_V9:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 9].w[0], m_v[ 9].w[1], m_v[ 9].w[2], m_v[ 9].w[3], m_v[ 9].w[4], m_v[ 9].w[5], m_v[ 9].w[6], m_v[ 9].w[7]); break;
+ case RSP_V10:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[10].w[0], m_v[10].w[1], m_v[10].w[2], m_v[10].w[3], m_v[10].w[4], m_v[10].w[5], m_v[10].w[6], m_v[10].w[7]); break;
+ case RSP_V11:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[11].w[0], m_v[11].w[1], m_v[11].w[2], m_v[11].w[3], m_v[11].w[4], m_v[11].w[5], m_v[11].w[6], m_v[11].w[7]); break;
+ case RSP_V12:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[12].w[0], m_v[12].w[1], m_v[12].w[2], m_v[12].w[3], m_v[12].w[4], m_v[12].w[5], m_v[12].w[6], m_v[12].w[7]); break;
+ case RSP_V13:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[13].w[0], m_v[13].w[1], m_v[13].w[2], m_v[13].w[3], m_v[13].w[4], m_v[13].w[5], m_v[13].w[6], m_v[13].w[7]); break;
+ case RSP_V14:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[14].w[0], m_v[14].w[1], m_v[14].w[2], m_v[14].w[3], m_v[14].w[4], m_v[14].w[5], m_v[14].w[6], m_v[14].w[7]); break;
+ case RSP_V15:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[15].w[0], m_v[15].w[1], m_v[15].w[2], m_v[15].w[3], m_v[15].w[4], m_v[15].w[5], m_v[15].w[6], m_v[15].w[7]); break;
+ case RSP_V16:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[16].w[0], m_v[16].w[1], m_v[16].w[2], m_v[16].w[3], m_v[16].w[4], m_v[16].w[5], m_v[16].w[6], m_v[16].w[7]); break;
+ case RSP_V17:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[17].w[0], m_v[17].w[1], m_v[17].w[2], m_v[17].w[3], m_v[17].w[4], m_v[17].w[5], m_v[17].w[6], m_v[17].w[7]); break;
+ case RSP_V18:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[18].w[0], m_v[18].w[1], m_v[18].w[2], m_v[18].w[3], m_v[18].w[4], m_v[18].w[5], m_v[18].w[6], m_v[18].w[7]); break;
+ case RSP_V19:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[19].w[0], m_v[19].w[1], m_v[19].w[2], m_v[19].w[3], m_v[19].w[4], m_v[19].w[5], m_v[19].w[6], m_v[19].w[7]); break;
+ case RSP_V20:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[20].w[0], m_v[20].w[1], m_v[20].w[2], m_v[20].w[3], m_v[20].w[4], m_v[20].w[5], m_v[20].w[6], m_v[20].w[7]); break;
+ case RSP_V21:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[21].w[0], m_v[21].w[1], m_v[21].w[2], m_v[21].w[3], m_v[21].w[4], m_v[21].w[5], m_v[21].w[6], m_v[21].w[7]); break;
+ case RSP_V22:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[22].w[0], m_v[22].w[1], m_v[22].w[2], m_v[22].w[3], m_v[22].w[4], m_v[22].w[5], m_v[22].w[6], m_v[22].w[7]); break;
+ case RSP_V23:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[23].w[0], m_v[23].w[1], m_v[23].w[2], m_v[23].w[3], m_v[23].w[4], m_v[23].w[5], m_v[23].w[6], m_v[23].w[7]); break;
+ case RSP_V24:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[24].w[0], m_v[24].w[1], m_v[24].w[2], m_v[24].w[3], m_v[24].w[4], m_v[24].w[5], m_v[24].w[6], m_v[24].w[7]); break;
+ case RSP_V25:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[25].w[0], m_v[25].w[1], m_v[25].w[2], m_v[25].w[3], m_v[25].w[4], m_v[25].w[5], m_v[25].w[6], m_v[25].w[7]); break;
+ case RSP_V26:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[26].w[0], m_v[26].w[1], m_v[26].w[2], m_v[26].w[3], m_v[26].w[4], m_v[26].w[5], m_v[26].w[6], m_v[26].w[7]); break;
+ case RSP_V27:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[27].w[0], m_v[27].w[1], m_v[27].w[2], m_v[27].w[3], m_v[27].w[4], m_v[27].w[5], m_v[27].w[6], m_v[27].w[7]); break;
+ case RSP_V28:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[28].w[0], m_v[28].w[1], m_v[28].w[2], m_v[28].w[3], m_v[28].w[4], m_v[28].w[5], m_v[28].w[6], m_v[28].w[7]); break;
+ case RSP_V29:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[29].w[0], m_v[29].w[1], m_v[29].w[2], m_v[29].w[3], m_v[29].w[4], m_v[29].w[5], m_v[29].w[6], m_v[29].w[7]); break;
+ case RSP_V30:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[30].w[0], m_v[30].w[1], m_v[30].w[2], m_v[30].w[3], m_v[30].w[4], m_v[30].w[5], m_v[30].w[6], m_v[30].w[7]); break;
+ case RSP_V31:
+ str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[31].w[0], m_v[31].w[1], m_v[31].w[2], m_v[31].w[3], m_v[31].w[4], m_v[31].w[5], m_v[31].w[6], m_v[31].w[7]); break;
+ case STATE_GENFLAGS:
+ str = "";
+ break;
}
}
@@ -582,21 +519,11 @@ void rsp_device::device_stop()
#if SAVE_DMEM
{
int i;
- FILE *dmem;
-#if 0
- dmem = fopen("rsp_dmem.txt", "wt");
-
- for (i=0; i < 0x1000; i+=4)
- {
- fprintf(dmem, "%08X: %08X\n", 0x04000000 + i, READ32(0x04000000 + i));
- }
- fclose(dmem);
-#endif
- dmem = fopen("rsp_dmem.bin", "wb");
+ FILE *dmem = fopen("rsp_dmem.bin", "wb");
for (i=0; i < 0x1000; i++)
{
- fputc(READ8(0x04000000 + i), dmem);
+ fputc(read_dmem_byte(i), dmem);
}
fclose(dmem);
}
@@ -609,70 +536,2383 @@ void rsp_device::device_stop()
void rsp_device::device_reset()
{
- m_nextpc = ~0;
+ m_nextpc = 0xffff;
}
-void rsp_device::execute_run()
+uint16_t rsp_device::SATURATE_ACCUM(int accum, int slice, uint16_t negative, uint16_t positive)
{
- if (m_isdrc)
+ if ((int16_t)m_accum[accum].w[SLICE_H] < 0)
+ {
+ if ((uint16_t)m_accum[accum].w[SLICE_H] != 0xffff)
+ {
+ return negative;
+ }
+ else
+ {
+ if ((int16_t)m_accum[accum].w[SLICE_M] >= 0)
+ {
+ return negative;
+ }
+ else
+ {
+ if (slice == 0)
+ {
+ return m_accum[accum].w[SLICE_L];
+ }
+ else if (slice == 1)
+ {
+ return m_accum[accum].w[SLICE_M];
+ }
+ }
+ }
+ }
+ else
{
- execute_run_drc();
- return;
+ if ((uint16_t)m_accum[accum].w[SLICE_H] != 0)
+ {
+ return positive;
+ }
+ else
+ {
+ if ((int16_t)m_accum[accum].w[SLICE_M] < 0)
+ {
+ return positive;
+ }
+ else
+ {
+ if (slice == 0)
+ {
+ return m_accum[accum].w[SLICE_L];
+ }
+ else
+ {
+ return m_accum[accum].w[SLICE_M];
+ }
+ }
+ }
}
+ return 0;
+}
+
+void rsp_device::handle_vector_ops(uint32_t op)
+{
+ uint16_t vres[8];
- m_rsp_state->pc = 0x4001000 | (m_rsp_state->pc & 0xfff);
+ // Opcode legend:
+ // E = VS2 element type
+ // S = VS1, Source vector 1
+ // T = VS2, Source vector 2
+ // D = Destination vector
- if( m_sr & ( RSP_STATUS_HALT | RSP_STATUS_BROKE ) )
+ switch (op & 0x3f)
{
- m_rsp_state->icount = std::min(m_rsp_state->icount, 0);
+ 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 (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].s[i];
+ int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+
+ if (s1 == -32768 && s2 == -32768)
+ {
+ // overflow
+ m_accum[i].w[SLICE_H] = 0;
+ m_accum[i].w[SLICE_M] = -32768;
+ m_accum[i].w[SLICE_L] = -32768;
+ vres[i] = 0x7fff;
+ }
+ else
+ {
+ int64_t r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+ m_accum[i].w[SLICE_H] = (r < 0) ? 0xffff : 0; // Sign-extend to 48-bit
+ m_accum[i].w[SLICE_M] = (int16_t)(r >> 16);
+ m_accum[i].w[SLICE_L] = (uint16_t)r;
+ vres[i] = m_accum[i].w[SLICE_M];
+ }
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x01: /* VMULU */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 |
+ // ------------------------------------------------------
+ //
+
+ for (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].s[i];
+ int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+
+ int64_t r = s1 * s2 * 2;
+ r += 0x8000; // rounding ?
+
+ m_accum[i].w[SLICE_H] = (uint16_t)(r >> 32);
+ m_accum[i].w[SLICE_M] = (uint16_t)(r >> 16);
+ m_accum[i].w[SLICE_L] = (uint16_t)r;
+
+ if (r < 0)
+ {
+ vres[i] = 0;
+ }
+ else if (((int16_t)m_accum[i].w[SLICE_H] ^ (int16_t)m_accum[i].w[SLICE_M]) < 0)
+ {
+ vres[i] = -1;
+ }
+ else
+ {
+ vres[i] = m_accum[i].w[SLICE_M];
+ }
+ }
+ 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 (int i = 0; i < 8; i++)
+ {
+ uint32_t s1 = m_v[VS1REG].w[i];
+ uint32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)];
+ uint32_t r = s1 * s2;
+
+ m_accum[i].w[SLICE_H] = 0;
+ m_accum[i].w[SLICE_M] = 0;
+ m_accum[i].w[SLICE_L] = (uint16_t)(r >> 16);
+
+ vres[i] = m_accum[i].w[SLICE_L];
+ }
+ 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 (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].s[i];
+ int32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)]; // not sign-extended
+ int32_t r = s1 * s2;
+
+ m_accum[i].w[SLICE_H] = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit
+ m_accum[i].w[SLICE_M] = (int16_t)(r >> 16);
+ m_accum[i].w[SLICE_L] = (uint16_t)r;
+
+ vres[i] = m_accum[i].w[SLICE_M];
+ }
+ 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 (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].w[i]; // not sign-extended
+ int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+ int32_t r = s1 * s2;
+
+ m_accum[i].w[SLICE_H] = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit
+ m_accum[i].w[SLICE_M] = (int16_t)(r >> 16);
+ m_accum[i].w[SLICE_L] = (uint16_t)(r);
+
+ vres[i] = m_accum[i].w[SLICE_L];
+ }
+ 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 (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].s[i];
+ int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+ int32_t r = s1 * s2;
+
+ m_accum[i].w[SLICE_H] = (int16_t)(r >> 16);
+ m_accum[i].w[SLICE_M] = (uint16_t)(r);
+ m_accum[i].w[SLICE_L] = 0;
+
+ if (r < -32768) r = -32768;
+ if (r > 32767) r = 32767;
+ vres[i] = (int16_t)(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 (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].s[i];
+ int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+ int32_t r = s1 * s2;
+
+ uint64_t q = (uint64_t)(uint16_t)m_accum[i].w[SLICE_LL];
+ q |= (((uint64_t)(uint16_t)m_accum[i].w[SLICE_L]) << 16);
+ q |= (((uint64_t)(uint16_t)m_accum[i].w[SLICE_M]) << 32);
+ q |= (((uint64_t)(uint16_t)m_accum[i].w[SLICE_H]) << 48);
+
+ q += (int64_t)(r) << 17;
+
+ m_accum[i].w[SLICE_LL] = (uint16_t)q;
+ m_accum[i].w[SLICE_L] = (uint16_t)(q >> 16);
+ m_accum[i].w[SLICE_M] = (uint16_t)(q >> 32);
+ m_accum[i].w[SLICE_H] = (uint16_t)(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 (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].s[i];
+ int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+ int32_t r1 = s1 * s2;
+ uint32_t r2 = m_accum[i].w[SLICE_L] + ((uint16_t)r1 * 2);
+ uint32_t r3 = m_accum[i].w[SLICE_M] + (uint16_t)((r1 >> 16) * 2) + (uint16_t)(r2 >> 16);
+
+ m_accum[i].w[SLICE_L] = (uint16_t)r2;
+ m_accum[i].w[SLICE_M] = (uint16_t)r3;
+ m_accum[i].w[SLICE_H] += (uint16_t)(r3 >> 16) + (uint16_t)(r1 >> 31);
+
+ if ((int16_t)m_accum[i].w[SLICE_H] < 0)
+ {
+ vres[i] = 0;
+ }
+ else
+ {
+ if (m_accum[i].w[SLICE_H] != 0)
+ {
+ vres[i] = 0xffff;
+ }
+ else
+ {
+ if ((int16_t)m_accum[i].w[SLICE_M] < 0)
+ {
+ vres[i] = 0xffff;
+ }
+ else
+ {
+ vres[i] = m_accum[i].w[SLICE_M];
+ }
+ }
+ }
+ }
+ 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 (int i = 0; i < 8; i++)
+ {
+ uint32_t s1 = m_v[VS1REG].w[i];
+ uint32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)];
+ uint32_t r1 = s1 * s2;
+ uint32_t r2 = m_accum[i].w[SLICE_L] + (r1 >> 16);
+ uint32_t r3 = m_accum[i].w[SLICE_M] + (r2 >> 16);
+
+ m_accum[i].w[SLICE_L] = (uint16_t)r2;
+ m_accum[i].w[SLICE_M] = (uint16_t)r3;
+ m_accum[i].w[SLICE_H] += (int16_t)(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 (int i = 0; i < 8; i++)
+ {
+ uint32_t s1 = m_v[VS1REG].s[i];
+ uint32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)]; // not sign-extended
+ uint32_t r1 = s1 * s2;
+ uint32_t r2 = (uint16_t)m_accum[i].w[SLICE_L] + (uint16_t)(r1);
+ uint32_t r3 = (uint16_t)m_accum[i].w[SLICE_M] + (r1 >> 16) + (r2 >> 16);
+
+ m_accum[i].w[SLICE_L] = (uint16_t)r2;
+ m_accum[i].w[SLICE_M] = (uint16_t)r3;
+ m_accum[i].w[SLICE_H] += (uint16_t)(r3 >> 16);
+ if ((int32_t)r1 < 0)
+ m_accum[i].w[SLICE_H] -= 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 (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].w[i]; // not sign-extended
+ int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+
+ uint64_t q = (uint64_t)m_accum[i].w[SLICE_LL];
+ q |= (((uint64_t)m_accum[i].w[SLICE_L]) << 16);
+ q |= (((uint64_t)m_accum[i].w[SLICE_M]) << 32);
+ q |= (((uint64_t)m_accum[i].w[SLICE_H]) << 48);
+ q += (int64_t)(s1*s2) << 16;
+
+ m_accum[i].w[SLICE_LL] = (uint16_t)q;
+ m_accum[i].w[SLICE_L] = (uint16_t)(q >> 16);
+ m_accum[i].w[SLICE_M] = (uint16_t)(q >> 32);
+ m_accum[i].w[SLICE_H] = (uint16_t)(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 (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].s[i];
+ int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+
+ int32_t accum = (uint32_t)(uint16_t)m_accum[i].w[SLICE_M];
+ accum |= ((uint32_t)((uint16_t)m_accum[i].w[SLICE_H])) << 16;
+ accum += s1 * s2;
+
+ m_accum[i].w[SLICE_H] = (uint16_t)(accum >> 16);
+ m_accum[i].w[SLICE_M] = (uint16_t)accum;
+
+ vres[i] = SATURATE_ACCUM(i, 1, 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 (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].s[i];
+ int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+ int32_t r = s1 + s2 + BIT(m_vcarry, i);
+
+ m_accum[i].w[SLICE_L] = (int16_t)r;
+
+ if (r > 32767) r = 32767;
+ if (r < -32768) r = -32768;
+ vres[i] = (int16_t)(r);
+ }
+ m_vzero = 0;
+ m_vcarry = 0;
+ 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 (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].s[i];
+ int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+ int32_t r = s1 - s2 - BIT(m_vcarry, i);
+
+ m_accum[i].w[SLICE_L] = (int16_t)r;
+
+ if (r > 32767) r = 32767;
+ if (r < -32768) r = -32768;
+
+ vres[i] = (int16_t)(r);
+ }
+ m_vzero = 0;
+ m_vcarry = 0;
+ 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 (int i = 0; i < 8; i++)
+ {
+ int16_t s1 = m_v[VS1REG].s[i];
+ int16_t s2 = m_v[VS2REG].s[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;
+ }
+
+ m_accum[i].w[SLICE_L] = 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
+
+ m_vzero = 0;
+ m_vcarry = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].w[i];
+ int32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)];
+ int32_t r = s1 + s2;
+
+ vres[i] = (int16_t)r;
+ m_accum[i].w[SLICE_L] = (int16_t)r;
+
+ if (r & 0xffff0000)
+ {
+ m_vcarry |= 1 << 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
+
+ m_vzero = 0;
+ m_vcarry = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ int32_t s1 = m_v[VS1REG].w[i];
+ int32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)];
+ int32_t r = s1 - s2;
+
+ vres[i] = (int16_t)(r);
+ m_accum[i].w[SLICE_L] = (uint16_t)r;
+
+ if ((uint16_t)r != 0)
+ {
+ m_vzero |= 1 << i;
+ }
+ if (r & 0xffff0000)
+ {
+ m_vcarry |= 1 << 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 (int i = 0; i < 8; i++)
+ {
+ m_v[VDREG].w[i] = m_accum[i].w[SLICE_H];
+ }
+ break;
+ }
+ case 0x09: // VSAWM
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ m_v[VDREG].w[i] = m_accum[i].w[SLICE_M];
+ }
+ break;
+ }
+ case 0x0a: // VSAWL
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ m_v[VDREG].w[i] = m_accum[i].w[SLICE_L];
+ }
+ break;
+ }
+ default:
+ printf("RSP: VSAW: el = %d\n", EL);
+ break;
+ }
+ 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
+
+ m_vcompare = 0;
+ m_vclip2 = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ int16_t s1 = m_v[VS1REG].s[i];
+ int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+ if (s1 < s2)
+ {
+ m_vcompare |= 1 << i;
+ }
+ else if (s1 == s2)
+ {
+ if (BIT(m_vzero & m_vcarry, i))
+ {
+ m_vcompare |= 1 << i;
+ }
+ }
+
+ if (BIT(m_vcompare, i))
+ {
+ vres[i] = s1;
+ }
+ else
+ {
+ vres[i] = s2;
+ }
+
+ m_accum[i].w[SLICE_L] = vres[i];
+ }
+
+ m_vzero = 0;
+ m_vcarry = 0;
+ 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
+
+ m_vcompare = 0;
+ m_vclip2 = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ int16_t s1 = m_v[VS1REG].s[i];
+ int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+
+ if ((s1 == s2) && !BIT(m_vzero, i))
+ {
+ m_vcompare |= 1 << i;
+ vres[i] = s1;
+ }
+ else
+ {
+ vres[i] = s2;
+ }
+ m_accum[i].w[SLICE_L] = vres[i];
+ }
+
+ m_vzero = 0;
+ m_vcarry = 0;
+ 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
+
+ m_vcompare = 0;
+ m_vclip2 = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ int16_t s1 = m_v[VS1REG].s[i];
+ int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+
+ if (s1 != s2 || BIT(m_vzero, i))
+ {
+ m_vcompare |= 1 << i;
+ vres[i] = s1;
+ }
+ else
+ {
+ vres[i] = s2;
+ }
+
+ m_accum[i].w[SLICE_L] = vres[i];
+ }
+
+ m_vzero = 0;
+ m_vcarry = 0;
+ 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
+
+ m_vcompare = 0;
+ m_vclip2 = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ int16_t s1 = m_v[VS1REG].s[i];
+ int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+
+ if ((s1 == s2 && (!BIT(m_vzero, i) || !BIT(m_vcarry, i))) || s1 > s2)
+ {
+ m_vcompare |= 1 << i;
+ vres[i] = s1;
+ }
+ else
+ {
+ vres[i] = s2;
+ }
+
+ m_accum[i].w[SLICE_L] = vres[i];
+ }
+
+ m_vzero = 0;
+ m_vcarry = 0;
+ 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 (int i = 0; i < 8; i++)
+ {
+ int16_t s1 = m_v[VS1REG].s[i];
+ int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+
+ if (BIT(m_vcarry, i)) // vco_lo
+ {
+ if (BIT(m_vzero, i)) // vco_hi
+ {
+ if (BIT(m_vcompare, i)) // vcc_lo
+ {
+ m_accum[i].w[SLICE_L] = -(uint16_t)s2;
+ }
+ else
+ {
+ m_accum[i].w[SLICE_L] = s1;
+ }
+ }
+ else
+ {
+ if (BIT(m_vclip1, i)) // vce
+ {
+ if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) > 0x10000)
+ {
+ m_accum[i].w[SLICE_L] = s1;
+ m_vcompare &= ~(1 << i);
+ }
+ else
+ {
+ m_accum[i].w[SLICE_L] = -(uint16_t)s2;
+ m_vcompare |= 1 << i;
+ }
+ }
+ else
+ {
+ if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) != 0)
+ {
+ m_accum[i].w[SLICE_L] = s1;
+ m_vcompare &= ~(1 << i);
+ }
+ else
+ {
+ m_accum[i].w[SLICE_L] = -(uint16_t)s2;
+ m_vcompare |= 1 << i;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (BIT(m_vzero, i)) // vco_hi
+ {
+ if (BIT(m_vclip2, i)) // vcc_hi
+ {
+ m_accum[i].w[SLICE_L] = s2;
+ }
+ else
+ {
+ m_accum[i].w[SLICE_L] = s1;
+ }
+ }
+ else
+ {
+ if (((int32_t)(uint16_t)s1 - (int32_t)(uint16_t)s2) >= 0)
+ {
+ m_accum[i].w[SLICE_L] = s2;
+ m_vclip2 |= 1 << i;
+ }
+ else
+ {
+ m_accum[i].w[SLICE_L] = s1;
+ m_vclip2 &= ~(1 << i);
+ }
+ }
+ }
+
+ vres[i] = m_accum[i].w[SLICE_L];
+ }
+
+ m_vzero = 0;
+ m_vcarry = 0;
+ m_vclip1 = 0;
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x25: /* VCH */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 |
+ // ------------------------------------------------------
+ //
+ // Vector clip high
+
+ m_vcarry = 0;
+ m_vcompare = 0;
+ m_vclip1 = 0;
+ m_vzero = 0;
+ m_vclip2 = 0;
+ uint32_t vce;
+
+ for (int i = 0; i < 8; i++)
+ {
+ int16_t s1 = m_v[VS1REG].s[i];
+ int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+
+ if ((s1 ^ s2) < 0)
+ {
+ vce = (s1 + s2 == -1);
+ m_vcarry |= 1 << i;
+ if (s2 < 0)
+ {
+ m_vclip2 |= 1 << i;
+ }
+
+ if (s1 + s2 <= 0)
+ {
+ m_vcompare |= 1 << i;
+ vres[i] = -((uint16_t)s2);
+ }
+ else
+ {
+ vres[i] = s1;
+ }
+
+ if (s1 + s2 != 0)
+ {
+ if (s1 != ~s2)
+ {
+ m_vzero |= 1 << i;
+ }
+ }
+ }
+ else
+ {
+ vce = 0;
+ if (s2 < 0)
+ {
+ m_vcompare |= 1 << i;
+ }
+ if (s1 - s2 >= 0)
+ {
+ m_vclip2 |= 1 << i;
+ vres[i] = s2;
+ }
+ else
+ {
+ vres[i] = s1;
+ }
+
+ if ((s1 - s2) != 0)
+ {
+ if (s1 != ~s2)
+ {
+ m_vzero |= 1 << i;
+ }
+ }
+ }
+
+ if (vce != 0)
+ {
+ m_vclip1 |= 1 << i;
+ }
+
+ m_accum[i].w[SLICE_L] = 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
+
+ m_vcarry = 0;
+ m_vcompare = 0;
+ m_vclip1 = 0;
+ m_vzero = 0;
+ m_vclip2 = 0;
+
+ for (int i = 0; i < 8; i++)
+ {
+ int16_t s1 = m_v[VS1REG].s[i];
+ int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+
+ if ((int16_t)(s1 ^ s2) < 0)
+ {
+ if (s2 < 0)
+ {
+ m_vclip2 |= 1 << i;
+ }
+ if ((s1 + s2) <= 0)
+ {
+ m_accum[i].w[SLICE_L] = ~(uint16_t)s2;
+ m_vcompare |= 1 << i;
+ }
+ else
+ {
+ m_accum[i].w[SLICE_L] = s1;
+ }
+ }
+ else
+ {
+ if (s2 < 0)
+ {
+ m_vcompare |= 1 << i;
+ }
+ if ((s1 - s2) >= 0)
+ {
+ m_accum[i].w[SLICE_L] = s2;
+ m_vclip2 |= 1 << i;
+ }
+ else
+ {
+ m_accum[i].w[SLICE_L] = s1;
+ }
+ }
+
+ vres[i] = m_accum[i].w[SLICE_L];
+ }
+ 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 (int i = 0; i < 8; i++)
+ {
+ if (BIT(m_vcompare, i))
+ {
+ vres[i] = m_v[VS1REG].s[i];
+ }
+ else
+ {
+ vres[i] = m_v[VS2REG].s[VEC_EL_2(EL, i)];
+ }
+
+ m_accum[i].w[SLICE_L] = 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 (int i = 0; i < 8; i++)
+ {
+ vres[i] = m_v[VS1REG].w[i] & m_v[VS2REG].w[VEC_EL_2(EL, i)];
+ m_accum[i].w[SLICE_L] = 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 (int i = 0; i < 8; i++)
+ {
+ vres[i] = ~(m_v[VS1REG].w[i] & m_v[VS2REG].w[VEC_EL_2(EL, i)]);
+ m_accum[i].w[SLICE_L] = 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 (int i = 0; i < 8; i++)
+ {
+ vres[i] = m_v[VS1REG].w[i] | m_v[VS2REG].w[VEC_EL_2(EL, i)];
+ m_accum[i].w[SLICE_L] = 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 (int i = 0; i < 8; i++)
+ {
+ vres[i] = ~(m_v[VS1REG].w[i] | m_v[VS2REG].w[VEC_EL_2(EL, i)]);
+ m_accum[i].w[SLICE_L] = 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 (int i = 0; i < 8; i++)
+ {
+ vres[i] = m_v[VS1REG].w[i] ^ m_v[VS2REG].w[VEC_EL_2(EL, i)];
+ m_accum[i].w[SLICE_L] = 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 (int i = 0; i < 8; i++)
+ {
+ vres[i] = ~(m_v[VS1REG].w[i] ^ m_v[VS2REG].w[VEC_EL_2(EL, i)]);
+ m_accum[i].w[SLICE_L] = vres[i];
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x2e: /* V056 (Reserved) */
+ case 0x2f: /* V057 (Reserved) */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 |
+ // ------------------------------------------------------
+ //
+ // Reserved Opcode
+ // Appears to simply store the unsigned 16-bit sum of vector elements into low accumulator slice.
+ // Zeroes destination vector.
+
+ for (int i = 0; i < 8; i++)
+ {
+ vres[i] = 0;
+ uint16_t e1 = m_v[VS1REG].w[i];
+ uint16_t e2 = m_v[VS2REG].w[VEC_EL_2(EL, i)];
+ m_accum[i].w[SLICE_L] = e1 + e2;
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x30: /* VRCP */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 |
+ // ------------------------------------------------------
+ //
+ // Calculates reciprocal
+
+ int32_t shifter = 0;
+
+ int32_t rec = m_v[VS2REG].s[EL & 7];
+ int32_t 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_t address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ int32_t fetchval = rsp_divtable[address];
+ int32_t 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;
+
+ m_v[VDREG].w[VS1REG & 7] = (uint16_t)(rec & 0xffff);
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_accum[i].w[SLICE_L] = m_v[VS2REG].w[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_t shifter = 0;
+
+ int32_t rec = m_v[VS2REG].s[EL & 7];
+ int32_t 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 (int i = 0; i < 32; i++)
+ {
+ if (datainput & (1 << ((~i) & 0x1f)))
+ {
+ shifter = i;
+ break;
+ }
+ }
+
+ int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ int32_t fetchval = rsp_divtable[address];
+ int32_t 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;
+
+ m_v[VDREG].w[VS1REG & 7] = (uint16_t)(rec & 0xffff);
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_accum[i].w[SLICE_L] = m_v[VS2REG].w[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 = m_v[VS2REG].w[EL & 7] << 16;
+ m_dp_allowed = 1;
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_accum[i].w[SLICE_L] = m_v[VS2REG].w[VEC_EL_2(EL, i)];
+ }
+
+ m_v[VDREG].s[VS1REG & 7] = (int16_t)(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
+
+ m_v[VDREG].w[VS1REG & 7] = m_v[VS2REG].w[VEC_EL_2(EL, VS1REG & 7)];
+ for (int i = 0; i < 8; i++)
+ {
+ m_accum[i].w[SLICE_L] = m_v[VS2REG].w[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_t shifter = 0;
+
+ int32_t rec = m_v[VS2REG].s[EL & 7];
+ int32_t 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_t address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ address = ((address | 0x200) & 0x3fe) | (shifter & 1);
+
+ int32_t fetchval = rsp_divtable[address];
+ int32_t 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;
+
+ m_v[VDREG].w[VS1REG & 7] = (uint16_t)(rec & 0xffff);
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_accum[i].w[SLICE_L] = m_v[VS2REG].w[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_t shifter = 0;
+ int32_t rec = m_v[VS2REG].s[EL & 7];
+ int32_t 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_t address = ((datainput << shifter) & 0x7fc00000) >> 22;
+ address = ((address | 0x200) & 0x3fe) | (shifter & 1);
+
+ int32_t fetchval = rsp_divtable[address];
+ int32_t 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;
+
+ m_v[VDREG].w[VS1REG & 7] = (uint16_t)(rec & 0xffff);
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_accum[i].w[SLICE_L] = m_v[VS2REG].w[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 = m_v[VS2REG].w[EL & 7] << 16;
+ m_dp_allowed = 1;
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_accum[i].w[SLICE_L] = m_v[VS2REG].w[VEC_EL_2(EL, i)];
+ }
+
+ m_v[VDREG].s[VS1REG & 7] = (int16_t)(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;
+ }
+
+ case 0x3b: /* V073 (Reserved) */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 |
+ // ------------------------------------------------------
+ //
+ // Reserved Opcode
+ // Appears to simply store the unsigned 16-bit sum of vector elements into low accumulator slice.
+ // Zeroes destination vector.
+
+ for (int i = 0; i < 8; i++)
+ {
+ vres[i] = 0;
+ uint16_t e1 = m_v[VS1REG].w[i];
+ uint16_t e2 = m_v[VS2REG].w[VEC_EL_2(EL, i)];
+ m_accum[i].w[SLICE_L] = e1 + e2;
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ case 0x3f: /* VNULL (Reserved) */
+ {
+ // 31 25 24 20 15 10 5 0
+ // ------------------------------------------------------
+ // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 |
+ // ------------------------------------------------------
+ //
+ // Reserved Opcode
+ // Appears to simply store the unsigned 16-bit sum of vector elements into low accumulator slice.
+ // Zeroes destination vector.
+
+ for (int i = 0; i < 8; i++)
+ {
+ vres[i] = m_v[VS1REG].w[i];
+ m_accum[i].w[SLICE_L] = 0;
+ }
+ WRITEBACK_RESULT();
+ break;
+ }
+
+ default: unimplemented_opcode(op); break;
+ }
+}
+
+void rsp_device::handle_cop2(uint32_t 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_t b1 = VREG_B(RDREG, (el+0) & 0xf);
+ uint16_t b2 = VREG_B(RDREG, (el+1) & 0xf);
+ if (RTREG) m_r[RTREG] = (int32_t)(int16_t)((b1 << 8) | (b2));
+ break;
+ }
+
+ case 0x02: /* CFC2 */
+ {
+ // 31 25 20 15 10 0
+ // ------------------------------------------------
+ // | 010010 | 00010 | TTTTT | DDDDD | 00000000000 |
+ // ------------------------------------------------
+
+ if (RTREG)
+ {
+ switch (RDREG)
+ {
+ case 0:
+ m_r[RTREG] = (m_vzero << 8) | m_vcarry;
+ if (m_r[RTREG] & 0x8000) m_r[RTREG] |= 0xffff0000;
+ break;
+ case 1:
+ m_r[RTREG] = (m_vclip2 << 8) | m_vcompare;
+ if (m_r[RTREG] & 0x8000) m_r[RTREG] |= 0xffff0000;
+ break;
+ case 2:
+ // Anciliary clipping flags
+ m_r[RTREG] = m_vclip1;
+ break;
+ }
+ }
+ 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, (m_r[RTREG] >> 8) & 0xff);
+ W_VREG_B(RDREG, (el+1) & 0xf, (m_r[RTREG] >> 0) & 0xff);
+ break;
+ }
+
+ case 0x06: /* CTC2 */
+ {
+ // 31 25 20 15 10 0
+ // ------------------------------------------------
+ // | 010010 | 00110 | TTTTT | DDDDD | 00000000000 |
+ // ------------------------------------------------
+
+ switch (RDREG)
+ {
+ case 0:
+ m_vcarry = (uint8_t)m_r[RTREG];
+ m_vzero = (uint8_t)(m_r[RTREG] >> 8);
+ break;
+
+ case 1:
+ m_vcompare = (uint8_t)m_r[RTREG];
+ m_vclip2 = (uint8_t)(m_r[RTREG] >> 8);
+ break;
+
+ case 2:
+ m_vclip1 = (uint8_t)m_r[RTREG];
+ 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;
+ }
+}
+
+void rsp_device::handle_lwc2(uint32_t op)
+{
+ int base = (op >> 21) & 0x1f;
+ int dest = (op >> 16) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ offset = (offset << 25) >> 25;
+
+ 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
+
+ uint32_t ea = (base) ? m_r[base] + offset : offset;
+ VREG_B(dest, index) = read_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 2) : (offset * 2);
+
+ for (int i = index; i < index + 2; i++)
+ {
+ VREG_B(dest, i) = read_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 4) : (offset * 4);
+
+ for (int i = index; i < index + 4; i++)
+ {
+ VREG_B(dest, i) = read_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8);
+
+ for (int i = index; i < index + 8; i++)
+ {
+ VREG_B(dest, i) = read_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16);
+
+ int end = index + (16 - (ea & 0xf));
+ if (end > 16) end = 16;
+
+ for (int i = index; i < end; i++)
+ {
+ VREG_B(dest, i) = read_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16);
+
+ index = 16 - ((ea & 0xf) - index);
+ ea &= ~0xf;
+
+ for (int i = index; i < 16; i++)
+ {
+ VREG_B(dest, i) = read_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8);
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_v[dest].w[i] = read_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8);
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_v[dest].w[i] = read_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16);
+
+ for (int i = 0; i < 8; i++)
+ {
+ m_v[dest].w[i] = read_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16);
+
+ // NOTE: Not sure what happens if 16-byte boundary is crossed
+
+ int end = (index >> 1) + 4;
+
+ for (int i = index >> 1; i < end; i++)
+ {
+ m_v[dest].w[i] = read_dmem_byte(ea) << 7;
+ ea += 4;
+ }
+ break;
+ }
+
+ case 0x0a: /* LWV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 110010 | BBBBB | TTTTT | 01010 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Intended instruction behavior:
+ // Loads the full 128-bit vector starting from vector byte index and wrapping to index 0
+ // after byte index 15
+ //
+ // Actual instruction behavior:
+ // Loads the full 128-bit vector starting from vector byte index 0.
+ //
+ // Hardware testing has proven that the vector index is ignored when executing LWV.
+ // By contrast, SWV will function as intended when provided an index.
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16);
+
+ for (int i = 0; i < 16; i++)
+ {
+ VREG_B(dest, i) = read_dmem_byte(ea);
+ ea++;
+ }
+ 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
+
+ int32_t vs = (op >> 16) & 0x1f;
+ int32_t ve = vs + 8;
+ if (ve > 32)
+ ve = 32;
+
+ if (index & 1) fatalerror("RSP: LTV: index = %d\n", index);
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16);
+ ea = ((ea + 8) & ~0xf) + (index & 1);
+
+ for (int32_t i = vs; i < ve; i++)
+ {
+ int32_t element = ((8 - (index >> 1) + (i-vs)) << 1);
+ VREG_B(i, (element & 0xf)) = read_dmem_byte(ea);
+ VREG_B(i, ((element + 1) & 0xf)) = read_dmem_byte(ea + 1);
+
+ ea += 2;
+ }
+ break;
+ }
+
+ default:
+ {
+ unimplemented_opcode(op);
+ break;
+ }
}
+}
+
+
+/***************************************************************************
+ Vector Store Instructions
+***************************************************************************/
+
+void rsp_device::handle_swc2(uint32_t op)
+{
+ int base = (op >> 21) & 0x1f;
+ int dest = (op >> 16) & 0x1f;
+ int index = (op >> 7) & 0xf;
+ int offset = (op & 0x7f);
+ offset = (offset << 25) >> 25;
- while (m_rsp_state->icount > 0)
+ switch ((op >> 11) & 0x1f)
{
- m_ppc = m_rsp_state->pc;
- debugger_instruction_hook(m_rsp_state->pc);
+ case 0x00: /* SBV */
+ {
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 1 byte from vector byte index
+
+ uint32_t ea = (base) ? m_r[base] + offset : offset;
+ write_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 2) : (offset * 2);
+
+ for (int i = index; i < index + 2; i++)
+ {
+ write_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 4) : (offset * 4);
+
+ for (int i = index; i < index + 4; i++)
+ {
+ write_dmem_byte(ea, VREG_B(dest, i));
+ ea++;
+ }
+ break;
+ }
- uint32_t op = ROPCODE(m_rsp_state->pc);
- if (m_nextpc != ~0)
+ case 0x03: /* SDV */
{
- m_rsp_state->pc = m_nextpc;
- m_nextpc = ~0;
+ // 31 25 20 15 10 6 0
+ // --------------------------------------------------
+ // | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset |
+ // --------------------------------------------------
+ //
+ // Stores 8 bytes starting from vector byte index
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8);
+
+ for (int i = index; i < index + 8; i++)
+ {
+ write_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16);
+ int end = index + (16 - (ea & 0xf));
+
+ for (int i = index; i < end; i++)
+ {
+ write_dmem_byte(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
+
+ uint32_t ea = (base) ? m_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++)
+ {
+ write_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8);
+
+ for (int i = index; i < index + 8; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ write_dmem_byte(ea, VREG_B(dest, ((i & 0xf) << 1)));
+ }
+ else
+ {
+ write_dmem_byte(ea, m_v[dest].s[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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8);
+
+ for (int i = index; i < index + 8; i++)
+ {
+ if ((i & 0xf) < 8)
+ {
+ write_dmem_byte(ea, m_v[dest].s[i & 0x7] >> 7);
+ }
+ else
+ {
+ write_dmem_byte(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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16);
+
+ for (int i = 0; i < 8; i++)
+ {
+ uint8_t d = ((VREG_B(dest, ((index + (i << 1) + 0) & 0xf))) << 1) |
+ ((VREG_B(dest, ((index + (i << 1) + 1) & 0xf))) >> 7);
+
+ write_dmem_byte(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
+
+ uint32_t ea = (base) ? m_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++)
+ {
+ write_dmem_byte(ea + (eaoffset & 0xf), m_v[dest].s[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
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16);
+
+ int eaoffset = ea & 0xf;
+ ea &= ~0xf;
+
+ for (int i = index; i < index + 16; i++)
+ {
+ write_dmem_byte(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
+
+ int32_t vs = (op >> 16) & 0x1f;
+ int32_t ve = vs + 8;
+ if (ve > 32)
+ ve = 32;
+
+ int32_t element = 8 - (index >> 1);
+
+ uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16);
+
+ int32_t eaoffset = (ea & 0xf) + (element * 2);
+ ea &= ~0xf;
+
+ for (int32_t i = vs; i < ve; i++)
+ {
+ write_dmem_word(ea + (eaoffset & 0xf), m_v[i].w[element & 0x7]);
+ eaoffset += 2;
+ element++;
+ }
+ break;
+ }
+
+ default:
+ unimplemented_opcode(op);
+ break;
+ }
+}
+
+void rsp_device::update_scalar_op_deduction()
+{
+ /*if (m_paired_busy)
+ {
+ m_scalar_busy = false;
+ m_vector_busy = false;
+ m_paired_busy = false;
+ m_ideduct = 1;
+ }
+ else if (m_vector_busy)
+ {
+ m_scalar_busy = true;
+ m_paired_busy = true;
+ m_ideduct = 0;
+ }
+ else if (m_scalar_busy)
+ {
+ m_ideduct = 1;
+ }
+ else
+ {
+ m_scalar_busy = true;
+ m_ideduct = 0;
+ }*/
+}
+
+void rsp_device::update_vector_op_deduction()
+{
+ /*if (m_paired_busy)
+ {
+ m_scalar_busy = false;
+ m_vector_busy = false;
+ m_paired_busy = false;
+ m_ideduct = 1;
+ }
+ else if (m_scalar_busy)
+ {
+ m_vector_busy = true;
+ m_paired_busy = true;
+ m_ideduct = 0;
+ }
+ else if (m_vector_busy)
+ {
+ m_ideduct = 1;
+ }
+ else
+ {
+ m_vector_busy = true;
+ m_ideduct = 0;
+ }*/
+}
+
+void rsp_device::execute_run()
+{
+ if (m_sr & (RSP_STATUS_HALT | RSP_STATUS_BROKE))
+ {
+ m_ideduct = 0;
+ m_scalar_busy = false;
+ m_vector_busy = false;
+ m_paired_busy = false;
+ m_icount = std::min(m_icount, 0);
+ }
+
+ while (m_icount > 0)
+ {
+ m_ppc = m_pc;
+ debugger_instruction_hook(m_pc);
+
+ uint32_t op = ROPCODE(m_pc);
+ if (m_nextpc != 0xffff)
+ {
+ m_pc = m_nextpc;
+ m_nextpc = 0xffff;
}
else
{
- m_rsp_state->pc += 4;
+ m_pc += 4;
}
switch (op >> 26)
{
case 0x00: /* SPECIAL */
{
+ update_scalar_op_deduction();
switch (op & 0x3f)
{
- case 0x00: /* SLL */ if (RDREG) RDVAL = (uint32_t)RTVAL << SHIFT; break;
- case 0x02: /* SRL */ if (RDREG) RDVAL = (uint32_t)RTVAL >> SHIFT; break;
- case 0x03: /* SRA */ if (RDREG) RDVAL = (int32_t)RTVAL >> SHIFT; break;
- case 0x04: /* SLLV */ if (RDREG) RDVAL = (uint32_t)RTVAL << (RSVAL & 0x1f); break;
- case 0x06: /* SRLV */ if (RDREG) RDVAL = (uint32_t)RTVAL >> (RSVAL & 0x1f); break;
- case 0x07: /* SRAV */ if (RDREG) RDVAL = (int32_t)RTVAL >> (RSVAL & 0x1f); break;
- case 0x08: /* JR */ JUMP_PC(RSVAL); break;
- case 0x09: /* JALR */ JUMP_PC_L(RSVAL, RDREG); break;
+ case 0x00: /* SLL */ if (RDREG) m_r[RDREG] = m_r[RTREG] << SHIFT; break;
+ case 0x02: /* SRL */ if (RDREG) m_r[RDREG] = m_r[RTREG] >> SHIFT; break;
+ case 0x03: /* SRA */ if (RDREG) m_r[RDREG] = (int32_t)m_r[RTREG] >> SHIFT; break;
+ case 0x04: /* SLLV */ if (RDREG) m_r[RDREG] = m_r[RTREG] << (m_r[RSREG] & 0x1f); break;
+ case 0x06: /* SRLV */ if (RDREG) m_r[RDREG] = m_r[RTREG] >> (m_r[RSREG] & 0x1f); break;
+ case 0x07: /* SRAV */ if (RDREG) m_r[RDREG] = (int32_t)m_r[RTREG] >> (m_r[RSREG] & 0x1f); break;
+ case 0x08: /* JR */ JUMP_PC(m_r[RSREG]); break;
+ case 0x09: /* JALR */ JUMP_PC_L(m_r[RSREG], RDREG); break;
case 0x0d: /* BREAK */
{
+ m_ideduct = 1;
+ m_scalar_busy = false;
+ m_vector_busy = false;
+ m_paired_busy = false;
m_sp_set_status_func(0, 0x3, 0xffffffff);
- m_rsp_state->icount = std::min(m_rsp_state->icount, 1);
+ m_icount = std::min(m_icount, 1);
break;
}
- case 0x20: /* ADD */ if (RDREG) RDVAL = (int32_t)(RSVAL + RTVAL); break;
- case 0x21: /* ADDU */ if (RDREG) RDVAL = (int32_t)(RSVAL + RTVAL); break;
- case 0x22: /* SUB */ if (RDREG) RDVAL = (int32_t)(RSVAL - RTVAL); break;
- case 0x23: /* SUBU */ if (RDREG) RDVAL = (int32_t)(RSVAL - RTVAL); break;
- case 0x24: /* AND */ if (RDREG) RDVAL = RSVAL & RTVAL; break;
- case 0x25: /* OR */ if (RDREG) RDVAL = RSVAL | RTVAL; break;
- case 0x26: /* XOR */ if (RDREG) RDVAL = RSVAL ^ RTVAL; break;
- case 0x27: /* NOR */ if (RDREG) RDVAL = ~(RSVAL | RTVAL); break;
- case 0x2a: /* SLT */ if (RDREG) RDVAL = (int32_t)RSVAL < (int32_t)RTVAL; break;
- case 0x2b: /* SLTU */ if (RDREG) RDVAL = (uint32_t)RSVAL < (uint32_t)RTVAL; break;
+ case 0x20: /* ADD */ if (RDREG) m_r[RDREG] = (int32_t)(m_r[RSREG] + m_r[RTREG]); break;
+ case 0x21: /* ADDU */ if (RDREG) m_r[RDREG] = (int32_t)(m_r[RSREG] + m_r[RTREG]); break;
+ case 0x22: /* SUB */ if (RDREG) m_r[RDREG] = (int32_t)(m_r[RSREG] - m_r[RTREG]); break;
+ case 0x23: /* SUBU */ if (RDREG) m_r[RDREG] = (int32_t)(m_r[RSREG] - m_r[RTREG]); break;
+ case 0x24: /* AND */ if (RDREG) m_r[RDREG] = m_r[RSREG] & m_r[RTREG]; break;
+ case 0x25: /* OR */ if (RDREG) m_r[RDREG] = m_r[RSREG] | m_r[RTREG]; break;
+ case 0x26: /* XOR */ if (RDREG) m_r[RDREG] = m_r[RSREG] ^ m_r[RTREG]; break;
+ case 0x27: /* NOR */ if (RDREG) m_r[RDREG] = ~(m_r[RSREG] | m_r[RTREG]); break;
+ case 0x2a: /* SLT */ if (RDREG) m_r[RDREG] = (int32_t)m_r[RSREG] < (int32_t)m_r[RTREG]; break;
+ case 0x2b: /* SLTU */ if (RDREG) m_r[RDREG] = m_r[RSREG] < m_r[RTREG]; break;
default: unimplemented_opcode(op); break;
}
break;
@@ -680,38 +2920,40 @@ void rsp_device::execute_run()
case 0x01: /* REGIMM */
{
+ update_scalar_op_deduction();
switch (RTREG)
{
- case 0x00: /* BLTZ */ if ((int32_t)(RSVAL) < 0) JUMP_REL(SIMM16); break;
- case 0x01: /* BGEZ */ if ((int32_t)(RSVAL) >= 0) JUMP_REL(SIMM16); break;
- case 0x10: /* BLTZAL */ if ((int32_t)(RSVAL) < 0) JUMP_REL_L(SIMM16, 31); break;
- case 0x11: /* BGEZAL */ if ((int32_t)(RSVAL) >= 0) JUMP_REL_L(SIMM16, 31); break;
+ case 0x00: /* BLTZ */ if ((int32_t)m_r[RSREG] < 0) JUMP_REL(SIMM16); break;
+ case 0x01: /* BGEZ */ if ((int32_t)m_r[RSREG] >= 0) JUMP_REL(SIMM16); break;
+ case 0x10: /* BLTZAL */ if ((int32_t)m_r[RSREG] < 0) JUMP_REL_L(SIMM16, 31); break;
+ case 0x11: /* BGEZAL */ if ((int32_t)m_r[RSREG] >= 0) JUMP_REL_L(SIMM16, 31); break;
default: unimplemented_opcode(op); break;
}
break;
}
- case 0x02: /* J */ JUMP_ABS(UIMM26); break;
- case 0x03: /* JAL */ JUMP_ABS_L(UIMM26, 31); break;
- case 0x04: /* BEQ */ if (RSVAL == RTVAL) JUMP_REL(SIMM16); break;
- case 0x05: /* BNE */ if (RSVAL != RTVAL) JUMP_REL(SIMM16); break;
- case 0x06: /* BLEZ */ if ((int32_t)RSVAL <= 0) JUMP_REL(SIMM16); break;
- case 0x07: /* BGTZ */ if ((int32_t)RSVAL > 0) JUMP_REL(SIMM16); break;
- case 0x08: /* ADDI */ if (RTREG) RTVAL = (int32_t)(RSVAL + SIMM16); break;
- case 0x09: /* ADDIU */ if (RTREG) RTVAL = (int32_t)(RSVAL + SIMM16); break;
- case 0x0a: /* SLTI */ if (RTREG) RTVAL = (int32_t)(RSVAL) < ((int32_t)SIMM16); break;
- case 0x0b: /* SLTIU */ if (RTREG) RTVAL = (uint32_t)(RSVAL) < (uint32_t)((int32_t)SIMM16); break;
- case 0x0c: /* ANDI */ if (RTREG) RTVAL = RSVAL & UIMM16; break;
- case 0x0d: /* ORI */ if (RTREG) RTVAL = RSVAL | UIMM16; break;
- case 0x0e: /* XORI */ if (RTREG) RTVAL = RSVAL ^ UIMM16; break;
- case 0x0f: /* LUI */ if (RTREG) RTVAL = UIMM16 << 16; break;
+ case 0x02: /* J */ update_scalar_op_deduction(); JUMP_ABS(UIMM26); break;
+ case 0x03: /* JAL */ update_scalar_op_deduction(); JUMP_ABS_L(UIMM26, 31); break;
+ case 0x04: /* BEQ */ update_scalar_op_deduction(); if (m_r[RSREG] == m_r[RTREG]) JUMP_REL(SIMM16); break;
+ case 0x05: /* BNE */ update_scalar_op_deduction(); if (m_r[RSREG] != m_r[RTREG]) JUMP_REL(SIMM16); break;
+ case 0x06: /* BLEZ */ update_scalar_op_deduction(); if ((int32_t)m_r[RSREG] <= 0) JUMP_REL(SIMM16); break;
+ case 0x07: /* BGTZ */ update_scalar_op_deduction(); if ((int32_t)m_r[RSREG] > 0) JUMP_REL(SIMM16); break;
+ case 0x08: /* ADDI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = (int32_t)m_r[RSREG] + SIMM16; break;
+ case 0x09: /* ADDIU */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = (int32_t)m_r[RSREG] + SIMM16; break;
+ case 0x0a: /* SLTI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = (int32_t)m_r[RSREG] < (int32_t)SIMM16; break;
+ case 0x0b: /* SLTIU */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = m_r[RSREG] < UIMM16; break;
+ case 0x0c: /* ANDI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = m_r[RSREG] & UIMM16; break;
+ case 0x0d: /* ORI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = m_r[RSREG] | UIMM16; break;
+ case 0x0e: /* XORI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = m_r[RSREG] ^ UIMM16; break;
+ case 0x0f: /* LUI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = UIMM16 << 16; break;
case 0x10: /* COP0 */
{
+ update_scalar_op_deduction();
switch ((op >> 21) & 0x1f)
{
- case 0x00: /* MFC0 */ if (RTREG) RTVAL = get_cop0_reg(RDREG); break;
- case 0x04: /* MTC0 */ set_cop0_reg(RDREG, RTVAL); break;
+ case 0x00: /* MFC0 */ if (RTREG) m_r[RTREG] = get_cop0_reg(RDREG); break;
+ case 0x04: /* MTC0 */ set_cop0_reg(RDREG, m_r[RTREG]); break;
default: unimplemented_opcode(op); break;
}
break;
@@ -719,20 +2961,21 @@ void rsp_device::execute_run()
case 0x12: /* COP2 */
{
- m_cop2->handle_cop2(op);
+ update_vector_op_deduction();
+ handle_cop2(op);
break;
}
- case 0x20: /* LB */ if (RTREG) RTVAL = (int32_t)(int8_t)READ8(RSVAL + SIMM16); break;
- case 0x21: /* LH */ if (RTREG) RTVAL = (int32_t)(int16_t)READ16(RSVAL + SIMM16); break;
- case 0x23: /* LW */ if (RTREG) RTVAL = READ32(RSVAL + SIMM16); break;
- case 0x24: /* LBU */ if (RTREG) RTVAL = (uint8_t)READ8(RSVAL + SIMM16); break;
- case 0x25: /* LHU */ if (RTREG) RTVAL = (uint16_t)READ16(RSVAL + SIMM16); break;
- 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 */ m_cop2->handle_lwc2(op); break;
- case 0x3a: /* SWC2 */ m_cop2->handle_swc2(op); break;
+ case 0x20: /* LB */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = (int32_t)(int8_t)read_dmem_byte(m_r[RSREG] + SIMM16); break;
+ case 0x21: /* LH */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = (int32_t)(int16_t)read_dmem_word(m_r[RSREG] + SIMM16); break;
+ case 0x23: /* LW */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = read_dmem_dword(m_r[RSREG] + SIMM16); break;
+ case 0x24: /* LBU */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = read_dmem_byte(m_r[RSREG] + SIMM16); break;
+ case 0x25: /* LHU */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = read_dmem_word(m_r[RSREG] + SIMM16); break;
+ case 0x28: /* SB */ update_scalar_op_deduction(); write_dmem_byte(m_r[RSREG] + SIMM16, m_r[RTREG]); break;
+ case 0x29: /* SH */ update_scalar_op_deduction(); write_dmem_word(m_r[RSREG] + SIMM16, m_r[RTREG]); break;
+ case 0x2b: /* SW */ update_scalar_op_deduction(); write_dmem_dword(m_r[RSREG] + SIMM16, m_r[RTREG]); break;
+ case 0x32: /* LWC2 */ update_scalar_op_deduction(); handle_lwc2(op); break;
+ case 0x3a: /* SWC2 */ update_scalar_op_deduction(); handle_swc2(op); break;
default:
{
@@ -743,8 +2986,8 @@ void rsp_device::execute_run()
if (LOG_INSTRUCTION_EXECUTION)
{
- int i, l;
static uint32_t prev_regs[32];
+ static VECTOR_REG prev_vecs[32];
rsp_disassembler rspd;
std::ostringstream string;
@@ -752,10 +2995,10 @@ void rsp_device::execute_run()
fprintf(m_exec_output, "%08X: %s", m_ppc, string.str().c_str());
- l = string.str().size();
+ int l = string.str().size();
if (l < 36)
{
- for (i=l; i < 36; i++)
+ for (int i = l; i < 36; i++)
{
fprintf(m_exec_output, " ");
}
@@ -763,26 +3006,36 @@ void rsp_device::execute_run()
fprintf(m_exec_output, "| ");
- for (i=0; i < 32; i++)
+ for (int i = 0; i < 32; i++)
{
- if (m_rsp_state->r[i] != prev_regs[i])
+ if (m_r[i] != prev_regs[i])
{
- fprintf(m_exec_output, "R%d: %08X ", i, m_rsp_state->r[i]);
+ fprintf(m_exec_output, "R%d: %08X ", i, m_r[i]);
}
- prev_regs[i] = m_rsp_state->r[i];
+ prev_regs[i] = m_r[i];
}
- m_cop2->log_instruction_execution();
+ 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_exec_output, "V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X ", i,
+ m_v[i].w[0], m_v[i].w[1], m_v[i].w[2], m_v[i].w[3], m_v[i].w[4], m_v[i].w[5], m_v[i].w[6], m_v[i].w[7]);
+ }
+ prev_vecs[i].d[0] = m_v[i].d[0];
+ prev_vecs[i].d[1] = m_v[i].d[1];
+ }
fprintf(m_exec_output, "\n");
}
- --m_rsp_state->icount;
+ //m_icount -= m_ideduct;
+ --m_icount;
- if( m_sr & RSP_STATUS_SSTEP )
+ if (m_sr & RSP_STATUS_SSTEP)
{
- if( m_step_count )
+ if (m_step_count)
{
m_step_count--;
}
@@ -792,14 +3045,13 @@ void rsp_device::execute_run()
}
}
- if( m_sr & ( RSP_STATUS_HALT | RSP_STATUS_BROKE ) )
+ if (m_sr & (RSP_STATUS_HALT | RSP_STATUS_BROKE))
{
- m_rsp_state->icount = std::min(m_rsp_state->icount, 0);
+ m_ideduct = 0;
+ m_scalar_busy = false;
+ m_vector_busy = false;
+ m_paired_busy = false;
+ m_icount = std::min(m_icount, 0);
}
- /*m_cop2->dump(op);
- if (((op >> 26) & 0x3f) == 0x3a)
- {
- m_cop2->dump_dmem();
- }*/
}
}
diff --git a/src/devices/cpu/rsp/rsp.h b/src/devices/cpu/rsp/rsp.h
index 5383889cdd3..b33012bddda 100644
--- a/src/devices/cpu/rsp/rsp.h
+++ b/src/devices/cpu/rsp/rsp.h
@@ -14,9 +14,6 @@
#pragma once
-#include "cpu/drcfe.h"
-#include "cpu/drcuml.h"
-
/***************************************************************************
REGISTER ENUMERATION
***************************************************************************/
@@ -81,14 +78,9 @@ enum
#define RSP_STATUS_SIGNAL6 0x2000
#define RSP_STATUS_SIGNAL7 0x4000
-#define RSPDRC_STRICT_VERIFY 0x0001 /* verify all instructions */
-
-
class rsp_device : public cpu_device
{
- class frontend;
class cop2;
- class cop2_drc;
public:
// construction/destruction
@@ -102,24 +94,6 @@ public:
auto sp_reg_w() { return m_sp_reg_w_func.bind(); }
auto status_set() { return m_sp_set_status_func.bind(); }
- void rspdrc_flush_drc_cache();
- void rspdrc_set_options(uint32_t options);
- void rsp_add_dmem(uint32_t *base);
- void rsp_add_imem(uint32_t *base);
-
- void ccfunc_read8();
- void ccfunc_read16();
- void ccfunc_read32();
- void ccfunc_write8();
- void ccfunc_write16();
- void ccfunc_write32();
- void ccfunc_get_cop0_reg();
- void ccfunc_set_cop0_reg();
- void ccfunc_sp_set_status_cb();
- void ccfunc_unimplemented();
-
- uint8_t* get_dmem() { return m_dmem8; }
-
protected:
// device-level overrides
virtual void device_start() override;
@@ -146,95 +120,56 @@ protected:
void unimplemented_opcode(uint32_t op);
- /* internal compiler state */
- struct compiler_state
- {
- compiler_state &operator=(compiler_state &) = delete;
-
- uint32_t cycles; /* accumulated cycles */
- uint8_t checkints; /* need to check interrupts before next instruction */
- uint8_t checksoftints; /* need to check software interrupts before next instruction */
- uml::code_label labelnum; /* index for local labels */
- };
-
private:
- address_space_config m_program_config;
-
- /* fast RAM info */
- struct fast_ram_info
- {
- offs_t start; /* start of the RAM block */
- offs_t end; /* end of the RAM block */
- bool readonly; /* true if read-only */
- void * base; /* base in memory where the RAM lives */
- };
+ address_space_config m_imem_config;
+ address_space_config m_dmem_config;
- /* core state */
- drc_cache m_cache; /* pointer to the DRC code cache */
- std::unique_ptr<drcuml_state> m_drcuml; /* DRC UML generator state */
- std::unique_ptr<frontend> m_drcfe; /* pointer to the DRC front-end state */
- uint32_t m_drcoptions; /* configurable DRC options */
-
- /* internal stuff */
- uint8_t m_cache_dirty; /* true if we need to flush the cache */
-
- /* parameters for subroutines */
- uint64_t m_numcycles; /* return value from gettotalcycles */
- const char * m_format; /* format string for print_debug */
- uint32_t m_arg2; /* print_debug argument 3 */
- uint32_t m_arg3; /* print_debug argument 4 */
-
- /* register mappings */
- uml::parameter m_regmap[34]; /* parameter to register mappings for all 32 integer registers */
-
- /* subroutines */
- uml::code_handle * m_entry; /* entry point */
- uml::code_handle * m_nocode; /* nocode exception handler */
- uml::code_handle * m_out_of_cycles; /* out of cycles exception handler */
- uml::code_handle * m_read8; /* read byte */
- uml::code_handle * m_write8; /* write byte */
- uml::code_handle * m_read16; /* read half */
- uml::code_handle * m_write16; /* write half */
- uml::code_handle * m_read32; /* read word */
- uml::code_handle * m_write32; /* write word */
-
- struct internal_rsp_state
- {
- uint32_t pc;
- uint32_t r[35];
- uint32_t arg0;
- uint32_t arg1;
- uint32_t jmpdest;
- int icount;
- };
+ uint16_t m_pc;
+ uint32_t m_r[35];
+ int m_icount;
+ int m_ideduct;
+ bool m_scalar_busy;
+ bool m_vector_busy;
+ bool m_paired_busy;
- internal_rsp_state *m_rsp_state;
+ void update_scalar_op_deduction();
+ void update_vector_op_deduction();
FILE *m_exec_output;
uint32_t m_sr;
uint32_t m_step_count;
- uint32_t m_ppc;
- uint32_t m_nextpc;
+ uint16_t m_ppc;
+ uint16_t m_nextpc;
protected:
- memory_access<32, 2, 0, ENDIANNESS_BIG>::cache m_pcache;
- memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_program;
+ memory_access<12, 2, 0, ENDIANNESS_BIG>::cache m_icache;
+ memory_access<12, 2, 0, ENDIANNESS_BIG>::specific m_imem;
+ memory_access<12, 2, 0, ENDIANNESS_BIG>::cache m_dcache;
+ memory_access<12, 2, 0, ENDIANNESS_BIG>::specific m_dmem;
private:
- std::unique_ptr<cop2> m_cop2;
-
- uint32_t *m_dmem32;
- uint16_t *m_dmem16;
- uint8_t *m_dmem8;
+ union VECTOR_REG
+ {
+ uint64_t d[2];
+ uint32_t l[4];
+ uint16_t w[8];
+ int16_t s[8];
+ uint8_t b[16];
+ };
- uint32_t *m_imem32;
- uint16_t *m_imem16;
- uint8_t *m_imem8;
+ union ACCUMULATOR_REG
+ {
+ uint64_t q;
+ uint32_t l[2];
+ uint16_t w[4];
+ };
uint32_t m_debugger_temp;
- bool m_isdrc;
+ uint16_t m_pc_temp;
+ uint16_t m_ppc_temp;
+ uint16_t m_nextpc_temp;
devcb_read32 m_dp_reg_r_func;
devcb_write32 m_dp_reg_w_func;
@@ -242,42 +177,40 @@ private:
devcb_write32 m_sp_reg_w_func;
devcb_write32 m_sp_set_status_func;
- uint8_t READ8(uint32_t address);
- uint16_t READ16(uint32_t address);
- uint32_t READ32(uint32_t address);
- void WRITE8(uint32_t address, uint8_t data);
- void WRITE16(uint32_t address, uint16_t data);
- void WRITE32(uint32_t address, uint32_t data);
+ uint8_t read_dmem_byte(uint32_t address);
+ uint16_t read_dmem_word(uint32_t address);
+ uint32_t read_dmem_dword(uint32_t address);
+ void write_dmem_byte(uint32_t address, uint8_t data);
+ void write_dmem_word(uint32_t address, uint16_t data);
+ void write_dmem_dword(uint32_t address, uint32_t data);
uint32_t get_cop0_reg(int reg);
void set_cop0_reg(int reg, uint32_t data);
- void load_fast_iregs(drcuml_block &block);
- void save_fast_iregs(drcuml_block &block);
- uint8_t DM_READ8(uint32_t address);
- uint16_t DM_READ16(uint32_t address);
- uint32_t DM_READ32(uint32_t address);
- void DM_WRITE8(uint32_t address, uint8_t data);
- void DM_WRITE16(uint32_t address, uint16_t data);
- void DM_WRITE32(uint32_t address, uint32_t data);
void rspcom_init();
- void execute_run_drc();
- void code_flush_cache();
- void code_compile_block(offs_t pc);
- void static_generate_entry_point();
- void static_generate_nocode_handler();
- void static_generate_out_of_cycles();
- void static_generate_memory_accessor(int size, int iswrite, const char *name, uml::code_handle *&handleptr);
- void generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception);
- void generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
- void generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- void generate_delay_slot_and_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t linkreg);
- void generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- bool generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- bool generate_special(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- bool generate_regimm(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- bool generate_cop0(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op);
-};
+ // COP2 (vectors)
+ uint16_t SATURATE_ACCUM(int accum, int slice, uint16_t negative, uint16_t positive);
+
+ uint16_t m_vres[8];
+ VECTOR_REG m_v[32];
+ ACCUMULATOR_REG m_accum[8];
+ uint8_t m_vcarry;
+ uint8_t m_vcompare;
+ uint8_t m_vclip1;
+ uint8_t m_vzero;
+ uint8_t m_vclip2;
+
+ int32_t m_reciprocal_res;
+ uint32_t m_reciprocal_high;
+ int32_t m_dp_allowed;
+
+ void handle_cop2(uint32_t op);
+ void handle_lwc2(uint32_t op);
+ void handle_swc2(uint32_t op);
+ void handle_vector_ops(uint32_t op);
+
+ uint32_t m_div_in;
+ uint32_t m_div_out;
+};
DECLARE_DEVICE_TYPE(RSP, rsp_device)
diff --git a/src/devices/cpu/rsp/rsp_dasm.cpp b/src/devices/cpu/rsp/rsp_dasm.cpp
index 6db58a28f4a..84647274764 100644
--- a/src/devices/cpu/rsp/rsp_dasm.cpp
+++ b/src/devices/cpu/rsp/rsp_dasm.cpp
@@ -157,6 +157,8 @@ void rsp_disassembler::disasm_cop2(std::ostream &stream, uint32_t op)
case 0x2b: util::stream_format(stream, "vnor %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
case 0x2c: util::stream_format(stream, "vxor %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
case 0x2d: util::stream_format(stream, "vnxor %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break;
+ case 0x2e: util::stream_format(stream, "v056 %s, %s[%c]", vreg[dest], vreg[s2], element2[el][s1 & 7]); break;
+ case 0x2f: util::stream_format(stream, "v057 %s, %s[%c]", vreg[dest], vreg[s2], element2[el][s1 & 7]); break;
case 0x30: util::stream_format(stream, "vrcp %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
case 0x31: util::stream_format(stream, "vrcpl %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
case 0x32: util::stream_format(stream, "vrcph %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
@@ -165,6 +167,8 @@ void rsp_disassembler::disasm_cop2(std::ostream &stream, uint32_t op)
case 0x35: util::stream_format(stream, "vrsql %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
case 0x36: util::stream_format(stream, "vrsqh %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break;
case 0x37: util::stream_format(stream, "vnop"); break;
+ case 0x3b: util::stream_format(stream, "v073 %s, %s[%c]", vreg[dest], vreg[s2], element2[el][s1 & 7]); break;
+ case 0x3f: util::stream_format(stream, "vnull"); break;
default: util::stream_format(stream, "??? (VECTOR OP)"); break;
}
break;
diff --git a/src/devices/cpu/rsp/rspcp2.cpp b/src/devices/cpu/rsp/rspcp2.cpp
deleted file mode 100644
index 3180d7103f6..00000000000
--- a/src/devices/cpu/rsp/rspcp2.cpp
+++ /dev/null
@@ -1,4223 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz,Tyler J. Stachecki
-/***************************************************************************
-
- rspcp2.c
-
- Universal machine language-based Nintendo/SGI RSP COP2 emulator.
- Written by Ryan Holtz of the MAME team.
-
-***************************************************************************/
-
-#include "emu.h"
-#include "rspcp2.h"
-
-#include "rsp.h"
-#include "rspdefs.h"
-
-
-#if USE_SIMD
-#include <emmintrin.h>
-
-const rsp_device::cop2::vec_helpers_t rsp_device::cop2::m_vec_helpers = {
- { 0 },
- { // logic_mask
- { 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }
- },
- { // vrsq_mask_table
- { 0xffff, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0xffff, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0xffff, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0xffff, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0xffff, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0xffff, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0xffff, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0xffff }
- },
- { // shuffle_keys
- { 0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e }, /* -- */
- { 0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e }, /* -- */
-
- { 0x0100, 0x0100, 0x0504, 0x0504, 0x0908, 0x0908, 0x0d0c, 0x0d0c }, /* 0q */
- { 0x0302, 0x0302, 0x0706, 0x0706, 0x0b0a, 0x0b0a, 0x0f0e, 0x0f0e }, /* 1q */
-
- { 0x0100, 0x0100, 0x0100, 0x0100, 0x0908, 0x0908, 0x0908, 0x0908 }, /* 0h */
- { 0x0302, 0x0302, 0x0302, 0x0302, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a }, /* 1h */
- { 0x0504, 0x0504, 0x0504, 0x0504, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c }, /* 2h */
- { 0x0706, 0x0706, 0x0706, 0x0706, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e }, /* 3h */
-
- { 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100 }, /* 0w */
- { 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302 }, /* 1w */
- { 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504 }, /* 2w */
- { 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706 }, /* 3w */
- { 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908 }, /* 4w */
- { 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a }, /* 5w */
- { 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c }, /* 6w */
- { 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e } /* 7w */
- },
- { // sll_b2l_keys
- { 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c },
- { 0x8003, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d },
- { 0x8080, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e },
- { 0x8080, 0x8003, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f },
-
- { 0x8080, 0x8080, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908 },
- { 0x8080, 0x8080, 0x8003, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09 },
- { 0x8080, 0x8080, 0x8080, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a },
- { 0x8080, 0x8080, 0x8080, 0x8003, 0x0201, 0x0007, 0x0605, 0x040b },
-
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x0302, 0x0100, 0x0706, 0x0504 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8003, 0x0201, 0x0007, 0x0605 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0302, 0x0100, 0x0706 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8003, 0x0201, 0x0007 },
-
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0302, 0x0100 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8003, 0x0201 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0302 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8003 },
- },
- { // sll_l2b_keys
- { 0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e },
- { 0x0201, 0x8003, 0x0605, 0x0007, 0x0a09, 0x040b, 0x0e0d, 0x080f },
- { 0x0302, 0x8080, 0x0706, 0x0100, 0x0b0a, 0x0504, 0x0f0e, 0x0908 },
- { 0x8003, 0x8080, 0x0007, 0x0201, 0x040b, 0x0605, 0x080f, 0x0a09 },
-
- { 0x8080, 0x8080, 0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a },
- { 0x8080, 0x8080, 0x0201, 0x8003, 0x0605, 0x0007, 0x0a09, 0x040b },
- { 0x8080, 0x8080, 0x0302, 0x8080, 0x0706, 0x0100, 0x0b0a, 0x0504 },
- { 0x8080, 0x8080, 0x8003, 0x8080, 0x0007, 0x0201, 0x040b, 0x0605 },
-
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x0100, 0x0302, 0x0504, 0x0706 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x0201, 0x8003, 0x0605, 0x0007 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x0302, 0x8080, 0x0706, 0x0100 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8003, 0x8080, 0x0007, 0x0201 },
-
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0100, 0x0302 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0201, 0x8003 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0302, 0x8080 },
- { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8003, 0x8080 },
- },
- { // srl_b2l_keys
- { 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c },
- { 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c80 },
- { 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x8080 },
- { 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c80, 0x8080 },
-
- { 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x8080, 0x8080 },
- { 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c80, 0x8080, 0x8080 },
- { 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x8080, 0x8080, 0x8080 },
- { 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c80, 0x8080, 0x8080, 0x8080 },
-
- { 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x8080, 0x8080, 0x8080, 0x8080 },
- { 0x0a09, 0x080f, 0x0e0d, 0x0c80, 0x8080, 0x8080, 0x8080, 0x8080 },
- { 0x0908, 0x0f0e, 0x0d0c, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 },
- { 0x080f, 0x0e0d, 0x0c80, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 },
-
- { 0x0f0e, 0x0d0c, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 },
- { 0x0e0d, 0x0c80, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 },
- { 0x0d0c, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 },
- { 0x0c80, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 },
- },
- { // ror_b2l_keys
- { 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c },
- { 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c03 },
- { 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302 },
- { 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c03, 0x0201 },
-
- { 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100 },
- { 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c03, 0x0201, 0x0007 },
- { 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706 },
- { 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c03, 0x0201, 0x0007, 0x0605 },
-
- { 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504 },
- { 0x0a09, 0x080f, 0x0e0d, 0x0c03, 0x0201, 0x0007, 0x0605, 0x040b },
- { 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a },
- { 0x080f, 0x0e0d, 0x0c03, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09 },
-
- { 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908 },
- { 0x0e0d, 0x0c03, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f },
- { 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e },
- { 0x0c03, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d },
- },
- { // rol_l2b_keys
- { 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c },
- { 0x0003, 0x0e01, 0x0407, 0x0205, 0x080b, 0x0609, 0x0c0f, 0x0a0d },
- { 0x0100, 0x0f0e, 0x0504, 0x0302, 0x0908, 0x0706, 0x0d0c, 0x0b0a },
- { 0x0e01, 0x0c0f, 0x0205, 0x0003, 0x0609, 0x0407, 0x0a0d, 0x080b },
-
- { 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908 },
- { 0x0c0f, 0x0a0d, 0x0003, 0x0e01, 0x0407, 0x0205, 0x080b, 0x0609 },
- { 0x0d0c, 0x0b0a, 0x0100, 0x0f0e, 0x0504, 0x0302, 0x0908, 0x0706 },
- { 0x0a0d, 0x080b, 0x0e01, 0x0c0f, 0x0205, 0x0003, 0x0609, 0x0407 },
-
- { 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504 },
- { 0x080b, 0x0609, 0x0c0f, 0x0a0d, 0x0003, 0x0e01, 0x0407, 0x0205 },
- { 0x0908, 0x0706, 0x0d0c, 0x0b0a, 0x0100, 0x0f0e, 0x0504, 0x0302 },
- { 0x0609, 0x0407, 0x0a0d, 0x080b, 0x0e01, 0x0c0f, 0x0205, 0x0003 },
-
- { 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100 },
- { 0x0407, 0x0205, 0x080b, 0x0609, 0x0c0f, 0x0a0d, 0x0003, 0x0e01 },
- { 0x0504, 0x0302, 0x0908, 0x0706, 0x0d0c, 0x0b0a, 0x0100, 0x0f0e },
- { 0x0205, 0x0003, 0x0609, 0x0407, 0x0a0d, 0x080b, 0x0e01, 0x0c0f },
- },
- { // ror_l2b_keys
- { 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c },
- { 0x0205, 0x0003, 0x0609, 0x0407, 0x0a0d, 0x080b, 0x0e01, 0x0c0f },
- { 0x0504, 0x0302, 0x0908, 0x0706, 0x0d0c, 0x0b0a, 0x0100, 0x0f0e },
- { 0x0407, 0x0205, 0x080b, 0x0609, 0x0c0f, 0x0a0d, 0x0003, 0x0e01 },
-
- { 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100 },
- { 0x0609, 0x0407, 0x0a0d, 0x080b, 0x0e01, 0x0c0f, 0x0205, 0x0003 },
- { 0x0908, 0x0706, 0x0d0c, 0x0b0a, 0x0100, 0x0f0e, 0x0504, 0x0302 },
- { 0x080b, 0x0609, 0x0c0f, 0x0a0d, 0x0003, 0x0e01, 0x0407, 0x0205 },
-
- { 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504 },
- { 0x0a0d, 0x080b, 0x0e01, 0x0c0f, 0x0205, 0x0003, 0x0609, 0x0407 },
- { 0x0d0c, 0x0b0a, 0x0100, 0x0f0e, 0x0504, 0x0302, 0x0908, 0x0706 },
- { 0x0c0f, 0x0a0d, 0x0003, 0x0e01, 0x0407, 0x0205, 0x080b, 0x0609 },
-
- { 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908 },
- { 0x0e01, 0x0c0f, 0x0205, 0x0003, 0x0609, 0x0407, 0x0a0d, 0x080b },
- { 0x0100, 0x0f0e, 0x0504, 0x0302, 0x0908, 0x0706, 0x0d0c, 0x0b0a },
- { 0x0003, 0x0e01, 0x0407, 0x0205, 0x080b, 0x0609, 0x0c0f, 0x0a0d },
- },
- { // qr_lut
- { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff },
- { 0xffff, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff },
- { 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff },
- { 0xff00, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff },
-
- { 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
- { 0x0000, 0x0000, 0xffff, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff },
- { 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff },
- { 0x0000, 0x0000, 0xff00, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff },
-
- { 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff },
- { 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xff00, 0xffff, 0xffff },
- { 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0xffff },
- { 0x0000, 0x0000, 0x0000, 0x0000, 0xff00, 0x0000, 0xffff, 0xffff },
-
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff },
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xff00 },
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000 },
- { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xff00, 0x0000 }
- },
- { // bdls_lut - mask to denote which part of the vector to load/store.
- { 0x0000, 0xff00, 0x0000, 0x0000 }, // B
- { 0x0000, 0xffff, 0x0000, 0x0000 }, // S
- { 0xffff, 0xffff, 0x0000, 0x0000 }, // L
- { 0xffff, 0xffff, 0xffff, 0xffff } // D
- },
- { // word_reverse
- 0x0203, 0x0001, 0x0607, 0x0405, 0x0a0b, 0x0809, 0x0e0f, 0x0c0d
- }
-};
-
-#if !(defined(__SSSE3__) || defined(_MSC_VER))
-// TODO: Highly optimized. More of a stopgap measure.
-static inline rsp_vec_t sse2_pshufb(rsp_vec_t v, const uint16_t *keys)
-{
- uint8_t dest[16];
- uint8_t temp[16];
-
- _mm_storeu_si128((rsp_vec_t *) temp, v);
-
- for (uint32_t j = 0; j < 8; j++)
- {
- uint16_t key = keys[j];
- uint8_t key_hi = key >> 8;
- uint8_t key_lo = key >> 0;
-
- dest[(j << 1) + 1] = key_hi == 0x80 ? 0x00 : temp[key_hi];
- dest[(j << 1) + 0] = key_lo == 0x80 ? 0x00 : temp[key_lo];
- }
-
- return _mm_loadu_si128((rsp_vec_t *) dest);
-}
-
-rsp_vec_t rsp_device::cop2::vec_load_and_shuffle_operand(const uint16_t* src, uint32_t element)
-{
- if (element >= 8) // element => 0w ... 7w
- {
- uint16_t word_lo;
-
- memcpy(&word_lo, src + (element - 8), sizeof(word_lo));
- uint64_t dword = word_lo | ((uint32_t) word_lo << 16);
-
- return _mm_shuffle_epi32(_mm_loadl_epi64((rsp_vec_t*) &dword), _MM_SHUFFLE(0,0,0,0));
- }
- else if (element >= 4) // element => 0h ... 3h
- {
- uint16_t word_lo;
- uint16_t word_hi;
-
- memcpy(&word_hi, src + element - 0, sizeof(word_hi));
- memcpy(&word_lo, src + element - 4, sizeof(word_lo));
- uint64_t dword = word_lo | ((uint32_t) word_hi << 16);
-
- rsp_vec_t v = _mm_loadl_epi64((rsp_vec_t*) &dword);
- v = _mm_shufflelo_epi16(v, _MM_SHUFFLE(1,1,0,0));
- return _mm_shuffle_epi32(v, _MM_SHUFFLE(1,1,0,0));
- }
- else if (element >= 2) // element => 0q ... 1q
- {
- rsp_vec_t v = vec_load_unshuffled_operand(src);
-
- if (element == 2) {
- v = _mm_shufflelo_epi16(v, _MM_SHUFFLE(3,3,1,1));
- v = _mm_shufflehi_epi16(v, _MM_SHUFFLE(3,3,1,1));
- }
- else
- {
- v = _mm_shufflelo_epi16(v, _MM_SHUFFLE(2,2,0,0));
- v = _mm_shufflehi_epi16(v, _MM_SHUFFLE(2,2,0,0));
- }
-
- return v;
- }
-
- return vec_load_unshuffled_operand(src);
-}
-#else
-rsp_vec_t rsp_device::cop2::vec_load_and_shuffle_operand(const uint16_t* src, uint32_t element)
-{
- rsp_vec_t operand = _mm_load_si128((rsp_vec_t*) src);
- rsp_vec_t key = _mm_load_si128((rsp_vec_t*) m_vec_helpers.shuffle_keys[element]);
-
- return _mm_shuffle_epi8(operand, key);
-}
-#endif
-//
-// SSSE3+ accelerated loads for group I. Byteswap big-endian to 2-byte
-// little-endian vector. Start at vector element offset, discarding any
-// wraparound as necessary.
-//
-// TODO: Reverse-engineer what happens when loads to vector elements must
-// wraparound. Do we just discard the data, as below, or does the
-// data effectively get rotated around the edge of the vector?
-//
-void rsp_device::cop2::vec_load_group1(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm)
-{
- uint32_t offset = addr & 0x7;
- uint32_t ror = offset - element;
-
- // Always load in 8-byte chunks to emulate wraparound.
- rsp_vec_t data;
- if (offset) {
- uint32_t aligned_addr_lo = addr & ~0x7;
- uint32_t aligned_addr_hi = (aligned_addr_lo + 8) & 0xFFF;
-
- data = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_lo));
- rsp_vec_t temp = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_hi));
- data = _mm_unpacklo_epi64(data, temp);
- }
- else
- {
- data = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + addr));
- }
-
- // Shift the DQM up to the point where we mux in the data.
-#if !(defined(__SSSE3__) || defined(_MSC_VER))
- dqm = sse2_pshufb(dqm, m_vec_helpers.sll_b2l_keys[element]);
-#else
- rsp_vec_t ekey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.sll_b2l_keys[element]));
- dqm = _mm_shuffle_epi8(dqm, ekey);
-#endif
-
- // Align the data to the DQM so we can mask it in.
-#if !(defined(__SSSE3__) || defined(_MSC_VER))
- data = sse2_pshufb(data, m_vec_helpers.ror_b2l_keys[ror & 0xF]);
-#else
- ekey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.ror_b2l_keys[ror & 0xF]));
- data = _mm_shuffle_epi8(data, ekey);
-#endif
-
- // Mask and mux in the data.
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- reg = _mm_blendv_epi8(reg, data, dqm);
-#else
- data = _mm_and_si128(dqm, data);
- reg = _mm_andnot_si128(dqm, reg);
- reg = _mm_or_si128(data, reg);
-#endif
-
- _mm_store_si128((rsp_vec_t *) regp, reg);
-}
-
-//
-// SSSE3+ accelerated loads for group II.
-//
-// TODO: Reverse-engineer what happens when loads to vector elements must
-// wraparound. Do we just discard the data, as below, or does the
-// data effectively get rotated around the edge of the vector?
-//
-// TODO: Reverse-engineer what happens when element != 0.
-//
-void rsp_device::cop2::vec_load_group2(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type) {
- uint32_t offset = addr & 0x7;
- rsp_vec_t data;
-
- // Always load in 8-byte chunks to emulate wraparound.
- if (offset) {
- uint32_t aligned_addr_lo = addr & ~0x7;
- uint32_t aligned_addr_hi = (aligned_addr_lo + 8) & 0xFFF;
- uint64_t datalow, datahigh;
-
- memcpy(&datalow, m_rsp.get_dmem() + aligned_addr_lo, sizeof(datalow));
- memcpy(&datahigh, m_rsp.get_dmem() + aligned_addr_hi, sizeof(datahigh));
-
- // TODO: Test for endian issues?
- datahigh >>= ((8 - offset) << 3);
- datalow <<= (offset << 3);
- datalow = datahigh | datalow;
-
- data = _mm_loadl_epi64((rsp_vec_t *) &datalow);
- }
- else
- {
- data = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + addr));
- }
-
- // "Unpack" the data.
- rsp_vec_t zero = _mm_setzero_si128();
- data = _mm_unpacklo_epi8(zero, data);
-
- if (request_type != RSP_MEM_REQUEST_PACK)
- {
- data = _mm_srli_epi16(data, 1);
- }
-
- data = _mm_shufflehi_epi16(data, _MM_SHUFFLE(0, 1, 2, 3));
- data = _mm_shufflelo_epi16(data, _MM_SHUFFLE(0, 1, 2, 3));
-
- _mm_store_si128((rsp_vec_t *) regp, data);
-}
-
-//
-// SSSE3+ accelerated loads for group IV. Byteswap big-endian to 2-byte
-// little-endian vector. Stop loading at quadword boundaries.
-//
-// TODO: Reverse-engineer what happens when loads from vector elements
-// must wraparound (i.e., the address offset is small, starting
-// element is large).
-//
-void rsp_device::cop2::vec_load_group4(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type)
-{
- uint32_t aligned_addr = addr & 0xFF0;
- uint32_t offset = addr & 0xF;
- static uint32_t call_count = 0;
-
- rsp_vec_t data = _mm_load_si128((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr));
-
- uint32_t ror;
- if (request_type == RSP_MEM_REQUEST_QUAD)
- {
- ror = 16 - element + offset;
- }
- else
- {
- // TODO: How is this adjusted for LRV when e != 0?
- dqm = _mm_cmpeq_epi8(_mm_setzero_si128(), dqm);
- ror = 16 - offset;
- }
-
-#if !(defined(__SSSE3__) || defined(_MSC_VER))
- data = sse2_pshufb(data, m_vec_helpers.ror_b2l_keys[ror & 0xF]);
- dqm = sse2_pshufb(dqm, m_vec_helpers.ror_b2l_keys[ror & 0xF]);
-#else
- rsp_vec_t dkey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.ror_b2l_keys[ror & 0xF]));
- data = _mm_shuffle_epi8(data, dkey);
- dqm = _mm_shuffle_epi8(dqm, dkey);
-#endif
-
- // Mask and mux in the data.
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- data = _mm_blendv_epi8(reg, data, dqm);
-#else
- data = _mm_and_si128(dqm, data);
- reg = _mm_andnot_si128(dqm, reg);
- data = _mm_or_si128(data, reg);
-#endif
-
- _mm_store_si128((rsp_vec_t *) regp, data);
-
- call_count++;
-}
-
-//
-// SSE3+ accelerated stores for group I. Byteswap 2-byte little-endian
-// vector back to big-endian. Start at vector element offset, wrapping
-// around the edge of the vector as necessary.
-//
-// TODO: Reverse-engineer what happens when stores from vector elements
-// must wraparound. Do we just stop storing the data, or do we
-// continue storing from the front of the vector, as below?
-//
-void rsp_device::cop2::vec_store_group1(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm)
-{
- uint32_t offset = addr & 0x7;
- uint32_t ror = element - offset;
-
- // Shift the DQM up to the point where we mux in the data.
-#if !(defined(__SSSE3__) || defined(_MSC_VER))
- dqm = sse2_pshufb(dqm, m_vec_helpers.sll_l2b_keys[offset]);
-#else
- rsp_vec_t ekey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.sll_l2b_keys[offset]));
- dqm = _mm_shuffle_epi8(dqm, ekey);
-#endif
-
- // Rotate the reg to align with the DQM.
-#if !(defined(__SSSE3__) || defined(_MSC_VER))
- reg = sse2_pshufb(reg, m_vec_helpers.ror_l2b_keys[ror & 0xF]);
-#else
- ekey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.ror_l2b_keys[ror & 0xF]));
- reg = _mm_shuffle_epi8(reg, ekey);
-#endif
-
- // Always load in 8-byte chunks to emulate wraparound.
- rsp_vec_t data;
- if (offset)
- {
- uint32_t aligned_addr_lo = addr & ~0x7;
- uint32_t aligned_addr_hi = (aligned_addr_lo + 8) & 0xFFF;
-
- data = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_lo));
- rsp_vec_t temp = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_hi));
- data = _mm_unpacklo_epi64(data, temp);
-
- // Mask and mux in the data.
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- data = _mm_blendv_epi8(data, reg, dqm);
-#else
- data = _mm_andnot_si128(dqm, data);
- reg = _mm_and_si128(dqm, reg);
- data = _mm_or_si128(data, reg);
-#endif
-
- _mm_storel_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_lo), data);
-
- data = _mm_srli_si128(data, 8);
- _mm_storel_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_hi), data);
- }
- else
- {
- data = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + addr));
-
- // Mask and mux in the data.
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- data = _mm_blendv_epi8(data, reg, dqm);
-#else
- data = _mm_andnot_si128(dqm, data);
- reg = _mm_and_si128(dqm, reg);
- data = _mm_or_si128(data, reg);
-#endif
-
- _mm_storel_epi64((rsp_vec_t *) (m_rsp.get_dmem() + addr), data);
- }
-}
-
-//
-// SSE3+ accelerated stores for group II. Byteswap 2-byte little-endian
-// vector back to big-endian. Start at vector element offset, wrapping
-// around the edge of the vector as necessary.
-//
-// TODO: Reverse-engineer what happens when stores from vector elements
-// must wraparound. Do we just stop storing the data, or do we
-// continue storing from the front of the vector, as below?
-//
-// TODO: Reverse-engineer what happens when element != 0.
-//
-void rsp_device::cop2::vec_store_group2(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type) {
- // "Pack" the data.
- if (request_type != RSP_MEM_REQUEST_PACK)
- {
- reg = _mm_slli_epi16(reg, 1);
- }
-
- reg = _mm_srai_epi16(reg, 8);
- reg = _mm_packs_epi16(reg, reg);
-
-#if !(defined(__SSSE3__) || defined(_MSC_VER))
- reg = sse2_pshufb(reg, m_vec_helpers.word_reverse);
-#else
- rsp_vec_t dkey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.word_reverse));
- reg = _mm_shuffle_epi8(reg, dkey);
-#endif
-
- // TODO: Always store in 8-byte chunks to emulate wraparound.
- _mm_storel_epi64((rsp_vec_t *) (m_rsp.get_dmem() + addr), reg);
-}
-
-//
-// SSE3+ accelerated stores for group IV. Byteswap 2-byte little-endian
-// vector back to big-endian. Stop storing at quadword boundaries.
-//
-void rsp_device::cop2::vec_store_group4(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type) {
- uint32_t aligned_addr = addr & 0xFF0;
- uint32_t offset = addr & 0xF;
- uint32_t rol = offset;
-
- rsp_vec_t data = _mm_load_si128((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr));
-
- if (request_type == RSP_MEM_REQUEST_QUAD)
- {
- rol -= element;
- }
- else
- {
- // TODO: How is this adjusted for SRV when e != 0?
- dqm = _mm_cmpeq_epi8(_mm_setzero_si128(), dqm);
- }
-
-#if !(defined(__SSSE3__) || defined(_MSC_VER))
- reg = sse2_pshufb(reg, m_vec_helpers.rol_l2b_keys[rol & 0xF]);
-#else
- rsp_vec_t ekey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.rol_l2b_keys[rol & 0xF]));
- reg = _mm_shuffle_epi8(reg, ekey);
-#endif
-
- // Mask and mux out the data, write.
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- data = _mm_blendv_epi8(data, reg, dqm);
-#else
- reg = _mm_and_si128(dqm, reg);
- data = _mm_andnot_si128(dqm, data);
- data = _mm_or_si128(data, reg);
-#endif
-
- _mm_store_si128((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr), data);
-}
-#endif
-
-/***************************************************************************
- 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_t)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_t)m_accum[x].w[3]
-#define ACCUM_M(x) (uint16_t)m_accum[x].w[2]
-#define ACCUM_L(x) (uint16_t)m_accum[x].w[1]
-#define ACCUM_LL(x) (uint16_t)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]; \
-}
-
-#if !USE_SIMD
-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
-};
-#endif
-
-rsp_device::cop2::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));
-#if USE_SIMD
- memset(&m_acc, 0, sizeof(m_acc));
- memset(&m_flags, 0, sizeof(aligned_rsp_2vect_t) * 3);
- m_div_out = 0;
- m_div_in = 0;
-#endif
- m_rspcop2_state = (internal_rspcop2_state *)rsp.m_cache.alloc_near(sizeof(internal_rspcop2_state));
-}
-
-rsp_device::cop2::~cop2()
-{
-}
-
-void rsp_device::cop2::init()
-{
- CLEAR_CARRY_FLAGS();
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP1_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP2_FLAGS();
-}
-
-void rsp_device::cop2::start()
-{
- for(auto & elem : m_v)
- {
- elem.d[0] = 0;
- elem.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(auto & elem : m_accum)
- {
- elem.q = 0;
- }
-}
-
-void rsp_device::cop2::state_string_export(const int index, std::string &str) const
-{
- switch (index)
- {
- case RSP_V0:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 0, 0), (uint16_t)VREG_S( 0, 1), (uint16_t)VREG_S( 0, 2), (uint16_t)VREG_S( 0, 3), (uint16_t)VREG_S( 0, 4), (uint16_t)VREG_S( 0, 5), (uint16_t)VREG_S( 0, 6), (uint16_t)VREG_S( 0, 7));
- break;
- case RSP_V1:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 1, 0), (uint16_t)VREG_S( 1, 1), (uint16_t)VREG_S( 1, 2), (uint16_t)VREG_S( 1, 3), (uint16_t)VREG_S( 1, 4), (uint16_t)VREG_S( 1, 5), (uint16_t)VREG_S( 1, 6), (uint16_t)VREG_S( 1, 7));
- break;
- case RSP_V2:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 2, 0), (uint16_t)VREG_S( 2, 1), (uint16_t)VREG_S( 2, 2), (uint16_t)VREG_S( 2, 3), (uint16_t)VREG_S( 2, 4), (uint16_t)VREG_S( 2, 5), (uint16_t)VREG_S( 2, 6), (uint16_t)VREG_S( 2, 7));
- break;
- case RSP_V3:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 3, 0), (uint16_t)VREG_S( 3, 1), (uint16_t)VREG_S( 3, 2), (uint16_t)VREG_S( 3, 3), (uint16_t)VREG_S( 3, 4), (uint16_t)VREG_S( 3, 5), (uint16_t)VREG_S( 3, 6), (uint16_t)VREG_S( 3, 7));
- break;
- case RSP_V4:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 4, 0), (uint16_t)VREG_S( 4, 1), (uint16_t)VREG_S( 4, 2), (uint16_t)VREG_S( 4, 3), (uint16_t)VREG_S( 4, 4), (uint16_t)VREG_S( 4, 5), (uint16_t)VREG_S( 4, 6), (uint16_t)VREG_S( 4, 7));
- break;
- case RSP_V5:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 5, 0), (uint16_t)VREG_S( 5, 1), (uint16_t)VREG_S( 5, 2), (uint16_t)VREG_S( 5, 3), (uint16_t)VREG_S( 5, 4), (uint16_t)VREG_S( 5, 5), (uint16_t)VREG_S( 5, 6), (uint16_t)VREG_S( 5, 7));
- break;
- case RSP_V6:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 6, 0), (uint16_t)VREG_S( 6, 1), (uint16_t)VREG_S( 6, 2), (uint16_t)VREG_S( 6, 3), (uint16_t)VREG_S( 6, 4), (uint16_t)VREG_S( 6, 5), (uint16_t)VREG_S( 6, 6), (uint16_t)VREG_S( 6, 7));
- break;
- case RSP_V7:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 7, 0), (uint16_t)VREG_S( 7, 1), (uint16_t)VREG_S( 7, 2), (uint16_t)VREG_S( 7, 3), (uint16_t)VREG_S( 7, 4), (uint16_t)VREG_S( 7, 5), (uint16_t)VREG_S( 7, 6), (uint16_t)VREG_S( 7, 7));
- break;
- case RSP_V8:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 8, 0), (uint16_t)VREG_S( 8, 1), (uint16_t)VREG_S( 8, 2), (uint16_t)VREG_S( 8, 3), (uint16_t)VREG_S( 8, 4), (uint16_t)VREG_S( 8, 5), (uint16_t)VREG_S( 8, 6), (uint16_t)VREG_S( 8, 7));
- break;
- case RSP_V9:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 9, 0), (uint16_t)VREG_S( 9, 1), (uint16_t)VREG_S( 9, 2), (uint16_t)VREG_S( 9, 3), (uint16_t)VREG_S( 9, 4), (uint16_t)VREG_S( 9, 5), (uint16_t)VREG_S( 9, 6), (uint16_t)VREG_S( 9, 7));
- break;
- case RSP_V10:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(10, 0), (uint16_t)VREG_S(10, 1), (uint16_t)VREG_S(10, 2), (uint16_t)VREG_S(10, 3), (uint16_t)VREG_S(10, 4), (uint16_t)VREG_S(10, 5), (uint16_t)VREG_S(10, 6), (uint16_t)VREG_S(10, 7));
- break;
- case RSP_V11:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(11, 0), (uint16_t)VREG_S(11, 1), (uint16_t)VREG_S(11, 2), (uint16_t)VREG_S(11, 3), (uint16_t)VREG_S(11, 4), (uint16_t)VREG_S(11, 5), (uint16_t)VREG_S(11, 6), (uint16_t)VREG_S(11, 7));
- break;
- case RSP_V12:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(12, 0), (uint16_t)VREG_S(12, 1), (uint16_t)VREG_S(12, 2), (uint16_t)VREG_S(12, 3), (uint16_t)VREG_S(12, 4), (uint16_t)VREG_S(12, 5), (uint16_t)VREG_S(12, 6), (uint16_t)VREG_S(12, 7));
- break;
- case RSP_V13:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(13, 0), (uint16_t)VREG_S(13, 1), (uint16_t)VREG_S(13, 2), (uint16_t)VREG_S(13, 3), (uint16_t)VREG_S(13, 4), (uint16_t)VREG_S(13, 5), (uint16_t)VREG_S(13, 6), (uint16_t)VREG_S(13, 7));
- break;
- case RSP_V14:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(14, 0), (uint16_t)VREG_S(14, 1), (uint16_t)VREG_S(14, 2), (uint16_t)VREG_S(14, 3), (uint16_t)VREG_S(14, 4), (uint16_t)VREG_S(14, 5), (uint16_t)VREG_S(14, 6), (uint16_t)VREG_S(14, 7));
- break;
- case RSP_V15:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(15, 0), (uint16_t)VREG_S(15, 1), (uint16_t)VREG_S(15, 2), (uint16_t)VREG_S(15, 3), (uint16_t)VREG_S(15, 4), (uint16_t)VREG_S(15, 5), (uint16_t)VREG_S(15, 6), (uint16_t)VREG_S(15, 7));
- break;
- case RSP_V16:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(16, 0), (uint16_t)VREG_S(16, 1), (uint16_t)VREG_S(16, 2), (uint16_t)VREG_S(16, 3), (uint16_t)VREG_S(16, 4), (uint16_t)VREG_S(16, 5), (uint16_t)VREG_S(16, 6), (uint16_t)VREG_S(16, 7));
- break;
- case RSP_V17:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(17, 0), (uint16_t)VREG_S(17, 1), (uint16_t)VREG_S(17, 2), (uint16_t)VREG_S(17, 3), (uint16_t)VREG_S(17, 4), (uint16_t)VREG_S(17, 5), (uint16_t)VREG_S(17, 6), (uint16_t)VREG_S(17, 7));
- break;
- case RSP_V18:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(18, 0), (uint16_t)VREG_S(18, 1), (uint16_t)VREG_S(18, 2), (uint16_t)VREG_S(18, 3), (uint16_t)VREG_S(18, 4), (uint16_t)VREG_S(18, 5), (uint16_t)VREG_S(18, 6), (uint16_t)VREG_S(18, 7));
- break;
- case RSP_V19:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(19, 0), (uint16_t)VREG_S(19, 1), (uint16_t)VREG_S(19, 2), (uint16_t)VREG_S(19, 3), (uint16_t)VREG_S(19, 4), (uint16_t)VREG_S(19, 5), (uint16_t)VREG_S(19, 6), (uint16_t)VREG_S(19, 7));
- break;
- case RSP_V20:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(20, 0), (uint16_t)VREG_S(20, 1), (uint16_t)VREG_S(20, 2), (uint16_t)VREG_S(20, 3), (uint16_t)VREG_S(20, 4), (uint16_t)VREG_S(20, 5), (uint16_t)VREG_S(20, 6), (uint16_t)VREG_S(20, 7));
- break;
- case RSP_V21:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(21, 0), (uint16_t)VREG_S(21, 1), (uint16_t)VREG_S(21, 2), (uint16_t)VREG_S(21, 3), (uint16_t)VREG_S(21, 4), (uint16_t)VREG_S(21, 5), (uint16_t)VREG_S(21, 6), (uint16_t)VREG_S(21, 7));
- break;
- case RSP_V22:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(22, 0), (uint16_t)VREG_S(22, 1), (uint16_t)VREG_S(22, 2), (uint16_t)VREG_S(22, 3), (uint16_t)VREG_S(22, 4), (uint16_t)VREG_S(22, 5), (uint16_t)VREG_S(22, 6), (uint16_t)VREG_S(22, 7));
- break;
- case RSP_V23:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(23, 0), (uint16_t)VREG_S(23, 1), (uint16_t)VREG_S(23, 2), (uint16_t)VREG_S(23, 3), (uint16_t)VREG_S(23, 4), (uint16_t)VREG_S(23, 5), (uint16_t)VREG_S(23, 6), (uint16_t)VREG_S(23, 7));
- break;
- case RSP_V24:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(24, 0), (uint16_t)VREG_S(24, 1), (uint16_t)VREG_S(24, 2), (uint16_t)VREG_S(24, 3), (uint16_t)VREG_S(24, 4), (uint16_t)VREG_S(24, 5), (uint16_t)VREG_S(24, 6), (uint16_t)VREG_S(24, 7));
- break;
- case RSP_V25:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(25, 0), (uint16_t)VREG_S(25, 1), (uint16_t)VREG_S(25, 2), (uint16_t)VREG_S(25, 3), (uint16_t)VREG_S(25, 4), (uint16_t)VREG_S(25, 5), (uint16_t)VREG_S(25, 6), (uint16_t)VREG_S(25, 7));
- break;
- case RSP_V26:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(26, 0), (uint16_t)VREG_S(26, 1), (uint16_t)VREG_S(26, 2), (uint16_t)VREG_S(26, 3), (uint16_t)VREG_S(26, 4), (uint16_t)VREG_S(26, 5), (uint16_t)VREG_S(26, 6), (uint16_t)VREG_S(26, 7));
- break;
- case RSP_V27:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(27, 0), (uint16_t)VREG_S(27, 1), (uint16_t)VREG_S(27, 2), (uint16_t)VREG_S(27, 3), (uint16_t)VREG_S(27, 4), (uint16_t)VREG_S(27, 5), (uint16_t)VREG_S(27, 6), (uint16_t)VREG_S(27, 7));
- break;
- case RSP_V28:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(28, 0), (uint16_t)VREG_S(28, 1), (uint16_t)VREG_S(28, 2), (uint16_t)VREG_S(28, 3), (uint16_t)VREG_S(28, 4), (uint16_t)VREG_S(28, 5), (uint16_t)VREG_S(28, 6), (uint16_t)VREG_S(28, 7));
- break;
- case RSP_V29:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(29, 0), (uint16_t)VREG_S(29, 1), (uint16_t)VREG_S(29, 2), (uint16_t)VREG_S(29, 3), (uint16_t)VREG_S(29, 4), (uint16_t)VREG_S(29, 5), (uint16_t)VREG_S(29, 6), (uint16_t)VREG_S(29, 7));
- break;
- case RSP_V30:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(30, 0), (uint16_t)VREG_S(30, 1), (uint16_t)VREG_S(30, 2), (uint16_t)VREG_S(30, 3), (uint16_t)VREG_S(30, 4), (uint16_t)VREG_S(30, 5), (uint16_t)VREG_S(30, 6), (uint16_t)VREG_S(30, 7));
- break;
- case RSP_V31:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(31, 0), (uint16_t)VREG_S(31, 1), (uint16_t)VREG_S(31, 2), (uint16_t)VREG_S(31, 3), (uint16_t)VREG_S(31, 4), (uint16_t)VREG_S(31, 5), (uint16_t)VREG_S(31, 6), (uint16_t)VREG_S(31, 7));
- break;
- }
-}
-
-/***************************************************************************
- Vector Load Instructions
-***************************************************************************/
-
-void rsp_device::cop2::handle_lwc2(uint32_t op)
-{
- int base = (op >> 21) & 0x1f;
-#if !USE_SIMD
- int i, end;
- uint32_t ea;
- int dest = (op >> 16) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- offset |= 0xffffffc0;
-#endif
-
- 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
-
- //printf("LBV ");
-#if USE_SIMD
- vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]);
-#else
- ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset;
- VREG_B(dest, index) = m_rsp.READ8(ea);
-#endif
- //
- 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
-
- //printf("LSV ");
-#if USE_SIMD
- vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- 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
-
- //printf("LLV ");
-#if USE_SIMD
- vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- 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
-
- //printf("LDV ");
-#if USE_SIMD
- vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- 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
-
- //printf("LQV ");
-#if USE_SIMD
- vec_lqrv_sqrv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- 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
-
- //printf("LRV ");
-#if USE_SIMD
- vec_lqrv_sqrv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- 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
-
- //printf("LPV ");
-#if USE_SIMD
- vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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;
- }
-#endif
- //
- 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
-
- //printf("LUV ");
-#if USE_SIMD
- vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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;
- }
-#endif
- //
- 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
-
- //printf("LHV ");
-#if USE_SIMD
- vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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;
- }
-#endif
- //
- 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
-
- //printf("LFV ");
-#if USE_SIMD
- vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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;
- }
-#endif
- //
- 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
-
- //printf("LWV ");
-#if USE_SIMD
-#else
- 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;
- }
-#endif
- //
- 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
-
- //printf("LTV ");
-#if 0
-#else
- int32_t index = (op >> 7) & 0xf;
- int32_t offset = (op & 0x7f);
- if (offset & 0x40)
- offset |= 0xffffffc0;
-
- int32_t vs = (op >> 16) & 0x1f;
- int32_t ve = vs + 8;
- if (ve > 32)
- ve = 32;
-
- int32_t element;
-
- if (index & 1) fatalerror("RSP: LTV: index = %d\n", index);
-
- uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- ea = ((ea + 8) & ~0xf) + (index & 1);
- for (int32_t 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;
- }
-#endif
- //
- break;
- }
-
- default:
- {
- m_rsp.unimplemented_opcode(op);
- break;
- }
- }
-}
-
-
-/***************************************************************************
- Vector Store Instructions
-***************************************************************************/
-
-void rsp_device::cop2::handle_swc2(uint32_t op)
-{
- int base = (op >> 21) & 0x1f;
-#if !USE_SIMD
- int i, end;
- int eaoffset;
- uint32_t ea;
- int dest = (op >> 16) & 0x1f;
- int index = (op >> 7) & 0xf;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- offset |= 0xffffffc0;
-#endif
-
- 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
-
- //printf("SBV ");
-#if USE_SIMD
- vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]);
-#else
- ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset;
- m_rsp.WRITE8(ea, VREG_B(dest, index));
-#endif
- //
- 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
-
- //printf("SSV ");
-#if USE_SIMD
- vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- 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
-
- //printf("SLV ");
-#if USE_SIMD
- vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- 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
-
- //printf("SDV ");
-#if USE_SIMD
- vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- 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
-
- //printf("SQV ");
-#if USE_SIMD
- vec_lqrv_sqrv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- 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
-
- //printf("SRV ");
-#if USE_SIMD
- vec_lqrv_sqrv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- break;
- }
- case 0x06: /* SPV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores upper 8 bits of each element
-
- //printf("SPV ");
-#if USE_SIMD
- vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- break;
- }
- case 0x07: /* SUV */
- {
- // 31 25 20 15 10 6 0
- // --------------------------------------------------
- // | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset |
- // --------------------------------------------------
- //
- // Stores bits 14-7 of each element
-
- //printf("SUV ");
-#if USE_SIMD
- vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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++;
- }
-#endif
- //
- 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
-
- //printf("SHV ");
-#if USE_SIMD
- vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]);
-#else
- ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- for (i=0; i < 8; i++)
- {
- uint8_t 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;
- }
-#endif
- //
- 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
-
- //printf("SFV ");
-#if USE_SIMD
- vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]);
-#else
- 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;
- }
-#endif
- //
- 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
-
- //printf("SWV ");
-#if USE_SIMD
-#else
- 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++;
- }
-#endif
- //
- 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
-
- //printf("STV ");
-#if 0
-#else
- int32_t index = (op >> 7) & 0xf;
- int32_t offset = (op & 0x7f);
- if (offset & 0x40)
- offset |= 0xffffffc0;
-
- int32_t vs = (op >> 16) & 0x1f;
- int32_t ve = vs + 8;
- if (ve > 32)
- ve = 32;
-
- int32_t element = 8 - (index >> 1);
-
- uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16);
-
- int32_t eaoffset = (ea & 0xf) + (element * 2);
- ea &= ~0xf;
-
- for (int32_t i = vs; i < ve; i++)
- {
- m_rsp.WRITE16(ea + (eaoffset & 0xf), VREG_S(i, element & 0x7));
- eaoffset += 2;
- element++;
- }
-#endif
- //
- break;
- }
-
- default:
- {
- m_rsp.unimplemented_opcode(op);
- break;
- }
- }
-}
-
-/***************************************************************************
- Vector Accumulator Helpers
-***************************************************************************/
-
-uint16_t rsp_device::cop2::SATURATE_ACCUM(int accum, int slice, uint16_t negative, uint16_t positive)
-{
- if ((int16_t)ACCUM_H(accum) < 0)
- {
- if ((uint16_t)(ACCUM_H(accum)) != 0xffff)
- {
- return negative;
- }
- else
- {
- if ((int16_t)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_t)(ACCUM_H(accum)) != 0)
- {
- return positive;
- }
- else
- {
- if ((int16_t)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_device::cop2::handle_vector_ops(uint32_t op)
-{
-#if !USE_SIMD
- int i;
-#endif
-
- // 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
-
- //printf("MULF ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo, acc_mid, acc_hi;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmulf_vmulu(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i=0; i < 8; i++)
- {
- int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i);
- int32_t s2 = (int32_t)(int16_t)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_t r = s1 * s2 * 2;
- r += 0x8000; // rounding ?
- SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit
- SET_ACCUM_M((int16_t)(r >> 16), i);
- SET_ACCUM_L((uint16_t)(r), i);
- m_vres[i] = ACCUM_M(i);
- }
- }
- WRITEBACK_RESULT();
-#endif
- //
- break;
-
- }
-
- case 0x01: /* VMULU */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 |
- // ------------------------------------------------------
- //
-
- //printf("MULU ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo, acc_mid, acc_hi;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmulf_vmulu(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i=0; i < 8; i++)
- {
- int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i);
- int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- int64_t r = s1 * s2 * 2;
- r += 0x8000; // rounding ?
-
- SET_ACCUM_H((uint16_t)(r >> 32), i);
- SET_ACCUM_M((uint16_t)(r >> 16), i);
- SET_ACCUM_L((uint16_t)(r), i);
-
- if (r < 0)
- {
- m_vres[i] = 0;
- }
- else if (((int16_t)(ACCUM_H(i)) ^ (int16_t)(ACCUM_M(i))) < 0)
- {
- m_vres[i] = -1;
- }
- else
- {
- m_vres[i] = ACCUM_M(i);
- }
- }
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("MUDL ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo, acc_mid, acc_hi;
-
- acc_lo = read_acc_lo(acc);
- acc_mid = read_acc_mid(acc);
- acc_hi = read_acc_hi(acc);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmadl_vmudl(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i=0; i < 8; i++)
- {
- uint32_t s1 = (uint32_t)(uint16_t)VREG_S(VS1REG, i);
- uint32_t s2 = (uint32_t)(uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
- uint32_t r = s1 * s2;
-
- SET_ACCUM_H(0, i);
- SET_ACCUM_M(0, i);
- SET_ACCUM_L((uint16_t)(r >> 16), i);
-
- m_vres[i] = ACCUM_L(i);
- }
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("MUDM ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo, acc_mid, acc_hi;
-
- acc_lo = read_acc_lo(acc);
- acc_mid = read_acc_mid(acc);
- acc_hi = read_acc_hi(acc);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmadm_vmudm(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i=0; i < 8; i++)
- {
- int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i);
- int32_t s2 = (uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); // not sign-extended
- int32_t r = s1 * s2;
-
- SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit
- SET_ACCUM_M((int16_t)(r >> 16), i);
- SET_ACCUM_L((uint16_t)(r), i);
-
- m_vres[i] = ACCUM_M(i);
- }
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("MUDN ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo = read_acc_lo(acc);
- rsp_vec_t acc_mid = read_acc_mid(acc);
- rsp_vec_t acc_hi = read_acc_hi(acc);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmadn_vmudn(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i=0; i < 8; i++)
- {
- int32_t s1 = (uint16_t)VREG_S(VS1REG, i); // not sign-extended
- int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
- int32_t r = s1 * s2;
-
- SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit
- SET_ACCUM_M((int16_t)(r >> 16), i);
- SET_ACCUM_L((uint16_t)(r), i);
-
- m_vres[i] = ACCUM_L(i);
- }
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("MUDH ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo, acc_mid, acc_hi;
-
- acc_lo = read_acc_lo(acc);
- acc_mid = read_acc_mid(acc);
- acc_hi = read_acc_hi(acc);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmadh_vmudh(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i=0; i < 8; i++)
- {
- int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i);
- int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
- int32_t r = s1 * s2;
-
- SET_ACCUM_H((int16_t)(r >> 16), i);
- SET_ACCUM_M((uint16_t)(r), i);
- SET_ACCUM_L(0, i);
-
- if (r < -32768) r = -32768;
- if (r > 32767) r = 32767;
- m_vres[i] = (int16_t)(r);
- }
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("MACF ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo, acc_mid, acc_hi;
-
- acc_lo = read_acc_lo(acc);
- acc_mid = read_acc_mid(acc);
- acc_hi = read_acc_hi(acc);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmacf_vmacu(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i=0; i < 8; i++)
- {
- int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i);
- int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
- int32_t r = s1 * s2;
-
- uint64_t q = (uint64_t)(uint16_t)ACCUM_LL(i);
- q |= (((uint64_t)(uint16_t)ACCUM_L(i)) << 16);
- q |= (((uint64_t)(uint16_t)ACCUM_M(i)) << 32);
- q |= (((uint64_t)(uint16_t)ACCUM_H(i)) << 48);
-
- q += (int64_t)(r) << 17;
-
- SET_ACCUM_LL((uint16_t)q, i);
- SET_ACCUM_L((uint16_t)(q >> 16), i);
- SET_ACCUM_M((uint16_t)(q >> 32), i);
- SET_ACCUM_H((uint16_t)(q >> 48), i);
-
- m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
-#endif
- //
- break;
- }
- case 0x09: /* VMACU */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 |
- // ------------------------------------------------------
- //
-
- //printf("MACU ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo, acc_mid, acc_hi;
-
- acc_lo = read_acc_lo(acc);
- acc_mid = read_acc_mid(acc);
- acc_hi = read_acc_hi(acc);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmacf_vmacu(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i = 0; i < 8; i++)
- {
- int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i);
- int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
- int32_t r1 = s1 * s2;
- uint32_t r2 = (uint16_t)ACCUM_L(i) + ((uint16_t)(r1) * 2);
- uint32_t r3 = (uint16_t)ACCUM_M(i) + (uint16_t)((r1 >> 16) * 2) + (uint16_t)(r2 >> 16);
-
- SET_ACCUM_L((uint16_t)(r2), i);
- SET_ACCUM_M((uint16_t)(r3), i);
- SET_ACCUM_H(ACCUM_H(i) + (uint16_t)(r3 >> 16) + (uint16_t)(r1 >> 31), i);
-
- if ((int16_t)ACCUM_H(i) < 0)
- {
- m_vres[i] = 0;
- }
- else
- {
- if (ACCUM_H(i) != 0)
- {
- m_vres[i] = 0xffff;
- }
- else
- {
- if ((int16_t)ACCUM_M(i) < 0)
- {
- m_vres[i] = 0xffff;
- }
- else
- {
- m_vres[i] = ACCUM_M(i);
- }
- }
- }
- }
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("MADL ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo, acc_mid, acc_hi;
-
- acc_lo = read_acc_lo(acc);
- acc_mid = read_acc_mid(acc);
- acc_hi = read_acc_hi(acc);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmadl_vmudl(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i = 0; i < 8; i++)
- {
- uint32_t s1 = (uint32_t)(uint16_t)VREG_S(VS1REG, i);
- uint32_t s2 = (uint32_t)(uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
- uint32_t r1 = s1 * s2;
- uint32_t r2 = (uint16_t)ACCUM_L(i) + (r1 >> 16);
- uint32_t r3 = (uint16_t)ACCUM_M(i) + (r2 >> 16);
-
- SET_ACCUM_L((uint16_t)(r2), i);
- SET_ACCUM_M((uint16_t)(r3), i);
- SET_ACCUM_H(ACCUM_H(i) + (int16_t)(r3 >> 16), i);
-
- m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
- }
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("MADM ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo, acc_mid, acc_hi;
-
- acc_lo = read_acc_lo(acc);
- acc_mid = read_acc_mid(acc);
- acc_hi = read_acc_hi(acc);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmadm_vmudm(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i=0; i < 8; i++)
- {
- uint32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i);
- uint32_t s2 = (uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); // not sign-extended
- uint32_t r1 = s1 * s2;
- uint32_t r2 = (uint16_t)ACCUM_L(i) + (uint16_t)(r1);
- uint32_t r3 = (uint16_t)ACCUM_M(i) + (r1 >> 16) + (r2 >> 16);
-
- SET_ACCUM_L((uint16_t)(r2), i);
- SET_ACCUM_M((uint16_t)(r3), i);
- SET_ACCUM_H(ACCUM_H(i) + (uint16_t)(r3 >> 16), i);
- if ((int32_t)(r1) < 0)
- SET_ACCUM_H(ACCUM_H(i) - 1, i);
-
- m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("MADN ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo, acc_mid, acc_hi;
-
- acc_lo = read_acc_lo(acc);
- acc_mid = read_acc_mid(acc);
- acc_hi = read_acc_hi(acc);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmadn_vmudn(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i=0; i < 8; i++)
- {
- int32_t s1 = (uint16_t)VREG_S(VS1REG, i); // not sign-extended
- int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- uint64_t q = (uint64_t)ACCUM_LL(i);
- q |= (((uint64_t)ACCUM_L(i)) << 16);
- q |= (((uint64_t)ACCUM_M(i)) << 32);
- q |= (((uint64_t)ACCUM_H(i)) << 48);
- q += (int64_t)(s1*s2) << 16;
-
- SET_ACCUM_LL((uint16_t)q, i);
- SET_ACCUM_L((uint16_t)(q >> 16), i);
- SET_ACCUM_M((uint16_t)(q >> 32), i);
- SET_ACCUM_H((uint16_t)(q >> 48), i);
-
- m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
- }
- WRITEBACK_RESULT();
-
-#endif
- //
- 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
-
- //printf("MADH ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t acc_lo, acc_mid, acc_hi;
-
- acc_lo = read_acc_lo(acc);
- acc_mid = read_acc_mid(acc);
- acc_hi = read_acc_hi(acc);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmadh_vmudh(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi);
-
- write_acc_lo(acc, acc_lo);
- write_acc_mid(acc, acc_mid);
- write_acc_hi(acc, acc_hi);
-#else
- for (i = 0; i < 8; i++)
- {
- int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i);
- int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- int32_t accum = (uint32_t)(uint16_t)ACCUM_M(i);
- accum |= ((uint32_t)((uint16_t)ACCUM_H(i))) << 16;
- accum += s1 * s2;
-
- SET_ACCUM_H((uint16_t)(accum >> 16), i);
- SET_ACCUM_M((uint16_t)accum, i);
-
- m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
-
-#endif
- //
- 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
-
- //printf("ADD ");
-#if USE_SIMD
- rsp_vec_t acc_lo;
- uint16_t *acc = m_acc.s;
- rsp_vec_t carry = read_vco_lo(m_flags[RSP_VCO].s);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vadd(vs, vt_shuffle, carry, &acc_lo);
-
- write_vco_hi(m_flags[RSP_VCO].s, vec_zero());
- write_vco_lo(m_flags[RSP_VCO].s, vec_zero());
- write_acc_lo(acc, acc_lo);
-#else
- for (i=0; i < 8; i++)
- {
- int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i);
- int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
- int32_t r = s1 + s2 + (CARRY_FLAG(i) != 0 ? 1 : 0);
-
- SET_ACCUM_L((int16_t)(r), i);
-
- if (r > 32767) r = 32767;
- if (r < -32768) r = -32768;
- m_vres[i] = (int16_t)(r);
- }
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("SUB ");
-#if USE_SIMD
- rsp_vec_t acc_lo;
- uint16_t *acc = m_acc.s;
- rsp_vec_t carry = read_vco_lo(m_flags[RSP_VCO].s);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vsub(vs, vt_shuffle, carry, &acc_lo);
-
- write_vco_hi(m_flags[RSP_VCO].s, vec_zero());
- write_vco_lo(m_flags[RSP_VCO].s, vec_zero());
- write_acc_lo(acc, acc_lo);
-#else
- for (i = 0; i < 8; i++)
- {
- int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i);
- int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
- int32_t r = s1 - s2 - (CARRY_FLAG(i) != 0 ? 1 : 0);
-
- SET_ACCUM_L((int16_t)(r), i);
-
- if (r > 32767) r = 32767;
- if (r < -32768) r = -32768;
-
- m_vres[i] = (int16_t)(r);
- }
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("ABS ");
-#if USE_SIMD
- rsp_vec_t acc_lo;
- uint16_t *acc = m_acc.s;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vabs(vs, vt_shuffle, vec_zero(), &acc_lo);
-
- write_acc_lo(acc, acc_lo);
-#else
- for (i=0; i < 8; i++)
- {
- int16_t s1 = (int16_t)VREG_S(VS1REG, i);
- int16_t s2 = (int16_t)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();
-#endif
- //
- 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
-
- //printf("ADDC ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t sn;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vaddc(vs, vt_shuffle, vec_zero(), &sn);
-
- write_vco_hi(m_flags[RSP_VCO].s, vec_zero());
- write_vco_lo(m_flags[RSP_VCO].s, sn);
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
-
- for (i=0; i < 8; i++)
- {
- int32_t s1 = (uint32_t)(uint16_t)VREG_S(VS1REG, i);
- int32_t s2 = (uint32_t)(uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
- int32_t r = s1 + s2;
-
- m_vres[i] = (int16_t)(r);
- SET_ACCUM_L((int16_t)(r), i);
-
- if (r & 0xffff0000)
- {
- SET_CARRY_FLAG(i);
- }
- }
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("SUBC ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t eq, sn;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vsubc(vs, vt_shuffle, vec_zero(), &eq, &sn);
-
- write_vco_hi(m_flags[RSP_VCO].s, eq);
- write_vco_lo(m_flags[RSP_VCO].s, sn);
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
-
- for (i=0; i < 8; i++)
- {
- int32_t s1 = (uint32_t)(uint16_t)VREG_S(VS1REG, i);
- int32_t s2 = (uint32_t)(uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i));
- int32_t r = s1 - s2;
-
- m_vres[i] = (int16_t)(r);
- SET_ACCUM_L((uint16_t)(r), i);
-
- if ((uint16_t)(r) != 0)
- {
- SET_ZERO_FLAG(i);
- }
- if (r & 0xffff0000)
- {
- SET_CARRY_FLAG(i);
- }
- }
- WRITEBACK_RESULT();
-#endif
- //
- 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
-
- //printf("SAW ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- switch (EL)
- {
- case 8:
- m_v[VDREG].v = read_acc_hi(acc);
- break;
- case 9:
- m_v[VDREG].v = read_acc_mid(acc);
- break;
- case 10:
- m_v[VDREG].v = read_acc_lo(acc);
- break;
-
- default:
- m_v[VDREG].v = _mm_setzero_si128();
- break;
- }
-#else
- 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);
- }
-#endif
- //
- 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
-
- //printf("LT ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t le;
-
- rsp_vec_t eq = read_vco_hi(m_flags[RSP_VCO].s);
- rsp_vec_t sign = read_vco_lo(m_flags[RSP_VCO].s);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_veq_vge_vlt_vne(op, vs, vt_shuffle, vec_zero(), &le, eq, sign);
-
- write_vcc_hi(m_flags[RSP_VCC].s, vec_zero());
- write_vcc_lo(m_flags[RSP_VCC].s, le);
- write_vco_hi(m_flags[RSP_VCO].s, vec_zero());
- write_vco_lo(m_flags[RSP_VCO].s, vec_zero());
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (i=0; i < 8; i++)
- {
- int16_t 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();
-#endif
- //
- 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
-
- //printf("EQ ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t le;
-
- rsp_vec_t eq = read_vco_hi(m_flags[RSP_VCO].s);
- rsp_vec_t sign = read_vco_lo(m_flags[RSP_VCO].s);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_veq_vge_vlt_vne(op, vs, vt_shuffle, vec_zero(), &le, eq, sign);
-
- write_vcc_hi(m_flags[RSP_VCC].s, vec_zero());
- write_vcc_lo(m_flags[RSP_VCC].s, le);
- write_vco_hi(m_flags[RSP_VCO].s, vec_zero());
- write_vco_lo(m_flags[RSP_VCO].s, vec_zero());
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (i = 0; i < 8; i++)
- {
- int16_t s1 = VREG_S(VS1REG, i);
- int16_t 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();
-#endif
- //
- 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
-
- //printf("NE ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t le;
-
- rsp_vec_t eq = read_vco_hi(m_flags[RSP_VCO].s);
- rsp_vec_t sign = read_vco_lo(m_flags[RSP_VCO].s);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_veq_vge_vlt_vne(op, vs, vt_shuffle, vec_zero(), &le, eq, sign);
-
- write_vcc_hi(m_flags[RSP_VCC].s, vec_zero());
- write_vcc_lo(m_flags[RSP_VCC].s, le);
- write_vco_hi(m_flags[RSP_VCO].s, vec_zero());
- write_vco_lo(m_flags[RSP_VCO].s, vec_zero());
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (i = 0; i < 8; i++)
- {
- int16_t s1 = VREG_S(VS1REG, i);
- int16_t 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();
-#endif
- //
- 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
-
- //printf("GE ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t le;
-
- rsp_vec_t eq = read_vco_hi(m_flags[RSP_VCO].s);
- rsp_vec_t sign = read_vco_lo(m_flags[RSP_VCO].s);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_veq_vge_vlt_vne(op, vs, vt_shuffle, vec_zero(), &le, eq, sign);
-
- write_vcc_hi(m_flags[RSP_VCC].s, vec_zero());
- write_vcc_lo(m_flags[RSP_VCC].s, le);
- write_vco_hi(m_flags[RSP_VCO].s, vec_zero());
- write_vco_lo(m_flags[RSP_VCO].s, vec_zero());
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (i=0; i < 8; i++)
- {
- int16_t s1 = VREG_S(VS1REG, i);
- int16_t 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();
-#endif
- //
- break;
- }
-
- case 0x24: /* VCL */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 |
- // ------------------------------------------------------
- //
- // Vector clip low
-
- //printf("CL ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
-
- rsp_vec_t ge = read_vcc_hi(m_flags[RSP_VCC].s);
- rsp_vec_t le = read_vcc_lo(m_flags[RSP_VCC].s);
- rsp_vec_t eq = read_vco_hi(m_flags[RSP_VCO].s);
- rsp_vec_t sign = read_vco_lo(m_flags[RSP_VCO].s);
- rsp_vec_t vce = read_vce(m_flags[RSP_VCE].s);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
- m_v[VDREG].v = vec_vcl(vs, vt_shuffle, vec_zero(), &ge, &le, eq, sign, vce);
-
- write_vcc_hi(m_flags[RSP_VCC].s, ge);
- write_vcc_lo(m_flags[RSP_VCC].s, le);
- write_vco_hi(m_flags[RSP_VCO].s, vec_zero());
- write_vco_lo(m_flags[RSP_VCO].s, vec_zero());
- write_vce(m_flags[RSP_VCE].s, vec_zero());
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- for (i = 0; i < 8; i++)
- {
- int16_t s1 = VREG_S(VS1REG, i);
- int16_t s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- if (CARRY_FLAG(i) != 0) // vco_lo
- {
- if (ZERO_FLAG(i) != 0) // vco_hi
- {
- if (COMPARE_FLAG(i) != 0) // vcc_lo
- {
- SET_ACCUM_L(-(uint16_t)s2, i);
- }
- else
- {
- SET_ACCUM_L(s1, i);
- }
- }
- else
- {
- if (CLIP1_FLAG(i) != 0) // vce
- {
- if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) > 0x10000)
- {
- SET_ACCUM_L(s1, i);
- CLEAR_COMPARE_FLAG(i);
- }
- else
- {
- SET_ACCUM_L(-((uint16_t)s2), i);
- SET_COMPARE_FLAG(i);
- }
- }
- else
- {
- if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) != 0)
- {
- SET_ACCUM_L(s1, i);
- CLEAR_COMPARE_FLAG(i);
- }
- else
- {
- SET_ACCUM_L(-((uint16_t)s2), i);
- SET_COMPARE_FLAG(i);
- }
- }
- }
- }
- else
- {
- if (ZERO_FLAG(i) != 0) // vco_hi
- {
- if (CLIP2_FLAG(i) != 0) // vcc_hi
- {
- SET_ACCUM_L(s2, i);
- }
- else
- {
- SET_ACCUM_L(s1, i);
- }
- }
- else
- {
- if (((int32_t)(uint16_t)s1 - (int32_t)(uint16_t)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(); // vco_lo
- CLEAR_ZERO_FLAGS(); // vco_hi
- CLEAR_CLIP1_FLAGS(); // vce
- WRITEBACK_RESULT();
-#endif
- //
- break;
- }
-
- case 0x25: /* VCH */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 |
- // ------------------------------------------------------
- //
- // Vector clip high
-
- //printf("CH ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t ge, le, sign, eq, vce;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vch(vs, vt_shuffle, vec_zero(), &ge, &le, &eq, &sign, &vce);
-
- write_vcc_hi(m_flags[RSP_VCC].s, ge);
- write_vcc_lo(m_flags[RSP_VCC].s, le);
- write_vco_hi(m_flags[RSP_VCO].s, eq);
- write_vco_lo(m_flags[RSP_VCO].s, sign);
- write_vce(m_flags[RSP_VCE].s, vce);
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- CLEAR_CARRY_FLAGS();
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP1_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP2_FLAGS();
- uint32_t vce;
-
- for (i=0; i < 8; i++)
- {
- int16_t s1 = VREG_S(VS1REG, i);
- int16_t 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_t)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();
-#endif
- //
- break;
- }
-
- case 0x26: /* VCR */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 |
- // ------------------------------------------------------
- //
- // Vector clip reverse
-
- //printf("CR ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t ge, le;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vcr(vs, vt_shuffle, vec_zero(), &ge, &le);
-
- write_vcc_hi(m_flags[RSP_VCC].s, ge);
- write_vcc_lo(m_flags[RSP_VCC].s, le);
- write_vco_hi(m_flags[RSP_VCO].s, vec_zero());
- write_vco_lo(m_flags[RSP_VCO].s, vec_zero());
- write_vce(m_flags[RSP_VCE].s, vec_zero());
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- CLEAR_CARRY_FLAGS();
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP1_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (i=0; i < 8; i++)
- {
- int16_t s1 = VREG_S(VS1REG, i);
- int16_t s2 = VREG_S(VS2REG, VEC_EL_2(EL, i));
-
- if ((int16_t)(s1 ^ s2) < 0)
- {
- if (s2 < 0)
- {
- SET_CLIP2_FLAG(i);
- }
- if ((s1 + s2) <= 0)
- {
- SET_ACCUM_L(~((uint16_t)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();
-#endif
- //
- 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
-
- //printf("MRG ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
- rsp_vec_t le = read_vcc_lo(m_flags[RSP_VCC].s);
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vmrg(vs, vt_shuffle, le);
-
- write_vco_hi(m_flags[RSP_VCO].s, vec_zero());
- write_vco_lo(m_flags[RSP_VCO].s, vec_zero());
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- 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();
-#endif
- //
- 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
-
- //printf("AND ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vand_vnand(op, vs, vt_shuffle);
-
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- 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();
-#endif
- //
- 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
-
- //printf("NAND ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vand_vnand(op, vs, vt_shuffle);
-
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- 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();
-#endif
- //
- 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
-
- //printf("OR ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vor_vnor(op, vs, vt_shuffle);
-
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- 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();
-#endif
- //
- 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
-
- //printf("NOR ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vor_vnor(op, vs, vt_shuffle);
-
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- 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();
-#endif
- //
- 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
-
- //printf("XOR ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vxor_vnxor(op, vs, vt_shuffle);
-
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- 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();
-#endif
- //
- 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
-
- //printf("NXOR ");
-#if USE_SIMD
- uint16_t *acc = m_acc.s;
-
- rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s);
- rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL);
-
- m_v[VDREG].v = vec_vxor_vnxor(op, vs, vt_shuffle);
-
- write_acc_lo(acc, m_v[VDREG].v);
-#else
- 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();
-#endif
- //
- break;
- }
-
- case 0x30: /* VRCP */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 |
- // ------------------------------------------------------
- //
- // Calculates reciprocal
-
- //printf("RCP ");
-#if USE_SIMD
- write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL));
-
- int32_t dp = op & m_dp_flag;
- m_dp_flag = 0;
-
- m_v[VDREG].v = vec_vrcp_vrsq(op, dp, VS2REG, EL, VDREG, VS1REG);
-#else
- int32_t shifter = 0;
-
- int32_t rec = (int16_t)(VREG_S(VS2REG, EL & 7));
- int32_t 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_t address = ((datainput << shifter) & 0x7fc00000) >> 22;
- int32_t fetchval = rsp_divtable[address];
- int32_t 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_t)(rec & 0xffff);
-
- for (i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
- }
-
-
-#endif
- //
- break;
- }
-
- case 0x31: /* VRCPL */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 |
- // ------------------------------------------------------
- //
- // Calculates reciprocal low part
-
- //printf("RCPL ");
-#if USE_SIMD
- write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL));
-
- int32_t dp = op & m_dp_flag;
- m_dp_flag = 0;
-
- m_v[VDREG].v = vec_vrcp_vrsq(op, dp, VS2REG, EL, VDREG, VS1REG);
-#else
- int32_t shifter = 0;
-
- int32_t rec = (int16_t)VREG_S(VS2REG, EL & 7);
- int32_t 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_t address = ((datainput << shifter) & 0x7fc00000) >> 22;
- int32_t fetchval = rsp_divtable[address];
- int32_t 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_t)(rec & 0xffff);
-
- for (i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
- }
-
-#endif
- //
- break;
- }
-
- case 0x32: /* VRCPH */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 |
- // ------------------------------------------------------
- //
- // Calculates reciprocal high part
-
- //printf("RCPH ");
-#if USE_SIMD
- write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL));
-
- m_dp_flag = 1;
-
- m_v[VDREG].v = vec_vdivh(VS2REG, EL, VDREG, VS1REG);
-#else
- 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_t)(m_reciprocal_res >> 16);
-
-#endif
- //
- 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
-
- //printf("MOV ");
-#if USE_SIMD
- write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL));
- m_v[VDREG].v = vec_vmov(VS2REG, EL, VDREG, VS1REG);
-#else
- 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);
- }
-#endif
- //
- break;
- }
-
- case 0x34: /* VRSQ */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 |
- // ------------------------------------------------------
- //
- // Calculates reciprocal square-root
-
- //printf("RSQ ");
-#if USE_SIMD
- write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL));
-
- int32_t dp = op & m_dp_flag;
- m_dp_flag = 0;
-
- m_v[VDREG].v = vec_vrcp_vrsq(op, dp, VS2REG, EL, VDREG, VS1REG);
-#else
- int32_t shifter = 0;
-
- int32_t rec = (int16_t)(VREG_S(VS2REG, EL & 7));
- int32_t 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_t address = ((datainput << shifter) & 0x7fc00000) >> 22;
- address = ((address | 0x200) & 0x3fe) | (shifter & 1);
-
- int32_t fetchval = rsp_divtable[address];
- int32_t 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_t)(rec & 0xffff);
-
- for (i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
- }
-
-#endif
- //
- 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
-
- //printf("RSQL ");
-#if USE_SIMD
- write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL));
-
- int32_t dp = op & m_dp_flag;
- m_dp_flag = 0;
-
- m_v[VDREG].v = vec_vrcp_vrsq(op, dp, VS2REG, EL, VDREG, VS1REG);
-#else
- int32_t shifter = 0;
- int32_t rec = (int16_t)VREG_S(VS2REG, EL & 7);
- int32_t 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_t address = ((datainput << shifter) & 0x7fc00000) >> 22;
- address = ((address | 0x200) & 0x3fe) | (shifter & 1);
-
- int32_t fetchval = rsp_divtable[address];
- int32_t 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_t)(rec & 0xffff);
-
- for (i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i);
- }
-
-#endif
- //
- 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
-
- //printf("RSQH ");
-#if USE_SIMD
- write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL));
-
- m_dp_flag = 1;
-
- m_v[VDREG].v = vec_vdivh(VS2REG, EL, VDREG, VS1REG);
-#else
- 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_t)(m_reciprocal_res >> 16); // store high part
-#endif
- //
- break;
- }
-
- case 0x37: /* VNOP */
- {
- // 31 25 24 20 15 10 5 0
- // ------------------------------------------------------
- // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110111 |
- // ------------------------------------------------------
- //
- // Vector null instruction
-
- //printf("NOP ");
- break;
- }
-
- default: m_rsp.unimplemented_opcode(op); break;
- }
-}
-
-/***************************************************************************
- Vector Flag Reading/Writing
-***************************************************************************/
-
-void rsp_device::cop2::handle_cop2(uint32_t op)
-{
- switch ((op >> 21) & 0x1f)
- {
- case 0x00: /* MFC2 */
- {
- // 31 25 20 15 10 6 0
- // ---------------------------------------------------
- // | 010010 | 00000 | TTTTT | DDDDD | IIII | 0000000 |
- // ---------------------------------------------------
- //
- //printf("MFC2 ");
- int el = (op >> 7) & 0xf;
- uint16_t b1 = VREG_B(RDREG, (el+0) & 0xf);
- uint16_t b2 = VREG_B(RDREG, (el+1) & 0xf);
- if (RTREG) RTVAL = (int32_t)(int16_t)((b1 << 8) | (b2));
- break;
- }
-
- case 0x02: /* CFC2 */
- {
- // 31 25 20 15 10 0
- // ------------------------------------------------
- // | 010010 | 00010 | TTTTT | DDDDD | 00000000000 |
- // ------------------------------------------------
- //
- //printf("CFC2 ");
- if (RTREG)
- {
-#if USE_SIMD
- int32_t src = RDREG & 3;
- if (src == 3) {
- src = 2;
- }
- RTVAL = get_flags(m_flags[src].s);
-#else
- 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);
- }
-#endif
- }
- break;
- }
-
- case 0x04: /* MTC2 */
- {
- // 31 25 20 15 10 6 0
- // ---------------------------------------------------
- // | 010010 | 00100 | TTTTT | DDDDD | IIII | 0000000 |
- // ---------------------------------------------------
- //
- //printf("MTC2 ");
- 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)
- {
-#if USE_SIMD
- case 0:
- case 1:
- case 2:
- uint16_t r0 = (RTVAL & (1 << 0)) ? 0xffff : 0;
- uint16_t r1 = (RTVAL & (1 << 1)) ? 0xffff : 0;
- uint16_t r2 = (RTVAL & (1 << 2)) ? 0xffff : 0;
- uint16_t r3 = (RTVAL & (1 << 3)) ? 0xffff : 0;
- uint16_t r4 = (RTVAL & (1 << 4)) ? 0xffff : 0;
- uint16_t r5 = (RTVAL & (1 << 5)) ? 0xffff : 0;
- uint16_t r6 = (RTVAL & (1 << 6)) ? 0xffff : 0;
- uint16_t r7 = (RTVAL & (1 << 7)) ? 0xffff : 0;
- m_flags[RDREG].__align[0] = _mm_set_epi16(r7, r6, r5, r4, r3, r2, r1, r0);
- r0 = (RTVAL & (1 << 8)) ? 0xffff : 0;
- r1 = (RTVAL & (1 << 9)) ? 0xffff : 0;
- r2 = (RTVAL & (1 << 10)) ? 0xffff : 0;
- r3 = (RTVAL & (1 << 11)) ? 0xffff : 0;
- r4 = (RTVAL & (1 << 12)) ? 0xffff : 0;
- r5 = (RTVAL & (1 << 13)) ? 0xffff : 0;
- r6 = (RTVAL & (1 << 14)) ? 0xffff : 0;
- r7 = (RTVAL & (1 << 15)) ? 0xffff : 0;
- m_flags[RDREG].__align[1] = _mm_set_epi16(r7, r6, r5, r4, r3, r2, r1, r0);
- break;
-#else
- 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;
-#endif
- }
- 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:
- {
- //printf("V");
- handle_vector_ops(op);
- break;
- }
-
- default:
- m_rsp.unimplemented_opcode(op);
- break;
- }
- //dump(op);
-}
-
-inline void rsp_device::cop2::mfc2()
-{
- uint32_t op = m_rspcop2_state->op;
- int el = (op >> 7) & 0xf;
-
- uint16_t b1 = VREG_B(VS1REG, (el+0) & 0xf);
- uint16_t b2 = VREG_B(VS1REG, (el+1) & 0xf);
- if (RTREG) RTVAL = (int32_t)(int16_t)((b1 << 8) | (b2));
-}
-
-inline void rsp_device::cop2::cfc2()
-{
- uint32_t op = m_rspcop2_state->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_device::cop2::mtc2()
-{
- uint32_t op = m_rspcop2_state->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_device::cop2::ctc2()
-{
- uint32_t op = m_rspcop2_state->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_device::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_t)VREG_S(i,0), (uint16_t)VREG_S(i,1), (uint16_t)VREG_S(i,2), (uint16_t)VREG_S(i,3), (uint16_t)VREG_S(i,4), (uint16_t)VREG_S(i,5), (uint16_t)VREG_S(i,6), (uint16_t)VREG_S(i,7));
- }
- prev_vecs[i].d[0] = m_v[i].d[0];
- prev_vecs[i].d[1] = m_v[i].d[1];
- }
-}
-
-void rsp_device::cop2::dump(uint32_t op)
-{
- printf("%08x ", op);
- for (int i = 0; i < 32; i++)
- {
- printf("%08x ", m_rsp.m_rsp_state->r[i]);
- }
- printf("\n");
-
- for (int i = 0; i < 32; i++)
- {
- printf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", VREG_B(i, 0), VREG_B(i, 1), VREG_B(i, 2), VREG_B(i, 3), VREG_B(i, 4), VREG_B(i, 5), VREG_B(i, 6), VREG_B(i, 7), VREG_B(i, 8), VREG_B(i, 9), VREG_B(i, 10), VREG_B(i, 11), VREG_B(i, 12), VREG_B(i, 13), VREG_B(i, 14), VREG_B(i, 15));
- }
-
-#if USE_SIMD
- printf("acc_h: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_acc.s[0], m_acc.s[1], m_acc.s[2], m_acc.s[3], m_acc.s[4], m_acc.s[5], m_acc.s[6], m_acc.s[7]);
- printf("acc_m: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_acc.s[8], m_acc.s[9], m_acc.s[10], m_acc.s[11], m_acc.s[12], m_acc.s[13], m_acc.s[14], m_acc.s[15]);
- printf("acc_l: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_acc.s[16], m_acc.s[17], m_acc.s[18], m_acc.s[19], m_acc.s[20], m_acc.s[21], m_acc.s[22], m_acc.s[23]);
- printf("vcc_hi: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_flags[RSP_VCC].s[0], m_flags[RSP_VCC].s[1], m_flags[RSP_VCC].s[2], m_flags[RSP_VCC].s[3], m_flags[RSP_VCC].s[4], m_flags[RSP_VCC].s[5], m_flags[RSP_VCC].s[6], m_flags[RSP_VCC].s[7]);
- printf("vcc_lo: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_flags[RSP_VCC].s[8], m_flags[RSP_VCC].s[9], m_flags[RSP_VCC].s[10], m_flags[RSP_VCC].s[11], m_flags[RSP_VCC].s[12], m_flags[RSP_VCC].s[13], m_flags[RSP_VCC].s[14], m_flags[RSP_VCC].s[15]);
- printf("vco_hi: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_flags[RSP_VCO].s[0], m_flags[RSP_VCO].s[1], m_flags[RSP_VCO].s[2], m_flags[RSP_VCO].s[3], m_flags[RSP_VCO].s[4], m_flags[RSP_VCO].s[5], m_flags[RSP_VCO].s[6], m_flags[RSP_VCO].s[7]);
- printf("vco_lo: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_flags[RSP_VCO].s[8], m_flags[RSP_VCO].s[9], m_flags[RSP_VCO].s[10], m_flags[RSP_VCO].s[11], m_flags[RSP_VCO].s[12], m_flags[RSP_VCO].s[13], m_flags[RSP_VCO].s[14], m_flags[RSP_VCO].s[15]);
- printf("vce: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_flags[RSP_VCE].s[0], m_flags[RSP_VCE].s[1], m_flags[RSP_VCE].s[2], m_flags[RSP_VCE].s[3], m_flags[RSP_VCE].s[4], m_flags[RSP_VCE].s[5], m_flags[RSP_VCE].s[6], m_flags[RSP_VCE].s[7]);
-#else
- printf("acc_h: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", ACCUM_H(0), ACCUM_H(1), ACCUM_H(2), ACCUM_H(3), ACCUM_H(4), ACCUM_H(5), ACCUM_H(6), ACCUM_H(7));
- printf("acc_m: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", ACCUM_M(0), ACCUM_M(1), ACCUM_M(2), ACCUM_M(3), ACCUM_M(4), ACCUM_M(5), ACCUM_M(6), ACCUM_M(7));
- printf("acc_l: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", ACCUM_L(0), ACCUM_L(1), ACCUM_L(2), ACCUM_L(3), ACCUM_L(4), ACCUM_L(5), ACCUM_L(6), ACCUM_L(7));
- printf("vcc_hi: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_vflag[4][0], m_vflag[4][1], m_vflag[4][2], m_vflag[4][3], m_vflag[4][4], m_vflag[4][5], m_vflag[4][6], m_vflag[4][7]);
- printf("vcc_lo: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_vflag[1][0], m_vflag[1][1], m_vflag[1][2], m_vflag[1][3], m_vflag[1][4], m_vflag[1][5], m_vflag[1][6], m_vflag[1][7]);
- printf("vco_hi: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_vflag[3][0], m_vflag[3][1], m_vflag[3][2], m_vflag[3][3], m_vflag[3][4], m_vflag[3][5], m_vflag[3][6], m_vflag[3][7]);
- printf("vco_lo: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_vflag[0][0], m_vflag[0][1], m_vflag[0][2], m_vflag[0][3], m_vflag[0][4], m_vflag[0][5], m_vflag[0][6], m_vflag[0][7]);
- printf("vce: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_vflag[2][0], m_vflag[2][1], m_vflag[2][2], m_vflag[2][3], m_vflag[2][4], m_vflag[2][5], m_vflag[2][6], m_vflag[2][7]);
-#endif
-}
-
-void rsp_device::cop2::dump_dmem()
-{
- uint8_t* dmem = m_rsp.get_dmem();
- printf("\n");
- for (int i = 0; i < 0x1000; i += 32)
- {
- printf("%04x: ", i);
- for (int j = 0; j < 32; j++)
- {
- printf("%02x ", dmem[i + j]);
- }
- printf("\n");
- }
- printf("\n");
-}
diff --git a/src/devices/cpu/rsp/rspcp2.h b/src/devices/cpu/rsp/rspcp2.h
deleted file mode 100644
index 7e374e71ae3..00000000000
--- a/src/devices/cpu/rsp/rspcp2.h
+++ /dev/null
@@ -1,395 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz,Tyler J. Stachecki
-/***************************************************************************
-
- rspcp2.h
-
- Interface file for Reality Signal Processor (RSP) vector extensions.
-
-***************************************************************************/
-#ifndef MAME_CPU_RSP_RSPCP2_H
-#define MAME_CPU_RSP_RSPCP2_H
-
-#pragma once
-
-#include "rsp.h"
-#include "rspdiv.h"
-#include "cpu/drcuml.h"
-
-#define SIMD_OFF (1)
-
-#if (defined(__SSE2__) || defined(__SSE3__) || defined(__SSSE3__) || defined(__SSE4_1__) || defined(__SSE4_2__))
-#define SSE_AVAILABLE (1)
-#else
-#define SSE_AVAILABLE (0)
-#endif
-
-#if (SSE_AVAILABLE || defined(_MSC_VER)) && defined(PTR64) && !SIMD_OFF
-#define USE_SIMD (1)
-#else
-#define USE_SIMD (0)
-#endif
-
-#if USE_SIMD
-
-#ifdef _MSC_VER
-#define __align16 __declspec(align(16))
-#else
-#define __align16 __attribute__((aligned(16)))
-#endif
-
-#if (defined(__SSE4_2__) || defined(_MSC_VER))
-#include <nmmintrin.h>
-#elif (defined(__SSE4_1__) || defined(_MSC_VER))
-#include <smmintrin.h>
-#elif (defined(__SSSE3__) || defined(_MSC_VER))
-#include <tmmintrin.h>
-#elif (defined(__SSE3__ ) || defined(_MSC_VER))
-#include <pmmintrin.h>
-#else
-#include <emmintrin.h>
-#endif
-
-typedef __m128i rsp_vec_t;
-#endif
-
-union VECTOR_REG
-{
- uint64_t d[2];
- uint32_t l[4];
- uint16_t s[8];
- uint8_t b[16];
-#if USE_SIMD
- rsp_vec_t v;
-#endif
-};
-
-union ACCUMULATOR_REG
-{
- uint64_t q;
- uint32_t l[2];
- uint16_t w[4];
-};
-
-struct compiler_state;
-
-class rsp_device::cop2
-{
- friend class rsp_device;
-
-public:
- cop2(rsp_device &rsp, running_machine &machine);
-
-protected:
- virtual void init();
- virtual void start();
-
- virtual bool generate_cop2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) { return true; }
- virtual bool generate_lwc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) { return true; }
- virtual bool generate_swc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) { return true; }
-
- virtual void state_string_export(const int index, std::string &str) const;
-
-public:
- virtual ~cop2();
-
- 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_t op);
-
- void log_instruction_execution();
- virtual void cfunc_unimplemented_opcode() { }
-
- void dump(uint32_t op);
- void dump_dmem();
-
-protected:
- virtual bool generate_vector_opcode(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) { return true; }
-
- uint16_t SATURATE_ACCUM(int accum, int slice, uint16_t negative, uint16_t positive);
-
- // Data that needs to be stored close to the generated DRC code
- struct internal_rspcop2_state
- {
- uint32_t op;
- };
-
- internal_rspcop2_state *m_rspcop2_state;
- rsp_device& m_rsp;
- running_machine& m_machine;
- uint32_t m_vres[8]; /* used for temporary vector results */
-
-#if USE_SIMD
- __align16 VECTOR_REG m_v[32];
-#else
- VECTOR_REG m_v[32];
-#endif
- ACCUMULATOR_REG m_accum[8];
- uint16_t m_vflag[6][8];
-
- int32_t m_reciprocal_res;
- uint32_t m_reciprocal_high;
- int32_t m_dp_allowed;
-
-#if USE_SIMD
- enum rsp_flags_t {
- RSP_VCO = 0,
- RSP_VCC = 1,
- RSP_VCE = 2
- };
-
- enum rsp_acc_t {
- RSP_ACC_LO = 16,
- RSP_ACC_MD = 8,
- RSP_ACC_HI = 0,
- };
-
- enum rsp_mem_request_type {
- RSP_MEM_REQUEST_NONE,
- RSP_MEM_REQUEST_INT_MEM,
- RSP_MEM_REQUEST_VECTOR,
- RSP_MEM_REQUEST_FOURTH,
- RSP_MEM_REQUEST_HALF,
- RSP_MEM_REQUEST_PACK,
- RSP_MEM_REQUEST_QUAD,
- RSP_MEM_REQUEST_REST,
- RSP_MEM_REQUEST_UPACK
- };
-
- union aligned_rsp_1vect_t {
- rsp_vec_t __align;
- uint16_t s[8];
- };
-
- union aligned_rsp_2vect_t {
- rsp_vec_t __align[2];
- uint16_t s[16];
- };
-
- union aligned_rsp_3vect_t {
- rsp_vec_t __align[3];
- uint16_t s[24];
- };
-
- __align16 aligned_rsp_1vect_t m_vdqm;
- __align16 aligned_rsp_2vect_t m_flags[3];
- __align16 aligned_rsp_3vect_t m_acc;
- uint32_t m_dp_flag;
-
- typedef struct
- {
- rsp_vec_t dummy_for_alignment;
- const uint16_t logic_mask[2][8];
- const uint16_t vrsq_mask_table[8][8];
- const uint16_t shuffle_keys[16][8];
- const uint16_t sll_b2l_keys[16][8];
- const uint16_t sll_l2b_keys[16][8];
- const uint16_t srl_b2l_keys[16][8];
- const uint16_t ror_b2l_keys[16][8];
- const uint16_t rol_l2b_keys[16][8];
- const uint16_t ror_l2b_keys[16][8];
- const uint16_t qr_lut[16][8];
- const uint16_t bdls_lut[4][4];
- const uint16_t word_reverse[8];
- } vec_helpers_t;
-
- static const vec_helpers_t m_vec_helpers;
-
- rsp_vec_t vec_load_and_shuffle_operand(const uint16_t* src, uint32_t element);
- static inline uint32_t sign_extend_6(int32_t i) {
- return ((i << (32 - 7)) >> (32 - 7)) & 0xfff;
- }
- static inline rsp_vec_t vec_load_unshuffled_operand(const void* src)
- {
- return _mm_load_si128((rsp_vec_t*) src);
- }
- static inline void vec_write_operand(uint16_t* dest, rsp_vec_t src)
- {
- _mm_store_si128((rsp_vec_t*) dest, src);
- }
- static inline rsp_vec_t read_acc_lo(const uint16_t* acc)
- {
- return vec_load_unshuffled_operand(acc + sizeof(rsp_vec_t));
- }
- static inline rsp_vec_t read_acc_mid(const uint16_t* acc)
- {
- return vec_load_unshuffled_operand(acc + (sizeof(rsp_vec_t) >> 1));
- }
- static inline rsp_vec_t read_acc_hi(const void* acc)
- {
- return vec_load_unshuffled_operand(acc);
- }
- static inline rsp_vec_t read_vcc_lo(const uint16_t *vcc)
- {
- return vec_load_unshuffled_operand(vcc + (sizeof(rsp_vec_t) >> 1));
- }
- static inline rsp_vec_t read_vcc_hi(const uint16_t *vcc)
- {
- return vec_load_unshuffled_operand(vcc);
- }
- static inline rsp_vec_t read_vco_lo(const uint16_t *vco)
- {
- return vec_load_unshuffled_operand(vco + (sizeof(rsp_vec_t) >> 1));
- }
- static inline rsp_vec_t read_vco_hi(const uint16_t *vco)
- {
- return vec_load_unshuffled_operand(vco);
- }
- static inline rsp_vec_t read_vce(const uint16_t *vce)
- {
- return vec_load_unshuffled_operand(vce + (sizeof(rsp_vec_t) >> 1));
- }
- static inline void write_acc_lo(uint16_t *acc, rsp_vec_t acc_lo)
- {
- return vec_write_operand(acc + sizeof(rsp_vec_t), acc_lo);
- }
- static inline void write_acc_mid(uint16_t *acc, rsp_vec_t acc_mid)
- {
- return vec_write_operand(acc + (sizeof(rsp_vec_t) >> 1), acc_mid);
- }
- static inline void write_acc_hi(uint16_t *acc, rsp_vec_t acc_hi)
- {
- return vec_write_operand(acc, acc_hi);
- }
- static inline void write_vcc_lo(uint16_t *vcc, rsp_vec_t vcc_lo)
- {
- return vec_write_operand(vcc + (sizeof(rsp_vec_t) >> 1), vcc_lo);
- }
- static inline void write_vcc_hi(uint16_t *vcc, rsp_vec_t vcc_hi)
- {
- return vec_write_operand(vcc, vcc_hi);
- }
- static inline void write_vco_lo(uint16_t *vcc, rsp_vec_t vco_lo)
- {
- return vec_write_operand(vcc + (sizeof(rsp_vec_t) >> 1), vco_lo);
- }
- static inline void write_vco_hi(uint16_t *vcc, rsp_vec_t vco_hi)
- {
- return vec_write_operand(vcc, vco_hi);
- }
- static inline void write_vce(uint16_t *vce, rsp_vec_t vce_r)
- {
- return vec_write_operand(vce + (sizeof(rsp_vec_t) >> 1), vce_r);
- }
-
- static inline int16_t get_flags(const uint16_t *flags)
- {
- return _mm_movemask_epi8(_mm_packs_epi16(_mm_load_si128((rsp_vec_t*) (flags + (sizeof(rsp_vec_t) >> 1))), _mm_load_si128((rsp_vec_t*) flags)));
- }
-
- static inline rsp_vec_t vec_zero()
- {
- return _mm_setzero_si128();
- }
-
- void vec_load_group1(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm);
- void vec_load_group2(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type);
- void vec_load_group4(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type);
- void vec_store_group1(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm);
- void vec_store_group2(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type);
- void vec_store_group4(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type);
-
-#include "clamp.h"
-#include "vabs.h"
-#include "vadd.h"
-#include "vaddc.h"
-#include "vand.h"
-#include "vch.h"
-#include "vcmp.h"
-#include "vcl.h"
-#include "vcr.h"
-#include "vdivh.h"
-#include "vmac.h"
-#include "vmov.h"
-#include "vmrg.h"
-#include "vmul.h"
-#include "vmulh.h"
-#include "vmull.h"
-#include "vmulm.h"
-#include "vmuln.h"
-#include "vor.h"
-#include "vrcpsq.h"
-#include "vrsq.h"
-#include "vsub.h"
-#include "vsubc.h"
-#include "vxor.h"
-#include "vldst.h"
-#endif
-
-private:
- void handle_lwc2(uint32_t op);
- void handle_swc2(uint32_t op);
- void handle_vector_ops(uint32_t op);
-
- uint32_t m_div_in;
- uint32_t m_div_out;
-};
-
-#endif // MAME_CPU_RSP_RSPCP2_H
diff --git a/src/devices/cpu/rsp/rspcp2d.cpp b/src/devices/cpu/rsp/rspcp2d.cpp
deleted file mode 100644
index a77ab072cab..00000000000
--- a/src/devices/cpu/rsp/rspcp2d.cpp
+++ /dev/null
@@ -1,3388 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-/***************************************************************************
-
- rspcp2d.c
-
- Universal machine language-based Nintendo/SGI RSP COP2 emulator.
- Written by Ryan Holtz
-
-***************************************************************************/
-
-#include "emu.h"
-#include "rspcp2d.h"
-
-#include "rsp_dasm.h"
-
-#include "cpu/drcfe.h"
-#include "cpu/drcuml.h"
-#include "cpu/drcumlsh.h"
-
-#include "rspdefs.h"
-
-
-/***************************************************************************
- 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_t)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
-
-#define ACCUM_H(x) (uint16_t)m_accum[x].w[3]
-#define ACCUM_M(x) (uint16_t)m_accum[x].w[2]
-#define ACCUM_L(x) (uint16_t)m_accum[x].w[1]
-#define ACCUM_LL(x) (uint16_t)m_accum[x].w[0]
-#define ACCUM(x) m_accum[x].q
-
-#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 SET_ACCUM(v, x) m_accum[x].q = 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 CACHE_VALUES() \
- const int op = m_rspcop2_state->op; \
- const int vdreg = VDREG; \
- const int vs1reg = VS1REG; \
- const int vs2reg = VS2REG; \
- const int el = EL;
-
-#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_device::cop2_drc::cfunc_unimplemented_opcode()
-{
- const uint32_t ppc = m_rsp.m_ppc;
- if ((m_machine.debug_flags & DEBUG_FLAG_ENABLED) != 0)
- {
- rsp_disassembler rspd;
- std::ostringstream stream;
- rspd.dasm_one(stream, ppc, m_rspcop2_state->op);
- const std::string stream_string = stream.str();
- osd_printf_debug("%08X: %s\n", ppc, stream_string);
- }
- fatalerror("RSP: unknown opcode %02X (%08X) at %08X\n", m_rspcop2_state->op >> 26, m_rspcop2_state->op, ppc);
-}
-
-void rsp_device::cop2_drc::state_string_export(const int index, std::string &str) const
-{
- switch (index)
- {
- case RSP_V0:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 0, 0), (uint16_t)VREG_S( 0, 1), (uint16_t)VREG_S( 0, 2), (uint16_t)VREG_S( 0, 3), (uint16_t)VREG_S( 0, 4), (uint16_t)VREG_S( 0, 5), (uint16_t)VREG_S( 0, 6), (uint16_t)VREG_S( 0, 7));
- break;
- case RSP_V1:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 1, 0), (uint16_t)VREG_S( 1, 1), (uint16_t)VREG_S( 1, 2), (uint16_t)VREG_S( 1, 3), (uint16_t)VREG_S( 1, 4), (uint16_t)VREG_S( 1, 5), (uint16_t)VREG_S( 1, 6), (uint16_t)VREG_S( 1, 7));
- break;
- case RSP_V2:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 2, 0), (uint16_t)VREG_S( 2, 1), (uint16_t)VREG_S( 2, 2), (uint16_t)VREG_S( 2, 3), (uint16_t)VREG_S( 2, 4), (uint16_t)VREG_S( 2, 5), (uint16_t)VREG_S( 2, 6), (uint16_t)VREG_S( 2, 7));
- break;
- case RSP_V3:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 3, 0), (uint16_t)VREG_S( 3, 1), (uint16_t)VREG_S( 3, 2), (uint16_t)VREG_S( 3, 3), (uint16_t)VREG_S( 3, 4), (uint16_t)VREG_S( 3, 5), (uint16_t)VREG_S( 3, 6), (uint16_t)VREG_S( 3, 7));
- break;
- case RSP_V4:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 4, 0), (uint16_t)VREG_S( 4, 1), (uint16_t)VREG_S( 4, 2), (uint16_t)VREG_S( 4, 3), (uint16_t)VREG_S( 4, 4), (uint16_t)VREG_S( 4, 5), (uint16_t)VREG_S( 4, 6), (uint16_t)VREG_S( 4, 7));
- break;
- case RSP_V5:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 5, 0), (uint16_t)VREG_S( 5, 1), (uint16_t)VREG_S( 5, 2), (uint16_t)VREG_S( 5, 3), (uint16_t)VREG_S( 5, 4), (uint16_t)VREG_S( 5, 5), (uint16_t)VREG_S( 5, 6), (uint16_t)VREG_S( 5, 7));
- break;
- case RSP_V6:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 6, 0), (uint16_t)VREG_S( 6, 1), (uint16_t)VREG_S( 6, 2), (uint16_t)VREG_S( 6, 3), (uint16_t)VREG_S( 6, 4), (uint16_t)VREG_S( 6, 5), (uint16_t)VREG_S( 6, 6), (uint16_t)VREG_S( 6, 7));
- break;
- case RSP_V7:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 7, 0), (uint16_t)VREG_S( 7, 1), (uint16_t)VREG_S( 7, 2), (uint16_t)VREG_S( 7, 3), (uint16_t)VREG_S( 7, 4), (uint16_t)VREG_S( 7, 5), (uint16_t)VREG_S( 7, 6), (uint16_t)VREG_S( 7, 7));
- break;
- case RSP_V8:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 8, 0), (uint16_t)VREG_S( 8, 1), (uint16_t)VREG_S( 8, 2), (uint16_t)VREG_S( 8, 3), (uint16_t)VREG_S( 8, 4), (uint16_t)VREG_S( 8, 5), (uint16_t)VREG_S( 8, 6), (uint16_t)VREG_S( 8, 7));
- break;
- case RSP_V9:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 9, 0), (uint16_t)VREG_S( 9, 1), (uint16_t)VREG_S( 9, 2), (uint16_t)VREG_S( 9, 3), (uint16_t)VREG_S( 9, 4), (uint16_t)VREG_S( 9, 5), (uint16_t)VREG_S( 9, 6), (uint16_t)VREG_S( 9, 7));
- break;
- case RSP_V10:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(10, 0), (uint16_t)VREG_S(10, 1), (uint16_t)VREG_S(10, 2), (uint16_t)VREG_S(10, 3), (uint16_t)VREG_S(10, 4), (uint16_t)VREG_S(10, 5), (uint16_t)VREG_S(10, 6), (uint16_t)VREG_S(10, 7));
- break;
- case RSP_V11:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(11, 0), (uint16_t)VREG_S(11, 1), (uint16_t)VREG_S(11, 2), (uint16_t)VREG_S(11, 3), (uint16_t)VREG_S(11, 4), (uint16_t)VREG_S(11, 5), (uint16_t)VREG_S(11, 6), (uint16_t)VREG_S(11, 7));
- break;
- case RSP_V12:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(12, 0), (uint16_t)VREG_S(12, 1), (uint16_t)VREG_S(12, 2), (uint16_t)VREG_S(12, 3), (uint16_t)VREG_S(12, 4), (uint16_t)VREG_S(12, 5), (uint16_t)VREG_S(12, 6), (uint16_t)VREG_S(12, 7));
- break;
- case RSP_V13:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(13, 0), (uint16_t)VREG_S(13, 1), (uint16_t)VREG_S(13, 2), (uint16_t)VREG_S(13, 3), (uint16_t)VREG_S(13, 4), (uint16_t)VREG_S(13, 5), (uint16_t)VREG_S(13, 6), (uint16_t)VREG_S(13, 7));
- break;
- case RSP_V14:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(14, 0), (uint16_t)VREG_S(14, 1), (uint16_t)VREG_S(14, 2), (uint16_t)VREG_S(14, 3), (uint16_t)VREG_S(14, 4), (uint16_t)VREG_S(14, 5), (uint16_t)VREG_S(14, 6), (uint16_t)VREG_S(14, 7));
- break;
- case RSP_V15:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(15, 0), (uint16_t)VREG_S(15, 1), (uint16_t)VREG_S(15, 2), (uint16_t)VREG_S(15, 3), (uint16_t)VREG_S(15, 4), (uint16_t)VREG_S(15, 5), (uint16_t)VREG_S(15, 6), (uint16_t)VREG_S(15, 7));
- break;
- case RSP_V16:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(16, 0), (uint16_t)VREG_S(16, 1), (uint16_t)VREG_S(16, 2), (uint16_t)VREG_S(16, 3), (uint16_t)VREG_S(16, 4), (uint16_t)VREG_S(16, 5), (uint16_t)VREG_S(16, 6), (uint16_t)VREG_S(16, 7));
- break;
- case RSP_V17:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(17, 0), (uint16_t)VREG_S(17, 1), (uint16_t)VREG_S(17, 2), (uint16_t)VREG_S(17, 3), (uint16_t)VREG_S(17, 4), (uint16_t)VREG_S(17, 5), (uint16_t)VREG_S(17, 6), (uint16_t)VREG_S(17, 7));
- break;
- case RSP_V18:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(18, 0), (uint16_t)VREG_S(18, 1), (uint16_t)VREG_S(18, 2), (uint16_t)VREG_S(18, 3), (uint16_t)VREG_S(18, 4), (uint16_t)VREG_S(18, 5), (uint16_t)VREG_S(18, 6), (uint16_t)VREG_S(18, 7));
- break;
- case RSP_V19:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(19, 0), (uint16_t)VREG_S(19, 1), (uint16_t)VREG_S(19, 2), (uint16_t)VREG_S(19, 3), (uint16_t)VREG_S(19, 4), (uint16_t)VREG_S(19, 5), (uint16_t)VREG_S(19, 6), (uint16_t)VREG_S(19, 7));
- break;
- case RSP_V20:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(20, 0), (uint16_t)VREG_S(20, 1), (uint16_t)VREG_S(20, 2), (uint16_t)VREG_S(20, 3), (uint16_t)VREG_S(20, 4), (uint16_t)VREG_S(20, 5), (uint16_t)VREG_S(20, 6), (uint16_t)VREG_S(20, 7));
- break;
- case RSP_V21:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(21, 0), (uint16_t)VREG_S(21, 1), (uint16_t)VREG_S(21, 2), (uint16_t)VREG_S(21, 3), (uint16_t)VREG_S(21, 4), (uint16_t)VREG_S(21, 5), (uint16_t)VREG_S(21, 6), (uint16_t)VREG_S(21, 7));
- break;
- case RSP_V22:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(22, 0), (uint16_t)VREG_S(22, 1), (uint16_t)VREG_S(22, 2), (uint16_t)VREG_S(22, 3), (uint16_t)VREG_S(22, 4), (uint16_t)VREG_S(22, 5), (uint16_t)VREG_S(22, 6), (uint16_t)VREG_S(22, 7));
- break;
- case RSP_V23:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(23, 0), (uint16_t)VREG_S(23, 1), (uint16_t)VREG_S(23, 2), (uint16_t)VREG_S(23, 3), (uint16_t)VREG_S(23, 4), (uint16_t)VREG_S(23, 5), (uint16_t)VREG_S(23, 6), (uint16_t)VREG_S(23, 7));
- break;
- case RSP_V24:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(24, 0), (uint16_t)VREG_S(24, 1), (uint16_t)VREG_S(24, 2), (uint16_t)VREG_S(24, 3), (uint16_t)VREG_S(24, 4), (uint16_t)VREG_S(24, 5), (uint16_t)VREG_S(24, 6), (uint16_t)VREG_S(24, 7));
- break;
- case RSP_V25:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(25, 0), (uint16_t)VREG_S(25, 1), (uint16_t)VREG_S(25, 2), (uint16_t)VREG_S(25, 3), (uint16_t)VREG_S(25, 4), (uint16_t)VREG_S(25, 5), (uint16_t)VREG_S(25, 6), (uint16_t)VREG_S(25, 7));
- break;
- case RSP_V26:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(26, 0), (uint16_t)VREG_S(26, 1), (uint16_t)VREG_S(26, 2), (uint16_t)VREG_S(26, 3), (uint16_t)VREG_S(26, 4), (uint16_t)VREG_S(26, 5), (uint16_t)VREG_S(26, 6), (uint16_t)VREG_S(26, 7));
- break;
- case RSP_V27:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(27, 0), (uint16_t)VREG_S(27, 1), (uint16_t)VREG_S(27, 2), (uint16_t)VREG_S(27, 3), (uint16_t)VREG_S(27, 4), (uint16_t)VREG_S(27, 5), (uint16_t)VREG_S(27, 6), (uint16_t)VREG_S(27, 7));
- break;
- case RSP_V28:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(28, 0), (uint16_t)VREG_S(28, 1), (uint16_t)VREG_S(28, 2), (uint16_t)VREG_S(28, 3), (uint16_t)VREG_S(28, 4), (uint16_t)VREG_S(28, 5), (uint16_t)VREG_S(28, 6), (uint16_t)VREG_S(28, 7));
- break;
- case RSP_V29:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(29, 0), (uint16_t)VREG_S(29, 1), (uint16_t)VREG_S(29, 2), (uint16_t)VREG_S(29, 3), (uint16_t)VREG_S(29, 4), (uint16_t)VREG_S(29, 5), (uint16_t)VREG_S(29, 6), (uint16_t)VREG_S(29, 7));
- break;
- case RSP_V30:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(30, 0), (uint16_t)VREG_S(30, 1), (uint16_t)VREG_S(30, 2), (uint16_t)VREG_S(30, 3), (uint16_t)VREG_S(30, 4), (uint16_t)VREG_S(30, 5), (uint16_t)VREG_S(30, 6), (uint16_t)VREG_S(30, 7));
- break;
- case RSP_V31:
- str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(31, 0), (uint16_t)VREG_S(31, 1), (uint16_t)VREG_S(31, 2), (uint16_t)VREG_S(31, 3), (uint16_t)VREG_S(31, 4), (uint16_t)VREG_S(31, 5), (uint16_t)VREG_S(31, 6), (uint16_t)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
-
-void rsp_device::cop2_drc::lbv()
-{
- uint32_t op = m_rspcop2_state->op;
-
- uint32_t 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;
- }
-
- ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset;
- VREG_B(dest, index) = m_rsp.DM_READ8(ea);
-}
-
-
-// LSV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00001 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads 2 bytes starting from vector byte index
-
-void rsp_device::cop2_drc::lsv()
-{
- uint32_t op = m_rspcop2_state->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_t 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++;
- }
-}
-
-
-// LLV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00010 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads 4 bytes starting from vector byte index
-
-void rsp_device::cop2_drc::llv()
-{
- uint32_t op = m_rspcop2_state->op;
- uint32_t 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;
- }
-
- 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++;
- }
-}
-
-
-// LDV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00011 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads 8 bytes starting from vector byte index
-
-void rsp_device::cop2_drc::ldv()
-{
- uint32_t op = m_rspcop2_state->op;
- uint32_t 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;
- }
-
- 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++;
- }
-}
-
-
-// LQV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 110010 | BBBBB | TTTTT | 00100 | IIII | Offset |
-// --------------------------------------------------
-//
-// Loads up to 16 bytes starting from vector byte index
-
-void rsp_device::cop2_drc::lqv()
-{
- uint32_t op = m_rspcop2_state->op;
- int dest = (op >> 16) & 0x1f;
- int base = (op >> 21) & 0x1f;
- int offset = (op & 0x7f);
- if (offset & 0x40)
- {
- offset |= 0xffffffc0;
- }
-
- uint32_t 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++;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::lrv()
-{
- uint32_t op = m_rspcop2_state->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_t 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++;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::lpv()
-{
- uint32_t op = m_rspcop2_state->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_t 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;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::luv()
-{
- uint32_t op = m_rspcop2_state->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_t 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;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::lhv()
-{
- uint32_t op = m_rspcop2_state->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_t 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;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::lfv()
-{
- uint32_t op = m_rspcop2_state->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_t 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;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::lwv()
-{
- uint32_t op = m_rspcop2_state->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_t 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;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::ltv()
-{
- uint32_t op = m_rspcop2_state->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;
-
- uint32_t 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;
- }
-}
-
-
-bool rsp_device::cop2_drc::generate_lwc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc)
-{
- uint32_t 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_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_lbv, this);
- return true;
-
- case 0x01: /* LSV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_lsv, this);
- return true;
-
- case 0x02: /* LLV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_llv, this);
- return true;
-
- case 0x03: /* LDV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_ldv, this);
- return true;
-
- case 0x04: /* LQV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_lqv, this);
- return true;
-
- case 0x05: /* LRV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_lrv, this);
- return true;
-
- case 0x06: /* LPV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_lpv, this);
- return true;
-
- case 0x07: /* LUV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_luv, this);
- return true;
-
- case 0x08: /* LHV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_lhv, this);
- return true;
-
- case 0x09: /* LFV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_lfv, this);
- return true;
-
- case 0x0a: /* LWV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_lwv, this);
- return true;
-
- case 0x0b: /* LTV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l
- UML_CALLC(block, &cop2_drc::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
-
-void rsp_device::cop2_drc::sbv()
-{
- uint32_t op = m_rspcop2_state->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_t ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset;
- m_rsp.DM_WRITE8(ea, VREG_B(dest, index));
-}
-
-
-// SSV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores 2 bytes starting from vector byte index
-
-void rsp_device::cop2_drc::ssv()
-{
- uint32_t op = m_rspcop2_state->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_t 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++;
- }
-}
-
-
-// SLV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores 4 bytes starting from vector byte index
-
-void rsp_device::cop2_drc::slv()
-{
- uint32_t op = m_rspcop2_state->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_t 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++;
- }
-}
-
-
-// SDV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores 8 bytes starting from vector byte index
-
-void rsp_device::cop2_drc::sdv()
-{
- uint32_t op = m_rspcop2_state->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_t 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++;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::sqv()
-{
- uint32_t op = m_rspcop2_state->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_t 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++;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::srv()
-{
- uint32_t op = m_rspcop2_state->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_t 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++;
- }
-}
-
-
-// SPV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores upper 8 bits of each element
-
-void rsp_device::cop2_drc::spv()
-{
- uint32_t op = m_rspcop2_state->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_t 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++;
- }
-}
-
-
-// SUV
-//
-// 31 25 20 15 10 6 0
-// --------------------------------------------------
-// | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset |
-// --------------------------------------------------
-//
-// Stores bits 14-7 of each element
-
-void rsp_device::cop2_drc::suv()
-{
- uint32_t op = m_rspcop2_state->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_t 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++;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::shv()
-{
- uint32_t op = m_rspcop2_state->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_t 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_t d = (VREG_B(dest, (element & 0xf)) << 1) |
- (VREG_B(dest, ((element + 1) & 0xf)) >> 7);
- m_rsp.DM_WRITE8(ea, d);
- ea += 2;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::sfv()
-{
- uint32_t op = m_rspcop2_state->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_t 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;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::swv()
-{
- uint32_t op = m_rspcop2_state->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_t 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++;
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::stv()
-{
- uint32_t op = m_rspcop2_state->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_t 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++;
- }
-}
-
-bool rsp_device::cop2_drc::generate_swc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc)
-{
- uint32_t 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_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_sbv, this);
- return true;
-
- case 0x01: /* SSV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_ssv, this);
- return true;
-
- case 0x02: /* SLV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_slv, this);
- return true;
-
- case 0x03: /* SDV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_sdv, this);
- return true;
-
- case 0x04: /* SQV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_sqv, this);
- return true;
-
- case 0x05: /* SRV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_srv, this);
- return true;
-
- case 0x06: /* SPV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_spv, this);
- return true;
-
- case 0x07: /* SUV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_suv, this);
- return true;
-
- case 0x08: /* SHV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_shv, this);
- return true;
-
- case 0x09: /* SFV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_sfv, this);
- return true;
-
- case 0x0a: /* SWV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_swv, this);
- return true;
-
- case 0x0b: /* STV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::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
-
-void rsp_device::cop2_drc::vmulf()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (int32_t)(int16_t)w1;
- int32_t s2 = (int32_t)(int16_t)w2;
-
- if (s1 == -32768 && s2 == -32768)
- {
- // overflow
- ACCUM(i) = s64(0x0000800080000000U);
- m_vres[i] = 0x7fff;
- }
- else
- {
- ACCUM(i) = (int64_t)(s1 * s2 * 2 + 0x8000) << 16; // rounding?
- m_vres[i] = ACCUM_M(i);
- }
- }
- WRITEBACK_RESULT();
-}
-
-
-// VMULU
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 |
-// ------------------------------------------------------
-//
-
-void rsp_device::cop2_drc::vmulu()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (int32_t)(int16_t)w1;
- int32_t s2 = (int32_t)(int16_t)w2;
-
- int64_t r = s1 * s2 * 2 + 0x8000; // rounding?
-
- ACCUM(i) = r << 16;
-
- if (r < 0)
- {
- m_vres[i] = 0;
- }
- else if (((int16_t)(ACCUM_H(i)) ^ (int16_t)(ACCUM_M(i))) < 0)
- {
- m_vres[i] = -1;
- }
- else
- {
- m_vres[i] = ACCUM_M(i);
- }
- }
- WRITEBACK_RESULT();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vmudl()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- uint32_t s1 = (uint32_t)(uint16_t)w1;
- uint32_t s2 = (uint32_t)(uint16_t)w2;
-
- ACCUM(i) = s1 * s2;
-
- m_vres[i] = ACCUM_L(i);
- }
- WRITEBACK_RESULT();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vmudm()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (int32_t)(int16_t)w1;
- int32_t s2 = (uint16_t)w2;
-
- ACCUM(i) = (int64_t)(s1 * s2) << 16;
-
- m_vres[i] = ACCUM_M(i);
- }
- WRITEBACK_RESULT();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vmudn()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (uint16_t)w1;
- int32_t s2 = (int32_t)(int16_t)w2;
-
- int32_t r = s1 * s2;
-
- ACCUM(i) = (int64_t)(s1 * s2) << 16;
-
- m_vres[i] = (uint16_t)(r);
- }
- WRITEBACK_RESULT();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vmudh()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (int32_t)(int16_t)w1;
- int32_t s2 = (int32_t)(int16_t)w2;
-
- int32_t r = s1 * s2;
-
- ACCUM(i) = (int64_t)r << 32;
-
- if (r < -32768) r = -32768;
- if (r > 32767) r = 32767;
- m_vres[i] = (int16_t)(r);
- }
- WRITEBACK_RESULT();
-}
-
-
-// VMACF
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001000 |
-// ------------------------------------------------------
-//
-
-void rsp_device::cop2_drc::vmacf()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (int32_t)(int16_t)w1;
- int32_t s2 = (int32_t)(int16_t)w2;
-
- ACCUM(i) += (int64_t)(s1 * s2 * 2) << 16;
-
- m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
-}
-
-
-// VMACU
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 |
-// ------------------------------------------------------
-//
-
-void rsp_device::cop2_drc::vmacu()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (int32_t)(int16_t)w1;
- int32_t s2 = (int32_t)(int16_t)w2;
-
- ACCUM(i) += (int64_t)(s1 * s2 * 2) << 16;
-
- if ((int16_t)ACCUM_H(i) < 0)
- {
- m_vres[i] = 0;
- }
- else
- {
- if (ACCUM_H(i) != 0)
- {
- m_vres[i] = (int16_t)0xffff;
- }
- else
- {
- if ((int16_t)ACCUM_M(i) < 0)
- {
- m_vres[i] = (int16_t)0xffff;
- }
- else
- {
- m_vres[i] = ACCUM_M(i);
- }
- }
- }
- }
- WRITEBACK_RESULT();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vmadl()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- uint32_t s1 = w1;
- uint32_t s2 = w2;
-
- ACCUM(i) += (s1 * s2) & 0xffff0000;
-
- m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
- }
- WRITEBACK_RESULT();
-}
-
-
-// VMADM
-//
-
-void rsp_device::cop2_drc::vmadm()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- uint32_t s1 = (int32_t)(int16_t)w1;
- uint32_t s2 = (uint16_t)w2;
-
- ACCUM(i) += (int64_t)(int32_t)(s1 * s2) << 16;
-
- m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
-}
-
-
-// VMADN
-//
-
-void rsp_device::cop2_drc::vmadn()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (uint16_t)w1;
- int32_t s2 = (int32_t)(int16_t)w2;
-
- ACCUM(i) += (int64_t)(s1 * s2) << 16;
-
- m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff);
- }
- WRITEBACK_RESULT();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vmadh()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (int32_t)(int16_t)w1;
- int32_t s2 = (int32_t)(int16_t)w2;
-
- ACCUM(i) += (int64_t)(s1 * s2) << 32;
-
- m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff);
- }
- WRITEBACK_RESULT();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vadd()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (int32_t)(int16_t)w1;
- int32_t s2 = (int32_t)(int16_t)w2;
- int32_t r = s1 + s2 + (((CARRY_FLAG(i)) != 0) ? 1 : 0);
-
- SET_ACCUM_L((int16_t)(r), i);
-
- if (r > 32767) r = 32767;
- if (r < -32768) r = -32768;
- m_vres[i] = (int16_t)(r);
- }
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vsub()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (int32_t)(int16_t)w1;
- int32_t s2 = (int32_t)(int16_t)w2;
- int32_t r = s1 - s2 - (((CARRY_FLAG(i)) != 0) ? 1 : 0);
-
- SET_ACCUM_L((int16_t)(r), i);
-
- if (r > 32767) r = 32767;
- if (r < -32768) r = -32768;
-
- m_vres[i] = (int16_t)(r);
- }
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
- WRITEBACK_RESULT();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vabs()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t 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();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vaddc()
-{
- CACHE_VALUES();
-
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (uint32_t)(uint16_t)w1;
- int32_t s2 = (uint32_t)(uint16_t)w2;
- int32_t r = s1 + s2;
-
- m_vres[i] = (int16_t)(r);
- SET_ACCUM_L((int16_t)r, i);
-
- if (r & 0xffff0000)
- {
- SET_CARRY_FLAG(i);
- }
- }
- WRITEBACK_RESULT();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vsubc()
-{
- CACHE_VALUES();
-
- CLEAR_ZERO_FLAGS();
- CLEAR_CARRY_FLAGS();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
- int32_t s1 = (uint32_t)(uint16_t)w1;
- int32_t s2 = (uint32_t)(uint16_t)w2;
- int32_t r = s1 - s2;
-
- m_vres[i] = (int16_t)(r);
- SET_ACCUM_L((uint16_t)r, i);
-
- if ((uint16_t)(r) != 0)
- {
- SET_ZERO_FLAG(i);
- }
- if (r & 0xffff0000)
- {
- SET_CARRY_FLAG(i);
- }
- }
- WRITEBACK_RESULT();
-}
-
-
-// VADDB
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010110 |
-// ------------------------------------------------------
-//
-// Adds two vector registers bytewise with rounding
-
-void rsp_device::cop2_drc::vaddb()
-{
- CACHE_VALUES();
- const int round = (el == 0) ? 0 : (1 << (el - 1));
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t w1, w2;
- GET_VS1(w1, i);
- GET_VS2(w2, i);
-
- uint8_t hb1 = w1 >> 8;
- uint8_t lb1 = w1 & 0xff;
- uint8_t hb2 = w2 >> 8;
- uint8_t lb2 = w2 & 0xff;
-
- uint16_t hs = hb1 + hb2 + round;
- uint16_t 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();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vsaw()
-{
- const int op = m_rspcop2_state->op;
- const int vdreg = VDREG;
- const int el = EL;
-
- 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;
- }
- }
- }
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vlt()
-{
- CACHE_VALUES();
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t 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();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::veq()
-{
- CACHE_VALUES();
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t 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();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vne()
-{
- CACHE_VALUES();
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t 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();
-}
-
-
-// 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
-
-void rsp_device::cop2_drc::vge()
-{
- CACHE_VALUES();
-
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t 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();
-}
-
-
-// VCL
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 |
-// ------------------------------------------------------
-//
-// Vector clip low
-
-void rsp_device::cop2_drc::vcl()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t 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_t)s2, i);
- }
- else
- {
- SET_ACCUM_L(s1, i);
- }
- }
- else
- {
- if (CLIP1_FLAG(i) != 0)
- {
- if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) > 0x10000)
- {
- SET_ACCUM_L(s1, i);
- CLEAR_COMPARE_FLAG(i);
- }
- else
- {
- SET_ACCUM_L(-((uint16_t)s2), i);
- SET_COMPARE_FLAG(i);
- }
- }
- else
- {
- if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) != 0)
- {
- SET_ACCUM_L(s1, i);
- CLEAR_COMPARE_FLAG(i);
- }
- else
- {
- SET_ACCUM_L(-((uint16_t)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_t)(uint16_t)s1 - (int32_t)(uint16_t)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();
-}
-
-
-// VCH
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 |
-// ------------------------------------------------------
-//
-// Vector clip high
-
-void rsp_device::cop2_drc::vch()
-{
- CACHE_VALUES();
-
- CLEAR_CARRY_FLAGS();
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP1_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- uint32_t vce;
- for (int i = 0; i < 8; i++)
- {
- int16_t 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_t)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();
-}
-
-
-// VCR
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 |
-// ------------------------------------------------------
-//
-// Vector clip reverse
-
-void rsp_device::cop2_drc::vcr()
-{
- CACHE_VALUES();
-
- CLEAR_CARRY_FLAGS();
- CLEAR_COMPARE_FLAGS();
- CLEAR_CLIP1_FLAGS();
- CLEAR_ZERO_FLAGS();
- CLEAR_CLIP2_FLAGS();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t s1, s2;
- GET_VS1(s1, i);
- GET_VS2(s2, i);
-
- if ((int16_t)(s1 ^ s2) < 0)
- {
- if (s2 < 0)
- {
- SET_CLIP2_FLAG(i);
- }
- if ((s1 + s2) <= 0)
- {
- SET_ACCUM_L(~((uint16_t)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();
-}
-
-
-// VMRG
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100111 |
-// ------------------------------------------------------
-//
-// Merges two vectors according to compare flags
-
-void rsp_device::cop2_drc::vmrg()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- int16_t 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();
-}
-
-
-// VAND
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 |
-// ------------------------------------------------------
-//
-// Bitwise AND of two vector registers
-
-void rsp_device::cop2_drc::vand()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t s1, s2;
- GET_VS1(s1, i);
- GET_VS2(s2, i);
- m_vres[i] = s1 & s2;
- SET_ACCUM_L(m_vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-
-// VNAND
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101001 |
-// ------------------------------------------------------
-//
-// Bitwise NOT AND of two vector registers
-
-void rsp_device::cop2_drc::vnand()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t s1, s2;
- GET_VS1(s1, i);
- GET_VS2(s2, i);
- m_vres[i] = ~((s1 & s2));
- SET_ACCUM_L(m_vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-
-// VOR
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101010 |
-// ------------------------------------------------------
-//
-// Bitwise OR of two vector registers
-
-void rsp_device::cop2_drc::vor()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t s1, s2;
- GET_VS1(s1, i);
- GET_VS2(s2, i);
- m_vres[i] = s1 | s2;
- SET_ACCUM_L(m_vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-
-// VNOR
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101011 |
-// ------------------------------------------------------
-//
-// Bitwise NOT OR of two vector registers
-
-void rsp_device::cop2_drc::vnor()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t s1, s2;
- GET_VS1(s1, i);
- GET_VS2(s2, i);
- m_vres[i] = ~(s1 | s2);
- SET_ACCUM_L(m_vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-
-// VXOR
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101100 |
-// ------------------------------------------------------
-//
-// Bitwise XOR of two vector registers
-
-void rsp_device::cop2_drc::vxor()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t s1, s2;
- GET_VS1(s1, i);
- GET_VS2(s2, i);
- m_vres[i] = s1 ^ s2;
- SET_ACCUM_L(m_vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-
-// VNXOR
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 |
-// ------------------------------------------------------
-//
-// Bitwise NOT XOR of two vector registers
-
-void rsp_device::cop2_drc::vnxor()
-{
- CACHE_VALUES();
-
- for (int i = 0; i < 8; i++)
- {
- uint16_t s1, s2;
- GET_VS1(s1, i);
- GET_VS2(s2, i);
- m_vres[i] = ~(s1 ^ s2);
- SET_ACCUM_L(m_vres[i], i);
- }
- WRITEBACK_RESULT();
-}
-
-
-// VRCP
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 |
-// ------------------------------------------------------
-//
-// Calculates reciprocal
-
-void rsp_device::cop2_drc::vrcp()
-{
- CACHE_VALUES();
-
- int32_t shifter = 0;
- int32_t rec = (int16_t)(VREG_S(vs2reg, el & 7));
- int32_t 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_t address = ((datainput << shifter) & 0x7fc00000) >> 22;
- int32_t fetchval = rsp_divtable[address];
- int32_t 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_t)rec;
- for (int i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(vs2reg, VEC_EL_2(el, i)), i);
- }
-}
-
-
-// VRCPL
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 |
-// ------------------------------------------------------
-//
-// Calculates reciprocal low part
-
-void rsp_device::cop2_drc::vrcpl()
-{
- CACHE_VALUES();
-
- int32_t shifter = 0;
- int32_t rec = (int16_t)VREG_S(vs2reg, el & 7);
- int32_t 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_t address = (datainput << shifter) >> 22;
- int32_t fetchval = rsp_divtable[address & 0x1ff];
- int32_t 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_t)rec;
-
- for (int i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(vs2reg, VEC_EL_2(el, i)), i);
- }
-}
-
-
-// VRCPH
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 |
-// ------------------------------------------------------
-//
-// Calculates reciprocal high part
-
-void rsp_device::cop2_drc::vrcph()
-{
- CACHE_VALUES();
-
- 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_t)(m_reciprocal_res >> 16);
-}
-
-
-// VMOV
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110011 |
-// ------------------------------------------------------
-//
-// Moves element from vector to destination vector
-
-void rsp_device::cop2_drc::vmov()
-{
- CACHE_VALUES();
-
- 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);
- }
-}
-
-
-// VRSQ
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 |
-// ------------------------------------------------------
-//
-// Calculates reciprocal square-root
-
-void rsp_device::cop2_drc::vrsq()
-{
- CACHE_VALUES();
-
- int32_t shifter = 0;
- int32_t rec = (int16_t)VREG_S(vs2reg, el & 7);
- int32_t 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_t address = ((datainput << shifter) & 0x7fc00000) >> 22;
- address = ((address | 0x200) & 0x3fe) | (shifter & 1);
-
- int32_t fetchval = rsp_divtable[address];
- int32_t 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_t)rec;
- for (int i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(vs2reg, VEC_EL_2(el, i)), i);
- }
-}
-
-
-// VRSQL
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 |
-// ------------------------------------------------------
-//
-// Calculates reciprocal square-root low part
-
-void rsp_device::cop2_drc::vrsql()
-{
- CACHE_VALUES();
-
- int32_t shifter = 0;
- int32_t rec = (int16_t)VREG_S(vs2reg, el & 7);
- int32_t 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_t address = ((datainput << shifter) & 0x7fc00000) >> 22;
- address = ((address | 0x200) & 0x3fe) | (shifter & 1);
-
- int32_t fetchval = rsp_divtable[address];
- int32_t 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_t)(rec & 0xffff);
- for (int i = 0; i < 8; i++)
- {
- SET_ACCUM_L(VREG_S(vs2reg, VEC_EL_2(el, i)), i);
- }
-}
-
-
-// VRSQH
-//
-// 31 25 24 20 15 10 5 0
-// ------------------------------------------------------
-// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110110 |
-// ------------------------------------------------------
-//
-// Calculates reciprocal square-root high part
-
-void rsp_device::cop2_drc::vrsqh()
-{
- CACHE_VALUES();
-
- 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_t)(m_reciprocal_res >> 16); // store high part
-}
-
-
-/*-------------------------------------------------
- generate_vector_opcode - generate code for a
- vector opcode
--------------------------------------------------*/
-
-bool rsp_device::cop2_drc::generate_vector_opcode(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc)
-{
- uint32_t 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_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmulf, this);
- return true;
-
- case 0x01: /* VMULU */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmulu, this);
- return true;
-
- case 0x04: /* VMUDL */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmudl, this);
- return true;
-
- case 0x05: /* VMUDM */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmudm, this);
- return true;
-
- case 0x06: /* VMUDN */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmudn, this);
- return true;
-
- case 0x07: /* VMUDH */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmudh, this);
- return true;
-
- case 0x08: /* VMACF */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmacf, this);
- return true;
-
- case 0x09: /* VMACU */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmacu, this);
- return true;
-
- case 0x0c: /* VMADL */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmadl, this);
- return true;
-
- case 0x0d: /* VMADM */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmadm, this);
- return true;
-
- case 0x0e: /* VMADN */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmadn, this);
- return true;
-
- case 0x0f: /* VMADH */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmadh, this);
- return true;
-
- case 0x10: /* VADD */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vadd, this);
- return true;
-
- case 0x11: /* VSUB */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vsub, this);
- return true;
-
- case 0x13: /* VABS */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vabs, this);
- return true;
-
- case 0x14: /* VADDC */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vaddc, this);
- return true;
-
- case 0x15: /* VSUBC */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vsubc, this);
- return true;
-
- case 0x16: /* VADDB */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vaddb, this);
- return true;
-
- case 0x17: /* VSUBB (reserved, functionally identical to VADDB) */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vaddb, this);
- return true;
-
- case 0x18: /* VACCB (reserved, functionally identical to VADDB) */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vaddb, this);
- return true;
-
- case 0x19: /* VSUCB (reserved, functionally identical to VADDB) */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vaddb, this);
- return true;
-
- case 0x1d: /* VSAW */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vsaw, this);
- return true;
-
- case 0x20: /* VLT */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vlt, this);
- return true;
-
- case 0x21: /* VEQ */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_veq, this);
- return true;
-
- case 0x22: /* VNE */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vne, this);
- return true;
-
- case 0x23: /* VGE */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vge, this);
- return true;
-
- case 0x24: /* VCL */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vcl, this);
- return true;
-
- case 0x25: /* VCH */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vch, this);
- return true;
-
- case 0x26: /* VCR */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vcr, this);
- return true;
-
- case 0x27: /* VMRG */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmrg, this);
- return true;
-
- case 0x28: /* VAND */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vand, this);
- return true;
-
- case 0x29: /* VNAND */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vnand, this);
- return true;
-
- case 0x2a: /* VOR */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vor, this);
- return true;
-
- case 0x2b: /* VNOR */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vnor, this);
- return true;
-
- case 0x2c: /* VXOR */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vxor, this);
- return true;
-
- case 0x2d: /* VNXOR */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vnxor, this);
- return true;
-
- case 0x30: /* VRCP */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vrcp, this);
- return true;
-
- case 0x31: /* VRCPL */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vrcpl, this);
- return true;
-
- case 0x32: /* VRCPH */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vrcph, this);
- return true;
-
- case 0x33: /* VMOV */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vmov, this);
- return true;
-
- case 0x34: /* VRSQ */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vrsq, this);
- return true;
-
- case 0x35: /* VRSQL */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vrsql, this);
- return true;
-
- case 0x36: /* VRSQH */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_vrsqh, this);
- return true;
-
- case 0x37: /* VNOP */
- case 0x3F: /* VNULL */
- return true;
-
- default:
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::unimplemented_opcode, &m_rsp);
- return false;
- }
-}
-
-
-/***************************************************************************
- Vector Flag Reading/Writing
-***************************************************************************/
-
-void rsp_device::cop2_drc::mfc2()
-{
- uint32_t op = m_rspcop2_state->op;
- int el = (op >> 7) & 0xf;
-
- uint16_t b1 = VREG_B(VS1REG, (el+0) & 0xf);
- uint16_t b2 = VREG_B(VS1REG, (el+1) & 0xf);
- if (RTREG) RTVAL = (int32_t)(int16_t)((b1 << 8) | (b2));
-}
-
-void rsp_device::cop2_drc::cfc2()
-{
- uint32_t op = m_rspcop2_state->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;
- }
- }
-}
-
-
-void rsp_device::cop2_drc::mtc2()
-{
- uint32_t op = m_rspcop2_state->op;
- int el = (op >> 7) & 0xf;
- VREG_B(VS1REG, (el+0) & 0xf) = (RTVAL >> 8) & 0xff;
- VREG_B(VS1REG, (el+1) & 0xf) = (RTVAL >> 0) & 0xff;
-}
-
-
-void rsp_device::cop2_drc::ctc2()
-{
- uint32_t op = m_rspcop2_state->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;
- }
-}
-
-/***************************************************************************
- COP2 Opcode Compilation
-***************************************************************************/
-
-bool rsp_device::cop2_drc::generate_cop2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc)
-{
- uint32_t op = desc->opptr.l[0];
- uint8_t opswitch = RSREG;
-
- switch (opswitch)
- {
- case 0x00: /* MFCz */
- if (RTREG != 0)
- {
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_mfc2, this); // callc mfc2
- }
- return true;
-
- case 0x02: /* CFCz */
- if (RTREG != 0)
- {
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_cfc2, this); // callc cfc2
- }
- return true;
-
- case 0x04: /* MTCz */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::cfunc_mtc2, this); // callc mtc2
- return true;
-
- case 0x06: /* CTCz */
- UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, &cop2_drc::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/devices/cpu/rsp/rspcp2d.h b/src/devices/cpu/rsp/rspcp2d.h
deleted file mode 100644
index 09263a39cdf..00000000000
--- a/src/devices/cpu/rsp/rspcp2d.h
+++ /dev/null
@@ -1,179 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-/***************************************************************************
-
- rspcp2d.h
-
- Interface file for Reality Signal Processor (RSP) vector extensions
- using Universal Machine Language (UML) dynamic recompilation.
-
-***************************************************************************/
-#ifndef MAME_CPU_RSP_RSPCP2D_H
-#define MAME_CPU_RSP_RSPCP2D_H
-
-#pragma once
-
-#include "rsp.h"
-#include "rspcp2.h"
-#include "cpu/drcuml.h"
-
-
-class rsp_device::cop2_drc : public rsp_device::cop2
-{
- friend class rsp_device;
-public:
- cop2_drc(rsp_device &rsp, running_machine &machine) : cop2(rsp, machine) { }
-private:
- virtual bool generate_cop2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) override;
- virtual bool generate_lwc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) override;
- virtual bool generate_swc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) override;
-
- virtual void state_string_export(const int index, std::string &str) const override;
-
- void cfunc_unimplemented_opcode() override;
-
- static void unimplemented_opcode(void *param) { ((cop2 *)param)->cfunc_unimplemented_opcode(); }
- static void cfunc_lbv(void *param) { ((cop2 *)param)->lbv(); }
- static void cfunc_lsv(void *param) { ((cop2 *)param)->lsv(); }
- static void cfunc_llv(void *param) { ((cop2 *)param)->llv(); }
- static void cfunc_ldv(void *param) { ((cop2 *)param)->ldv(); }
- static void cfunc_lqv(void *param) { ((cop2 *)param)->lqv(); }
- static void cfunc_lrv(void *param) { ((cop2 *)param)->lrv(); }
- static void cfunc_lpv(void *param) { ((cop2 *)param)->lpv(); }
- static void cfunc_luv(void *param) { ((cop2 *)param)->luv(); }
- static void cfunc_lhv(void *param) { ((cop2 *)param)->lhv(); }
- static void cfunc_lfv(void *param) { ((cop2 *)param)->lfv(); }
- static void cfunc_lwv(void *param) { ((cop2 *)param)->lwv(); }
- static void cfunc_ltv(void *param) { ((cop2 *)param)->ltv(); }
- static void cfunc_sbv(void *param) { ((cop2 *)param)->sbv(); }
- static void cfunc_ssv(void *param) { ((cop2 *)param)->ssv(); }
- static void cfunc_slv(void *param) { ((cop2 *)param)->slv(); }
- static void cfunc_sdv(void *param) { ((cop2 *)param)->sdv(); }
- static void cfunc_sqv(void *param) { ((cop2 *)param)->sqv(); }
- static void cfunc_srv(void *param) { ((cop2 *)param)->srv(); }
- static void cfunc_spv(void *param) { ((cop2 *)param)->spv(); }
- static void cfunc_suv(void *param) { ((cop2 *)param)->suv(); }
- static void cfunc_shv(void *param) { ((cop2 *)param)->shv(); }
- static void cfunc_sfv(void *param) { ((cop2 *)param)->sfv(); }
- static void cfunc_swv(void *param) { ((cop2 *)param)->swv(); }
- static void cfunc_stv(void *param) { ((cop2 *)param)->stv(); }
- static void cfunc_vmulf(void *param) { ((cop2 *)param)->vmulf(); }
- static void cfunc_vmulu(void *param) { ((cop2 *)param)->vmulu(); }
- static void cfunc_vmudl(void *param) { ((cop2 *)param)->vmudl(); }
- static void cfunc_vmudm(void *param) { ((cop2 *)param)->vmudm(); }
- static void cfunc_vmudn(void *param) { ((cop2 *)param)->vmudn(); }
- static void cfunc_vmudh(void *param) { ((cop2 *)param)->vmudh(); }
- static void cfunc_vmacf(void *param) { ((cop2 *)param)->vmacf(); }
- static void cfunc_vmacu(void *param) { ((cop2 *)param)->vmacu(); }
- static void cfunc_vmadl(void *param) { ((cop2 *)param)->vmadl(); }
- static void cfunc_vmadm(void *param) { ((cop2 *)param)->vmadm(); }
- static void cfunc_vmadn(void *param) { ((cop2 *)param)->vmadn(); }
- static void cfunc_vmadh(void *param) { ((cop2 *)param)->vmadh(); }
- static void cfunc_vadd(void *param) { ((cop2 *)param)->vadd(); }
- static void cfunc_vsub(void *param) { ((cop2 *)param)->vsub(); }
- static void cfunc_vabs(void *param) { ((cop2 *)param)->vabs(); }
- static void cfunc_vaddc(void *param) { ((cop2 *)param)->vaddc(); }
- static void cfunc_vsubc(void *param) { ((cop2 *)param)->vsubc(); }
- static void cfunc_vaddb(void *param) { ((cop2 *)param)->vaddb(); }
- static void cfunc_vsaw(void *param) { ((cop2 *)param)->vsaw(); }
- static void cfunc_vlt(void *param) { ((cop2 *)param)->vlt(); }
- static void cfunc_veq(void *param) { ((cop2 *)param)->veq(); }
- static void cfunc_vne(void *param) { ((cop2 *)param)->vne(); }
- static void cfunc_vge(void *param) { ((cop2 *)param)->vge(); }
- static void cfunc_vcl(void *param) { ((cop2 *)param)->vcl(); }
- static void cfunc_vch(void *param) { ((cop2 *)param)->vch(); }
- static void cfunc_vcr(void *param) { ((cop2 *)param)->vcr(); }
- static void cfunc_vmrg(void *param) { ((cop2 *)param)->vmrg(); }
- static void cfunc_vand(void *param) { ((cop2 *)param)->vand(); }
- static void cfunc_vnand(void *param) { ((cop2 *)param)->vnand(); }
- static void cfunc_vor(void *param) { ((cop2 *)param)->vor(); }
- static void cfunc_vnor(void *param) { ((cop2 *)param)->vnor(); }
- static void cfunc_vxor(void *param) { ((cop2 *)param)->vxor(); }
- static void cfunc_vnxor(void *param) { ((cop2 *)param)->vnxor(); }
- static void cfunc_vrcp(void *param) { ((cop2 *)param)->vrcp(); }
- static void cfunc_vrcpl(void *param) { ((cop2 *)param)->vrcpl(); }
- static void cfunc_vrcph(void *param) { ((cop2 *)param)->vrcph(); }
- static void cfunc_vmov(void *param) { ((cop2 *)param)->vmov(); }
- static void cfunc_vrsq(void *param) { ((cop2 *)param)->vrsq(); }
- static void cfunc_vrsql(void *param) { ((cop2 *)param)->vrsql(); }
- static void cfunc_vrsqh(void *param) { ((cop2 *)param)->vrsqh(); }
- static void cfunc_mfc2(void *param) { ((cop2 *)param)->mfc2(); }
- static void cfunc_cfc2(void *param) { ((cop2 *)param)->cfc2(); }
- static void cfunc_mtc2(void *param) { ((cop2 *)param)->mtc2(); }
- static void cfunc_ctc2(void *param) { ((cop2 *)param)->ctc2(); }
-
-public:
- virtual void lbv() override;
- virtual void lsv() override;
- virtual void llv() override;
- virtual void ldv() override;
- virtual void lqv() override;
- virtual void lrv() override;
- virtual void lpv() override;
- virtual void luv() override;
- virtual void lhv() override;
- virtual void lfv() override;
- virtual void lwv() override;
- virtual void ltv() override;
- virtual void sbv() override;
- virtual void ssv() override;
- virtual void slv() override;
- virtual void sdv() override;
- virtual void sqv() override;
- virtual void srv() override;
- virtual void spv() override;
- virtual void suv() override;
- virtual void shv() override;
- virtual void sfv() override;
- virtual void swv() override;
- virtual void stv() override;
- virtual void vmulf() override;
- virtual void vmulu() override;
- virtual void vmudl() override;
- virtual void vmudm() override;
- virtual void vmudn() override;
- virtual void vmudh() override;
- virtual void vmacf() override;
- virtual void vmacu() override;
- virtual void vmadl() override;
- virtual void vmadm() override;
- virtual void vmadn() override;
- virtual void vmadh() override;
- virtual void vadd() override;
- virtual void vsub() override;
- virtual void vabs() override;
- virtual void vaddc() override;
- virtual void vsubc() override;
- virtual void vaddb() override;
- virtual void vsaw() override;
- virtual void vlt() override;
- virtual void veq() override;
- virtual void vne() override;
- virtual void vge() override;
- virtual void vcl() override;
- virtual void vch() override;
- virtual void vcr() override;
- virtual void vmrg() override;
- virtual void vand() override;
- virtual void vnand() override;
- virtual void vor() override;
- virtual void vnor() override;
- virtual void vxor() override;
- virtual void vnxor() override;
- virtual void vrcp() override;
- virtual void vrcpl() override;
- virtual void vrcph() override;
- virtual void vmov() override;
- virtual void vrsql() override;
- virtual void vrsqh() override;
- virtual void vrsq() override;
- virtual void mfc2() override;
- virtual void cfc2() override;
- virtual void mtc2() override;
- virtual void ctc2() override;
-
-private:
- virtual bool generate_vector_opcode(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) override;
-};
-
-#endif // MAME_CPU_RSP_RSPCP2D_H
diff --git a/src/devices/cpu/rsp/rspdrc.cpp b/src/devices/cpu/rsp/rspdrc.cpp
deleted file mode 100644
index d2e89b4a77a..00000000000
--- a/src/devices/cpu/rsp/rspdrc.cpp
+++ /dev/null
@@ -1,1279 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-/***************************************************************************
-
- rspdrc.c
-
- Universal machine language-based Nintendo/SGI RSP emulator.
- Written by Ryan Holtz
- SIMD versions of vector multiplication opcodes provided by Marathon Man
- of the CEN64 team.
-
-****************************************************************************
-
- Future improvements/changes:
-
- * Confer with Aaron Giles about adding a memory hash-based caching
- system and static recompilation for maximum overhead minimization
-
-***************************************************************************/
-
-#include "emu.h"
-#include "rsp.h"
-#include "rsp_dasm.h"
-
-#include "rspfe.h"
-#include "rspcp2.h"
-#include "cpu/drcfe.h"
-#include "cpu/drcuml.h"
-#include "cpu/drcumlsh.h"
-
-#include "debugger.h"
-
-#include "rspdefs.h"
-
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-/* map variables */
-#define MAPVAR_PC M0
-#define MAPVAR_CYCLES M1
-
-/* exit codes */
-#define EXECUTE_OUT_OF_CYCLES 0
-#define EXECUTE_MISSING_CODE 1
-#define EXECUTE_UNMAPPED_CODE 2
-#define EXECUTE_RESET_CACHE 3
-
-
-
-/***************************************************************************
- Macros
-***************************************************************************/
-
-#define R32(reg) m_regmap[reg]
-
-/***************************************************************************
- Inline Functions
-***************************************************************************/
-
-/*-------------------------------------------------
- epc - compute the exception PC from a
- descriptor
--------------------------------------------------*/
-
-static inline uint32_t epc(const opcode_desc *desc)
-{
- return ((desc->flags & OPFLAG_IN_DELAY_SLOT) ? (desc->pc - 3) : desc->pc) | 0x1000;
-}
-
-
-/*-------------------------------------------------
- alloc_handle - allocate a handle if not
- already allocated
--------------------------------------------------*/
-
-static inline void alloc_handle(drcuml_state &drcuml, uml::code_handle *&handleptr, const char *name)
-{
- if (!handleptr)
- handleptr = drcuml.handle_alloc(name);
-}
-
-
-/*-------------------------------------------------
- load_fast_iregs - load any fast integer
- registers
--------------------------------------------------*/
-
-inline void rsp_device::load_fast_iregs(drcuml_block &block)
-{
- int regnum;
-
- for (regnum = 0; regnum < std::size(m_regmap); regnum++)
- if (m_regmap[regnum].is_int_register())
- UML_MOV(block, ireg(m_regmap[regnum].ireg() - REG_I0), mem(&m_rsp_state->r[regnum]));
-}
-
-
-/*-------------------------------------------------
- save_fast_iregs - save any fast integer
- registers
--------------------------------------------------*/
-
-inline void rsp_device::save_fast_iregs(drcuml_block &block)
-{
- int regnum;
-
- for (regnum = 0; regnum < std::size(m_regmap); regnum++)
- if (m_regmap[regnum].is_int_register())
- UML_MOV(block, mem(&m_rsp_state->r[regnum]), ireg(m_regmap[regnum].ireg() - REG_I0));
-}
-
-/***************************************************************************
- CORE CALLBACKS
-***************************************************************************/
-
-inline void rsp_device::ccfunc_read8()
-{
- m_rsp_state->arg0 = DM_READ8(m_rsp_state->arg0);
-}
-
-static void cfunc_read8(void *param)
-{
- ((rsp_device *)param)->ccfunc_read8();
-}
-
-inline void rsp_device::ccfunc_read16()
-{
- m_rsp_state->arg0 = DM_READ16(m_rsp_state->arg0);
-}
-
-static void cfunc_read16(void *param)
-{
- ((rsp_device *)param)->ccfunc_read16();
-}
-
-inline void rsp_device::ccfunc_read32()
-{
- m_rsp_state->arg0 = DM_READ32(m_rsp_state->arg0);
-}
-
-static void cfunc_read32(void *param)
-{
- ((rsp_device *)param)->ccfunc_read32();
-}
-
-inline void rsp_device::ccfunc_write8()
-{
- DM_WRITE8(m_rsp_state->arg0, m_rsp_state->arg1);
-}
-
-static void cfunc_write8(void *param)
-{
- ((rsp_device *)param)->ccfunc_write8();
-}
-
-inline void rsp_device::ccfunc_write16()
-{
- DM_WRITE16(m_rsp_state->arg0, m_rsp_state->arg1);
-}
-
-static void cfunc_write16(void *param)
-{
- ((rsp_device *)param)->ccfunc_write16();
-}
-
-inline void rsp_device::ccfunc_write32()
-{
- DM_WRITE32(m_rsp_state->arg0, m_rsp_state->arg1);
-}
-
-static void cfunc_write32(void *param)
-{
- ((rsp_device *)param)->ccfunc_write32();
-}
-
-/*****************************************************************************/
-
-/*-------------------------------------------------
- rspdrc_set_options - configure DRC options
--------------------------------------------------*/
-
-void rsp_device::rspdrc_set_options(uint32_t options)
-{
- if (!allow_drc()) return;
- m_drcoptions = options;
-}
-
-
-inline void rsp_device::ccfunc_get_cop0_reg()
-{
- int reg = m_rsp_state->arg0;
- int dest = m_rsp_state->arg1;
-
- if (reg >= 0 && reg < 8)
- {
- if(dest)
- {
- m_rsp_state->r[dest] = m_sp_reg_r_func(reg, 0xffffffff);
- }
- }
- else if (reg >= 8 && reg < 16)
- {
- if(dest)
- {
- m_rsp_state->r[dest] = m_dp_reg_r_func(reg - 8, 0xffffffff);
- }
- }
- else
- {
- fatalerror("RSP: cfunc_get_cop0_reg: %d\n", reg);
- }
-}
-
-static void cfunc_get_cop0_reg(void *param)
-{
- ((rsp_device *)param)->ccfunc_get_cop0_reg();
-}
-
-inline void rsp_device::ccfunc_set_cop0_reg()
-{
- int reg = m_rsp_state->arg0;
- uint32_t data = m_rsp_state->arg1;
-
- if (reg >= 0 && reg < 8)
- {
- m_sp_reg_w_func(reg, data, 0xffffffff);
- }
- else if (reg >= 8 && reg < 16)
- {
- m_dp_reg_w_func(reg - 8, data, 0xffffffff);
- }
- else
- {
- fatalerror("RSP: set_cop0_reg: %d, %08X\n", reg, data);
- }
-}
-
-static void cfunc_set_cop0_reg(void *param)
-{
- ((rsp_device *)param)->ccfunc_set_cop0_reg();
-}
-
-/*****************************************************************************/
-
-void rsp_device::rspcom_init()
-{
-}
-
-inline void rsp_device::ccfunc_sp_set_status_cb()
-{
- m_sp_set_status_func(0, m_rsp_state->arg0, 0xffffffff);
-}
-
-void cfunc_sp_set_status_cb(void *param)
-{
- ((rsp_device *)param)->ccfunc_sp_set_status_cb();
-}
-
-void rsp_device::execute_run_drc()
-{
- int execute_result;
-
- /* reset the cache if dirty */
- if (m_cache_dirty)
- code_flush_cache();
- m_cache_dirty = false;
-
- /* execute */
- do
- {
- if( m_sr & ( RSP_STATUS_HALT | RSP_STATUS_BROKE ) )
- {
- m_rsp_state->icount = std::min(m_rsp_state->icount, 0);
- break;
- }
-
- /* run as much as we can */
- execute_result = m_drcuml->execute(*m_entry);
-
- /* if we need to recompile, do it */
- if (execute_result == EXECUTE_MISSING_CODE)
- {
- code_compile_block(m_rsp_state->pc);
- }
- else if (execute_result == EXECUTE_UNMAPPED_CODE)
- {
- fatalerror("Attempted to execute unmapped code at PC=%08X\n", m_rsp_state->pc);
- }
- else if (execute_result == EXECUTE_RESET_CACHE)
- {
- code_flush_cache();
- }
- } while (execute_result != EXECUTE_OUT_OF_CYCLES);
-}
-
-/***************************************************************************
- CACHE MANAGEMENT
-***************************************************************************/
-
-/*-------------------------------------------------
- rspdrc_flush_drc_cache - outward-facing
- accessor to code_flush_cache
--------------------------------------------------*/
-
-void rsp_device::rspdrc_flush_drc_cache()
-{
- if (!allow_drc()) return;
- m_cache_dirty = true;
-}
-
-/*-------------------------------------------------
- code_flush_cache - flush the cache and
- regenerate static code
--------------------------------------------------*/
-
-void rsp_device::code_flush_cache()
-{
- /* empty the transient cache contents */
- m_drcuml->reset();
-
- try
- {
- /* generate the entry point and out-of-cycles handlers */
- static_generate_entry_point();
- static_generate_nocode_handler();
- static_generate_out_of_cycles();
-
- /* add subroutines for memory accesses */
- static_generate_memory_accessor(1, false, "read8", m_read8);
- static_generate_memory_accessor(1, true, "write8", m_write8);
- static_generate_memory_accessor(2, false, "read16", m_read16);
- static_generate_memory_accessor(2, true, "write16", m_write16);
- static_generate_memory_accessor(4, false, "read32", m_read32);
- static_generate_memory_accessor(4, true, "write32", m_write32);
- }
- catch (drcuml_block::abort_compilation &)
- {
- fatalerror("Unable to generate static RSP code\n");
- }
-}
-
-
-/*-------------------------------------------------
- code_compile_block - compile a block of the
- given mode at the specified pc
--------------------------------------------------*/
-
-void rsp_device::code_compile_block(offs_t pc)
-{
- compiler_state compiler = { 0 };
- const opcode_desc *seqhead, *seqlast;
- const opcode_desc *desclist;
- int override = false;
-
- g_profiler.start(PROFILER_DRC_COMPILE);
-
- /* get a description of this sequence */
- desclist = m_drcfe->describe_code(pc);
-
- bool succeeded = false;
- while (!succeeded)
- {
- try
- {
- /* start the block */
- drcuml_block &block(m_drcuml->begin_block(4096));
-
- /* loop until we get through all instruction sequences */
- for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next())
- {
- const opcode_desc *curdesc;
- uint32_t nextpc;
-
- /* add a code log entry */
- if (m_drcuml->logging())
- block.append_comment("-------------------------"); // comment
-
- /* determine the last instruction in this sequence */
- for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next())
- if (seqlast->flags & OPFLAG_END_SEQUENCE)
- break;
- assert(seqlast != nullptr);
-
- /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
- if (override || !m_drcuml->hash_exists(0, seqhead->pc))
- UML_HASH(block, 0, seqhead->pc); // hash mode,pc
-
- /* if we already have a hash, and this is the first sequence, assume that we */
- /* are recompiling due to being out of sync and allow future overrides */
- else if (seqhead == desclist)
- {
- override = true;
- UML_HASH(block, 0, seqhead->pc); // hash mode,pc
- }
-
- /* otherwise, redispatch to that fixed PC and skip the rest of the processing */
- else
- {
- UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc
- UML_HASHJMP(block, 0, seqhead->pc, *m_nocode);
- // hashjmp <0>,seqhead->pc,nocode
- continue;
- }
-
- /* validate this code block if we're not pointing into ROM */
- if (m_program.space().get_write_ptr(seqhead->physpc) != nullptr)
- generate_checksum_block(block, compiler, seqhead, seqlast);
-
- /* label this instruction, if it may be jumped to locally */
- if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET)
- UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc
-
- /* iterate over instructions in the sequence and compile them */
- for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
- generate_sequence_instruction(block, compiler, curdesc);
-
- /* if we need to return to the start, do it */
- if (seqlast->flags & OPFLAG_RETURN_TO_START)
- nextpc = pc;
-
- /* otherwise we just go to the next instruction */
- else
- nextpc = seqlast->pc + (seqlast->skipslots + 1) * 4;
-
- /* count off cycles and go there */
- generate_update_cycles(block, compiler, nextpc, true); // <subtract cycles>
-
- /* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */
- if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc)
- UML_HASHJMP(block, 0, nextpc, *m_nocode); // hashjmp <mode>,nextpc,nocode
- }
-
- /* end the sequence */
- block.end();
- g_profiler.stop();
- succeeded = true;
- }
- catch (drcuml_block::abort_compilation &)
- {
- code_flush_cache();
- }
- }
-}
-
-/***************************************************************************
- C FUNCTION CALLBACKS
-***************************************************************************/
-
-/*-------------------------------------------------
- cfunc_unimplemented - handler for
- unimplemented opcdes
--------------------------------------------------*/
-
-inline void rsp_device::ccfunc_unimplemented()
-{
- uint32_t opcode = m_rsp_state->arg0;
- fatalerror("PC=%08X: Unimplemented op %08X (%02X,%02X)\n", m_rsp_state->pc, opcode, opcode >> 26, opcode & 0x3f);
-}
-
-static void cfunc_unimplemented(void *param)
-{
- ((rsp_device *)param)->ccfunc_unimplemented();
-}
-
-/*-------------------------------------------------
- cfunc_fatalerror - a generic fatalerror call
--------------------------------------------------*/
-
-#ifdef UNUSED_CODE
-static void cfunc_fatalerror(void *param)
-{
- fatalerror("fatalerror\n");
-}
-#endif
-
-
-/***************************************************************************
- STATIC CODEGEN
-***************************************************************************/
-
-/*-------------------------------------------------
- ferate_entry_point - generate a
- static entry point
--------------------------------------------------*/
-
-void rsp_device::static_generate_entry_point()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(20));
-
- /* forward references */
- alloc_handle(*m_drcuml, m_nocode, "nocode");
-
- alloc_handle(*m_drcuml, m_entry, "entry");
- UML_HANDLE(block, *m_entry); // handle entry
-
- /* load fast integer registers */
- load_fast_iregs(block);
-
- /* generate a hash jump via the current mode and PC */
- UML_HASHJMP(block, 0, mem(&m_rsp_state->pc), *m_nocode); // hashjmp <mode>,<pc>,nocode
- block.end();
-}
-
-
-/*-------------------------------------------------
- static_generate_nocode_handler - generate an
- exception handler for "out of code"
--------------------------------------------------*/
-
-void rsp_device::static_generate_nocode_handler()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(10));
-
- /* generate a hash jump via the current mode and PC */
- alloc_handle(*m_drcuml, m_nocode, "nocode");
- UML_HANDLE(block, *m_nocode); // handle nocode
- UML_GETEXP(block, I0); // getexp i0
- UML_MOV(block, mem(&m_rsp_state->pc), I0); // mov [pc],i0
- save_fast_iregs(block);
- UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE
-
- block.end();
-}
-
-
-/*-------------------------------------------------
- static_generate_out_of_cycles - generate an
- out of cycles exception handler
--------------------------------------------------*/
-
-void rsp_device::static_generate_out_of_cycles()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(10));
-
- /* generate a hash jump via the current mode and PC */
- alloc_handle(*m_drcuml, m_out_of_cycles, "out_of_cycles");
- UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles
- UML_GETEXP(block, I0); // getexp i0
- UML_MOV(block, mem(&m_rsp_state->pc), I0); // mov <pc>,i0
- save_fast_iregs(block);
- UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES
-
- block.end();
-}
-
-/*------------------------------------------------------------------
- static_generate_memory_accessor
-------------------------------------------------------------------*/
-
-void rsp_device::static_generate_memory_accessor(int size, int iswrite, const char *name, uml::code_handle *&handleptr)
-{
- /* on entry, address is in I0; data for writes is in I1 */
- /* on exit, read result is in I0 */
- /* routine trashes I0-I1 */
-
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(1024));
-
- /* add a global entry for this */
- alloc_handle(*m_drcuml, handleptr, name);
- UML_HANDLE(block, *handleptr); // handle *handleptr
-
- // write:
- if (iswrite)
- {
- if (size == 1)
- {
- UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address
- UML_MOV(block, mem(&m_rsp_state->arg1), I1); // mov [arg1],i1 ; data
- UML_CALLC(block, cfunc_write8, this); // callc cfunc_write8
- }
- else if (size == 2)
- {
- UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address
- UML_MOV(block, mem(&m_rsp_state->arg1), I1); // mov [arg1],i1 ; data
- UML_CALLC(block, cfunc_write16, this); // callc cfunc_write16
- }
- else if (size == 4)
- {
- UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address
- UML_MOV(block, mem(&m_rsp_state->arg1), I1); // mov [arg1],i1 ; data
- UML_CALLC(block, cfunc_write32, this); // callc cfunc_write32
- }
- }
- else
- {
- if (size == 1)
- {
- UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address
- 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)
- {
- UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address
- UML_CALLC(block, cfunc_read16, this); // callc cfunc_read16
- UML_MOV(block, I0, mem(&m_rsp_state->arg0)); // mov i0,[arg0],i0 ; result
- }
- else if (size == 4)
- {
- UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address
- UML_CALLC(block, cfunc_read32, this); // callc cfunc_read32
- UML_MOV(block, I0, mem(&m_rsp_state->arg0)); // mov i0,[arg0],i0 ; result
- }
- }
- UML_RET(block);
-
- block.end();
-}
-
-
-
-/***************************************************************************
- CODE GENERATION
-***************************************************************************/
-
-/*-------------------------------------------------
- generate_update_cycles - generate code to
- subtract cycles from the icount and generate
- an exception if out
--------------------------------------------------*/
-void rsp_device::generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception)
-{
- /* account for cycles */
- if (compiler.cycles > 0)
- {
- UML_SUB(block, mem(&m_rsp_state->icount), mem(&m_rsp_state->icount), MAPVAR_CYCLES); // sub icount,icount,cycles
- UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0
- UML_EXHc(block, COND_S, *m_out_of_cycles, param);
- }
- compiler.cycles = 0;
-}
-
-/*-------------------------------------------------
- generate_checksum_block - generate code to
- validate a sequence of opcodes
--------------------------------------------------*/
-
-void rsp_device::generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast)
-{
- const opcode_desc *curdesc;
- if (m_drcuml->logging())
- {
- block.append_comment("[Validation for %08X]", seqhead->pc | 0x1000); // comment
- }
- /* loose verify or single instruction: just compare and fail */
- if (!(m_drcoptions & RSPDRC_STRICT_VERIFY) || seqhead->next() == nullptr)
- {
- if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
- {
- uint32_t sum = seqhead->opptr.l[0];
- void *base = m_pcache.read_ptr(seqhead->physpc | 0x1000);
- UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword
-
- if (seqhead->delay.first() != nullptr && seqhead->physpc != seqhead->delay.first()->physpc)
- {
- base = m_pcache.read_ptr((seqhead->delay.first()->physpc & 0x00000fff) | 0x1000);
- assert(base != nullptr);
- UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword
- UML_ADD(block, I0, I0, I1); // add i0,i0,i1
-
- sum += seqhead->delay.first()->opptr.l[0];
- }
-
- UML_CMP(block, I0, sum); // cmp i0,opptr[0]
- UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc
- }
- }
-
- /* full verification; sum up everything */
- else
- {
- uint32_t sum = 0;
- void *base = m_pcache.read_ptr(seqhead->physpc | 0x1000);
- UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword
- sum += seqhead->opptr.l[0];
- for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
- if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
- {
- base = m_pcache.read_ptr(curdesc->physpc | 0x1000);
- assert(base != nullptr);
- UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword
- UML_ADD(block, I0, I0, I1); // add i0,i0,i1
- sum += curdesc->opptr.l[0];
-
- if (curdesc->delay.first() != nullptr && (curdesc == seqlast || (curdesc->next() != nullptr && curdesc->next()->physpc != curdesc->delay.first()->physpc)))
- {
- base = m_pcache.read_ptr((curdesc->delay.first()->physpc & 0x00000fff) | 0x1000);
- assert(base != nullptr);
- UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword
- UML_ADD(block, I0, I0, I1); // add i0,i0,i1
-
- sum += curdesc->delay.first()->opptr.l[0];
- }
- }
- UML_CMP(block, I0, sum); // cmp i0,sum
- UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc
- }
-}
-
-
-/*-------------------------------------------------
- generate_sequence_instruction - generate code
- for a single instruction in a sequence
--------------------------------------------------*/
-
-void rsp_device::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
-{
- offs_t expc;
-
- /* add an entry for the log */
- if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
- log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]);
-
- /* set the PC map variable */
- expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 3 : desc->pc;
- UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc
-
- /* accumulate total cycles */
- compiler.cycles += desc->cycles;
-
- /* update the icount map variable */
- UML_MAPVAR(block, MAPVAR_CYCLES, compiler.cycles); // mapvar CYCLES,compiler.cycles
-
- /* if we are debugging, call the debugger */
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
- {
- UML_MOV(block, mem(&m_rsp_state->pc), desc->pc); // mov [pc],desc->pc
- save_fast_iregs(block);
- UML_DEBUG(block, desc->pc); // debug desc->pc
- }
-
- /* if we hit an unmapped address, fatal error */
-#if 0
- if (desc->flags & OPFLAG_COMPILER_UNMAPPED)
- {
- UML_MOV(block, mem(&m_rsp_state->pc), desc->pc); // mov [pc],desc->pc
- save_fast_iregs(block);
- UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE
- }
-#endif
-
- /* otherwise, unless this is a virtual no-op, it's a regular instruction */
- /*else*/ if (!(desc->flags & OPFLAG_VIRTUAL_NOOP))
- {
- /* compile the instruction */
- if (!generate_opcode(block, compiler, desc))
- {
- UML_MOV(block, mem(&m_rsp_state->pc), desc->pc); // mov [pc],desc->pc
- UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l
- UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented
- }
- }
-}
-
-/*------------------------------------------------------------------
- generate_branch
-------------------------------------------------------------------*/
-
-void rsp_device::generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
-{
- compiler_state compiler_temp(compiler);
-
- /* update the cycles and jump through the hash table to the target */
- if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
- {
- generate_update_cycles(block, compiler_temp, desc->targetpc, true); // <subtract cycles>
- if (desc->flags & OPFLAG_INTRABLOCK_BRANCH)
- UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc
- else
- UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp <mode>,desc->targetpc,nocode
- }
- else
- {
- generate_update_cycles(block, compiler_temp, uml::mem(&m_rsp_state->jmpdest), true); // <subtract cycles>
- UML_HASHJMP(block, 0, mem(&m_rsp_state->jmpdest), *m_nocode); // hashjmp <mode>,<rsreg>,nocode
- }
-}
-
-/*------------------------------------------------------------------
- generate_delay_slot_and_branch
-------------------------------------------------------------------*/
-
-void rsp_device::generate_delay_slot_and_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t linkreg)
-{
- compiler_state compiler_temp(compiler);
- uint32_t op = desc->opptr.l[0];
-
- /* fetch the target register if dynamic, in case it is modified by the delay slot */
- if (desc->targetpc == BRANCH_TARGET_DYNAMIC)
- {
- UML_AND(block, mem(&m_rsp_state->jmpdest), R32(RSREG), 0x00000fff);
- UML_OR(block, mem(&m_rsp_state->jmpdest), mem(&m_rsp_state->jmpdest), 0x1000);
- }
-
- /* set the link if needed -- before the delay slot */
- if (linkreg != 0)
- {
- UML_MOV(block, R32(linkreg), (int32_t)((desc->pc + 8) & 0x0000fff)); // mov <linkreg>,desc->pc + 8
- }
-
- /* compile the delay slot using temporary compiler state */
- assert(desc->delay.first() != nullptr);
- generate_sequence_instruction(block, compiler_temp, desc->delay.first()); // <next instruction>
-
- generate_branch(block, compiler, desc);
-
- /* update the label */
- compiler.labelnum = compiler_temp.labelnum;
-
- /* reset the mapvar to the current cycles and account for skipped slots */
- compiler.cycles += desc->skipslots;
- UML_MAPVAR(block, MAPVAR_CYCLES, compiler.cycles); // mapvar CYCLES,compiler.cycles
-}
-
-bool 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);
- uint32_t op = desc->opptr.l[0];
- uint8_t opswitch = op >> 26;
- uml::code_label skip;
-
- switch (opswitch)
- {
- /* ----- sub-groups ----- */
-
- case 0x00: /* SPECIAL - MIPS I */
- return generate_special(block, compiler, desc);
-
- case 0x01: /* REGIMM - MIPS I */
- return generate_regimm(block, compiler, desc);
-
- /* ----- jumps and branches ----- */
-
- case 0x02: /* J - MIPS I */
- generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp>
- return true;
-
- case 0x03: /* JAL - MIPS I */
- generate_delay_slot_and_branch(block, compiler, desc, 31); // <next instruction + hashjmp>
- return true;
-
- case 0x04: /* BEQ - MIPS I */
- UML_CMP(block, R32(RSREG), R32(RTREG)); // cmp <rsreg>,<rtreg>
- UML_JMPc(block, COND_NE, skip = compiler.labelnum++); // jmp skip,NE
- generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp>
- UML_LABEL(block, skip); // skip:
- return true;
-
- case 0x05: /* BNE - MIPS I */
- UML_CMP(block, R32(RSREG), R32(RTREG)); // dcmp <rsreg>,<rtreg>
- UML_JMPc(block, COND_E, skip = compiler.labelnum++); // jmp skip,E
- generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp>
- UML_LABEL(block, skip); // skip:
- return true;
-
- case 0x06: /* BLEZ - MIPS I */
- if (RSREG != 0)
- {
- UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0
- UML_JMPc(block, COND_G, skip = compiler.labelnum++); // jmp skip,G
- generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp>
- UML_LABEL(block, skip); // skip:
- }
- else
- generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp>
- return true;
-
- case 0x07: /* BGTZ - MIPS I */
- UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0
- UML_JMPc(block, COND_LE, skip = compiler.labelnum++); // jmp skip,LE
- generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp>
- UML_LABEL(block, skip); // skip:
- return true;
-
-
- /* ----- immediate arithmetic ----- */
-
- case 0x0f: /* LUI - MIPS I */
- if (RTREG != 0)
- UML_MOV(block, R32(RTREG), SIMMVAL << 16); // dmov <rtreg>,SIMMVAL << 16
- return true;
-
- case 0x08: /* ADDI - MIPS I */
- case 0x09: /* ADDIU - MIPS I */
- if (RTREG != 0)
- {
- UML_ADD(block, R32(RTREG), R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL,V
- }
- return true;
-
- case 0x0a: /* SLTI - MIPS I */
- if (RTREG != 0)
- {
- UML_CMP(block, R32(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
- UML_SETc(block, COND_L, R32(RTREG)); // dset <rtreg>,l
- }
- return true;
-
- case 0x0b: /* SLTIU - MIPS I */
- if (RTREG != 0)
- {
- UML_CMP(block, R32(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL
- UML_SETc(block, COND_B, R32(RTREG)); // dset <rtreg>,b
- }
- return true;
-
-
- case 0x0c: /* ANDI - MIPS I */
- if (RTREG != 0)
- UML_AND(block, R32(RTREG), R32(RSREG), UIMMVAL); // dand <rtreg>,<rsreg>,UIMMVAL
- return true;
-
- case 0x0d: /* ORI - MIPS I */
- if (RTREG != 0)
- UML_OR(block, R32(RTREG), R32(RSREG), UIMMVAL); // dor <rtreg>,<rsreg>,UIMMVAL
- return true;
-
- case 0x0e: /* XORI - MIPS I */
- if (RTREG != 0)
- UML_XOR(block, R32(RTREG), R32(RSREG), UIMMVAL); // dxor <rtreg>,<rsreg>,UIMMVAL
- return true;
-
- /* ----- memory load operations ----- */
-
- case 0x20: /* LB - MIPS I */
- UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
- UML_CALLH(block, *m_read8); // callh read8
- if (RTREG != 0)
- UML_SEXT(block, R32(RTREG), I0, SIZE_BYTE); // dsext <rtreg>,i0,byte
- if (!in_delay_slot)
- generate_update_cycles(block, compiler, desc->pc + 4, true);
- return true;
-
- case 0x21: /* LH - MIPS I */
- UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
- UML_CALLH(block, *m_read16); // callh read16
- if (RTREG != 0)
- UML_SEXT(block, R32(RTREG), I0, SIZE_WORD); // dsext <rtreg>,i0,word
- if (!in_delay_slot)
- generate_update_cycles(block, compiler, desc->pc + 4, true);
- return true;
-
- case 0x23: /* LW - MIPS I */
- UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
- UML_CALLH(block, *m_read32); // callh read32
- if (RTREG != 0)
- UML_MOV(block, R32(RTREG), I0);
- if (!in_delay_slot)
- generate_update_cycles(block, compiler, desc->pc + 4, true);
- return true;
-
- case 0x24: /* LBU - MIPS I */
- UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
- UML_CALLH(block, *m_read8); // callh read8
- if (RTREG != 0)
- UML_AND(block, R32(RTREG), I0, 0xff); // dand <rtreg>,i0,0xff
- if (!in_delay_slot)
- generate_update_cycles(block, compiler, desc->pc + 4, true);
- return true;
-
- case 0x25: /* LHU - MIPS I */
- UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
- UML_CALLH(block, *m_read16); // callh read16
- if (RTREG != 0)
- UML_AND(block, R32(RTREG), I0, 0xffff); // dand <rtreg>,i0,0xffff
- if (!in_delay_slot)
- generate_update_cycles(block, compiler, desc->pc + 4, true);
- return true;
-
- case 0x32: /* LWC2 - MIPS I */
- return m_cop2->generate_lwc2(block, compiler, desc);
-
-
- /* ----- memory store operations ----- */
-
- case 0x28: /* SB - MIPS I */
- UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
- UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg>
- UML_CALLH(block, *m_write8); // callh write8
- if (!in_delay_slot)
- generate_update_cycles(block, compiler, desc->pc + 4, true);
- return true;
-
- case 0x29: /* SH - MIPS I */
- UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
- UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg>
- UML_CALLH(block, *m_write16); // callh write16
- if (!in_delay_slot)
- generate_update_cycles(block, compiler, desc->pc + 4, true);
- return true;
-
- case 0x2b: /* SW - MIPS I */
- UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL
- UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg>
- UML_CALLH(block, *m_write32); // callh write32
- if (!in_delay_slot)
- generate_update_cycles(block, compiler, desc->pc + 4, true);
- return true;
-
- case 0x3a: /* SWC2 - MIPS I */
- return m_cop2->generate_swc2(block, compiler, desc);
-
- /* ----- coprocessor instructions ----- */
-
- case 0x10: /* COP0 - MIPS I */
- return generate_cop0(block, compiler, desc);
-
- case 0x12: /* COP2 - MIPS I */
- return m_cop2->generate_cop2(block, compiler, desc);
-
-
- /* ----- unimplemented/illegal instructions ----- */
-
- //default: /* ??? */ invalid_instruction(op); break;
- }
-
- return false;
-}
-
-
-/*-------------------------------------------------
- generate_special - compile opcodes in the
- 'SPECIAL' group
--------------------------------------------------*/
-
-bool rsp_device::generate_special(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
-{
- uint32_t op = desc->opptr.l[0];
- uint8_t opswitch = op & 63;
- //uml::code_label skip;
-
- switch (opswitch)
- {
- /* ----- shift instructions ----- */
-
- case 0x00: /* SLL - MIPS I */
- if (RDREG != 0)
- {
- UML_SHL(block, R32(RDREG), R32(RTREG), SHIFT);
- }
- return true;
-
- case 0x02: /* SRL - MIPS I */
- if (RDREG != 0)
- {
- UML_SHR(block, R32(RDREG), R32(RTREG), SHIFT);
- }
- return true;
-
- case 0x03: /* SRA - MIPS I */
- if (RDREG != 0)
- {
- UML_SAR(block, R32(RDREG), R32(RTREG), SHIFT);
- }
- return true;
-
- case 0x04: /* SLLV - MIPS I */
- if (RDREG != 0)
- {
- UML_SHL(block, R32(RDREG), R32(RTREG), R32(RSREG));
- }
- return true;
-
- case 0x06: /* SRLV - MIPS I */
- if (RDREG != 0)
- {
- UML_SHR(block, R32(RDREG), R32(RTREG), R32(RSREG));
- }
- return true;
-
- case 0x07: /* SRAV - MIPS I */
- if (RDREG != 0)
- {
- UML_SAR(block, R32(RDREG), R32(RTREG), R32(RSREG));
- }
- return true;
-
- /* ----- basic arithmetic ----- */
-
- case 0x20: /* ADD - MIPS I */
- case 0x21: /* ADDU - MIPS I */
- if (RDREG != 0)
- {
- UML_ADD(block, R32(RDREG), R32(RSREG), R32(RTREG));
- }
- return true;
-
- case 0x22: /* SUB - MIPS I */
- case 0x23: /* SUBU - MIPS I */
- if (RDREG != 0)
- {
- UML_SUB(block, R32(RDREG), R32(RSREG), R32(RTREG));
- }
- return true;
-
- /* ----- basic logical ops ----- */
-
- case 0x24: /* AND - MIPS I */
- if (RDREG != 0)
- {
- UML_AND(block, R32(RDREG), R32(RSREG), R32(RTREG)); // dand <rdreg>,<rsreg>,<rtreg>
- }
- return true;
-
- case 0x25: /* OR - MIPS I */
- if (RDREG != 0)
- {
- UML_OR(block, R32(RDREG), R32(RSREG), R32(RTREG)); // dor <rdreg>,<rsreg>,<rtreg>
- }
- return true;
-
- case 0x26: /* XOR - MIPS I */
- if (RDREG != 0)
- {
- UML_XOR(block, R32(RDREG), R32(RSREG), R32(RTREG)); // dxor <rdreg>,<rsreg>,<rtreg>
- }
- return true;
-
- case 0x27: /* NOR - MIPS I */
- if (RDREG != 0)
- {
- UML_OR(block, I0, R32(RSREG), R32(RTREG)); // dor i0,<rsreg>,<rtreg>
- UML_XOR(block, R32(RDREG), I0, (uint64_t)~0); // dxor <rdreg>,i0,~0
- }
- return true;
-
-
- /* ----- basic comparisons ----- */
-
- case 0x2a: /* SLT - MIPS I */
- if (RDREG != 0)
- {
- UML_CMP(block, R32(RSREG), R32(RTREG)); // dcmp <rsreg>,<rtreg>
- UML_SETc(block, COND_L, R32(RDREG)); // dset <rdreg>,l
- }
- return true;
-
- case 0x2b: /* SLTU - MIPS I */
- if (RDREG != 0)
- {
- UML_CMP(block, R32(RSREG), R32(RTREG)); // dcmp <rsreg>,<rtreg>
- UML_SETc(block, COND_B, R32(RDREG)); // dset <rdreg>,b
- }
- return true;
-
-
- /* ----- jumps and branches ----- */
-
- case 0x08: /* JR - MIPS I */
- generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp>
- return true;
-
- case 0x09: /* JALR - MIPS I */
- generate_delay_slot_and_branch(block, compiler, desc, RDREG); // <next instruction + hashjmp>
- return true;
-
-
- /* ----- system calls ----- */
-
- case 0x0d: /* BREAK - MIPS I */
- UML_MOV(block, mem(&m_rsp_state->arg0), 3); // mov [arg0],3
- UML_CALLC(block, cfunc_sp_set_status_cb, this); // callc cfunc_sp_set_status_cb
- UML_MOV(block, mem(&m_rsp_state->icount), 0); // mov icount, #0
- UML_MOV(block, mem(&m_rsp_state->jmpdest), desc->targetpc);
-
- generate_branch(block, compiler, desc);
-
- UML_EXIT(block, EXECUTE_OUT_OF_CYCLES);
- return true;
- }
- return false;
-}
-
-
-
-/*-------------------------------------------------
- generate_regimm - compile opcodes in the
- 'REGIMM' group
--------------------------------------------------*/
-
-bool rsp_device::generate_regimm(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
-{
- uint32_t op = desc->opptr.l[0];
- uint8_t opswitch = RTREG;
- uml::code_label skip;
-
- switch (opswitch)
- {
- case 0x00: /* BLTZ */
- case 0x10: /* BLTZAL */
- if (RSREG != 0)
- {
- UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0
- UML_JMPc(block, COND_GE, skip = compiler.labelnum++); // jmp skip,GE
- generate_delay_slot_and_branch(block, compiler, desc, (opswitch & 0x10) ? 31 : 0);
- // <next instruction + hashjmp>
- UML_LABEL(block, skip); // skip:
- }
- return true;
-
- case 0x01: /* BGEZ */
- case 0x11: /* BGEZAL */
- if (RSREG != 0)
- {
- UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0
- UML_JMPc(block, COND_L, skip = compiler.labelnum++); // jmp skip,L
- generate_delay_slot_and_branch(block, compiler, desc, (opswitch & 0x10) ? 31 : 0);
- // <next instruction + hashjmp>
- UML_LABEL(block, skip); // skip:
- }
- else
- generate_delay_slot_and_branch(block, compiler, desc, (opswitch & 0x10) ? 31 : 0);
- // <next instruction + hashjmp>
- return true;
- }
- return false;
-}
-
-
-/*-------------------------------------------------
- generate_cop0 - compile COP0 opcodes
--------------------------------------------------*/
-
-bool rsp_device::generate_cop0(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
-{
- uint32_t op = desc->opptr.l[0];
- uint8_t opswitch = RSREG;
-
- switch (opswitch)
- {
- case 0x00: /* MFCz */
- if (RTREG != 0)
- {
- UML_MOV(block, mem(&m_rsp_state->arg0), RDREG); // mov [arg0],<rdreg>
- UML_MOV(block, mem(&m_rsp_state->arg1), RTREG); // mov [arg1],<rtreg>
- UML_CALLC(block, cfunc_get_cop0_reg, this); // callc cfunc_get_cop0_reg
- if(RDREG == 2)
- {
- generate_update_cycles(block, compiler, uml::mem(&m_rsp_state->pc), true);
- UML_HASHJMP(block, 0, mem(&m_rsp_state->pc), *m_nocode);
- }
- }
- return true;
-
- case 0x04: /* MTCz */
- UML_MOV(block, mem(&m_rsp_state->arg0), RDREG); // mov [arg0],<rdreg>
- UML_MOV(block, mem(&m_rsp_state->arg1), R32(RTREG)); // mov [arg1],rtreg
- UML_CALLC(block, cfunc_set_cop0_reg, this); // callc cfunc_set_cop0_reg
- return true;
- }
-
- return false;
-}
-
-/***************************************************************************
- CODE LOGGING HELPERS
-***************************************************************************/
-
-/*-------------------------------------------------
- log_add_disasm_comment - add a comment
- including disassembly of a RSP instruction
--------------------------------------------------*/
-
-void rsp_device::log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op)
-{
- if (m_drcuml->logging())
- {
- rsp_disassembler rspd;
- std::ostringstream buffer;
- rspd.dasm_one(buffer, pc, op);
- block.append_comment("%08X: %s", pc, buffer.str()); // comment
- }
-}
diff --git a/src/devices/cpu/rsp/rspfe.cpp b/src/devices/cpu/rsp/rspfe.cpp
deleted file mode 100644
index 83778386a0e..00000000000
--- a/src/devices/cpu/rsp/rspfe.cpp
+++ /dev/null
@@ -1,307 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-/***************************************************************************
-
- rspfe.c
-
- Front-end for RSP recompiler
-
-***************************************************************************/
-
-#include "emu.h"
-#include "rspfe.h"
-
-#include "rspdefs.h"
-
-
-//**************************************************************************
-// RSP FRONTEND
-//**************************************************************************
-
-//-------------------------------------------------
-// rsp_device::frontend - constructor
-//-------------------------------------------------
-
-rsp_device::frontend::frontend(rsp_device &rsp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence)
- : drc_frontend(rsp, window_start, window_end, max_sequence), m_rsp(rsp)
-{
-}
-
-
-//-------------------------------------------------
-// describe - build a description of a single
-// instruction
-//-------------------------------------------------
-
-bool rsp_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev)
-{
- uint32_t op, opswitch;
-
- // fetch the opcode
- op = desc.opptr.l[0] = m_rsp.m_pcache.read_dword((desc.physpc & 0x00000fff) | 0x1000);
-
- // all instructions are 4 bytes and default to a single cycle each
- desc.length = 4;
- desc.cycles = 1;
-
- // parse the instruction
- opswitch = op >> 26;
- switch (opswitch)
- {
- case 0x00: // SPECIAL
- return describe_special(op, desc);
-
- case 0x01: // REGIMM
- return describe_regimm(op, desc);
-
- case 0x10: // COP0
- return describe_cop0(op, desc);
-
- case 0x12: // COP2
- return describe_cop2(op, desc);
-
- case 0x02: // J
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc.targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
- desc.delayslots = 1;
- return true;
-
- case 0x03: // JAL
- desc.regout[0] |= REGFLAG_R(31);
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc.targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000;
- desc.delayslots = 1;
- return true;
-
- case 0x04: // BEQ
- case 0x05: // BNE
- if ((opswitch == 0x04 || opswitch == 0x14) && RSREG == RTREG)
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- else
- {
- desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- }
- desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000;
- desc.delayslots = 1;
- desc.skipslots = (opswitch & 0x10) ? 1 : 0;
- return true;
-
- case 0x06: // BLEZ
- case 0x07: // BGTZ
- if ((opswitch == 0x06 || opswitch == 0x16) && RSREG == 0)
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- else
- {
- desc.regin[0] |= REGFLAG_R(RSREG);
- desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- }
- desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000;
- desc.delayslots = 1;
- desc.skipslots = (opswitch & 0x10) ? 1 : 0;
- return true;
-
- case 0x08: // ADDI
- desc.regin[0] |= REGFLAG_R(RSREG);
- desc.regout[0] |= REGFLAG_R(RTREG);
- return true;
-
- case 0x09: // ADDIU
- case 0x0a: // SLTI
- case 0x0b: // SLTIU
- case 0x0c: // ANDI
- case 0x0d: // ORI
- case 0x0e: // XORI
- desc.regin[0] |= REGFLAG_R(RSREG);
- desc.regout[0] |= REGFLAG_R(RTREG);
- return true;
-
- case 0x0f: // LUI
- desc.regout[0] |= REGFLAG_R(RTREG);
- return true;
-
- case 0x20: // LB
- case 0x21: // LH
- case 0x23: // LW
- case 0x24: // LBU
- case 0x25: // LHU
- case 0x27: // LWU
- desc.regin[0] |= REGFLAG_R(RSREG);
- desc.regout[0] |= REGFLAG_R(RTREG);
- desc.flags |= OPFLAG_READS_MEMORY;
- return true;
-
- case 0x28: // SB
- case 0x29: // SH
- case 0x2b: // SW
- desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc.flags |= OPFLAG_WRITES_MEMORY;
- return true;
-
- case 0x32: // LWC2
- desc.regin[0] |= REGFLAG_R(RSREG);
- desc.flags |= OPFLAG_READS_MEMORY;
- return true;
-
- case 0x3a: // SWC2
- desc.regin[0] |= REGFLAG_R(RSREG);
- desc.flags |= OPFLAG_WRITES_MEMORY;
- return true;
- }
-
- return false;
-}
-
-
-//-------------------------------------------------
-// describe_special - build a description of a
-// single instruction in the 'special' group
-//-------------------------------------------------
-
-bool rsp_device::frontend::describe_special(uint32_t op, opcode_desc &desc)
-{
- switch (op & 63)
- {
- case 0x00: // SLL
- case 0x02: // SRL
- case 0x03: // SRA
- desc.regin[0] |= REGFLAG_R(RTREG);
- desc.regout[0] |= REGFLAG_R(RDREG);
- return true;
-
- case 0x04: // SLLV
- case 0x06: // SRLV
- case 0x07: // SRAV
- case 0x21: // ADDU
- case 0x23: // SUBU
- case 0x24: // AND
- case 0x25: // OR
- case 0x26: // XOR
- case 0x27: // NOR
- case 0x2a: // SLT
- case 0x2b: // SLTU
- desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc.regout[0] |= REGFLAG_R(RDREG);
- return true;
-
- case 0x20: // ADD
- case 0x22: // SUB
- desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG);
- desc.regout[0] |= REGFLAG_R(RDREG);
- return true;
-
- case 0x08: // JR
- desc.regin[0] |= REGFLAG_R(RSREG);
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc.targetpc = BRANCH_TARGET_DYNAMIC;
- desc.delayslots = 1;
- return true;
-
- case 0x09: // JALR
- desc.regin[0] |= REGFLAG_R(RSREG);
- desc.regout[0] |= REGFLAG_R(RDREG);
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc.targetpc = BRANCH_TARGET_DYNAMIC;
- desc.delayslots = 1;
- return true;
-
- case 0x0d: // BREAK
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc.targetpc = (op >> 5) & 0x000fffff;
- return true;
- }
-
- return false;
-}
-
-
-//-------------------------------------------------
-// describe_regimm - build a description of a
-// single instruction in the 'regimm' group
-//-------------------------------------------------
-
-bool rsp_device::frontend::describe_regimm(uint32_t op, opcode_desc &desc)
-{
- switch (RTREG)
- {
- case 0x00: // BLTZ
- case 0x01: // BGEZ
- if (RTREG == 0x01 && RSREG == 0)
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- else
- {
- desc.regin[0] |= REGFLAG_R(RSREG);
- desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- }
- desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000;
- desc.delayslots = 1;
- desc.skipslots = (RTREG & 0x02) ? 1 : 0;
- return true;
-
- case 0x10: // BLTZAL
- case 0x11: // BGEZAL
- if (RTREG == 0x11 && RSREG == 0)
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- else
- {
- desc.regin[0] |= REGFLAG_R(RSREG);
- desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
- }
- desc.regout[0] |= REGFLAG_R(31);
- desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000;
- desc.delayslots = 1;
- desc.skipslots = (RTREG & 0x02) ? 1 : 0;
- return true;
- }
-
- return false;
-}
-
-
-//-------------------------------------------------
-// describe_cop0 - build a description of a
-// single instruction in the COP0 group
-//-------------------------------------------------
-
-bool rsp_device::frontend::describe_cop0(uint32_t op, opcode_desc &desc)
-{
- switch (RSREG)
- {
- case 0x00: // MFCz
- desc.regout[0] |= REGFLAG_R(RTREG);
- return true;
-
- case 0x04: // MTCz
- desc.regin[0] |= REGFLAG_R(RTREG);
- if(RDREG == 2) // SP_RD_LEN, initiating DMA
- {
- desc.flags |= OPFLAG_END_SEQUENCE;
- }
- return true;
- }
-
- return false;
-}
-
-//-------------------------------------------------
-// describe_cop2 - build a description of a
-// single instruction in the COP2 group
-//-------------------------------------------------
-
-bool rsp_device::frontend::describe_cop2(uint32_t op, opcode_desc &desc)
-{
- switch (RSREG)
- {
- case 0x00: // MFCz
- case 0x02: // CFCz
- desc.regout[0] |= REGFLAG_R(RTREG);
- return true;
-
- case 0x04: // MTCz
- case 0x06: // CTCz
- desc.regin[0] |= REGFLAG_R(RTREG);
- return true;
- }
-
- return false;
-}
diff --git a/src/devices/cpu/rsp/rspfe.h b/src/devices/cpu/rsp/rspfe.h
deleted file mode 100644
index 5f965a96e11..00000000000
--- a/src/devices/cpu/rsp/rspfe.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-/***************************************************************************
-
- rspfe.h
-
- Front-end for RSP recompiler
-
-***************************************************************************/
-#ifndef MAME_CPU_RSP_RSPFE_H
-#define MAME_CPU_RSP_RSPFE_H
-
-#pragma once
-
-#include "rsp.h"
-#include "cpu/drcfe.h"
-
-
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-// register flags 0
-#define REGFLAG_R(n) (((n) == 0) ? 0 : (1 << (n)))
-
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class rsp_device::frontend : public drc_frontend
-{
-public:
- // construction/destruction
- frontend(rsp_device &rsp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence);
-
-protected:
- // required overrides
- virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override;
-
-private:
- // internal helpers
- bool describe_special(uint32_t op, opcode_desc &desc);
- bool describe_regimm(uint32_t op, opcode_desc &desc);
- bool describe_cop0(uint32_t op, opcode_desc &desc);
- bool describe_cop2(uint32_t op, opcode_desc &desc);
-
- // internal state
- rsp_device &m_rsp;
-};
-
-
-
-#endif // MAME_CPU_RSP_RSPFE_H
diff --git a/src/devices/cpu/rsp/vabs.h b/src/devices/cpu/rsp/vabs.h
deleted file mode 100644
index 273841b9610..00000000000
--- a/src/devices/cpu/rsp/vabs.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vabs(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo)
-{
- rsp_vec_t vs_zero = _mm_cmpeq_epi16(vs, zero);
- rsp_vec_t sign_lt = _mm_srai_epi16(vs, 15);
- rsp_vec_t vd = _mm_andnot_si128(vs_zero, vt);
-
- // Careful: if VT = 0x8000 and VS is negative,
- // acc_lo will be 0x8000 but vd will be 0x7FFF.
- vd = _mm_xor_si128(vd, sign_lt);
- *acc_lo = _mm_sub_epi16(vd, sign_lt);
- return _mm_subs_epi16(vd, sign_lt);
-}
diff --git a/src/devices/cpu/rsp/vadd.h b/src/devices/cpu/rsp/vadd.h
deleted file mode 100644
index 16009e53287..00000000000
--- a/src/devices/cpu/rsp/vadd.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vadd(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t carry, rsp_vec_t *acc_lo)
-{
- // VCC uses unsaturated arithmetic.
- rsp_vec_t vd = _mm_add_epi16(vs, vt);
- *acc_lo = _mm_sub_epi16(vd, carry);
-
- // VD is the signed sum of the two sources and the carry. Since we
- // have to saturate the sum of all three, we have to be clever.
- rsp_vec_t minimum = _mm_min_epi16(vs, vt);
- rsp_vec_t maximum = _mm_max_epi16(vs, vt);
- minimum = _mm_subs_epi16(minimum, carry);
- return _mm_adds_epi16(minimum, maximum);
-}
diff --git a/src/devices/cpu/rsp/vaddc.h b/src/devices/cpu/rsp/vaddc.h
deleted file mode 100644
index 0ebd30cbd31..00000000000
--- a/src/devices/cpu/rsp/vaddc.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vaddc(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *sn)
-{
- rsp_vec_t sat_sum = _mm_adds_epu16(vs, vt);
- rsp_vec_t unsat_sum = _mm_add_epi16(vs, vt);
-
- *sn = _mm_cmpeq_epi16(sat_sum, unsat_sum);
- *sn = _mm_cmpeq_epi16(*sn, zero);
-
- return unsat_sum;
-}
diff --git a/src/devices/cpu/rsp/vand.h b/src/devices/cpu/rsp/vand.h
deleted file mode 100644
index 8f638330e2a..00000000000
--- a/src/devices/cpu/rsp/vand.h
+++ /dev/null
@@ -1,9 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vand_vnand(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt) {
- rsp_vec_t vmask = _mm_load_si128((rsp_vec_t *) m_vec_helpers.logic_mask[iw & 0x1]);
-
- rsp_vec_t vd = _mm_and_si128(vs, vt);
- return _mm_xor_si128(vd, vmask);
-}
diff --git a/src/devices/cpu/rsp/vch.h b/src/devices/cpu/rsp/vch.h
deleted file mode 100644
index 6abac437a2c..00000000000
--- a/src/devices/cpu/rsp/vch.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vch(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *ge, rsp_vec_t *le, rsp_vec_t *eq, rsp_vec_t *sign, rsp_vec_t *vce) {
- // sign = (vs ^ vt) < 0
- *sign = _mm_xor_si128(vs, vt);
- *sign = _mm_cmplt_epi16(*sign, zero);
-
- // sign_negvt = sign ? -vt : vt
- rsp_vec_t sign_negvt = _mm_xor_si128(vt, *sign);
- sign_negvt = _mm_sub_epi16(sign_negvt, *sign);
-
- // Compute diff, diff_zero:
- rsp_vec_t diff = _mm_sub_epi16(vs, sign_negvt);
- rsp_vec_t diff_zero = _mm_cmpeq_epi16(diff, zero);
-
- // Compute le/ge:
- rsp_vec_t vt_neg = _mm_cmplt_epi16(vt, zero);
- rsp_vec_t diff_lez = _mm_cmpgt_epi16(diff, zero);
- rsp_vec_t diff_gez = _mm_or_si128(diff_lez, diff_zero);
- diff_lez = _mm_cmpeq_epi16(zero, diff_lez);
-
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- *ge = _mm_blendv_epi8(diff_gez, vt_neg, *sign);
- *le = _mm_blendv_epi8(vt_neg, diff_lez, *sign);
-#else
- *ge = _mm_and_si128(*sign, vt_neg);
- diff_gez = _mm_andnot_si128(*sign, diff_gez);
- *ge = _mm_or_si128(*ge, diff_gez);
-
- *le = _mm_and_si128(*sign, diff_lez);
- diff_lez = _mm_andnot_si128(*sign, vt_neg);
- *le = _mm_or_si128(*le, diff_lez);
-#endif
-
- // Compute vce:
- *vce = _mm_cmpeq_epi16(diff, *sign);
- *vce = _mm_and_si128(*vce, *sign);
-
- // Compute !eq:
- *eq = _mm_or_si128(diff_zero, *vce);
- *eq = _mm_cmpeq_epi16(*eq, zero);
-
- // Compute result:
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- rsp_vec_t diff_sel_mask = _mm_blendv_epi8(*ge, *le, *sign);
- return _mm_blendv_epi8(vs, sign_negvt, diff_sel_mask);
-#else
- diff_lez = _mm_and_si128(*sign, *le);
- diff_gez = _mm_andnot_si128(*sign, *ge);
- rsp_vec_t diff_sel_mask = _mm_or_si128(diff_lez, diff_gez);
-
- diff_lez = _mm_and_si128(diff_sel_mask, sign_negvt);
- diff_gez = _mm_andnot_si128(diff_sel_mask, vs);
- return _mm_or_si128(diff_lez, diff_gez);
-#endif
-}
diff --git a/src/devices/cpu/rsp/vcl.h b/src/devices/cpu/rsp/vcl.h
deleted file mode 100644
index e09a13d5a8e..00000000000
--- a/src/devices/cpu/rsp/vcl.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vcl(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *ge, rsp_vec_t *le, rsp_vec_t eq, rsp_vec_t sign, rsp_vec_t vce)
-{
- // sign_negvt = sign ? -vt : vt
- rsp_vec_t sign_negvt = _mm_xor_si128(vt, sign);
- sign_negvt = _mm_sub_epi16(sign_negvt, sign);
-
- // Compute diff, diff_zero, ncarry, and nvce:
- // Note: diff = sign ? (vs + vt) : (vs - vt).
- rsp_vec_t diff = _mm_sub_epi16(vs, sign_negvt);
- rsp_vec_t ncarry = _mm_adds_epu16(vs, vt);
- ncarry = _mm_cmpeq_epi16(diff, ncarry);
- rsp_vec_t nvce = _mm_cmpeq_epi16(vce, zero);
- rsp_vec_t diff_zero = _mm_cmpeq_epi16(diff, zero);
-
- // Compute results for if (sign && ne):
- rsp_vec_t le_case1 = _mm_and_si128(diff_zero, ncarry);
- le_case1 = _mm_and_si128(nvce, le_case1);
- rsp_vec_t le_case2 = _mm_or_si128(diff_zero, ncarry);
- le_case2 = _mm_and_si128(vce, le_case2);
- rsp_vec_t le_eq = _mm_or_si128(le_case1, le_case2);
-
- // Compute results for if (!sign && ne):
- rsp_vec_t ge_eq = _mm_subs_epu16(vt, vs);
- ge_eq = _mm_cmpeq_epi16(ge_eq, zero);
-
- // Blend everything together. Caveat: we don't update
- // the results of ge/le if ne is false, so be careful.
- rsp_vec_t do_le = _mm_andnot_si128(eq, sign);
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- *le = _mm_blendv_epi8(*le, le_eq, do_le);
-#else
- le_eq = _mm_and_si128(do_le, le_eq);
- *le = _mm_andnot_si128(do_le, *le);
- *le = _mm_or_si128(le_eq, *le);
-#endif
-
- rsp_vec_t do_ge = _mm_or_si128(sign, eq);
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- *ge = _mm_blendv_epi8(ge_eq, *ge, do_ge);
-#else
- *ge = _mm_and_si128(do_ge, *ge);
- ge_eq = _mm_andnot_si128(do_ge, ge_eq);
- *ge = _mm_or_si128(ge_eq, *ge);
-#endif
-
- // Mux the result based on the value of sign.
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- rsp_vec_t mux_mask = _mm_blendv_epi8(*ge, *le, sign);
-#else
- do_le = _mm_and_si128(sign, *le);
- do_ge = _mm_andnot_si128(sign, *ge);
- rsp_vec_t mux_mask = _mm_or_si128(do_le, do_ge);
-#endif
-
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- return _mm_blendv_epi8(vs, sign_negvt, mux_mask);
-#else
- sign_negvt = _mm_and_si128(mux_mask, sign_negvt);
- vs = _mm_andnot_si128(mux_mask, vs);
- return _mm_or_si128(sign_negvt, vs);
-#endif
-}
diff --git a/src/devices/cpu/rsp/vcmp.h b/src/devices/cpu/rsp/vcmp.h
deleted file mode 100644
index 7838322d26e..00000000000
--- a/src/devices/cpu/rsp/vcmp.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_veq_vge_vlt_vne(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *le, rsp_vec_t eq, rsp_vec_t sign)
-{
- rsp_vec_t equal = _mm_cmpeq_epi16(vs, vt);
-
- if (iw & 0x2) // VNE & VGE
- {
- if (iw & 0x1) // VGE
- {
- rsp_vec_t gt = _mm_cmpgt_epi16(vs, vt);
- rsp_vec_t equalsign = _mm_and_si128(eq, sign);
-
- equal = _mm_andnot_si128(equalsign, equal);
- *le = _mm_or_si128(gt, equal);
- }
- else // VNE
- {
- rsp_vec_t nequal = _mm_cmpeq_epi16(equal, zero);
-
- *le = _mm_and_si128(eq, equal);
- *le = _mm_or_si128(*le, nequal);
- }
- }
- else // VEQ & VLT
- {
- if (iw & 0x1) // VEQ
- {
- *le = _mm_andnot_si128(eq, equal);
- }
- else // VLT
- {
- rsp_vec_t lt = _mm_cmplt_epi16(vs, vt);
-
- equal = _mm_and_si128(eq, equal);
- equal = _mm_and_si128(sign, equal);
- *le = _mm_or_si128(lt, equal);
- }
- }
-
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- return _mm_blendv_epi8(vt, vs, *le);
-#else
- vs = _mm_and_si128(*le, vs);
- vt = _mm_andnot_si128(*le, vt);
- return _mm_or_si128(vs, vt);
-#endif
-}
diff --git a/src/devices/cpu/rsp/vcr.h b/src/devices/cpu/rsp/vcr.h
deleted file mode 100644
index 78f78c66244..00000000000
--- a/src/devices/cpu/rsp/vcr.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vcr(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *ge, rsp_vec_t *le) {
- // sign = (vs ^ vt) < 0
- rsp_vec_t sign = _mm_xor_si128(vs, vt);
- sign = _mm_srai_epi16(sign, 15);
-
- // Compute le
- rsp_vec_t diff_lez = _mm_and_si128(vs, sign);
- diff_lez = _mm_add_epi16(diff_lez, vt);
- *le = _mm_srai_epi16(diff_lez, 15);
-
- // Compute ge
- rsp_vec_t diff_gez = _mm_or_si128(vs, sign);
- diff_gez = _mm_min_epi16(diff_gez, vt);
- *ge = _mm_cmpeq_epi16(diff_gez, vt);
-
- // sign_notvt = sn ? ~vt : vt
- rsp_vec_t sign_notvt = _mm_xor_si128(vt, sign);
-
- // Compute result:
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- rsp_vec_t diff_sel_mask = _mm_blendv_epi8(*ge, *le, sign);
- return _mm_blendv_epi8(vs, sign_notvt, diff_sel_mask);
-#else
- rsp_vec_t diff_sel_mask = _mm_sub_epi16(*le, *ge);
- diff_sel_mask = _mm_and_si128(diff_sel_mask, sign);
- diff_sel_mask = _mm_add_epi16(diff_sel_mask, *ge);
-
- zero = _mm_sub_epi16(sign_notvt, vs);
- zero = _mm_and_si128(zero, diff_sel_mask);
- return _mm_add_epi16(zero, vs);
-#endif
-}
diff --git a/src/devices/cpu/rsp/vdivh.h b/src/devices/cpu/rsp/vdivh.h
deleted file mode 100644
index 5bd4093f6b4..00000000000
--- a/src/devices/cpu/rsp/vdivh.h
+++ /dev/null
@@ -1,12 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vdivh(uint32_t src, uint32_t e, uint32_t dest, uint32_t de)
-{
- // Get the element from VT.
- m_div_in = m_v[src].s[e & 0x7];
-
- // Write out the upper part of the result.
- m_v[dest].s[de & 0x7] = m_div_out;
- return vec_load_unshuffled_operand(m_v[dest].s);
-}
diff --git a/src/devices/cpu/rsp/vldst.h b/src/devices/cpu/rsp/vldst.h
deleted file mode 100644
index fadc8be63c0..00000000000
--- a/src/devices/cpu/rsp/vldst.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-// LBV, LDV, LLV, LSV, SBV, SDV, SLV, SSV
-inline void vec_lbdlsv_sbdlsv(uint32_t iw, uint32_t rs)
-{
- const uint32_t shift_and_idx = (iw >> 11) & 0x3;
- rsp_vec_t dqm = _mm_loadl_epi64((rsp_vec_t *) (m_vec_helpers.bdls_lut[shift_and_idx]));
-
- const uint32_t addr = (rs + (sign_extend_6(iw) << shift_and_idx)) & 0xfff;
- const uint32_t element = (iw >> 7) & 0xf;
- uint16_t* regp = m_v[(iw >> 16) & 0x1f].s;
-
- if (iw >> 29 & 0x1)
- {
- vec_store_group1(addr, element, regp, vec_load_unshuffled_operand(regp), dqm);
- }
- else
- {
- vec_load_group1(addr, element, regp, vec_load_unshuffled_operand(regp), dqm);
- }
-}
-
-// LPV, LUV, SPV, SUV
-inline void vec_lfhpuv_sfhpuv(uint32_t iw, uint32_t rs)
-{
- static const enum rsp_mem_request_type fhpu_type_lut[4] = {
- RSP_MEM_REQUEST_PACK,
- RSP_MEM_REQUEST_UPACK,
- RSP_MEM_REQUEST_HALF,
- RSP_MEM_REQUEST_FOURTH
- };
-
- const uint32_t addr = (rs + (sign_extend_6(iw) << 3)) & 0xfff;
- const uint32_t element = (iw >> 7) & 0xf;
- uint16_t* regp = m_v[(iw >> 16) & 0x1f].s;
-
- rsp_mem_request_type request_type = fhpu_type_lut[((iw >> 11) & 0x1f) - 6];
- if ((iw >> 29) & 0x1)
- {
- vec_store_group2(addr, element, regp, vec_load_unshuffled_operand(regp), _mm_setzero_si128(), request_type);
- }
- else
- {
- vec_load_group2(addr, element, regp, vec_load_unshuffled_operand(regp), _mm_setzero_si128(), request_type);
- }
-}
-
-// LQV, LRV, SQV, SRV
-inline void vec_lqrv_sqrv(uint32_t iw, uint32_t rs)
-{
- rs &= 0xfff;
-
- const uint32_t addr = rs + (sign_extend_6(iw) << 4);
- const uint32_t element = (iw >> 7) & 0xf;
- uint16_t* regp = m_v[(iw >> 16) & 0x1f].s;
-
- memcpy(m_vdqm.s, m_vec_helpers.qr_lut[addr & 0xf], sizeof(m_vdqm.s));
-
- rsp_mem_request_type request_type = (iw >> 11 & 0x1) ? RSP_MEM_REQUEST_REST : RSP_MEM_REQUEST_QUAD;
- if ((iw >> 29) & 0x1)
- {
- vec_store_group4(addr, element, regp, vec_load_unshuffled_operand(regp), vec_load_unshuffled_operand(m_vdqm.s), request_type);
- }
- else
- {
- vec_load_group4(addr, element, regp, vec_load_unshuffled_operand(regp), vec_load_unshuffled_operand(m_vdqm.s), request_type);
- }
-}
diff --git a/src/devices/cpu/rsp/vmac.h b/src/devices/cpu/rsp/vmac.h
deleted file mode 100644
index ade43511daa..00000000000
--- a/src/devices/cpu/rsp/vmac.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vmacf_vmacu(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_mid, rsp_vec_t *acc_hi)
-{
- // Get the product and shift it over
- // being sure to save the carries.
- rsp_vec_t lo = _mm_mullo_epi16(vs, vt);
- rsp_vec_t hi = _mm_mulhi_epi16(vs, vt);
-
- rsp_vec_t mid = _mm_slli_epi16(hi, 1);
- rsp_vec_t carry = _mm_srli_epi16(lo, 15);
- hi = _mm_srai_epi16(hi, 15);
- mid = _mm_or_si128(mid, carry);
- lo = _mm_slli_epi16(lo, 1);
-
- // Tricky part: start accumulating everything.
- // Get/keep the carry as we'll add it in later.
- rsp_vec_t overflow_mask = _mm_adds_epu16(*acc_lo, lo);
- *acc_lo = _mm_add_epi16(*acc_lo, lo);
-
- overflow_mask = _mm_cmpeq_epi16(*acc_lo, overflow_mask);
- overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero);
-
- // Add in the carry. If the middle portion is
- // already 0xFFFF and we have a carry, we have
- // to carry the all the way up to hi.
- mid = _mm_sub_epi16(mid, overflow_mask);
- carry = _mm_cmpeq_epi16(mid, zero);
- carry = _mm_and_si128(carry, overflow_mask);
- hi = _mm_sub_epi16(hi, carry);
-
- // Accumulate the middle portion.
- overflow_mask = _mm_adds_epu16(*acc_mid, mid);
- *acc_mid = _mm_add_epi16(*acc_mid, mid);
-
- overflow_mask = _mm_cmpeq_epi16(*acc_mid, overflow_mask);
- overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero);
-
- // Finish up the accumulation of the... accumulator.
- *acc_hi = _mm_add_epi16(*acc_hi, hi);
- *acc_hi = _mm_sub_epi16(*acc_hi, overflow_mask);
-
- if (iw & 0x1) // VMACU
- {
- rsp_vec_t overflow_hi_mask = _mm_srai_epi16(*acc_hi, 15);
- rsp_vec_t overflow_mid_mask = _mm_srai_epi16(*acc_mid, 15);
- mid = _mm_or_si128(overflow_mid_mask, *acc_mid);
- overflow_mask = _mm_cmpgt_epi16(*acc_hi, zero);
- mid = _mm_andnot_si128(overflow_hi_mask, mid);
- return _mm_or_si128(overflow_mask, mid);
- }
- else // VMACF
- {
- return sclamp_acc_to_mid(*acc_mid, *acc_hi);
- }
-}
diff --git a/src/devices/cpu/rsp/vmov.h b/src/devices/cpu/rsp/vmov.h
deleted file mode 100644
index 59e02e8b118..00000000000
--- a/src/devices/cpu/rsp/vmov.h
+++ /dev/null
@@ -1,9 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vmov(uint32_t src, uint32_t e, uint32_t dest, uint32_t de)
-{
- // Get the element from VT and write out the upper part of the result.
- m_v[dest].s[de & 0x7] = m_v[src].s[e & 0x7];
- return vec_load_unshuffled_operand(m_v[dest].s);
-}
diff --git a/src/devices/cpu/rsp/vmrg.h b/src/devices/cpu/rsp/vmrg.h
deleted file mode 100644
index ab9be63ef16..00000000000
--- a/src/devices/cpu/rsp/vmrg.h
+++ /dev/null
@@ -1,13 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vmrg(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t le)
-{
-#if (defined(__SSE4_1__) || defined(_MSC_VER))
- return _mm_blendv_epi8(vt, vs, le);
-#else
- vs = _mm_and_si128(le, vs);
- vt = _mm_andnot_si128(le, vt);
- return _mm_or_si128(vs, vt);
-#endif
-}
diff --git a/src/devices/cpu/rsp/vmudh.h b/src/devices/cpu/rsp/vmudh.h
deleted file mode 100644
index 71c3a38f4fb..00000000000
--- a/src/devices/cpu/rsp/vmudh.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t rsp_vmudh(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t *acc_md, rsp_vec_t *acc_hi)
-{
- *acc_md = _mm_mullo_epi16(vs, vt);
- *acc_hi = _mm_mulhi_epi16(vs, vt);
-
- return sclamp_acc_to_mid(*acc_md, *acc_hi);
-}
diff --git a/src/devices/cpu/rsp/vmul.h b/src/devices/cpu/rsp/vmul.h
deleted file mode 100644
index dc09e81768a..00000000000
--- a/src/devices/cpu/rsp/vmul.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-//
-// TODO: CHECK ME.
-//
-
-inline rsp_vec_t vec_vmulf_vmulu(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_md, rsp_vec_t *acc_hi)
-{
- rsp_vec_t lo = _mm_mullo_epi16(vs, vt);
- rsp_vec_t round = _mm_cmpeq_epi16(zero, zero);
- rsp_vec_t sign1 = _mm_srli_epi16(lo, 15);
- lo = _mm_add_epi16(lo, lo);
- round = _mm_slli_epi16(round, 15);
- rsp_vec_t hi = _mm_mulhi_epi16(vs, vt);
- rsp_vec_t sign2 = _mm_srli_epi16(lo, 15);
- *acc_lo = _mm_add_epi16(round, lo);
- sign1 = _mm_add_epi16(sign1, sign2);
-
- hi = _mm_slli_epi16(hi, 1);
- rsp_vec_t eq = _mm_cmpeq_epi16(vs, vt);
- rsp_vec_t neq = eq;
- *acc_md = _mm_add_epi16(hi, sign1);
-
- rsp_vec_t neg = _mm_srai_epi16(*acc_md, 15);
-
- if (iw & 0x1) // VMULU
- {
- *acc_hi = _mm_andnot_si128(eq, neg);
- hi =_mm_or_si128(*acc_md, neg);
- return _mm_andnot_si128(*acc_hi, hi);
- }
- else // VMULF
- {
- eq = _mm_and_si128(eq, neg);
- *acc_hi = _mm_andnot_si128(neq, neg);
- return _mm_add_epi16(*acc_md, eq);
- }
-}
diff --git a/src/devices/cpu/rsp/vmulh.h b/src/devices/cpu/rsp/vmulh.h
deleted file mode 100644
index 6265961f5a0..00000000000
--- a/src/devices/cpu/rsp/vmulh.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vmadh_vmudh(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_md, rsp_vec_t *acc_hi)
-{
- rsp_vec_t lo = _mm_mullo_epi16(vs, vt);
- rsp_vec_t hi = _mm_mulhi_epi16(vs, vt);
-
- if (iw & 0x8) // VMADH
- {
- // Tricky part: start accumulating everything.
- // Get/keep the carry as we'll add it in later.
- rsp_vec_t overflow_mask = _mm_adds_epu16(*acc_md, lo);
- *acc_md = _mm_add_epi16(*acc_md, lo);
-
- overflow_mask = _mm_cmpeq_epi16(*acc_md, overflow_mask);
- overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero);
-
- hi = _mm_sub_epi16(hi, overflow_mask);
- *acc_hi = _mm_add_epi16(*acc_hi, hi);
- }
- else // VMUDH
- {
- *acc_lo = zero;
- *acc_md = lo;
- *acc_hi = hi;
- }
-
- return sclamp_acc_to_mid(*acc_md, *acc_hi);
-}
diff --git a/src/devices/cpu/rsp/vmull.h b/src/devices/cpu/rsp/vmull.h
deleted file mode 100644
index e54399b01da..00000000000
--- a/src/devices/cpu/rsp/vmull.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vmadl_vmudl(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_md, rsp_vec_t *acc_hi)
-{
- rsp_vec_t hi = _mm_mulhi_epu16(vs, vt);
-
- if (iw & 0x8) // VMADL
- {
- // Tricky part: start accumulating everything.
- // Get/keep the carry as we'll add it in later.
- rsp_vec_t overflow_mask = _mm_adds_epu16(*acc_lo, hi);
- *acc_lo = _mm_add_epi16(*acc_lo, hi);
-
- overflow_mask = _mm_cmpeq_epi16(*acc_lo, overflow_mask);
- overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero);
- hi = _mm_sub_epi16(zero, overflow_mask);
-
- // Check for overflow of the upper sum.
- //
- // TODO: Since hi can only be {0,1}, we should
- // be able to generalize this for performance.
- overflow_mask = _mm_adds_epu16(*acc_md, hi);
- *acc_md = _mm_add_epi16(*acc_md, hi);
-
- overflow_mask = _mm_cmpeq_epi16(*acc_md, overflow_mask);
- overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero);
-
- // Finish up the accumulation of the... accumulator.
- // Since the product was unsigned, only worry about
- // positive overflow (i.e.: borrowing not possible).
- *acc_hi = _mm_sub_epi16(*acc_hi, overflow_mask);
-
- return uclamp_acc(*acc_lo, *acc_md, *acc_hi, zero);
- }
- else // VMUDL
- {
- *acc_lo = hi;
- *acc_md = zero;
- *acc_hi = zero;
-
- return hi;
- }
-}
diff --git a/src/devices/cpu/rsp/vmulm.h b/src/devices/cpu/rsp/vmulm.h
deleted file mode 100644
index df76833ed0c..00000000000
--- a/src/devices/cpu/rsp/vmulm.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vmadm_vmudm(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_md, rsp_vec_t *acc_hi)
-{
- rsp_vec_t lo = _mm_mullo_epi16(vs, vt);
- rsp_vec_t hi = _mm_mulhi_epu16(vs, vt);
-
- // What we really want to do is unsigned vs * signed vt.
- // However, we have no such instructions to do so.
- //
- // There's a trick to "fix" an unsigned product, though:
- // If vt was negative, take the upper 16-bits of the product
- // and subtract vs.
- rsp_vec_t sign = _mm_srai_epi16(vs, 15);
- vt = _mm_and_si128(vt, sign);
- hi = _mm_sub_epi16(hi, vt);
-
- if (iw & 0x8) // VMADM
- {
- // Tricky part: start accumulating everything.
- // Get/keep the carry as we'll add it in later.
- rsp_vec_t overflow_mask = _mm_adds_epu16(*acc_lo, lo);
- *acc_lo = _mm_add_epi16(*acc_lo, lo);
-
- overflow_mask = _mm_cmpeq_epi16(*acc_lo, overflow_mask);
- overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero);
-
- // This is REALLY clever. Since the product results from
- // two 16-bit components, one positive and one negative,
- // we don't have to worry about carrying the 1 (we can
- // only borrow) past 32-bits. So we can just add it here.
- hi = _mm_sub_epi16(hi, overflow_mask);
-
- // Check for overflow of the upper sum.
- overflow_mask = _mm_adds_epu16(*acc_md, hi);
- *acc_md = _mm_add_epi16(*acc_md, hi);
-
- overflow_mask = _mm_cmpeq_epi16(*acc_md, overflow_mask);
- overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero);
-
- // Finish up the accumulation of the... accumulator.
- *acc_hi = _mm_add_epi16(*acc_hi, _mm_srai_epi16(hi, 15));
- *acc_hi = _mm_sub_epi16(*acc_hi, overflow_mask);
-
- return sclamp_acc_to_mid(*acc_md, *acc_hi);
- }
- else // VMUDM
- {
- *acc_lo = lo;
- *acc_md = hi;
- *acc_hi = _mm_srai_epi16(hi, 15);
-
- return hi;
- }
-}
diff --git a/src/devices/cpu/rsp/vmuln.h b/src/devices/cpu/rsp/vmuln.h
deleted file mode 100644
index 07453b631a8..00000000000
--- a/src/devices/cpu/rsp/vmuln.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vmadn_vmudn(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_md, rsp_vec_t *acc_hi)
-{
- rsp_vec_t lo = _mm_mullo_epi16(vs, vt);
- rsp_vec_t hi = _mm_mulhi_epu16(vs, vt);
-
- // What we really want to do is unsigned vs * signed vt.
- // However, we have no such instructions to do so.
- //
- // There's a trick to "fix" an unsigned product, though:
- // If vt was negative, take the upper 16-bits of the product
- // and subtract vs.
- rsp_vec_t sign = _mm_srai_epi16(vt, 15);
- vs = _mm_and_si128(vs, sign);
- hi = _mm_sub_epi16(hi, vs);
-
- if (iw & 0x8) // VMADN
- {
- // Tricky part: start accumulating everything.
- // Get/keep the carry as we'll add it in later.
- rsp_vec_t overflow_mask = _mm_adds_epu16(*acc_lo, lo);
- *acc_lo = _mm_add_epi16(*acc_lo, lo);
-
- overflow_mask = _mm_cmpeq_epi16(*acc_lo, overflow_mask);
- overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero);
-
- // This is REALLY clever. Since the product results from
- // two 16-bit components, one positive and one negative,
- // we don't have to worry about carrying the 1 (we can
- // only borrow) past 32-bits. So we can just add it here.
- hi = _mm_sub_epi16(hi, overflow_mask);
-
- // Check for overflow of the upper sum.
- overflow_mask = _mm_adds_epu16(*acc_md, hi);
- *acc_md = _mm_add_epi16(*acc_md, hi);
-
- overflow_mask = _mm_cmpeq_epi16(*acc_md, overflow_mask);
- overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero);
-
- // Finish up the accumulation of the... accumulator.
- *acc_hi = _mm_add_epi16(*acc_hi, _mm_srai_epi16(hi, 15));
- *acc_hi = _mm_sub_epi16(*acc_hi, overflow_mask);
- return uclamp_acc(*acc_lo, *acc_md, *acc_hi, zero);
- }
- else // VMUDN
- {
- *acc_lo = lo;
- *acc_md = hi;
- *acc_hi = _mm_srai_epi16(hi, 15);
-
- return lo;
- }
-}
diff --git a/src/devices/cpu/rsp/vor.h b/src/devices/cpu/rsp/vor.h
deleted file mode 100644
index 07cbb57164c..00000000000
--- a/src/devices/cpu/rsp/vor.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vor_vnor(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt)
-{
- rsp_vec_t vmask = _mm_load_si128((rsp_vec_t *) m_vec_helpers.logic_mask[iw & 0x1]);
-
- rsp_vec_t vd = _mm_or_si128(vs, vt);
- return _mm_xor_si128(vd, vmask);
-}
diff --git a/src/devices/cpu/rsp/vrcpsq.h b/src/devices/cpu/rsp/vrcpsq.h
deleted file mode 100644
index 4897e536193..00000000000
--- a/src/devices/cpu/rsp/vrcpsq.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vrcp_vrsq(uint32_t iw, int32_t dp, uint32_t src, uint32_t e, uint32_t dest, uint32_t de)
-{
- // Get the element from VT.
- int16_t vt = m_v[src].s[e & 0x7];
-
- uint32_t dp_input = ((uint32_t) m_div_in << 16) | (uint16_t) vt;
- uint32_t sp_input = vt;
-
- int32_t input = (dp) ? dp_input : sp_input;
- int32_t input_mask = input >> 31;
- int32_t data = input ^ input_mask;
-
- if (input > -32768)
- {
- data -= input_mask;
- }
-
- // Handle edge cases.
- int32_t result;
- if (data == 0)
- {
- result = 0x7fffffff;
- }
- else if (input == -32768)
- {
- result = 0xffff0000;
- }
- else // Main case: compute the reciprocal.
- {
- uint32_t shift = count_leading_zeros(data);
- uint32_t idx = (((uint64_t) data << shift) & 0x7FC00000) >> 22;
-
- if (iw & 0x4) // VRSQ
- {
- idx = ((idx | 0x200) & 0x3fe) | (shift % 2);
- result = rsp_divtable[idx];
-
- result = ((0x10000 | result) << 14) >> ((31 - shift) >> 1);
- }
- else // VRCP
- {
- result = rsp_divtable[idx];
-
- result = ((0x10000 | result) << 14) >> (31 - shift);
- }
-
- result = result ^ input_mask;
- }
-
- // Write out the results.
- m_div_out = result >> 16;
- m_v[dest].s[de & 0x7] = result;
-
- return vec_load_unshuffled_operand(m_v[dest].s);
-}
diff --git a/src/devices/cpu/rsp/vrsq.h b/src/devices/cpu/rsp/vrsq.h
deleted file mode 100644
index d4bdb190fec..00000000000
--- a/src/devices/cpu/rsp/vrsq.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-rsp_vec_t vec_vrsq(int32_t dp, uint32_t src, uint32_t e, uint32_t dest, uint32_t de)
-{
- // Get the element from VT.
- int16_t vt = m_v[src].s[e & 0x7];
-
- uint32_t dp_input = ((uint32_t) m_div_in << 16) | (uint16_t) vt;
- uint32_t sp_input = vt;
-
- int32_t input = (dp) ? dp_input : sp_input;
- int32_t input_mask = input >> 31;
- int32_t data = input ^ input_mask;
-
- if (input > -32768)
- {
- data -= input_mask;
- }
-
- // Handle edge cases.
- int32_t result;
- if (data == 0)
- {
- result = 0x7fffffff;
- }
- else if (input == -32768)
- {
- result = 0xffff0000;
- }
- else // Main case: compute the reciprocal.
- {
- uint32_t shift = count_leading_zeros(data);
-
- uint32_t idx = (((uint64_t) data << shift) & 0x7fc00000) >> 22;
- idx = ((idx | 0x200) & 0x3fe) | (shift % 2);
- result = rsp_divtable[idx];
-
- result = ((0x10000 | result) << 14) >> ((31 - shift) >> 1);
- result = result ^ input_mask;
- }
-
- // Write out the results.
- m_div_out = result >> 16;
- m_v[dest].s[de & 0x7] = result;
-
- return vec_load_unshuffled_operand(m_v[dest].s);
-}
-
-rsp_vec_t vec_vrsqh(uint32_t src, uint32_t e, uint32_t dest, uint32_t de)
-{
- int16_t elements[8];
-
- // Get the element from VT.
- memcpy(elements, &m_v[src], sizeof(rsp_vec_t));
- m_div_in = elements[e];
-
- // Write out the upper part of the result.
- rsp_vec_t vd_mask = _mm_load_si128((rsp_vec_t *) m_vec_helpers.vrsq_mask_table[de]);
- rsp_vec_t vd = _mm_load_si128((rsp_vec_t *) &m_v[dest]);
- vd = _mm_andnot_si128(vd_mask, vd);
-
- rsp_vec_t b_result = _mm_set1_epi16(m_div_out);
- b_result = _mm_and_si128(vd_mask, b_result);
- return _mm_or_si128(b_result, vd);
-}
diff --git a/src/devices/cpu/rsp/vsub.h b/src/devices/cpu/rsp/vsub.h
deleted file mode 100644
index c3df93627c8..00000000000
--- a/src/devices/cpu/rsp/vsub.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vsub(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t carry, rsp_vec_t *acc_lo)
-{
- // acc_lo uses saturated arithmetic.
- rsp_vec_t unsat_diff = _mm_sub_epi16(vt, carry);
- rsp_vec_t sat_diff = _mm_subs_epi16(vt, carry);
-
- *acc_lo = _mm_sub_epi16(vs, unsat_diff);
- rsp_vec_t vd = _mm_subs_epi16(vs, sat_diff);
-
- // VD is the signed diff of the two sources and the carry. Since we
- // have to saturate the diff of all three, we have to be clever.
- rsp_vec_t overflow = _mm_cmpgt_epi16(sat_diff, unsat_diff);
- return _mm_adds_epi16(vd, overflow);
-}
diff --git a/src/devices/cpu/rsp/vsubc.h b/src/devices/cpu/rsp/vsubc.h
deleted file mode 100644
index 8632b9462d9..00000000000
--- a/src/devices/cpu/rsp/vsubc.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vsubc(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *eq, rsp_vec_t *sn)
-{
- rsp_vec_t sat_udiff = _mm_subs_epu16(vs, vt);
- rsp_vec_t equal = _mm_cmpeq_epi16(vs, vt);
- rsp_vec_t sat_udiff_zero = _mm_cmpeq_epi16(sat_udiff, zero);
-
- *eq = _mm_cmpeq_epi16(equal, zero);
- *sn = _mm_andnot_si128(equal, sat_udiff_zero);
-
- return _mm_sub_epi16(vs, vt);
-}
diff --git a/src/devices/cpu/rsp/vxor.h b/src/devices/cpu/rsp/vxor.h
deleted file mode 100644
index 9f7f62853c5..00000000000
--- a/src/devices/cpu/rsp/vxor.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Tyler J. Stachecki,Ryan Holtz
-
-inline rsp_vec_t vec_vxor_vnxor(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt)
-{
- rsp_vec_t vmask = _mm_load_si128((rsp_vec_t *) m_vec_helpers.logic_mask[iw & 0x1]);
-
- rsp_vec_t vd = _mm_xor_si128(vs, vt);
- return _mm_xor_si128(vd, vmask);
-}