summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--scripts/src/cpu.lua35
-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
-rw-r--r--src/mame/drivers/aleck64.cpp17
-rw-r--r--src/mame/drivers/n64.cpp16
-rw-r--r--src/mame/includes/n64.h8
-rw-r--r--src/mame/machine/n64.cpp81
-rw-r--r--src/mame/video/n64.cpp1323
-rw-r--r--src/mame/video/n64.h87
-rw-r--r--src/mame/video/n64types.h1
44 files changed, 3574 insertions, 11894 deletions
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index cd1747e05e1..a8969301246 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -13,7 +13,7 @@
-- Dynamic recompiler objects
--------------------------------------------------
-DRC_CPUS = { "E1", "SH", "MIPS3", "POWERPC", "RSP", "ARM7", "ADSP21062", "MB86235", "DSP16", "UNSP" }
+DRC_CPUS = { "E1", "SH", "MIPS3", "POWERPC", "ARM7", "ADSP21062", "MB86235", "DSP16", "UNSP" }
CPU_INCLUDE_DRC = false
for i, v in ipairs(DRC_CPUS) do
if (CPUS[v]~=null) then
@@ -2143,39 +2143,6 @@ if CPUS["RSP"] then
MAME_DIR .. "src/devices/cpu/rsp/rsp.cpp",
MAME_DIR .. "src/devices/cpu/rsp/rsp.h",
MAME_DIR .. "src/devices/cpu/rsp/rspdefs.h",
- MAME_DIR .. "src/devices/cpu/rsp/rspdrc.cpp",
- MAME_DIR .. "src/devices/cpu/rsp/rspfe.cpp",
- MAME_DIR .. "src/devices/cpu/rsp/rspfe.h",
- MAME_DIR .. "src/devices/cpu/rsp/rspcp2.cpp",
- MAME_DIR .. "src/devices/cpu/rsp/rspcp2.h",
- MAME_DIR .. "src/devices/cpu/rsp/rspcp2d.cpp",
- MAME_DIR .. "src/devices/cpu/rsp/rspcp2d.h",
- MAME_DIR .. "src/devices/cpu/rsp/clamp.h",
- MAME_DIR .. "src/devices/cpu/rsp/vabs.h",
- MAME_DIR .. "src/devices/cpu/rsp/vadd.h",
- MAME_DIR .. "src/devices/cpu/rsp/vaddc.h",
- MAME_DIR .. "src/devices/cpu/rsp/vand.h",
- MAME_DIR .. "src/devices/cpu/rsp/vch.h",
- MAME_DIR .. "src/devices/cpu/rsp/vcl.h",
- MAME_DIR .. "src/devices/cpu/rsp/vcmp.h",
- MAME_DIR .. "src/devices/cpu/rsp/vcr.h",
- MAME_DIR .. "src/devices/cpu/rsp/vdivh.h",
- MAME_DIR .. "src/devices/cpu/rsp/vldst.h",
- MAME_DIR .. "src/devices/cpu/rsp/vmac.h",
- MAME_DIR .. "src/devices/cpu/rsp/vmov.h",
- MAME_DIR .. "src/devices/cpu/rsp/vmrg.h",
- MAME_DIR .. "src/devices/cpu/rsp/vmudh.h",
- MAME_DIR .. "src/devices/cpu/rsp/vmul.h",
- MAME_DIR .. "src/devices/cpu/rsp/vmulh.h",
- MAME_DIR .. "src/devices/cpu/rsp/vmull.h",
- MAME_DIR .. "src/devices/cpu/rsp/vmulm.h",
- MAME_DIR .. "src/devices/cpu/rsp/vmuln.h",
- MAME_DIR .. "src/devices/cpu/rsp/vor.h",
- MAME_DIR .. "src/devices/cpu/rsp/vrcpsq.h",
- MAME_DIR .. "src/devices/cpu/rsp/vrsq.h",
- MAME_DIR .. "src/devices/cpu/rsp/vsub.h",
- MAME_DIR .. "src/devices/cpu/rsp/vsubc.h",
- MAME_DIR .. "src/devices/cpu/rsp/vxor.h",
MAME_DIR .. "src/devices/cpu/rsp/rspdiv.h",
}
end
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);
-}
diff --git a/src/mame/drivers/aleck64.cpp b/src/mame/drivers/aleck64.cpp
index b0d380bffe0..b4b66f4464c 100644
--- a/src/mame/drivers/aleck64.cpp
+++ b/src/mame/drivers/aleck64.cpp
@@ -208,7 +208,8 @@ private:
void e90_map(address_map &map);
void n64_map(address_map &map);
- void rsp_map(address_map &map);
+ void rsp_imem_map(address_map &map);
+ void rsp_dmem_map(address_map &map);
optional_shared_ptr<uint32_t> m_e90_vram;
optional_shared_ptr<uint32_t> m_e90_pal;
@@ -380,12 +381,14 @@ void aleck64_state::e90_map(address_map &map)
map(0xd0030000, 0xd003001f).rw(FUNC(aleck64_state::e90_prot_r), FUNC(aleck64_state::e90_prot_w));
}
-void aleck64_state::rsp_map(address_map &map)
+void aleck64_state::rsp_imem_map(address_map &map)
+{
+ map(0x00000000, 0x00000fff).ram().share("rsp_imem");
+}
+
+void aleck64_state::rsp_dmem_map(address_map &map)
{
map(0x00000000, 0x00000fff).ram().share("rsp_dmem");
- map(0x00001000, 0x00001fff).ram().share("rsp_imem");
- map(0x04000000, 0x04000fff).ram().share("rsp_dmem");
- map(0x04001000, 0x04001fff).ram().share("rsp_imem");
}
static INPUT_PORTS_START( aleck64 )
@@ -1044,8 +1047,8 @@ void aleck64_state::aleck64(machine_config &config)
m_rsp->sp_reg_r().set(m_rcp_periphs, FUNC(n64_periphs::sp_reg_r));
m_rsp->sp_reg_w().set(m_rcp_periphs, FUNC(n64_periphs::sp_reg_w));
m_rsp->status_set().set(m_rcp_periphs, FUNC(n64_periphs::sp_set_status));
- m_rsp->set_addrmap(AS_PROGRAM, &aleck64_state::rsp_map);
- m_rsp->set_force_no_drc(true);
+ m_rsp->set_addrmap(AS_PROGRAM, &aleck64_state::rsp_imem_map);
+ m_rsp->set_addrmap(AS_DATA, &aleck64_state::rsp_dmem_map);
screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER));
screen.set_refresh_hz(60);
diff --git a/src/mame/drivers/n64.cpp b/src/mame/drivers/n64.cpp
index 4a94be10476..603c80f68bc 100644
--- a/src/mame/drivers/n64.cpp
+++ b/src/mame/drivers/n64.cpp
@@ -45,7 +45,8 @@ private:
DECLARE_DEVICE_IMAGE_UNLOAD_MEMBER(unload_n64dd);
void n64_map(address_map &map);
void n64dd_map(address_map &map);
- void rsp_map(address_map &map);
+ void rsp_imem_map(address_map &map);
+ void rsp_dmem_map(address_map &map);
};
uint32_t n64_mess_state::dd_null_r()
@@ -96,12 +97,14 @@ void n64_mess_state::n64dd_map(address_map &map)
map(0x1fc007c0, 0x1fc007ff).rw("rcp", FUNC(n64_periphs::pif_ram_r), FUNC(n64_periphs::pif_ram_w));
}
-void n64_mess_state::rsp_map(address_map &map)
+void n64_mess_state::rsp_imem_map(address_map &map)
+{
+ map(0x00000000, 0x00000fff).ram().share("rsp_imem");
+}
+
+void n64_mess_state::rsp_dmem_map(address_map &map)
{
map(0x00000000, 0x00000fff).ram().share("rsp_dmem");
- map(0x00001000, 0x00001fff).ram().share("rsp_imem");
- map(0x04000000, 0x04000fff).ram().share("rsp_dmem");
- map(0x04001000, 0x04001fff).ram().share("rsp_imem");
}
static INPUT_PORTS_START( n64 )
@@ -445,7 +448,8 @@ void n64_mess_state::n64(machine_config &config)
m_rsp->sp_reg_r().set(m_rcp_periphs, FUNC(n64_periphs::sp_reg_r));
m_rsp->sp_reg_w().set(m_rcp_periphs, FUNC(n64_periphs::sp_reg_w));
m_rsp->status_set().set(m_rcp_periphs, FUNC(n64_periphs::sp_set_status));
- m_rsp->set_addrmap(AS_PROGRAM, &n64_mess_state::rsp_map);
+ m_rsp->set_addrmap(AS_PROGRAM, &n64_mess_state::rsp_imem_map);
+ m_rsp->set_addrmap(AS_DATA, &n64_mess_state::rsp_dmem_map);
config.set_maximum_quantum(attotime::from_hz(500000));
diff --git a/src/mame/includes/n64.h b/src/mame/includes/n64.h
index 4dbfc7fe0aa..cfbaa3fbbe5 100644
--- a/src/mame/includes/n64.h
+++ b/src/mame/includes/n64.h
@@ -42,8 +42,6 @@ public:
n64_rdp* rdp() { return m_rdp.get(); }
uint32_t* rdram() { return m_rdram; }
uint32_t* sram() { return m_sram; }
- uint32_t* rsp_imem() { return m_rsp_imem; }
- uint32_t* rsp_dmem() { return m_rsp_dmem; }
protected:
required_device<mips3_device> m_vr4300;
@@ -174,11 +172,11 @@ private:
address_space *m_mem_map;
required_device<mips3_device> m_vr4300;
required_device<rsp_device> m_rsp;
+ required_shared_ptr<uint32_t> m_rsp_imem;
+ required_shared_ptr<uint32_t> m_rsp_dmem;
uint32_t *m_rdram;
uint32_t *m_sram;
- uint32_t *m_rsp_imem;
- uint32_t *m_rsp_dmem;
void clear_rcp_interrupt(int interrupt);
@@ -228,6 +226,8 @@ private:
uint32_t sp_mem_addr;
uint32_t sp_dram_addr;
+ uint32_t sp_mem_addr_start;
+ uint32_t sp_dram_addr_start;
int sp_dma_length;
int sp_dma_count;
int sp_dma_skip;
diff --git a/src/mame/machine/n64.cpp b/src/mame/machine/n64.cpp
index 1db37e4fe72..376a3b6162f 100644
--- a/src/mame/machine/n64.cpp
+++ b/src/mame/machine/n64.cpp
@@ -22,6 +22,8 @@ n64_periphs::n64_periphs(const machine_config &mconfig, const char *tag, device_
, cart_present(false)
, m_vr4300(*this, "^maincpu")
, m_rsp(*this, "^rsp")
+ , m_rsp_imem(*this, "^rsp_imem")
+ , m_rsp_dmem(*this, "^rsp_dmem")
, ai_dac(*this, "^dac%u", 1U)
{
for (int32_t i = 0; i < 256; i++)
@@ -130,8 +132,6 @@ void n64_periphs::device_reset()
m_mem_map = &m_vr4300->space(AS_PROGRAM);
m_rdram = m_n64->rdram();
- m_rsp_imem = m_n64->rsp_imem();
- m_rsp_dmem = m_n64->rsp_dmem();
m_sram = m_n64->sram();
mi_version = 0x01010101;
@@ -141,6 +141,8 @@ void n64_periphs::device_reset()
sp_mem_addr = 0;
sp_dram_addr = 0;
+ sp_mem_addr_start = 0;
+ sp_dram_addr_start = 0;
sp_dma_length = 0;
sp_dma_count = 0;
sp_dma_skip = 0;
@@ -546,6 +548,9 @@ void n64_periphs::rdram_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask)
void n64_periphs::sp_dma(int direction)
{
+ sp_mem_addr = sp_mem_addr_start;
+ sp_dram_addr = sp_dram_addr_start;
+
uint32_t length = sp_dma_length + 1;
if ((length & 7) != 0)
@@ -571,17 +576,16 @@ void n64_periphs::sp_dma(int direction)
int sp_mem_page = (sp_mem_addr >> 12) & 1;
- if(sp_mem_page == 1)
- m_rsp->rspdrc_flush_drc_cache();
+ //printf("DMA %s RSP: mem %08x, dram %08x, sp_dma_length: %03x, length: %04x, count: %02x, skip: %03x\n", direction ? "from" : "to", sp_mem_addr, sp_dram_addr, sp_dma_length, length, sp_dma_count, sp_dma_skip);
- if(direction == 0)// RDRAM -> I/DMEM
+ if (direction == 0)// RDRAM -> I/DMEM
{
- for(int c = 0; c <= sp_dma_count; c++)
+ for (int c = 0; c <= sp_dma_count; c++)
{
- uint32_t src = (sp_dram_addr & 0x007fffff) >> 2;
+ uint32_t src = sp_dram_addr >> 2;
uint32_t dst = (sp_mem_addr & 0xfff) >> 2;
- for(int i = 0; i < length / 4; i++)
+ for (int i = 0; i < length / 4; i++)
{
sp_mem[sp_mem_page][(dst + i) & 0x3ff] = m_rdram[src + i];
}
@@ -589,17 +593,18 @@ void n64_periphs::sp_dma(int direction)
sp_mem_addr += length;
sp_dram_addr += length;
- sp_dram_addr += sp_dma_skip;
+ if (c != sp_dma_count)
+ sp_dram_addr += sp_dma_skip;
}
}
else // I/DMEM -> RDRAM
{
- for(int c = 0; c <= sp_dma_count; c++)
+ for (int c = 0; c <= sp_dma_count; c++)
{
uint32_t src = (sp_mem_addr & 0xfff) >> 2;
- uint32_t dst = (sp_dram_addr & 0x007fffff) >> 2;
+ uint32_t dst = sp_dram_addr >> 2;
- for(int i = 0; i < length / 4; i++)
+ for (int i = 0; i < length / 4; i++)
{
m_rdram[dst + i] = sp_mem[sp_mem_page][(src + i) & 0x3ff];
}
@@ -607,9 +612,13 @@ void n64_periphs::sp_dma(int direction)
sp_mem_addr += length;
sp_dram_addr += length;
- sp_dram_addr += sp_dma_skip;
+ if (c != sp_dma_count)
+ sp_dram_addr += sp_dma_skip;
}
}
+
+ sp_dma_count = 0;
+ sp_dma_length = 0xff8;
}
void n64_periphs::sp_set_status(uint32_t data)
@@ -642,6 +651,7 @@ uint32_t n64_periphs::sp_reg_r(offs_t offset)
return sp_dram_addr;
case 0x08/4: // SP_RD_LEN_REG
+ case 0x0c/4: // SP_WR_LEN_REG
return (sp_dma_skip << 20) | (sp_dma_count << 12) | sp_dma_length;
case 0x10/4: // SP_STATUS_REG
@@ -710,24 +720,24 @@ void n64_periphs::sp_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask)
switch (offset & 0xffff)
{
case 0x00/4: // SP_MEM_ADDR_REG
- sp_mem_addr = data;
+ sp_mem_addr_start = data & 0x00001fff;
break;
case 0x04/4: // SP_DRAM_ADDR_REG
- sp_dram_addr = data & 0xffffff;
+ sp_dram_addr_start = data & 0x007fffff;
break;
case 0x08/4: // SP_RD_LEN_REG
sp_dma_length = data & 0xfff;
sp_dma_count = (data >> 12) & 0xff;
- sp_dma_skip = (data >> 20) & 0xfff;
+ sp_dma_skip = (data >> 20) & 0xff8;
sp_dma(0);
break;
case 0x0c/4: // SP_WR_LEN_REG
sp_dma_length = data & 0xfff;
sp_dma_count = (data >> 12) & 0xff;
- sp_dma_skip = (data >> 20) & 0xfff;
+ sp_dma_skip = (data >> 20) & 0xff8;
sp_dma(1);
break;
@@ -864,13 +874,13 @@ void n64_periphs::sp_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask)
switch (offset & 0xffff)
{
case 0x00/4: // SP_PC_REG
- if( m_rsp->state_int(RSP_NEXTPC) != 0xffffffff )
+ if (m_rsp->state_int(RSP_NEXTPC) != 0xffff)
{
- m_rsp->set_state_int(RSP_NEXTPC, 0x1000 | (data & 0xfff));
+ m_rsp->set_state_int(RSP_NEXTPC, data & 0xfff);
}
else
{
- m_rsp->set_state_int(RSP_PC, 0x1000 | (data & 0xfff));
+ m_rsp->set_state_int(RSP_PC, data & 0xfff);
}
break;
@@ -998,8 +1008,10 @@ void n64_periphs::vi_recalculate_resolution()
int x_end = vi_hstart & 0x000003ff;
int y_start = ((vi_vstart & 0x03ff0000) >> 16) >> 1;
int y_end = (vi_vstart & 0x000003ff) >> 1;
- int width = x_end - x_start;
- int height = y_end - y_start;
+ const float hcoeff = ((float)(vi_xscale & 0xfff) / (1 << 10));
+ const float vcoeff = ((float)(vi_yscale & 0xfff) / (1 << 10));
+ int width = (x_end - x_start) * hcoeff;
+ int height = (y_end - y_start) * vcoeff;
rectangle visarea = screen().visible_area();
// DACRATE is the quarter pixel clock and period will be for a field, not a frame
@@ -1494,6 +1506,14 @@ uint32_t n64_periphs::pi_reg_r(offs_t offset, uint32_t mem_mask)
ret = pi_cart_addr;
break;
+ case 0x08/4: // PI_RD_LEN_REG
+ ret = pi_rd_len;
+ break;
+
+ case 0x0c/4: // PI_WR_LEN_REG
+ ret = pi_wr_len;
+ break;
+
case 0x10/4: // PI_STATUS_REG
ret = pi_status;
break;
@@ -1543,13 +1563,10 @@ void n64_periphs::pi_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask)
switch (offset)
{
case 0x00/4: // PI_DRAM_ADDR_REG
- {
pi_dram_addr = data;
break;
- }
case 0x04/4: // PI_CART_ADDR_REG
- {
pi_cart_addr = data;
if(pi_cart_addr == 0x05000400 && dd_present)
{
@@ -1566,15 +1583,15 @@ void n64_periphs::pi_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask)
m_vr4300->set_input_line(INPUT_LINE_IRQ1, CLEAR_LINE);
}
break;
- }
case 0x08/4: // PI_RD_LEN_REG
{
+ //printf("pi_rd_len_reg: %08x\n", data);
//logerror("Start PI Read\n");
pi_rd_len = data;
pi_dma_dir = 0;
pi_status |= 1;
-
+ //pi_dma_tick();
attotime dma_period = attotime::from_hz(93750000) * (int)((float)(pi_rd_len + 1) * 5.08f); // Measured as between 2.53 cycles per byte and 2.55 cycles per byte
pi_dma_timer->adjust(dma_period);
break;
@@ -1582,11 +1599,12 @@ void n64_periphs::pi_reg_w(offs_t offset, uint32_t data, uint32_t mem_mask)
case 0x0c/4: // PI_WR_LEN_REG
{
+ //printf("pi_wr_len_reg: %08x\n", data);
//logerror("Start PI Write\n");
pi_wr_len = data;
pi_dma_dir = 1;
pi_status |= 1;
-
+ //pi_dma_tick();
attotime dma_period = attotime::from_hz(93750000) * (int)((float)(pi_wr_len + 1) * 5.08f); // Measured as between 2.53 cycles per byte and 2.55 cycles per byte
pi_dma_timer->adjust(dma_period);
break;
@@ -1762,6 +1780,7 @@ int n64_periphs::pif_channel_handle_command(int channel, int slength, uint8_t *s
}
case 4:
{
+ //printf("Read EEPROM status, type: %02x\n", (machine().root_device().ioport("input")->read() >> 8) & 0xC0);
// Read EEPROM status
rdata[0] = 0x00;
rdata[1] = (machine().root_device().ioport("input")->read() >> 8) & 0xC0;
@@ -1928,6 +1947,7 @@ int n64_periphs::pif_channel_handle_command(int channel, int slength, uint8_t *s
case 0x04: // Read from EEPROM
{
+ //printf("Read from EEPROM, channel %d: slength %d, rlength %d, sdata[1] %02x\n", channel, slength, rlength, sdata[1]);
if (channel != 4)
{
return 1;
@@ -2752,11 +2772,6 @@ void n64_state::machine_start()
/* configure fast RAM regions */
//m_vr4300->add_fastram(0x00000000, 0x007fffff, false, m_rdram);
- m_rsp->rspdrc_set_options(RSPDRC_STRICT_VERIFY);
- m_rsp->rspdrc_flush_drc_cache();
- m_rsp->rsp_add_dmem(m_rsp_dmem);
- m_rsp->rsp_add_imem(m_rsp_imem);
-
/* add a hook for battery save */
machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&n64_state::n64_machine_stop,this));
}
diff --git a/src/mame/video/n64.cpp b/src/mame/video/n64.cpp
index 5268e642323..ea42b9786c9 100644
--- a/src/mame/video/n64.cpp
+++ b/src/mame/video/n64.cpp
@@ -33,6 +33,12 @@ TODO:
#include <algorithm>
#define LOG_RDP_EXECUTION 0
+#define DEBUG_RDP_PIXEL 0
+#define DRAW_FRAME_COUNTER 0
+
+#if DEBUG_RDP_PIXEL
+static bool s_debug_drawing = false;
+#endif
static FILE* rdp_exec;
@@ -234,8 +240,44 @@ void n64_periphs::video_update16(bitmap_rgb32 &bitmap)
vres = bitmap.height();
}
+#if DRAW_FRAME_COUNTER
+ static uint32_t frame_num = 0;
+ static const uint8_t s_numbers[10][9] = {
+ { 0x00, 0x3c, 0x66, 0x6e, 0x7e, 0x76, 0x66, 0x3c, 0x00 },
+ { 0x00, 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00 },
+ { 0x00, 0x3c, 0x66, 0x06, 0x3c, 0x60, 0x60, 0x7e, 0x00 },
+ { 0x00, 0x3c, 0x66, 0x06, 0x0c, 0x06, 0x66, 0x3c, 0x00 },
+ { 0x00, 0x66, 0x66, 0x66, 0x7e, 0x06, 0x06, 0x06, 0x00 },
+ { 0x00, 0x7e, 0x60, 0x60, 0x7c, 0x06, 0x66, 0x3c, 0x00 },
+ { 0x00, 0x3c, 0x66, 0x60, 0x7c, 0x66, 0x66, 0x3c, 0x00 },
+ { 0x00, 0x7e, 0x66, 0x06, 0x0c, 0x18, 0x18, 0x18, 0x00 },
+ { 0x00, 0x3c, 0x66, 0x66, 0x3c, 0x66, 0x66, 0x3c, 0x00 },
+ { 0x00, 0x3c, 0x66, 0x66, 0x3e, 0x06, 0x66, 0x3c, 0x00 }
+ };
+#endif
+
if (frame_buffer)
{
+#if DRAW_FRAME_COUNTER
+ uint32_t digits[4] = { (frame_num / 1000) % 10, (frame_num / 100) % 10, (frame_num / 10) % 10, frame_num % 10 };
+
+ for (int32_t d = 0; d < 4; d++)
+ {
+ for (int32_t y = 0; y < 9; y++)
+ {
+ const uint8_t *pixdata = s_numbers[digits[d]];
+ for (int32_t x = 0; x < 8; x++)
+ {
+ frame_buffer[((y + 16) * vi_width + d * 8 + x + 16) ^ WORD_ADDR_XOR] = BIT(pixdata[y], 7 - x) ? 0x0000 : 0xffff;
+ }
+ }
+ }
+#if DEBUG_RDP_PIXEL
+ s_debug_drawing = (frame_num == 1392);
+#endif
+ frame_num++;
+#endif
+
const uint32_t aa_control = (vi_control >> 8) & 3;
float v0 = 0.0f;
if (aa_control < 3) // Resample pixels
@@ -296,7 +338,7 @@ void n64_periphs::video_update16(bitmap_rgb32 &bitmap)
uint8_t g8 = std::clamp((uint8_t)g, (uint8_t)0, (uint8_t)255);
uint8_t b8 = std::clamp((uint8_t)b, (uint8_t)0, (uint8_t)255);
- d[i] = (r8 << 16) | (g8 << 8) | b8;
+ d[iu0] = (r8 << 16) | (g8 << 8) | b8;
u0 += hcoeff;
}
@@ -319,7 +361,7 @@ void n64_periphs::video_update16(bitmap_rgb32 &bitmap)
const uint8_t r = ((pix >> 8) & 0xf8) | (pix >> 13);
const uint8_t g = ((pix >> 3) & 0xf8) | ((pix >> 8) & 0x07);
const uint8_t b = ((pix << 2) & 0xf8) | ((pix >> 3) & 0x07);
- d[i] = (r << 16) | (g << 8) | b;
+ d[u0] = (r << 16) | (g << 8) | b;
}
}
}
@@ -334,11 +376,15 @@ void n64_periphs::video_update32(bitmap_rgb32 &bitmap)
uint32_t* frame_buffer32 = (uint32_t*)&m_rdram[(vi_origin & 0xffffff) >> 2];
- const int32_t hdiff = (vi_hstart & 0x3ff) - ((vi_hstart >> 16) & 0x3ff);
+ int32_t hend = vi_hstart & 0x3ff;
+ int32_t hstart = (vi_hstart >> 16) & 0x3ff;
+ int32_t hdiff = hend - hstart;
const float hcoeff = ((float)(vi_xscale & 0xfff) / (1 << 10));
uint32_t hres = ((float)hdiff * hcoeff);
- const int32_t vdiff = ((vi_vstart & 0x3ff) - ((vi_vstart >> 16) & 0x3ff)) >> 1;
+ int32_t vend = (vi_vstart & 0x3ff) >> 1;
+ int32_t vstart = ((vi_vstart >> 16) & 0x3ff) >> 1;
+ int32_t vdiff = vend - vstart;
const float vcoeff = ((float)(vi_yscale & 0xfff) / (1 << 10));
const uint32_t vres = ((float)vdiff * vcoeff);
@@ -347,13 +393,15 @@ void n64_periphs::video_update32(bitmap_rgb32 &bitmap)
return;
}
+ //printf("hd,vd: %d,%d hc,vc: %f,%f hs,he: %d,%d vs,ve: %d,%d hr,vr: %d, %d viw: %d\n", hdiff, vdiff, hcoeff, vcoeff, hstart, hend, vstart, vend, hres, vres, vi_width);
+
if (frame_buffer32)
{
const uint32_t aa_control = (vi_control >> 8) & 3;
float v0 = 0.0f;
if (aa_control < 3) // Resample pixels
{
- for (int32_t j = 0; j < vdiff; j++, v0 += vcoeff)
+ for (int32_t j = 0; j < vres; j++, v0 += 1.0f)
{
uint32_t *const d = &bitmap.pix(j);
@@ -374,21 +422,21 @@ void n64_periphs::video_update32(bitmap_rgb32 &bitmap)
uint32_t pix01 = frame_buffer32[pix_v1_line + iu0];
uint32_t pix11 = frame_buffer32[pix_v1_line + iu1];
- const uint8_t r00 = (uint8_t)(pix00 >> 16);
- const uint8_t g00 = (uint8_t)(pix00 >> 8);
- const uint8_t b00 = (uint8_t)pix00;
+ const uint8_t r00 = (uint8_t)(pix00 >> 24);
+ const uint8_t g00 = (uint8_t)(pix00 >> 16);
+ const uint8_t b00 = (uint8_t)(pix00 >> 8);
- const uint8_t r10 = (uint8_t)(pix01 >> 16);
- const uint8_t g10 = (uint8_t)(pix01 >> 8);
- const uint8_t b10 = (uint8_t)pix01;
+ const uint8_t r10 = (uint8_t)(pix01 >> 24);
+ const uint8_t g10 = (uint8_t)(pix01 >> 16);
+ const uint8_t b10 = (uint8_t)(pix01 >> 8);
- const uint8_t r01 = (uint8_t)(pix10 >> 16);
- const uint8_t g01 = (uint8_t)(pix10 >> 8);
- const uint8_t b01 = (uint8_t)pix10;
+ const uint8_t r01 = (uint8_t)(pix10 >> 24);
+ const uint8_t g01 = (uint8_t)(pix10 >> 16);
+ const uint8_t b01 = (uint8_t)(pix10 >> 8);
- const uint8_t r11 = (uint8_t)(pix11 >> 16);
- const uint8_t g11 = (uint8_t)(pix11 >> 8);
- const uint8_t b11 = (uint8_t)pix11;
+ const uint8_t r11 = (uint8_t)(pix11 >> 24);
+ const uint8_t g11 = (uint8_t)(pix11 >> 16);
+ const uint8_t b11 = (uint8_t)(pix11 >> 8);
const float ut = u0 - (int)u0;
const float vt = v0 - (int)v0;
@@ -409,7 +457,7 @@ void n64_periphs::video_update32(bitmap_rgb32 &bitmap)
uint8_t g8 = std::clamp((uint8_t)g, (uint8_t)0, (uint8_t)255);
uint8_t b8 = std::clamp((uint8_t)b, (uint8_t)0, (uint8_t)255);
- d[i] = (r8 << 16) | (g8 << 8) | b8;
+ d[iu0] = (r8 << 16) | (g8 << 8) | b8;
u0 += hcoeff;
}
@@ -427,7 +475,7 @@ void n64_periphs::video_update32(bitmap_rgb32 &bitmap)
for (int32_t i = 0; i < hdiff; i++)
{
int u0 = (int)(i * hcoeff);
- d[i] = (frame_buffer32[pix_v0_line + u0] >> 8);
+ d[u0] = (frame_buffer32[pix_v0_line + u0] >> 8);
}
}
}
@@ -1277,7 +1325,7 @@ int32_t const n64_rdp::s_rdp_command_length[64] =
8 // 0x3f, Set_Color_Image
};
-void n64_rdp::disassemble(char* buffer)
+void n64_rdp::disassemble(uint64_t *cmd_buf, char* buffer)
{
char sl[32], tl[32], sh[32], th[32];
char s[32], t[32], w[32];
@@ -1291,126 +1339,84 @@ void n64_rdp::disassemble(char* buffer)
char drdy[32], dgdy[32], dbdy[32], dady[32];
char drde[32], dgde[32], dbde[32], dade[32];
- uint64_t cmd[32];
+ const int32_t tile = (cmd_buf[0] >> 56) & 0x7;
+ sprintf(sl, "%4.2f", (float)((cmd_buf[0] >> 44) & 0xfff) / 4.0f);
+ sprintf(tl, "%4.2f", (float)((cmd_buf[0] >> 32) & 0xfff) / 4.0f);
+ sprintf(sh, "%4.2f", (float)((cmd_buf[0] >> 12) & 0xfff) / 4.0f);
+ sprintf(th, "%4.2f", (float)((cmd_buf[0] >> 0) & 0xfff) / 4.0f);
- const uint32_t length = m_cmd_ptr * 8;
- if (length < 8)
- {
- sprintf(buffer, "ERROR: length = %d\n", length);
- return;
- }
-
- cmd[0] = m_cmd_data[m_cmd_cur];
+ const char* format = s_image_format[(cmd_buf[0] >> 53) & 0x7];
+ const char* size = s_image_size[(cmd_buf[0] >> 51) & 0x3];
- const int32_t tile = (cmd[0] >> 56) & 0x7;
- sprintf(sl, "%4.2f", (float)((cmd[0] >> 44) & 0xfff) / 4.0f);
- sprintf(tl, "%4.2f", (float)((cmd[0] >> 32) & 0xfff) / 4.0f);
- sprintf(sh, "%4.2f", (float)((cmd[0] >> 12) & 0xfff) / 4.0f);
- sprintf(th, "%4.2f", (float)((cmd[0] >> 0) & 0xfff) / 4.0f);
+ const uint32_t r = (cmd_buf[0] >> 24) & 0xff;
+ const uint32_t g = (cmd_buf[0] >> 16) & 0xff;
+ const uint32_t b = (cmd_buf[0] >> 8) & 0xff;
+ const uint32_t a = (cmd_buf[0] >> 0) & 0xff;
- const char* format = s_image_format[(cmd[0] >> 53) & 0x7];
- const char* size = s_image_size[(cmd[0] >> 51) & 0x3];
-
- const uint32_t r = (cmd[0] >> 24) & 0xff;
- const uint32_t g = (cmd[0] >> 16) & 0xff;
- const uint32_t b = (cmd[0] >> 8) & 0xff;
- const uint32_t a = (cmd[0] >> 0) & 0xff;
-
- const uint32_t command = (cmd[0] >> 56) & 0x3f;
+ const uint32_t command = (cmd_buf[0] >> 56) & 0x3f;
switch (command)
{
case 0x00: sprintf(buffer, "No Op"); break;
case 0x08: // Tri_NoShade
{
- const int32_t lft = (cmd[0] >> 55) & 0x1;
-
- if (length != s_rdp_command_length[command])
- {
- sprintf(buffer, "ERROR: Tri_NoShade length = %d\n", length);
- return;
- }
-
- cmd[1] = m_cmd_data[m_cmd_cur+1];
- cmd[2] = m_cmd_data[m_cmd_cur+2];
- cmd[3] = m_cmd_data[m_cmd_cur+3];
-
- sprintf(yl, "%4.4f", (float)((cmd[0] >> 32) & 0x1fff) / 4.0f);
- sprintf(ym, "%4.4f", (float)((cmd[0] >> 16) & 0x1fff) / 4.0f);
- sprintf(yh, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
- sprintf(xl, "%4.4f", (float)int32_t(cmd[1] >> 32) / 65536.0f);
- sprintf(dxldy, "%4.4f", (float)int32_t(cmd[1]) / 65536.0f);
- sprintf(xh, "%4.4f", (float)int32_t(cmd[2] >> 32) / 65536.0f);
- sprintf(dxhdy, "%4.4f", (float)int32_t(cmd[2]) / 65536.0f);
- sprintf(xm, "%4.4f", (float)int32_t(cmd[3] >> 32) / 65536.0f);
- sprintf(dxmdy, "%4.4f", (float)int32_t(cmd[3]) / 65536.0f);
+ const int32_t lft = (cmd_buf[0] >> 55) & 0x1;
+
+ sprintf(yl, "%4.4f", (float)((cmd_buf[0] >> 32) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd_buf[0] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd_buf[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)int32_t(cmd_buf[1] >> 32) / 65536.0f);
+ sprintf(dxldy, "%4.4f", (float)int32_t(cmd_buf[1]) / 65536.0f);
+ sprintf(xh, "%4.4f", (float)int32_t(cmd_buf[2] >> 32) / 65536.0f);
+ sprintf(dxhdy, "%4.4f", (float)int32_t(cmd_buf[2]) / 65536.0f);
+ sprintf(xm, "%4.4f", (float)int32_t(cmd_buf[3] >> 32) / 65536.0f);
+ sprintf(dxmdy, "%4.4f", (float)int32_t(cmd_buf[3]) / 65536.0f);
sprintf(buffer, "Tri_NoShade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
break;
}
case 0x09: // Tri_NoShadeZ
{
- const int32_t lft = (cmd[0] >> 55) & 0x1;
-
- if (length != s_rdp_command_length[command])
- {
- sprintf(buffer, "ERROR: Tri_NoShadeZ length = %d\n", length);
- return;
- }
-
- cmd[1] = m_cmd_data[m_cmd_cur+1];
- cmd[2] = m_cmd_data[m_cmd_cur+2];
- cmd[3] = m_cmd_data[m_cmd_cur+3];
-
- sprintf(yl, "%4.4f", (float)((cmd[0] >> 32) & 0x1fff) / 4.0f);
- sprintf(ym, "%4.4f", (float)((cmd[0] >> 16) & 0x1fff) / 4.0f);
- sprintf(yh, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
- sprintf(xl, "%4.4f", (float)int32_t(cmd[1] >> 32) / 65536.0f);
- sprintf(dxldy, "%4.4f", (float)int32_t(cmd[1]) / 65536.0f);
- sprintf(xh, "%4.4f", (float)int32_t(cmd[2] >> 32) / 65536.0f);
- sprintf(dxhdy, "%4.4f", (float)int32_t(cmd[2]) / 65536.0f);
- sprintf(xm, "%4.4f", (float)int32_t(cmd[3] >> 32) / 65536.0f);
- sprintf(dxmdy, "%4.4f", (float)int32_t(cmd[3]) / 65536.0f);
+ const int32_t lft = (cmd_buf[0] >> 55) & 0x1;
+
+ sprintf(yl, "%4.4f", (float)((cmd_buf[0] >> 32) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd_buf[0] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd_buf[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)int32_t(cmd_buf[1] >> 32) / 65536.0f);
+ sprintf(dxldy, "%4.4f", (float)int32_t(cmd_buf[1]) / 65536.0f);
+ sprintf(xh, "%4.4f", (float)int32_t(cmd_buf[2] >> 32) / 65536.0f);
+ sprintf(dxhdy, "%4.4f", (float)int32_t(cmd_buf[2]) / 65536.0f);
+ sprintf(xm, "%4.4f", (float)int32_t(cmd_buf[3] >> 32) / 65536.0f);
+ sprintf(dxmdy, "%4.4f", (float)int32_t(cmd_buf[3]) / 65536.0f);
sprintf(buffer, "Tri_NoShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
break;
}
case 0x0a: // Tri_Tex
{
- const int32_t lft = (cmd[0] >> 55) & 0x1;
-
- if (length < s_rdp_command_length[command])
- {
- sprintf(buffer, "ERROR: Tri_Tex length = %d\n", length);
- return;
- }
-
- for (int32_t i = 1; i < 12; i++)
- {
- cmd[i] = m_cmd_data[m_cmd_cur+i];
- }
-
- sprintf(yl, "%4.4f", (float)((cmd[0] >> 32) & 0x1fff) / 4.0f);
- sprintf(ym, "%4.4f", (float)((cmd[0] >> 16) & 0x1fff) / 4.0f);
- sprintf(yh, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
- sprintf(xl, "%4.4f", (float)int32_t(cmd[1] >> 32) / 65536.0f);
- sprintf(dxldy, "%4.4f", (float)int32_t(cmd[1]) / 65536.0f);
- sprintf(xh, "%4.4f", (float)int32_t(cmd[2] >> 32) / 65536.0f);
- sprintf(dxhdy, "%4.4f", (float)int32_t(cmd[2]) / 65536.0f);
- sprintf(xm, "%4.4f", (float)int32_t(cmd[3] >> 32) / 65536.0f);
- sprintf(dxmdy, "%4.4f", (float)int32_t(cmd[3]) / 65536.0f);
-
- sprintf(s, "%4.4f", (float)int32_t( ((cmd[4] >> 32) & 0xffff0000) | ((cmd[ 6] >> 48) & 0xffff)) / 65536.0f);
- sprintf(t, "%4.4f", (float)int32_t((((cmd[4] >> 32) & 0x0000ffff) << 16) | ((cmd[ 6] >> 32) & 0xffff)) / 65536.0f);
- sprintf(w, "%4.4f", (float)int32_t( (cmd[4] & 0xffff0000) | ((cmd[ 6] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsdx, "%4.4f", (float)int32_t( ((cmd[5] >> 32) & 0xffff0000) | ((cmd[ 7] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtdx, "%4.4f", (float)int32_t((((cmd[5] >> 32) & 0x0000ffff) << 16) | ((cmd[ 7] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwdx, "%4.4f", (float)int32_t( (cmd[5] & 0xffff0000) | ((cmd[ 7] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsde, "%4.4f", (float)int32_t( ((cmd[8] >> 32) & 0xffff0000) | ((cmd[10] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtde, "%4.4f", (float)int32_t((((cmd[8] >> 32) & 0x0000ffff) << 16) | ((cmd[10] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwde, "%4.4f", (float)int32_t( (cmd[8] & 0xffff0000) | ((cmd[10] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsdy, "%4.4f", (float)int32_t( ((cmd[9] >> 32) & 0xffff0000) | ((cmd[11] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtdy, "%4.4f", (float)int32_t((((cmd[9] >> 32) & 0x0000ffff) << 16) | ((cmd[11] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwdy, "%4.4f", (float)int32_t( (cmd[9] & 0xffff0000) | ((cmd[11] >> 16) & 0xffff)) / 65536.0f);
+ const int32_t lft = (cmd_buf[0] >> 55) & 0x1;
+
+ sprintf(yl, "%4.4f", (float)((cmd_buf[0] >> 32) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd_buf[0] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd_buf[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)int32_t(cmd_buf[1] >> 32) / 65536.0f);
+ sprintf(dxldy, "%4.4f", (float)int32_t(cmd_buf[1]) / 65536.0f);
+ sprintf(xh, "%4.4f", (float)int32_t(cmd_buf[2] >> 32) / 65536.0f);
+ sprintf(dxhdy, "%4.4f", (float)int32_t(cmd_buf[2]) / 65536.0f);
+ sprintf(xm, "%4.4f", (float)int32_t(cmd_buf[3] >> 32) / 65536.0f);
+ sprintf(dxmdy, "%4.4f", (float)int32_t(cmd_buf[3]) / 65536.0f);
+
+ sprintf(s, "%4.4f", (float)int32_t( ((cmd_buf[4] >> 32) & 0xffff0000) | ((cmd_buf[ 6] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(t, "%4.4f", (float)int32_t((((cmd_buf[4] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 6] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(w, "%4.4f", (float)int32_t( (cmd_buf[4] & 0xffff0000) | ((cmd_buf[ 6] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdx, "%4.4f", (float)int32_t( ((cmd_buf[5] >> 32) & 0xffff0000) | ((cmd_buf[ 7] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtdx, "%4.4f", (float)int32_t((((cmd_buf[5] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 7] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwdx, "%4.4f", (float)int32_t( (cmd_buf[5] & 0xffff0000) | ((cmd_buf[ 7] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsde, "%4.4f", (float)int32_t( ((cmd_buf[8] >> 32) & 0xffff0000) | ((cmd_buf[10] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtde, "%4.4f", (float)int32_t((((cmd_buf[8] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[10] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwde, "%4.4f", (float)int32_t( (cmd_buf[8] & 0xffff0000) | ((cmd_buf[10] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdy, "%4.4f", (float)int32_t( ((cmd_buf[9] >> 32) & 0xffff0000) | ((cmd_buf[11] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtdy, "%4.4f", (float)int32_t((((cmd_buf[9] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[11] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwdy, "%4.4f", (float)int32_t( (cmd_buf[9] & 0xffff0000) | ((cmd_buf[11] >> 16) & 0xffff)) / 65536.0f);
buffer+=sprintf(buffer, "Tri_Tex %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
buffer+=sprintf(buffer, " ");
@@ -1425,41 +1431,30 @@ void n64_rdp::disassemble(char* buffer)
}
case 0x0b: // Tri_TexZ
{
- const int32_t lft = (cmd[0] >> 55) & 0x1;
-
- if (length < s_rdp_command_length[command])
- {
- sprintf(buffer, "ERROR: Tri_TexZ length = %d\n", length);
- return;
- }
-
- for (int32_t i = 1; i < 12; i++)
- {
- cmd[i] = m_cmd_data[m_cmd_cur+i];
- }
-
- sprintf(yl, "%4.4f", (float)((cmd[0] >> 32) & 0x1fff) / 4.0f);
- sprintf(ym, "%4.4f", (float)((cmd[0] >> 16) & 0x1fff) / 4.0f);
- sprintf(yh, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
- sprintf(xl, "%4.4f", (float)int32_t(cmd[1] >> 32) / 65536.0f);
- sprintf(dxldy, "%4.4f", (float)int32_t(cmd[1]) / 65536.0f);
- sprintf(xh, "%4.4f", (float)int32_t(cmd[2] >> 32) / 65536.0f);
- sprintf(dxhdy, "%4.4f", (float)int32_t(cmd[2]) / 65536.0f);
- sprintf(xm, "%4.4f", (float)int32_t(cmd[3] >> 32) / 65536.0f);
- sprintf(dxmdy, "%4.4f", (float)int32_t(cmd[3]) / 65536.0f);
-
- sprintf(s, "%4.4f", (float)int32_t( ((cmd[4] >> 32) & 0xffff0000) | ((cmd[ 6] >> 48) & 0xffff)) / 65536.0f);
- sprintf(t, "%4.4f", (float)int32_t((((cmd[4] >> 32) & 0x0000ffff) << 16) | ((cmd[ 6] >> 32) & 0xffff)) / 65536.0f);
- sprintf(w, "%4.4f", (float)int32_t( (cmd[4] & 0xffff0000) | ((cmd[ 6] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsdx, "%4.4f", (float)int32_t( ((cmd[5] >> 32) & 0xffff0000) | ((cmd[ 7] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtdx, "%4.4f", (float)int32_t((((cmd[5] >> 32) & 0x0000ffff) << 16) | ((cmd[ 7] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwdx, "%4.4f", (float)int32_t( (cmd[5] & 0xffff0000) | ((cmd[ 7] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsde, "%4.4f", (float)int32_t( ((cmd[8] >> 32) & 0xffff0000) | ((cmd[10] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtde, "%4.4f", (float)int32_t((((cmd[8] >> 32) & 0x0000ffff) << 16) | ((cmd[10] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwde, "%4.4f", (float)int32_t( (cmd[8] & 0xffff0000) | ((cmd[10] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsdy, "%4.4f", (float)int32_t( ((cmd[9] >> 32) & 0xffff0000) | ((cmd[11] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtdy, "%4.4f", (float)int32_t((((cmd[9] >> 32) & 0x0000ffff) << 16) | ((cmd[11] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwdy, "%4.4f", (float)int32_t( (cmd[9] & 0xffff0000) | ((cmd[11] >> 16) & 0xffff)) / 65536.0f);
+ const int32_t lft = (cmd_buf[0] >> 55) & 0x1;
+
+ sprintf(yl, "%4.4f", (float)((cmd_buf[0] >> 32) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd_buf[0] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd_buf[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)int32_t(cmd_buf[1] >> 32) / 65536.0f);
+ sprintf(dxldy, "%4.4f", (float)int32_t(cmd_buf[1]) / 65536.0f);
+ sprintf(xh, "%4.4f", (float)int32_t(cmd_buf[2] >> 32) / 65536.0f);
+ sprintf(dxhdy, "%4.4f", (float)int32_t(cmd_buf[2]) / 65536.0f);
+ sprintf(xm, "%4.4f", (float)int32_t(cmd_buf[3] >> 32) / 65536.0f);
+ sprintf(dxmdy, "%4.4f", (float)int32_t(cmd_buf[3]) / 65536.0f);
+
+ sprintf(s, "%4.4f", (float)int32_t( ((cmd_buf[4] >> 32) & 0xffff0000) | ((cmd_buf[ 6] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(t, "%4.4f", (float)int32_t((((cmd_buf[4] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 6] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(w, "%4.4f", (float)int32_t( (cmd_buf[4] & 0xffff0000) | ((cmd_buf[ 6] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdx, "%4.4f", (float)int32_t( ((cmd_buf[5] >> 32) & 0xffff0000) | ((cmd_buf[ 7] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtdx, "%4.4f", (float)int32_t((((cmd_buf[5] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 7] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwdx, "%4.4f", (float)int32_t( (cmd_buf[5] & 0xffff0000) | ((cmd_buf[ 7] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsde, "%4.4f", (float)int32_t( ((cmd_buf[8] >> 32) & 0xffff0000) | ((cmd_buf[10] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtde, "%4.4f", (float)int32_t((((cmd_buf[8] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[10] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwde, "%4.4f", (float)int32_t( (cmd_buf[8] & 0xffff0000) | ((cmd_buf[10] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdy, "%4.4f", (float)int32_t( ((cmd_buf[9] >> 32) & 0xffff0000) | ((cmd_buf[11] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtdy, "%4.4f", (float)int32_t((((cmd_buf[9] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[11] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwdy, "%4.4f", (float)int32_t( (cmd_buf[9] & 0xffff0000) | ((cmd_buf[11] >> 16) & 0xffff)) / 65536.0f);
buffer+=sprintf(buffer, "Tri_TexZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
buffer+=sprintf(buffer, " ");
@@ -1474,45 +1469,34 @@ void n64_rdp::disassemble(char* buffer)
}
case 0x0c: // Tri_Shade
{
- const int32_t lft = (command >> 23) & 0x1;
-
- if (length != s_rdp_command_length[command])
- {
- sprintf(buffer, "ERROR: Tri_Shade length = %d\n", length);
- return;
- }
-
- for (int32_t i = 1; i < 12; i++)
- {
- cmd[i] = m_cmd_data[i];
- }
-
- sprintf(yl, "%4.4f", (float)((cmd[0] >> 32) & 0x1fff) / 4.0f);
- sprintf(ym, "%4.4f", (float)((cmd[0] >> 16) & 0x1fff) / 4.0f);
- sprintf(yh, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
- sprintf(xl, "%4.4f", (float)int32_t(cmd[1] >> 32) / 65536.0f);
- sprintf(dxldy, "%4.4f", (float)int32_t(cmd[1]) / 65536.0f);
- sprintf(xh, "%4.4f", (float)int32_t(cmd[2] >> 32) / 65536.0f);
- sprintf(dxhdy, "%4.4f", (float)int32_t(cmd[2]) / 65536.0f);
- sprintf(xm, "%4.4f", (float)int32_t(cmd[3] >> 32) / 65536.0f);
- sprintf(dxmdy, "%4.4f", (float)int32_t(cmd[3]) / 65536.0f);
-
- sprintf(rt, "%4.4f", (float)int32_t( ((cmd[4] >> 32) & 0xffff0000) | ((cmd[ 6] >> 48) & 0xffff)) / 65536.0f);
- sprintf(gt, "%4.4f", (float)int32_t((((cmd[4] >> 32) & 0x0000ffff) << 16) | ((cmd[ 6] >> 32) & 0xffff)) / 65536.0f);
- sprintf(bt, "%4.4f", (float)int32_t( (cmd[4] & 0xffff0000) | ((cmd[ 6] >> 16) & 0xffff)) / 65536.0f);
- sprintf(at, "%4.4f", (float)int32_t( ((cmd[4] & 0x0000ffff) << 16) | ( cmd[ 6] & 0xffff)) / 65536.0f);
- sprintf(drdx, "%4.4f", (float)int32_t( ((cmd[5] >> 32) & 0xffff0000) | ((cmd[ 7] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgdx, "%4.4f", (float)int32_t((((cmd[5] >> 32) & 0x0000ffff) << 16) | ((cmd[ 7] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbdx, "%4.4f", (float)int32_t( (cmd[5] & 0xffff0000) | ((cmd[ 7] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dadx, "%4.4f", (float)int32_t( ((cmd[5] & 0x0000ffff) << 16) | ( cmd[ 7] & 0xffff)) / 65536.0f);
- sprintf(drde, "%4.4f", (float)int32_t( ((cmd[8] >> 32) & 0xffff0000) | ((cmd[10] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgde, "%4.4f", (float)int32_t((((cmd[8] >> 32) & 0x0000ffff) << 16) | ((cmd[10] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbde, "%4.4f", (float)int32_t( (cmd[8] & 0xffff0000) | ((cmd[10] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dade, "%4.4f", (float)int32_t( ((cmd[8] & 0x0000ffff) << 16) | ( cmd[10] & 0xffff)) / 65536.0f);
- sprintf(drdy, "%4.4f", (float)int32_t( ((cmd[9] >> 32) & 0xffff0000) | ((cmd[11] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgdy, "%4.4f", (float)int32_t((((cmd[9] >> 32) & 0x0000ffff) << 16) | ((cmd[11] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbdy, "%4.4f", (float)int32_t( (cmd[9] & 0xffff0000) | ((cmd[11] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dady, "%4.4f", (float)int32_t( ((cmd[9] & 0x0000ffff) << 16) | ( cmd[11] & 0xffff)) / 65536.0f);
+ const int32_t lft = (cmd_buf[0] >> 23) & 0x1;
+
+ sprintf(yl, "%4.4f", (float)((cmd_buf[0] >> 32) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd_buf[0] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd_buf[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)int32_t(cmd_buf[1] >> 32) / 65536.0f);
+ sprintf(dxldy, "%4.4f", (float)int32_t(cmd_buf[1]) / 65536.0f);
+ sprintf(xh, "%4.4f", (float)int32_t(cmd_buf[2] >> 32) / 65536.0f);
+ sprintf(dxhdy, "%4.4f", (float)int32_t(cmd_buf[2]) / 65536.0f);
+ sprintf(xm, "%4.4f", (float)int32_t(cmd_buf[3] >> 32) / 65536.0f);
+ sprintf(dxmdy, "%4.4f", (float)int32_t(cmd_buf[3]) / 65536.0f);
+
+ sprintf(rt, "%4.4f", (float)int32_t( ((cmd_buf[4] >> 32) & 0xffff0000) | ((cmd_buf[ 6] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(gt, "%4.4f", (float)int32_t((((cmd_buf[4] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 6] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(bt, "%4.4f", (float)int32_t( (cmd_buf[4] & 0xffff0000) | ((cmd_buf[ 6] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(at, "%4.4f", (float)int32_t( ((cmd_buf[4] & 0x0000ffff) << 16) | ( cmd_buf[ 6] & 0xffff)) / 65536.0f);
+ sprintf(drdx, "%4.4f", (float)int32_t( ((cmd_buf[5] >> 32) & 0xffff0000) | ((cmd_buf[ 7] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgdx, "%4.4f", (float)int32_t((((cmd_buf[5] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 7] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbdx, "%4.4f", (float)int32_t( (cmd_buf[5] & 0xffff0000) | ((cmd_buf[ 7] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dadx, "%4.4f", (float)int32_t( ((cmd_buf[5] & 0x0000ffff) << 16) | ( cmd_buf[ 7] & 0xffff)) / 65536.0f);
+ sprintf(drde, "%4.4f", (float)int32_t( ((cmd_buf[8] >> 32) & 0xffff0000) | ((cmd_buf[10] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgde, "%4.4f", (float)int32_t((((cmd_buf[8] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[10] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbde, "%4.4f", (float)int32_t( (cmd_buf[8] & 0xffff0000) | ((cmd_buf[10] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dade, "%4.4f", (float)int32_t( ((cmd_buf[8] & 0x0000ffff) << 16) | ( cmd_buf[10] & 0xffff)) / 65536.0f);
+ sprintf(drdy, "%4.4f", (float)int32_t( ((cmd_buf[9] >> 32) & 0xffff0000) | ((cmd_buf[11] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgdy, "%4.4f", (float)int32_t((((cmd_buf[9] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[11] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbdy, "%4.4f", (float)int32_t( (cmd_buf[9] & 0xffff0000) | ((cmd_buf[11] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dady, "%4.4f", (float)int32_t( ((cmd_buf[9] & 0x0000ffff) << 16) | ( cmd_buf[11] & 0xffff)) / 65536.0f);
buffer+=sprintf(buffer, "Tri_Shade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
buffer+=sprintf(buffer, " ");
@@ -1527,45 +1511,34 @@ void n64_rdp::disassemble(char* buffer)
}
case 0x0d: // Tri_ShadeZ
{
- const int32_t lft = (command >> 23) & 0x1;
-
- if (length != s_rdp_command_length[command])
- {
- sprintf(buffer, "ERROR: Tri_ShadeZ length = %d\n", length);
- return;
- }
-
- for (int32_t i = 1; i < 12; i++)
- {
- cmd[i] = m_cmd_data[i];
- }
-
- sprintf(yl, "%4.4f", (float)((cmd[0] >> 32) & 0x1fff) / 4.0f);
- sprintf(ym, "%4.4f", (float)((cmd[0] >> 16) & 0x1fff) / 4.0f);
- sprintf(yh, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
- sprintf(xl, "%4.4f", (float)int32_t(cmd[1] >> 32) / 65536.0f);
- sprintf(dxldy, "%4.4f", (float)int32_t(cmd[1]) / 65536.0f);
- sprintf(xh, "%4.4f", (float)int32_t(cmd[2] >> 32) / 65536.0f);
- sprintf(dxhdy, "%4.4f", (float)int32_t(cmd[2]) / 65536.0f);
- sprintf(xm, "%4.4f", (float)int32_t(cmd[3] >> 32) / 65536.0f);
- sprintf(dxmdy, "%4.4f", (float)int32_t(cmd[3]) / 65536.0f);
-
- sprintf(rt, "%4.4f", (float)int32_t( ((cmd[4] >> 32) & 0xffff0000) | ((cmd[ 6] >> 48) & 0xffff)) / 65536.0f);
- sprintf(gt, "%4.4f", (float)int32_t((((cmd[4] >> 32) & 0x0000ffff) << 16) | ((cmd[ 6] >> 32) & 0xffff)) / 65536.0f);
- sprintf(bt, "%4.4f", (float)int32_t( (cmd[4] & 0xffff0000) | ((cmd[ 6] >> 16) & 0xffff)) / 65536.0f);
- sprintf(at, "%4.4f", (float)int32_t( ((cmd[4] & 0x0000ffff) << 16) | ( cmd[ 6] & 0xffff)) / 65536.0f);
- sprintf(drdx, "%4.4f", (float)int32_t( ((cmd[5] >> 32) & 0xffff0000) | ((cmd[ 7] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgdx, "%4.4f", (float)int32_t((((cmd[5] >> 32) & 0x0000ffff) << 16) | ((cmd[ 7] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbdx, "%4.4f", (float)int32_t( (cmd[5] & 0xffff0000) | ((cmd[ 7] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dadx, "%4.4f", (float)int32_t( ((cmd[5] & 0x0000ffff) << 16) | ( cmd[ 7] & 0xffff)) / 65536.0f);
- sprintf(drde, "%4.4f", (float)int32_t( ((cmd[8] >> 32) & 0xffff0000) | ((cmd[10] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgde, "%4.4f", (float)int32_t((((cmd[8] >> 32) & 0x0000ffff) << 16) | ((cmd[10] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbde, "%4.4f", (float)int32_t( (cmd[8] & 0xffff0000) | ((cmd[10] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dade, "%4.4f", (float)int32_t( ((cmd[8] & 0x0000ffff) << 16) | ( cmd[10] & 0xffff)) / 65536.0f);
- sprintf(drdy, "%4.4f", (float)int32_t( ((cmd[9] >> 32) & 0xffff0000) | ((cmd[11] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgdy, "%4.4f", (float)int32_t((((cmd[9] >> 32) & 0x0000ffff) << 16) | ((cmd[11] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbdy, "%4.4f", (float)int32_t( (cmd[9] & 0xffff0000) | ((cmd[11] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dady, "%4.4f", (float)int32_t( ((cmd[9] & 0x0000ffff) << 16) | ( cmd[11] & 0xffff)) / 65536.0f);
+ const int32_t lft = (cmd_buf[0] >> 23) & 0x1;
+
+ sprintf(yl, "%4.4f", (float)((cmd_buf[0] >> 32) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd_buf[0] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd_buf[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)int32_t(cmd_buf[1] >> 32) / 65536.0f);
+ sprintf(dxldy, "%4.4f", (float)int32_t(cmd_buf[1]) / 65536.0f);
+ sprintf(xh, "%4.4f", (float)int32_t(cmd_buf[2] >> 32) / 65536.0f);
+ sprintf(dxhdy, "%4.4f", (float)int32_t(cmd_buf[2]) / 65536.0f);
+ sprintf(xm, "%4.4f", (float)int32_t(cmd_buf[3] >> 32) / 65536.0f);
+ sprintf(dxmdy, "%4.4f", (float)int32_t(cmd_buf[3]) / 65536.0f);
+
+ sprintf(rt, "%4.4f", (float)int32_t( ((cmd_buf[4] >> 32) & 0xffff0000) | ((cmd_buf[ 6] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(gt, "%4.4f", (float)int32_t((((cmd_buf[4] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 6] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(bt, "%4.4f", (float)int32_t( (cmd_buf[4] & 0xffff0000) | ((cmd_buf[ 6] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(at, "%4.4f", (float)int32_t( ((cmd_buf[4] & 0x0000ffff) << 16) | ( cmd_buf[ 6] & 0xffff)) / 65536.0f);
+ sprintf(drdx, "%4.4f", (float)int32_t( ((cmd_buf[5] >> 32) & 0xffff0000) | ((cmd_buf[ 7] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgdx, "%4.4f", (float)int32_t((((cmd_buf[5] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 7] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbdx, "%4.4f", (float)int32_t( (cmd_buf[5] & 0xffff0000) | ((cmd_buf[ 7] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dadx, "%4.4f", (float)int32_t( ((cmd_buf[5] & 0x0000ffff) << 16) | ( cmd_buf[ 7] & 0xffff)) / 65536.0f);
+ sprintf(drde, "%4.4f", (float)int32_t( ((cmd_buf[8] >> 32) & 0xffff0000) | ((cmd_buf[10] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgde, "%4.4f", (float)int32_t((((cmd_buf[8] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[10] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbde, "%4.4f", (float)int32_t( (cmd_buf[8] & 0xffff0000) | ((cmd_buf[10] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dade, "%4.4f", (float)int32_t( ((cmd_buf[8] & 0x0000ffff) << 16) | ( cmd_buf[10] & 0xffff)) / 65536.0f);
+ sprintf(drdy, "%4.4f", (float)int32_t( ((cmd_buf[9] >> 32) & 0xffff0000) | ((cmd_buf[11] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgdy, "%4.4f", (float)int32_t((((cmd_buf[9] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[11] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbdy, "%4.4f", (float)int32_t( (cmd_buf[9] & 0xffff0000) | ((cmd_buf[11] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dady, "%4.4f", (float)int32_t( ((cmd_buf[9] & 0x0000ffff) << 16) | ( cmd_buf[11] & 0xffff)) / 65536.0f);
buffer+=sprintf(buffer, "Tri_ShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
buffer+=sprintf(buffer, " ");
@@ -1580,58 +1553,47 @@ void n64_rdp::disassemble(char* buffer)
}
case 0x0e: // Tri_TexShade
{
- const int32_t lft = (command >> 23) & 0x1;
-
- if (length < s_rdp_command_length[command])
- {
- sprintf(buffer, "ERROR: Tri_TexShade length = %d\n", length);
- return;
- }
-
- for (int32_t i = 1; i < 20; i++)
- {
- cmd[i] = m_cmd_data[m_cmd_cur+i];
- }
-
- sprintf(yl, "%4.4f", (float)((cmd[0] >> 32) & 0x1fff) / 4.0f);
- sprintf(ym, "%4.4f", (float)((cmd[0] >> 16) & 0x1fff) / 4.0f);
- sprintf(yh, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
- sprintf(xl, "%4.4f", (float)int32_t(cmd[1] >> 32) / 65536.0f);
- sprintf(dxldy, "%4.4f", (float)int32_t(cmd[1]) / 65536.0f);
- sprintf(xh, "%4.4f", (float)int32_t(cmd[2] >> 32) / 65536.0f);
- sprintf(dxhdy, "%4.4f", (float)int32_t(cmd[2]) / 65536.0f);
- sprintf(xm, "%4.4f", (float)int32_t(cmd[3] >> 32) / 65536.0f);
- sprintf(dxmdy, "%4.4f", (float)int32_t(cmd[3]) / 65536.0f);
-
- sprintf(rt, "%4.4f", (float)int32_t( ((cmd[4] >> 32) & 0xffff0000) | ((cmd[ 6] >> 48) & 0xffff)) / 65536.0f);
- sprintf(gt, "%4.4f", (float)int32_t((((cmd[4] >> 32) & 0x0000ffff) << 16) | ((cmd[ 6] >> 32) & 0xffff)) / 65536.0f);
- sprintf(bt, "%4.4f", (float)int32_t( (cmd[4] & 0xffff0000) | ((cmd[ 6] >> 16) & 0xffff)) / 65536.0f);
- sprintf(at, "%4.4f", (float)int32_t( ((cmd[4] & 0x0000ffff) << 16) | ( cmd[ 6] & 0xffff)) / 65536.0f);
- sprintf(drdx, "%4.4f", (float)int32_t( ((cmd[5] >> 32) & 0xffff0000) | ((cmd[ 7] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgdx, "%4.4f", (float)int32_t((((cmd[5] >> 32) & 0x0000ffff) << 16) | ((cmd[ 7] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbdx, "%4.4f", (float)int32_t( (cmd[5] & 0xffff0000) | ((cmd[ 7] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dadx, "%4.4f", (float)int32_t( ((cmd[5] & 0x0000ffff) << 16) | ( cmd[ 7] & 0xffff)) / 65536.0f);
- sprintf(drde, "%4.4f", (float)int32_t( ((cmd[8] >> 32) & 0xffff0000) | ((cmd[10] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgde, "%4.4f", (float)int32_t((((cmd[8] >> 32) & 0x0000ffff) << 16) | ((cmd[10] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbde, "%4.4f", (float)int32_t( (cmd[8] & 0xffff0000) | ((cmd[10] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dade, "%4.4f", (float)int32_t( ((cmd[8] & 0x0000ffff) << 16) | ( cmd[10] & 0xffff)) / 65536.0f);
- sprintf(drdy, "%4.4f", (float)int32_t( ((cmd[9] >> 32) & 0xffff0000) | ((cmd[11] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgdy, "%4.4f", (float)int32_t((((cmd[9] >> 32) & 0x0000ffff) << 16) | ((cmd[11] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbdy, "%4.4f", (float)int32_t( (cmd[9] & 0xffff0000) | ((cmd[11] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dady, "%4.4f", (float)int32_t( ((cmd[9] & 0x0000ffff) << 16) | ( cmd[11] & 0xffff)) / 65536.0f);
-
- sprintf(s, "%4.4f", (float)int32_t( ((cmd[4] >> 32) & 0xffff0000) | ((cmd[ 6] >> 48) & 0xffff)) / 65536.0f);
- sprintf(t, "%4.4f", (float)int32_t((((cmd[4] >> 32) & 0x0000ffff) << 16) | ((cmd[ 6] >> 32) & 0xffff)) / 65536.0f);
- sprintf(w, "%4.4f", (float)int32_t( (cmd[4] & 0xffff0000) | ((cmd[ 6] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsdx, "%4.4f", (float)int32_t( ((cmd[5] >> 32) & 0xffff0000) | ((cmd[ 7] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtdx, "%4.4f", (float)int32_t((((cmd[5] >> 32) & 0x0000ffff) << 16) | ((cmd[ 7] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwdx, "%4.4f", (float)int32_t( (cmd[5] & 0xffff0000) | ((cmd[ 7] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsde, "%4.4f", (float)int32_t( ((cmd[8] >> 32) & 0xffff0000) | ((cmd[10] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtde, "%4.4f", (float)int32_t((((cmd[8] >> 32) & 0x0000ffff) << 16) | ((cmd[10] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwde, "%4.4f", (float)int32_t( (cmd[8] & 0xffff0000) | ((cmd[10] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsdy, "%4.4f", (float)int32_t( ((cmd[9] >> 32) & 0xffff0000) | ((cmd[11] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtdy, "%4.4f", (float)int32_t((((cmd[9] >> 32) & 0x0000ffff) << 16) | ((cmd[11] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwdy, "%4.4f", (float)int32_t( (cmd[9] & 0xffff0000) | ((cmd[11] >> 16) & 0xffff)) / 65536.0f);
+ const int32_t lft = (cmd_buf[0] >> 23) & 0x1;
+
+ sprintf(yl, "%4.4f", (float)((cmd_buf[0] >> 32) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd_buf[0] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd_buf[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)int32_t(cmd_buf[1] >> 32) / 65536.0f);
+ sprintf(dxldy, "%4.4f", (float)int32_t(cmd_buf[1]) / 65536.0f);
+ sprintf(xh, "%4.4f", (float)int32_t(cmd_buf[2] >> 32) / 65536.0f);
+ sprintf(dxhdy, "%4.4f", (float)int32_t(cmd_buf[2]) / 65536.0f);
+ sprintf(xm, "%4.4f", (float)int32_t(cmd_buf[3] >> 32) / 65536.0f);
+ sprintf(dxmdy, "%4.4f", (float)int32_t(cmd_buf[3]) / 65536.0f);
+
+ sprintf(rt, "%4.4f", (float)int32_t( ((cmd_buf[4] >> 32) & 0xffff0000) | ((cmd_buf[ 6] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(gt, "%4.4f", (float)int32_t((((cmd_buf[4] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 6] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(bt, "%4.4f", (float)int32_t( (cmd_buf[4] & 0xffff0000) | ((cmd_buf[ 6] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(at, "%4.4f", (float)int32_t( ((cmd_buf[4] & 0x0000ffff) << 16) | ( cmd_buf[ 6] & 0xffff)) / 65536.0f);
+ sprintf(drdx, "%4.4f", (float)int32_t( ((cmd_buf[5] >> 32) & 0xffff0000) | ((cmd_buf[ 7] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgdx, "%4.4f", (float)int32_t((((cmd_buf[5] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 7] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbdx, "%4.4f", (float)int32_t( (cmd_buf[5] & 0xffff0000) | ((cmd_buf[ 7] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dadx, "%4.4f", (float)int32_t( ((cmd_buf[5] & 0x0000ffff) << 16) | ( cmd_buf[ 7] & 0xffff)) / 65536.0f);
+ sprintf(drde, "%4.4f", (float)int32_t( ((cmd_buf[8] >> 32) & 0xffff0000) | ((cmd_buf[10] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgde, "%4.4f", (float)int32_t((((cmd_buf[8] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[10] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbde, "%4.4f", (float)int32_t( (cmd_buf[8] & 0xffff0000) | ((cmd_buf[10] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dade, "%4.4f", (float)int32_t( ((cmd_buf[8] & 0x0000ffff) << 16) | ( cmd_buf[10] & 0xffff)) / 65536.0f);
+ sprintf(drdy, "%4.4f", (float)int32_t( ((cmd_buf[9] >> 32) & 0xffff0000) | ((cmd_buf[11] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgdy, "%4.4f", (float)int32_t((((cmd_buf[9] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[11] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbdy, "%4.4f", (float)int32_t( (cmd_buf[9] & 0xffff0000) | ((cmd_buf[11] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dady, "%4.4f", (float)int32_t( ((cmd_buf[9] & 0x0000ffff) << 16) | ( cmd_buf[11] & 0xffff)) / 65536.0f);
+
+ sprintf(s, "%4.4f", (float)int32_t( ((cmd_buf[4] >> 32) & 0xffff0000) | ((cmd_buf[ 6] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(t, "%4.4f", (float)int32_t((((cmd_buf[4] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 6] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(w, "%4.4f", (float)int32_t( (cmd_buf[4] & 0xffff0000) | ((cmd_buf[ 6] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdx, "%4.4f", (float)int32_t( ((cmd_buf[5] >> 32) & 0xffff0000) | ((cmd_buf[ 7] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtdx, "%4.4f", (float)int32_t((((cmd_buf[5] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 7] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwdx, "%4.4f", (float)int32_t( (cmd_buf[5] & 0xffff0000) | ((cmd_buf[ 7] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsde, "%4.4f", (float)int32_t( ((cmd_buf[8] >> 32) & 0xffff0000) | ((cmd_buf[10] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtde, "%4.4f", (float)int32_t((((cmd_buf[8] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[10] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwde, "%4.4f", (float)int32_t( (cmd_buf[8] & 0xffff0000) | ((cmd_buf[10] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdy, "%4.4f", (float)int32_t( ((cmd_buf[9] >> 32) & 0xffff0000) | ((cmd_buf[11] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtdy, "%4.4f", (float)int32_t((((cmd_buf[9] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[11] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwdy, "%4.4f", (float)int32_t( (cmd_buf[9] & 0xffff0000) | ((cmd_buf[11] >> 16) & 0xffff)) / 65536.0f);
buffer+=sprintf(buffer, "Tri_TexShade %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
buffer+=sprintf(buffer, " ");
@@ -1655,58 +1617,47 @@ void n64_rdp::disassemble(char* buffer)
}
case 0x0f: // Tri_TexShadeZ
{
- const int32_t lft = (command >> 23) & 0x1;
-
- if (length < s_rdp_command_length[command])
- {
- sprintf(buffer, "ERROR: Tri_TexShadeZ length = %d\n", length);
- return;
- }
-
- for (int32_t i = 1; i < 20; i++)
- {
- cmd[i] = m_cmd_data[m_cmd_cur+i];
- }
-
- sprintf(yl, "%4.4f", (float)((cmd[0] >> 32) & 0x1fff) / 4.0f);
- sprintf(ym, "%4.4f", (float)((cmd[0] >> 16) & 0x1fff) / 4.0f);
- sprintf(yh, "%4.4f", (float)((cmd[0] >> 0) & 0x1fff) / 4.0f);
- sprintf(xl, "%4.4f", (float)int32_t(cmd[1] >> 32) / 65536.0f);
- sprintf(dxldy, "%4.4f", (float)int32_t(cmd[1]) / 65536.0f);
- sprintf(xh, "%4.4f", (float)int32_t(cmd[2] >> 32) / 65536.0f);
- sprintf(dxhdy, "%4.4f", (float)int32_t(cmd[2]) / 65536.0f);
- sprintf(xm, "%4.4f", (float)int32_t(cmd[3] >> 32) / 65536.0f);
- sprintf(dxmdy, "%4.4f", (float)int32_t(cmd[3]) / 65536.0f);
-
- sprintf(rt, "%4.4f", (float)int32_t( ((cmd[4] >> 32) & 0xffff0000) | ((cmd[ 6] >> 48) & 0xffff)) / 65536.0f);
- sprintf(gt, "%4.4f", (float)int32_t((((cmd[4] >> 32) & 0x0000ffff) << 16) | ((cmd[ 6] >> 32) & 0xffff)) / 65536.0f);
- sprintf(bt, "%4.4f", (float)int32_t( (cmd[4] & 0xffff0000) | ((cmd[ 6] >> 16) & 0xffff)) / 65536.0f);
- sprintf(at, "%4.4f", (float)int32_t( ((cmd[4] & 0x0000ffff) << 16) | ( cmd[ 6] & 0xffff)) / 65536.0f);
- sprintf(drdx, "%4.4f", (float)int32_t( ((cmd[5] >> 32) & 0xffff0000) | ((cmd[ 7] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgdx, "%4.4f", (float)int32_t((((cmd[5] >> 32) & 0x0000ffff) << 16) | ((cmd[ 7] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbdx, "%4.4f", (float)int32_t( (cmd[5] & 0xffff0000) | ((cmd[ 7] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dadx, "%4.4f", (float)int32_t( ((cmd[5] & 0x0000ffff) << 16) | ( cmd[ 7] & 0xffff)) / 65536.0f);
- sprintf(drde, "%4.4f", (float)int32_t( ((cmd[8] >> 32) & 0xffff0000) | ((cmd[10] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgde, "%4.4f", (float)int32_t((((cmd[8] >> 32) & 0x0000ffff) << 16) | ((cmd[10] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbde, "%4.4f", (float)int32_t( (cmd[8] & 0xffff0000) | ((cmd[10] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dade, "%4.4f", (float)int32_t( ((cmd[8] & 0x0000ffff) << 16) | ( cmd[10] & 0xffff)) / 65536.0f);
- sprintf(drdy, "%4.4f", (float)int32_t( ((cmd[9] >> 32) & 0xffff0000) | ((cmd[11] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dgdy, "%4.4f", (float)int32_t((((cmd[9] >> 32) & 0x0000ffff) << 16) | ((cmd[11] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dbdy, "%4.4f", (float)int32_t( (cmd[9] & 0xffff0000) | ((cmd[11] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dady, "%4.4f", (float)int32_t( ((cmd[9] & 0x0000ffff) << 16) | ( cmd[11] & 0xffff)) / 65536.0f);
-
- sprintf(s, "%4.4f", (float)int32_t( ((cmd[4] >> 32) & 0xffff0000) | ((cmd[ 6] >> 48) & 0xffff)) / 65536.0f);
- sprintf(t, "%4.4f", (float)int32_t((((cmd[4] >> 32) & 0x0000ffff) << 16) | ((cmd[ 6] >> 32) & 0xffff)) / 65536.0f);
- sprintf(w, "%4.4f", (float)int32_t( (cmd[4] & 0xffff0000) | ((cmd[ 6] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsdx, "%4.4f", (float)int32_t( ((cmd[5] >> 32) & 0xffff0000) | ((cmd[ 7] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtdx, "%4.4f", (float)int32_t((((cmd[5] >> 32) & 0x0000ffff) << 16) | ((cmd[ 7] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwdx, "%4.4f", (float)int32_t( (cmd[5] & 0xffff0000) | ((cmd[ 7] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsde, "%4.4f", (float)int32_t( ((cmd[8] >> 32) & 0xffff0000) | ((cmd[10] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtde, "%4.4f", (float)int32_t((((cmd[8] >> 32) & 0x0000ffff) << 16) | ((cmd[10] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwde, "%4.4f", (float)int32_t( (cmd[8] & 0xffff0000) | ((cmd[10] >> 16) & 0xffff)) / 65536.0f);
- sprintf(dsdy, "%4.4f", (float)int32_t( ((cmd[9] >> 32) & 0xffff0000) | ((cmd[11] >> 48) & 0xffff)) / 65536.0f);
- sprintf(dtdy, "%4.4f", (float)int32_t((((cmd[9] >> 32) & 0x0000ffff) << 16) | ((cmd[11] >> 32) & 0xffff)) / 65536.0f);
- sprintf(dwdy, "%4.4f", (float)int32_t( (cmd[9] & 0xffff0000) | ((cmd[11] >> 16) & 0xffff)) / 65536.0f);
+ const int32_t lft = (cmd_buf[0] >> 23) & 0x1;
+
+ sprintf(yl, "%4.4f", (float)((cmd_buf[0] >> 32) & 0x1fff) / 4.0f);
+ sprintf(ym, "%4.4f", (float)((cmd_buf[0] >> 16) & 0x1fff) / 4.0f);
+ sprintf(yh, "%4.4f", (float)((cmd_buf[0] >> 0) & 0x1fff) / 4.0f);
+ sprintf(xl, "%4.4f", (float)int32_t(cmd_buf[1] >> 32) / 65536.0f);
+ sprintf(dxldy, "%4.4f", (float)int32_t(cmd_buf[1]) / 65536.0f);
+ sprintf(xh, "%4.4f", (float)int32_t(cmd_buf[2] >> 32) / 65536.0f);
+ sprintf(dxhdy, "%4.4f", (float)int32_t(cmd_buf[2]) / 65536.0f);
+ sprintf(xm, "%4.4f", (float)int32_t(cmd_buf[3] >> 32) / 65536.0f);
+ sprintf(dxmdy, "%4.4f", (float)int32_t(cmd_buf[3]) / 65536.0f);
+
+ sprintf(rt, "%4.4f", (float)int32_t( ((cmd_buf[4] >> 32) & 0xffff0000) | ((cmd_buf[ 6] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(gt, "%4.4f", (float)int32_t((((cmd_buf[4] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 6] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(bt, "%4.4f", (float)int32_t( (cmd_buf[4] & 0xffff0000) | ((cmd_buf[ 6] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(at, "%4.4f", (float)int32_t( ((cmd_buf[4] & 0x0000ffff) << 16) | ( cmd_buf[ 6] & 0xffff)) / 65536.0f);
+ sprintf(drdx, "%4.4f", (float)int32_t( ((cmd_buf[5] >> 32) & 0xffff0000) | ((cmd_buf[ 7] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgdx, "%4.4f", (float)int32_t((((cmd_buf[5] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 7] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbdx, "%4.4f", (float)int32_t( (cmd_buf[5] & 0xffff0000) | ((cmd_buf[ 7] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dadx, "%4.4f", (float)int32_t( ((cmd_buf[5] & 0x0000ffff) << 16) | ( cmd_buf[ 7] & 0xffff)) / 65536.0f);
+ sprintf(drde, "%4.4f", (float)int32_t( ((cmd_buf[8] >> 32) & 0xffff0000) | ((cmd_buf[10] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgde, "%4.4f", (float)int32_t((((cmd_buf[8] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[10] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbde, "%4.4f", (float)int32_t( (cmd_buf[8] & 0xffff0000) | ((cmd_buf[10] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dade, "%4.4f", (float)int32_t( ((cmd_buf[8] & 0x0000ffff) << 16) | ( cmd_buf[10] & 0xffff)) / 65536.0f);
+ sprintf(drdy, "%4.4f", (float)int32_t( ((cmd_buf[9] >> 32) & 0xffff0000) | ((cmd_buf[11] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dgdy, "%4.4f", (float)int32_t((((cmd_buf[9] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[11] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dbdy, "%4.4f", (float)int32_t( (cmd_buf[9] & 0xffff0000) | ((cmd_buf[11] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dady, "%4.4f", (float)int32_t( ((cmd_buf[9] & 0x0000ffff) << 16) | ( cmd_buf[11] & 0xffff)) / 65536.0f);
+
+ sprintf(s, "%4.4f", (float)int32_t( ((cmd_buf[4] >> 32) & 0xffff0000) | ((cmd_buf[ 6] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(t, "%4.4f", (float)int32_t((((cmd_buf[4] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 6] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(w, "%4.4f", (float)int32_t( (cmd_buf[4] & 0xffff0000) | ((cmd_buf[ 6] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdx, "%4.4f", (float)int32_t( ((cmd_buf[5] >> 32) & 0xffff0000) | ((cmd_buf[ 7] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtdx, "%4.4f", (float)int32_t((((cmd_buf[5] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[ 7] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwdx, "%4.4f", (float)int32_t( (cmd_buf[5] & 0xffff0000) | ((cmd_buf[ 7] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsde, "%4.4f", (float)int32_t( ((cmd_buf[8] >> 32) & 0xffff0000) | ((cmd_buf[10] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtde, "%4.4f", (float)int32_t((((cmd_buf[8] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[10] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwde, "%4.4f", (float)int32_t( (cmd_buf[8] & 0xffff0000) | ((cmd_buf[10] >> 16) & 0xffff)) / 65536.0f);
+ sprintf(dsdy, "%4.4f", (float)int32_t( ((cmd_buf[9] >> 32) & 0xffff0000) | ((cmd_buf[11] >> 48) & 0xffff)) / 65536.0f);
+ sprintf(dtdy, "%4.4f", (float)int32_t((((cmd_buf[9] >> 32) & 0x0000ffff) << 16) | ((cmd_buf[11] >> 32) & 0xffff)) / 65536.0f);
+ sprintf(dwdy, "%4.4f", (float)int32_t( (cmd_buf[9] & 0xffff0000) | ((cmd_buf[11] >> 16) & 0xffff)) / 65536.0f);
buffer+=sprintf(buffer, "Tri_TexShadeZ %d, XL: %s, XM: %s, XH: %s, YL: %s, YM: %s, YH: %s\n", lft, xl,xm,xh,yl,ym,yh);
buffer+=sprintf(buffer, " ");
@@ -1731,17 +1682,10 @@ void n64_rdp::disassemble(char* buffer)
case 0x24:
case 0x25:
{
- if (length < 16)
- {
- sprintf(buffer, "ERROR: Texture_Rectangle length = %d\n", length);
- return;
- }
-
- cmd[1] = m_cmd_data[m_cmd_cur+1];
- sprintf(s, "%4.4f", (float)int16_t((cmd[1] >> 48) & 0xffff) / 32.0f);
- sprintf(t, "%4.4f", (float)int16_t((cmd[1] >> 32) & 0xffff) / 32.0f);
- sprintf(dsdx, "%4.4f", (float)int16_t((cmd[1] >> 16) & 0xffff) / 1024.0f);
- sprintf(dtdy, "%4.4f", (float)int16_t((cmd[1] >> 0) & 0xffff) / 1024.0f);
+ sprintf(s, "%4.4f", (float)int16_t((cmd_buf[1] >> 48) & 0xffff) / 32.0f);
+ sprintf(t, "%4.4f", (float)int16_t((cmd_buf[1] >> 32) & 0xffff) / 32.0f);
+ sprintf(dsdx, "%4.4f", (float)int16_t((cmd_buf[1] >> 16) & 0xffff) / 1024.0f);
+ sprintf(dtdy, "%4.4f", (float)int16_t((cmd_buf[1] >> 0) & 0xffff) / 1024.0f);
if (command == 0x24)
sprintf(buffer, "Texture_Rectangle %d, %s, %s, %s, %s, %s, %s, %s, %s", tile, sh, th, sl, tl, s, t, dsdx, dtdy);
@@ -1755,24 +1699,24 @@ void n64_rdp::disassemble(char* buffer)
case 0x28: sprintf(buffer, "Sync_Tile"); break;
case 0x29: sprintf(buffer, "Sync_Full"); break;
case 0x2d: sprintf(buffer, "Set_Scissor %s, %s, %s, %s", sl, tl, sh, th); break;
- case 0x2e: sprintf(buffer, "Set_Prim_Depth %04X, %04X", uint32_t(cmd[0] >> 16) & 0xffff, (uint32_t)cmd[0] & 0xffff); break;
- case 0x2f: sprintf(buffer, "Set_Other_Modes %08X %08X", uint32_t(cmd[0] >> 32), (uint32_t)cmd[0]); break;
+ case 0x2e: sprintf(buffer, "Set_Prim_Depth %04X, %04X", uint32_t(cmd_buf[0] >> 16) & 0xffff, (uint32_t)cmd_buf[0] & 0xffff); break;
+ case 0x2f: sprintf(buffer, "Set_Other_Modes %08X %08X", uint32_t(cmd_buf[0] >> 32), (uint32_t)cmd_buf[0]); break;
case 0x30: sprintf(buffer, "Load_TLUT %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break;
case 0x32: sprintf(buffer, "Set_Tile_Size %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break;
- case 0x33: sprintf(buffer, "Load_Block %d, %03X, %03X, %03X, %03X", tile, uint32_t(cmd[0] >> 44) & 0xfff, uint32_t(cmd[0] >> 32) & 0xfff, uint32_t(cmd[0] >> 12) & 0xfff, uint32_t(cmd[0]) & 0xfff); break;
+ case 0x33: sprintf(buffer, "Load_Block %d, %03X, %03X, %03X, %03X", tile, uint32_t(cmd_buf[0] >> 44) & 0xfff, uint32_t(cmd_buf[0] >> 32) & 0xfff, uint32_t(cmd_buf[0] >> 12) & 0xfff, uint32_t(cmd_buf[0]) & 0xfff); break;
case 0x34: sprintf(buffer, "Load_Tile %d, %s, %s, %s, %s", tile, sl, tl, sh, th); break;
- case 0x35: sprintf(buffer, "Set_Tile %d, %s, %s, %d, %04X", tile, format, size, (uint32_t(cmd[0] >> 41) & 0x1ff) * 8, (uint32_t(cmd[0] >> 32) & 0x1ff) * 8); break;
+ case 0x35: sprintf(buffer, "Set_Tile %d, %s, %s, %d, %04X", tile, format, size, (uint32_t(cmd_buf[0] >> 41) & 0x1ff) * 8, (uint32_t(cmd_buf[0] >> 32) & 0x1ff) * 8); break;
case 0x36: sprintf(buffer, "Fill_Rectangle %s, %s, %s, %s", sh, th, sl, tl); break;
case 0x37: sprintf(buffer, "Set_Fill_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
case 0x38: sprintf(buffer, "Set_Fog_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
case 0x39: sprintf(buffer, "Set_Blend_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
- case 0x3a: sprintf(buffer, "Set_Prim_Color %d, %d, R: %d, G: %d, B: %d, A: %d", uint32_t(cmd[0] >> 40) & 0x1f, uint32_t(cmd[0] >> 32) & 0xff, r, g, b, a); break;
+ case 0x3a: sprintf(buffer, "Set_Prim_Color %d, %d, R: %d, G: %d, B: %d, A: %d", uint32_t(cmd_buf[0] >> 40) & 0x1f, uint32_t(cmd_buf[0] >> 32) & 0xff, r, g, b, a); break;
case 0x3b: sprintf(buffer, "Set_Env_Color R: %d, G: %d, B: %d, A: %d", r, g, b, a); break;
- case 0x3c: sprintf(buffer, "Set_Combine %08X %08X", uint32_t(cmd[0] >> 32), (uint32_t)cmd[0]); break;
- case 0x3d: sprintf(buffer, "Set_Texture_Image %s, %s, %d, %08X", format, size, (uint32_t(cmd[0] >> 32) & 0x1ff) + 1, (uint32_t)cmd[0]); break;
- case 0x3e: sprintf(buffer, "Set_Mask_Image %08X", (uint32_t)cmd[0]); break;
- case 0x3f: sprintf(buffer, "Set_Color_Image %s, %s, %d, %08X", format, size, (uint32_t(cmd[0] >> 32) & 0x1ff) + 1, (uint32_t)cmd[0]); break;
- default: sprintf(buffer, "Unknown (%08X %08X)", uint32_t(cmd[0] >> 32), (uint32_t)cmd[0]); break;
+ case 0x3c: sprintf(buffer, "Set_Combine %08X %08X", uint32_t(cmd_buf[0] >> 32), (uint32_t)cmd_buf[0]); break;
+ case 0x3d: sprintf(buffer, "Set_Texture_Image %s, %s, %d, %08X", format, size, (uint32_t(cmd_buf[0] >> 32) & 0x1ff) + 1, (uint32_t)cmd_buf[0]); break;
+ case 0x3e: sprintf(buffer, "Set_Mask_Image %08X", (uint32_t)cmd_buf[0]); break;
+ case 0x3f: sprintf(buffer, "Set_Color_Image %s, %s, %d, %08X", format, size, (uint32_t(cmd_buf[0] >> 32) & 0x1ff) + 1, (uint32_t)cmd_buf[0]); break;
+ default: sprintf(buffer, "Unknown (%08X %08X)", uint32_t(cmd_buf[0] >> 32), (uint32_t)cmd_buf[0]); break;
}
}
@@ -1959,11 +1903,10 @@ void n64_rdp::compute_cvg_flip(extent_t* spans, int32_t* majorx, int32_t* minorx
#define SIGN(x, numb) (((x) & ((1 << numb) - 1)) | -((x) & (1 << (numb - 1))))
-void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect)
+void n64_rdp::draw_triangle(uint64_t *cmd_buf, bool shade, bool texture, bool zbuffer, bool rect)
{
- const uint64_t* cmd_data = rect ? m_temp_rect_data : m_cmd_data;
- const uint32_t fifo_index = rect ? 0 : m_cmd_cur;
- const uint64_t w1 = cmd_data[fifo_index + 0];
+ const uint64_t* cmd_data = rect ? m_temp_rect_data : cmd_buf;
+ const uint64_t w1 = cmd_data[0];
int32_t flip = int32_t(w1 >> 55) & 1;
m_misc_state.m_max_level = uint32_t(w1 >> 51) & 7;
@@ -1979,9 +1922,9 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect)
int32_t maxxhx = 0;
int32_t minxhx = 0;
- int32_t shade_base = fifo_index + 4;
- int32_t texture_base = fifo_index + 4;
- int32_t zbuffer_base = fifo_index + 4;
+ int32_t shade_base = 4;
+ int32_t texture_base = 4;
+ int32_t zbuffer_base = 4;
if(shade)
{
texture_base += 8;
@@ -1992,9 +1935,9 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect)
zbuffer_base += 8;
}
- uint64_t w2 = cmd_data[fifo_index + 1];
- uint64_t w3 = cmd_data[fifo_index + 2];
- uint64_t w4 = cmd_data[fifo_index + 3];
+ uint64_t w2 = cmd_data[1];
+ uint64_t w3 = cmd_data[2];
+ uint64_t w4 = cmd_data[3];
int32_t yl = int32_t(w1 >> 32) & 0x3fff;
int32_t ym = int32_t(w1 >> 16) & 0x3fff;
@@ -2212,6 +2155,7 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect)
}
rdp_span_aux* userdata = (rdp_span_aux*)spans[spanidx].userdata;
+ memcpy(&userdata->m_combine, &m_combine, sizeof(combine_modes_t));
userdata->m_tmem = object->m_tmem;
userdata->m_blend_color = m_blend_color;
@@ -2223,6 +2167,8 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect)
userdata->m_key_scale = m_key_scale;
userdata->m_lod_fraction = m_lod_fraction;
userdata->m_prim_lod_fraction = m_prim_lod_fraction;
+ userdata->m_k4 = m_k4;
+ userdata->m_k5 = m_k5;
// Setup blender data for this scanline
set_blender_input(0, 0, &userdata->m_color_inputs.blender1a_rgb[0], &userdata->m_color_inputs.blender1b_a[0], m_other_modes.blend_m1a_0, m_other_modes.blend_m1b_0, userdata);
@@ -2301,57 +2247,16 @@ void n64_rdp::draw_triangle(bool shade, bool texture, bool zbuffer, bool rect)
// RDP COMMANDS
////////////////////////
-void n64_rdp::triangle(bool shade, bool texture, bool zbuffer)
+void n64_rdp::triangle(uint64_t *cmd_buf, bool shade, bool texture, bool zbuffer)
{
- draw_triangle(shade, texture, zbuffer, false);
+ draw_triangle(cmd_buf, shade, texture, zbuffer, false);
m_pipe_clean = false;
}
-void n64_rdp::cmd_triangle(uint64_t w1)
-{
- triangle(false, false, false);
-}
-
-void n64_rdp::cmd_triangle_z(uint64_t w1)
+void n64_rdp::cmd_tex_rect(uint64_t *cmd_buf)
{
- triangle(false, false, true);
-}
-
-void n64_rdp::cmd_triangle_t(uint64_t w1)
-{
- triangle(false, true, false);
-}
-
-void n64_rdp::cmd_triangle_tz(uint64_t w1)
-{
- triangle(false, true, true);
-}
-
-void n64_rdp::cmd_triangle_s(uint64_t w1)
-{
- triangle(true, false, false);
-}
-
-void n64_rdp::cmd_triangle_sz(uint64_t w1)
-{
- triangle(true, false, true);
-}
-
-void n64_rdp::cmd_triangle_st(uint64_t w1)
-{
- triangle(true, true, false);
-}
-
-void n64_rdp::cmd_triangle_stz(uint64_t w1)
-{
- triangle(true, true, true);
-}
-
-void n64_rdp::cmd_tex_rect(uint64_t w1)
-{
- const uint64_t* data = m_cmd_data + m_cmd_cur;
-
- const uint64_t w2 = data[1];
+ const uint64_t w1 = cmd_buf[0];
+ const uint64_t w2 = cmd_buf[1];
const uint64_t tilenum = (w1 >> 24) & 0x7;
const uint64_t xh = (w1 >> 12) & 0xfff;
@@ -2388,14 +2293,13 @@ void n64_rdp::cmd_tex_rect(uint64_t w1)
ewdata[38] = ((dtdy & 0x1f) << 11) << 32; // dsdy frac, dtdy frac, dwdy frac (0)
// ewdata[40-43] = 0; // depth
- draw_triangle(true, true, false, true);
+ draw_triangle(cmd_buf, true, true, false, true);
}
-void n64_rdp::cmd_tex_rect_flip(uint64_t w1)
+void n64_rdp::cmd_tex_rect_flip(uint64_t *cmd_buf)
{
- const uint64_t* data = m_cmd_data + m_cmd_cur;
-
- const uint64_t w2 = data[1];
+ const uint64_t w1 = cmd_buf[0];
+ const uint64_t w2 = cmd_buf[1];
const uint64_t tilenum = (w1 >> 56) & 0x7;
const uint64_t xh = (w1 >> 12) & 0xfff;
@@ -2431,49 +2335,51 @@ void n64_rdp::cmd_tex_rect_flip(uint64_t w1)
ewdata[18] = (dsdx & 0x1f) << 59; // dsde frac, dtde frac, dwde frac (0)
ewdata[19] = (dsdx & 0x1f) << 59; // dsdy frac, dtdy frac, dwdy frac (0)
- draw_triangle(true, true, false, true);
+ draw_triangle(cmd_buf, true, true, false, true);
}
-void n64_rdp::cmd_sync_load(uint64_t w1)
+void n64_rdp::cmd_sync_load(uint64_t *cmd_buf)
{
//wait("SyncLoad");
}
-void n64_rdp::cmd_sync_pipe(uint64_t w1)
+void n64_rdp::cmd_sync_pipe(uint64_t *cmd_buf)
{
//wait("SyncPipe");
}
-void n64_rdp::cmd_sync_tile(uint64_t w1)
+void n64_rdp::cmd_sync_tile(uint64_t *cmd_buf)
{
//wait("SyncTile");
}
-void n64_rdp::cmd_sync_full(uint64_t w1)
+void n64_rdp::cmd_sync_full(uint64_t *cmd_buf)
{
//wait("SyncFull");
m_n64_periphs->dp_full_sync();
}
-void n64_rdp::cmd_set_key_gb(uint64_t w1)
+void n64_rdp::cmd_set_key_gb(uint64_t *cmd_buf)
{
- m_key_scale.set_b(uint32_t(w1 >> 0) & 0xff);
- m_key_scale.set_g(uint32_t(w1 >> 16) & 0xff);
+ m_key_scale.set_b(uint32_t(cmd_buf[0] >> 0) & 0xff);
+ m_key_scale.set_g(uint32_t(cmd_buf[0] >> 16) & 0xff);
}
-void n64_rdp::cmd_set_key_r(uint64_t w1)
+void n64_rdp::cmd_set_key_r(uint64_t *cmd_buf)
{
- m_key_scale.set_r(uint32_t(w1 & 0xff));
+ m_key_scale.set_r(uint32_t(cmd_buf[0] & 0xff));
}
-void n64_rdp::cmd_set_fill_color32(uint64_t w1)
+void n64_rdp::cmd_set_fill_color32(uint64_t *cmd_buf)
{
//wait("SetFillColor");
- m_fill_color = (uint32_t)w1;
+ m_fill_color = (uint32_t)cmd_buf[0];
}
-void n64_rdp::cmd_set_convert(uint64_t w1)
+void n64_rdp::cmd_set_convert(uint64_t *cmd_buf)
{
+ const uint64_t w1 = cmd_buf[0];
+
if(!m_pipe_clean) { m_pipe_clean = true; wait("SetConvert"); }
int32_t k0 = int32_t(w1 >> 45) & 0x1ff;
int32_t k1 = int32_t(w1 >> 36) & 0x1ff;
@@ -2490,8 +2396,10 @@ void n64_rdp::cmd_set_convert(uint64_t w1)
set_yuv_factors(rgbaint_t(0, k0, k2, k3), rgbaint_t(0, 0, k1, 0), rgbaint_t(k4, k4, k4, k4), rgbaint_t(k5, k5, k5, k5));
}
-void n64_rdp::cmd_set_scissor(uint64_t w1)
+void n64_rdp::cmd_set_scissor(uint64_t *cmd_buf)
{
+ const uint64_t w1 = cmd_buf[0];
+
m_scissor.m_xh = ((w1 >> 44) & 0xfff) >> 2;
m_scissor.m_yh = ((w1 >> 32) & 0xfff) >> 2;
m_scissor.m_xl = ((w1 >> 12) & 0xfff) >> 2;
@@ -2500,14 +2408,16 @@ void n64_rdp::cmd_set_scissor(uint64_t w1)
// TODO: handle f & o?
}
-void n64_rdp::cmd_set_prim_depth(uint64_t w1)
+void n64_rdp::cmd_set_prim_depth(uint64_t *cmd_buf)
{
+ const uint64_t w1 = cmd_buf[0];
m_misc_state.m_primitive_z = (uint32_t)(w1 & 0x7fff0000);
m_misc_state.m_primitive_dz = (uint16_t)(w1 >> 32);
}
-void n64_rdp::cmd_set_other_modes(uint64_t w1)
+void n64_rdp::cmd_set_other_modes(uint64_t *cmd_buf)
{
+ const uint64_t w1 = cmd_buf[0];
//wait("SetOtherModes");
m_other_modes.cycle_type = (w1 >> 52) & 0x3; // 01
m_other_modes.persp_tex_en = (w1 >> 51) & 1; // 1
@@ -2549,10 +2459,11 @@ void n64_rdp::cmd_set_other_modes(uint64_t w1)
m_other_modes.alpha_dither_mode = (m_other_modes.alpha_compare_en << 1) | m_other_modes.dither_alpha_en;
}
-void n64_rdp::cmd_load_tlut(uint64_t w1)
+void n64_rdp::cmd_load_tlut(uint64_t *cmd_buf)
{
//wait("LoadTLUT");
n64_tile_t* tile = m_tiles;
+ const uint64_t w1 = cmd_buf[0];
const int32_t tilenum = (w1 >> 24) & 0x7;
const int32_t sl = tile[tilenum].sl = int32_t(w1 >> 44) & 0xfff;
@@ -2605,10 +2516,10 @@ void n64_rdp::cmd_load_tlut(uint64_t w1)
m_tiles[tilenum].stl = rgbaint_t(m_tiles[tilenum].sl, m_tiles[tilenum].sl, m_tiles[tilenum].tl, m_tiles[tilenum].tl);
}
-void n64_rdp::cmd_set_tile_size(uint64_t w1)
+void n64_rdp::cmd_set_tile_size(uint64_t *cmd_buf)
{
//wait("SetTileSize");
-
+ const uint64_t w1 = cmd_buf[0];
const int32_t tilenum = int32_t(w1 >> 24) & 0x7;
m_tiles[tilenum].sl = int32_t(w1 >> 44) & 0xfff;
@@ -2620,23 +2531,37 @@ void n64_rdp::cmd_set_tile_size(uint64_t w1)
m_tiles[tilenum].stl = rgbaint_t(m_tiles[tilenum].sl, m_tiles[tilenum].sl, m_tiles[tilenum].tl, m_tiles[tilenum].tl);
}
-void n64_rdp::cmd_load_block(uint64_t w1)
+void n64_rdp::cmd_load_block(uint64_t *cmd_buf)
{
//wait("LoadBlock");
n64_tile_t* tile = m_tiles;
+ const uint64_t w1 = cmd_buf[0];
- const int32_t tilenum = int32_t(w1 >> 24) & 0x7;
+ const uint8_t tilenum = uint8_t(w1 >> 24) & 0x7;
uint16_t* tc = get_tmem16();
- int32_t sl = tile[tilenum].sl = int32_t(w1 >> 44) & 0xfff;
- int32_t tl = tile[tilenum].tl = int32_t(w1 >> 32) & 0xfff;
- int32_t sh = tile[tilenum].sh = int32_t(w1 >> 12) & 0xfff;
- const int32_t dxt = int32_t(w1 >> 0) & 0xfff;
+ int32_t sl, tl, sh, dxt;
+ tile[tilenum].sl = sl = int32_t((w1 >> 44) & 0xfff);
+ tile[tilenum].tl = tl = int32_t((w1 >> 32) & 0xfff);
+ tile[tilenum].sh = sh = int32_t((w1 >> 12) & 0xfff);
+ tile[tilenum].th = dxt = int32_t((w1 >> 0) & 0xfff);
+
+ /*uint16_t tl_masked = tl & 0x3ff;
+
+ int32_t load_edge_walker_data[10] = {
+ ((cmd_buf[0] >> 32) & 0xff000000) | (0x10 << 19) | (tilenum << 16) | ((tl_masked << 2) | 3),
+ (((tl_masked << 2) | 3) << 16) | (tl_masked << 2),
+ sh << 16,
+ sl << 16,
+ sh << 16,
+ ((sl << 3) << 16) | (tl << 3),
+ (dxt & 0xff) << 8,
+ ((0x80 >> wstate->ti_size) << 16) | (dxt >> 8),
+ 0x20,
+ 0x20
+ };
- if (sh < sl)
- {
- fatalerror("load_block: sh < sl\n");
- }
+ do_load_edge_walker(load_edge_walker_data);*/
int32_t width = (sh - sl) + 1;
@@ -2819,10 +2744,11 @@ void n64_rdp::cmd_load_block(uint64_t w1)
m_tiles[tilenum].stl = rgbaint_t(m_tiles[tilenum].sl, m_tiles[tilenum].sl, m_tiles[tilenum].tl, m_tiles[tilenum].tl);
}
-void n64_rdp::cmd_load_tile(uint64_t w1)
+void n64_rdp::cmd_load_tile(uint64_t *cmd_buf)
{
//wait("LoadTile");
n64_tile_t* tile = m_tiles;
+ const uint64_t w1 = cmd_buf[0];
const int32_t tilenum = int32_t(w1 >> 24) & 0x7;
tile[tilenum].sl = int32_t(w1 >> 44) & 0xfff;
@@ -2952,9 +2878,10 @@ void n64_rdp::cmd_load_tile(uint64_t w1)
m_tiles[tilenum].stl = rgbaint_t(m_tiles[tilenum].sl, m_tiles[tilenum].sl, m_tiles[tilenum].tl, m_tiles[tilenum].tl);
}
-void n64_rdp::cmd_set_tile(uint64_t w1)
+void n64_rdp::cmd_set_tile(uint64_t *cmd_buf)
{
//wait("SetTile");
+ const uint64_t w1 = cmd_buf[0];
const int32_t tilenum = int32_t(w1 >> 24) & 0x7;
n64_tile_t* tex_tile = &m_tiles[tilenum];
@@ -3006,8 +2933,9 @@ void n64_rdp::cmd_set_tile(uint64_t w1)
//m_pending_mode_block = true;
}
-void n64_rdp::cmd_fill_rect(uint64_t w1)
+void n64_rdp::cmd_fill_rect(uint64_t *cmd_buf)
{
+ const uint64_t w1 = cmd_buf[0];
//if(m_pending_mode_block) { wait("Block on pending mode-change"); m_pending_mode_block = false; }
const uint64_t xh = (w1 >> 12) & 0xfff;
const uint64_t xl = (w1 >> 44) & 0xfff;
@@ -3029,21 +2957,24 @@ void n64_rdp::cmd_fill_rect(uint64_t w1)
ewdata[3] = (xlint << 48) | ((xl & 3) << 46); // xm, xm frac, dxmdy (0), dxmdy frac (0)
memset(&ewdata[4], 0, 18 * sizeof(uint64_t));//shade, texture, depth
- draw_triangle(false, false, false, true);
+ draw_triangle(cmd_buf, false, false, false, true);
}
-void n64_rdp::cmd_set_fog_color(uint64_t w1)
+void n64_rdp::cmd_set_fog_color(uint64_t *cmd_buf)
{
+ const uint64_t w1 = cmd_buf[0];
m_fog_color.set(uint8_t(w1), uint8_t(w1 >> 24), uint8_t(w1 >> 16), uint8_t(w1 >> 8));
}
-void n64_rdp::cmd_set_blend_color(uint64_t w1)
+void n64_rdp::cmd_set_blend_color(uint64_t *cmd_buf)
{
+ const uint64_t w1 = cmd_buf[0];
m_blend_color.set(uint8_t(w1), uint8_t(w1 >> 24), uint8_t(w1 >> 16), uint8_t(w1 >> 8));
}
-void n64_rdp::cmd_set_prim_color(uint64_t w1)
+void n64_rdp::cmd_set_prim_color(uint64_t *cmd_buf)
{
+ const uint64_t w1 = cmd_buf[0];
m_misc_state.m_min_level = uint32_t(w1 >> 40) & 0x1f;
const uint8_t prim_lod_fraction(w1 >> 32);
m_prim_lod_fraction.set(prim_lod_fraction, prim_lod_fraction, prim_lod_fraction, prim_lod_fraction);
@@ -3053,15 +2984,17 @@ void n64_rdp::cmd_set_prim_color(uint64_t w1)
m_prim_alpha.set(alpha, alpha, alpha, alpha);
}
-void n64_rdp::cmd_set_env_color(uint64_t w1)
+void n64_rdp::cmd_set_env_color(uint64_t *cmd_buf)
{
+ const uint64_t w1 = cmd_buf[0];
const uint8_t alpha(w1);
m_env_color.set(alpha, uint8_t(w1 >> 24), uint8_t(w1 >> 16), uint8_t(w1 >> 8));
m_env_alpha.set(alpha, alpha, alpha, alpha);
}
-void n64_rdp::cmd_set_combine(uint64_t w1)
+void n64_rdp::cmd_set_combine(uint64_t *cmd_buf)
{
+ const uint64_t w1 = cmd_buf[0];
m_combine.sub_a_rgb0 = uint32_t(w1 >> 52) & 0xf;
m_combine.mul_rgb0 = uint32_t(w1 >> 47) & 0x1f;
m_combine.sub_a_a0 = uint32_t(w1 >> 44) & 0x7;
@@ -3079,27 +3012,40 @@ void n64_rdp::cmd_set_combine(uint64_t w1)
m_combine.add_rgb1 = uint32_t(w1 >> 6) & 0x7;
m_combine.sub_b_a1 = uint32_t(w1 >> 3) & 0x7;
m_combine.add_a1 = uint32_t(w1 >> 0) & 0x7;
+
+ /*static const char *s_suba_rgb[16] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "ONE", "NOISE", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO" };
+ static const char *s_subb_rgb[16] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "KEYC", "K4", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO" };
+ static const char *s_mul_rgb[32] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "KEYS", "CombinedA", "TEX0A", "TEX1A", "PRIMA", "SHADEA", "ENVA", "LODF", "PLODF", "K5",
+ "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO" };
+ static const char *s_add_rgb[8] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "ONE", "ZERO" };
+ static const char *s_sub_a[16] = { "CombinedA", "TEX0A", "TEX1A", "PRIMA", "SHADEA", "ENVA", "ONE", "ZERO" };
+ static const char *s_mul_a[16] = { "LODF", "TEX0A", "TEX1A", "PRIMA", "SHADEA", "ENVA", "PLODF", "ZERO" };
+ printf("Cycle 0, Color: (%s - %s) * %s + %s\n", s_suba_rgb[m_combine.sub_a_rgb0], s_subb_rgb[m_combine.sub_b_rgb0], s_mul_rgb[m_combine.mul_rgb0], s_add_rgb[m_combine.add_rgb0]);
+ printf("Cycle 0, Alpha: (%s - %s) * %s + %s\n", s_sub_a[m_combine.sub_a_a0], s_sub_a[m_combine.sub_b_a0], s_mul_a[m_combine.mul_a0], s_add_rgb[m_combine.add_a0]);
+ printf("Cycle 1, Color: (%s - %s) * %s + %s\n", s_suba_rgb[m_combine.sub_a_rgb1], s_subb_rgb[m_combine.sub_b_rgb1], s_mul_rgb[m_combine.mul_rgb1], s_add_rgb[m_combine.add_rgb1]);
+ printf("Cycle 1, Alpha: (%s - %s) * %s + %s\n\n", s_sub_a[m_combine.sub_a_a1], s_sub_a[m_combine.sub_b_a1], s_mul_a[m_combine.mul_a1], s_add_rgb[m_combine.add_a1]);*/
}
-void n64_rdp::cmd_set_texture_image(uint64_t w1)
+void n64_rdp::cmd_set_texture_image(uint64_t *cmd_buf)
{
+ const uint64_t w1 = cmd_buf[0];
m_misc_state.m_ti_format = uint32_t(w1 >> 53) & 0x7;
m_misc_state.m_ti_size = uint32_t(w1 >> 51) & 0x3;
m_misc_state.m_ti_width = (uint32_t(w1 >> 32) & 0x3ff) + 1;
m_misc_state.m_ti_address = uint32_t(w1) & 0x01ffffff;
}
-void n64_rdp::cmd_set_mask_image(uint64_t w1)
+void n64_rdp::cmd_set_mask_image(uint64_t *cmd_buf)
{
//wait("SetMaskImage");
-
+ const uint64_t w1 = cmd_buf[0];
m_misc_state.m_zb_address = uint32_t(w1) & 0x01ffffff;
}
-void n64_rdp::cmd_set_color_image(uint64_t w1)
+void n64_rdp::cmd_set_color_image(uint64_t *cmd_buf)
{
//wait("SetColorImage");
-
+ const uint64_t w1 = cmd_buf[0];
m_misc_state.m_fb_format = uint32_t(w1 >> 53) & 0x7;
m_misc_state.m_fb_size = uint32_t(w1 >> 51) & 0x3;
m_misc_state.m_fb_width = (uint32_t(w1 >> 32) & 0x3ff) + 1;
@@ -3108,12 +3054,7 @@ void n64_rdp::cmd_set_color_image(uint64_t w1)
/*****************************************************************************/
-void n64_rdp::cmd_invalid(uint64_t w1)
-{
- fatalerror("n64_rdp::Invalid: %d, %08x %08x\n", uint32_t(w1 >> 56) & 0x3f, uint32_t(w1 >> 32), (uint32_t)w1);
-}
-
-void n64_rdp::cmd_noop(uint64_t w1)
+void n64_rdp::cmd_noop(uint64_t *cmd_buf)
{
// Do nothing
}
@@ -3123,111 +3064,100 @@ void n64_rdp::process_command_list()
{
int32_t length = m_end - m_current;
- if(length < 0)
+ if (length <= 0)
{
m_current = m_end;
return;
}
- // load command data
- for(int32_t i = 0; i < length; i += 8)
- {
- m_cmd_data[m_cmd_ptr++] = read_data((m_current & 0x1fffffff) + i);
- }
-
- m_current = m_end;
-
- uint32_t cmd = (m_cmd_data[0] >> 56) & 0x3f;
- uint32_t cmd_length = uint32_t(m_cmd_ptr + 1) * 8;
+ //printf("length: %08x\n", (uint32_t)length); fflush(stdout);
set_status(get_status() &~ DP_STATUS_FREEZE);
- // check if more data is needed
- if (cmd_length < s_rdp_command_length[cmd])
- {
- return;
- }
+ uint64_t curr_cmd_buf[176];
- while (m_cmd_cur < m_cmd_ptr)
+ while (m_current < m_end)
{
- cmd = (m_cmd_data[m_cmd_cur] >> 56) & 0x3f;
+ uint32_t start = m_current;
+ uint32_t buf_index = 0;
+ curr_cmd_buf[buf_index++] = read_data(m_current & 0x1fffffff);
+ uint8_t cmd = (curr_cmd_buf[0] >> 56) & 0x3f;
+
+ if ((m_end - m_current) < s_rdp_command_length[cmd])
+ {
+ // Not enough data, continue waiting.
+ break;
+ }
+ m_current += 8;
- if (((m_cmd_ptr - m_cmd_cur) * 8) < s_rdp_command_length[cmd])
+ while ((buf_index << 3) < s_rdp_command_length[cmd])
{
- return;
- //fatalerror("rdp_process_list: not enough rdp command data: cur = %d, ptr = %d, expected = %d\n", m_cmd_cur, m_cmd_ptr, s_rdp_command_length[cmd]);
+ curr_cmd_buf[buf_index++] = read_data(m_current & 0x1fffffff);
+ m_current += 8;
}
- m_capture.command(&m_cmd_data[m_cmd_cur], s_rdp_command_length[cmd] / 8);
+ m_capture.command(&curr_cmd_buf[0], s_rdp_command_length[cmd] / 8);
if (LOG_RDP_EXECUTION)
{
char string[4000];
- disassemble(string);
+ disassemble(curr_cmd_buf, string);
- fprintf(rdp_exec, "%08X: %08X%08X %s\n", m_start+(m_cmd_cur * 8), uint32_t(m_cmd_data[m_cmd_cur] >> 32), (uint32_t)m_cmd_data[m_cmd_cur], string);
+ fprintf(rdp_exec, "%08X: %08X%08X %s\n", start, (uint32_t)(curr_cmd_buf[0] >> 32), (uint32_t)curr_cmd_buf[0], string);
fflush(rdp_exec);
}
// execute the command
- uint64_t w = m_cmd_data[m_cmd_cur];
-
switch(cmd)
{
- case 0x00: cmd_noop(w); break;
-
- case 0x08: cmd_triangle(w); break;
- case 0x09: cmd_triangle_z(w); break;
- case 0x0a: cmd_triangle_t(w); break;
- case 0x0b: cmd_triangle_tz(w); break;
- case 0x0c: cmd_triangle_s(w); break;
- case 0x0d: cmd_triangle_sz(w); break;
- case 0x0e: cmd_triangle_st(w); break;
- case 0x0f: cmd_triangle_stz(w); break;
-
- case 0x24: cmd_tex_rect(w); break;
- case 0x25: cmd_tex_rect_flip(w); break;
-
- case 0x26: cmd_sync_load(w); break;
- case 0x27: cmd_sync_pipe(w); break;
- case 0x28: cmd_sync_tile(w); break;
- case 0x29: cmd_sync_full(w); break;
-
- case 0x2a: cmd_set_key_gb(w); break;
- case 0x2b: cmd_set_key_r(w); break;
-
- case 0x2c: cmd_set_convert(w); break;
- case 0x3c: cmd_set_combine(w); break;
- case 0x2d: cmd_set_scissor(w); break;
- case 0x2e: cmd_set_prim_depth(w); break;
- case 0x2f: cmd_set_other_modes(w);break;
-
- case 0x30: cmd_load_tlut(w); break;
- case 0x33: cmd_load_block(w); break;
- case 0x34: cmd_load_tile(w); break;
-
- case 0x32: cmd_set_tile_size(w); break;
- case 0x35: cmd_set_tile(w); break;
-
- case 0x36: cmd_fill_rect(w); break;
-
- case 0x37: cmd_set_fill_color32(w); break;
- case 0x38: cmd_set_fog_color(w); break;
- case 0x39: cmd_set_blend_color(w);break;
- case 0x3a: cmd_set_prim_color(w); break;
- case 0x3b: cmd_set_env_color(w); break;
-
- case 0x3d: cmd_set_texture_image(w); break;
- case 0x3e: cmd_set_mask_image(w); break;
- case 0x3f: cmd_set_color_image(w); break;
+ case 0x00: cmd_noop(curr_cmd_buf); break;
+
+ case 0x08: triangle(curr_cmd_buf, false, false, false); break;
+ case 0x09: triangle(curr_cmd_buf, false, false, true); break;
+ case 0x0a: triangle(curr_cmd_buf, false, true, false); break;
+ case 0x0b: triangle(curr_cmd_buf, false, true, true); break;
+ case 0x0c: triangle(curr_cmd_buf, true, false, false); break;
+ case 0x0d: triangle(curr_cmd_buf, true, false, true); break;
+ case 0x0e: triangle(curr_cmd_buf, true, true, false); break;
+ case 0x0f: triangle(curr_cmd_buf, true, true, true); break;
+
+ case 0x24: cmd_tex_rect(curr_cmd_buf); break;
+ case 0x25: cmd_tex_rect_flip(curr_cmd_buf); break;
+
+ case 0x26: cmd_sync_load(curr_cmd_buf); break;
+ case 0x27: cmd_sync_pipe(curr_cmd_buf); break;
+ case 0x28: cmd_sync_tile(curr_cmd_buf); break;
+ case 0x29: cmd_sync_full(curr_cmd_buf); break;
+
+ case 0x2a: cmd_set_key_gb(curr_cmd_buf); break;
+ case 0x2b: cmd_set_key_r(curr_cmd_buf); break;
+
+ case 0x2c: cmd_set_convert(curr_cmd_buf); break;
+ case 0x3c: cmd_set_combine(curr_cmd_buf); break;
+ case 0x2d: cmd_set_scissor(curr_cmd_buf); break;
+ case 0x2e: cmd_set_prim_depth(curr_cmd_buf); break;
+ case 0x2f: cmd_set_other_modes(curr_cmd_buf);break;
+
+ case 0x30: cmd_load_tlut(curr_cmd_buf); break;
+ case 0x33: cmd_load_block(curr_cmd_buf); break;
+ case 0x34: cmd_load_tile(curr_cmd_buf); break;
+
+ case 0x32: cmd_set_tile_size(curr_cmd_buf); break;
+ case 0x35: cmd_set_tile(curr_cmd_buf); break;
+
+ case 0x36: cmd_fill_rect(curr_cmd_buf); break;
+
+ case 0x37: cmd_set_fill_color32(curr_cmd_buf); break;
+ case 0x38: cmd_set_fog_color(curr_cmd_buf); break;
+ case 0x39: cmd_set_blend_color(curr_cmd_buf);break;
+ case 0x3a: cmd_set_prim_color(curr_cmd_buf); break;
+ case 0x3b: cmd_set_env_color(curr_cmd_buf); break;
+
+ case 0x3d: cmd_set_texture_image(curr_cmd_buf); break;
+ case 0x3e: cmd_set_mask_image(curr_cmd_buf); break;
+ case 0x3f: cmd_set_color_image(curr_cmd_buf); break;
}
-
- m_cmd_cur += s_rdp_command_length[cmd] / 8;
};
- m_cmd_ptr = 0;
- m_cmd_cur = 0;
-
- m_start = m_current = m_end;
}
/*****************************************************************************/
@@ -3246,9 +3176,6 @@ n64_rdp::n64_rdp(n64_state &state, uint32_t* rdram, uint32_t* dmem) : poly_manag
m_pending_mode_block = false;
- m_cmd_ptr = 0;
- m_cmd_cur = 0;
-
m_start = 0;
m_end = 0;
m_current = 0;
@@ -3447,6 +3374,17 @@ void n64_rdp::rgbaz_correct_triangle(int32_t offx, int32_t offy, int32_t* r, int
void n64_rdp::write_pixel4(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object)
{
// Not yet implemented
+#if DEBUG_RDP_PIXEL
+ if (s_debug_drawing)
+ {
+ uint32_t y = curpixel / object.m_misc_state.m_fb_width;
+ uint32_t x = curpixel % object.m_misc_state.m_fb_width;
+ if (x == 157 && y == 89)
+ {
+ printf("Writing 4-bit final color: %08x\n", (uint32_t)color.to_rgba());
+ }
+ }
+#endif
}
void n64_rdp::write_pixel8(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object)
@@ -3454,6 +3392,18 @@ void n64_rdp::write_pixel8(uint32_t curpixel, color_t& color, rdp_span_aux* user
const uint8_t c = (color.get_r() & 0xf8) | ((color.get_g() & 0xf8) >> 5);
if (c != 0)
RWRITEADDR8(object.m_misc_state.m_fb_address + curpixel, c);
+
+#if DEBUG_RDP_PIXEL
+ if (s_debug_drawing)
+ {
+ uint32_t y = curpixel / object.m_misc_state.m_fb_width;
+ uint32_t x = curpixel % object.m_misc_state.m_fb_width;
+ if (x == 157 && y == 89)
+ {
+ printf("Writing 8-bit final color: %08x\n", (uint32_t)color.to_rgba());
+ }
+ }
+#endif
}
void n64_rdp::write_pixel16(uint32_t curpixel, color_t& color, rdp_span_aux* userdata, const rdp_poly_state &object)
@@ -3471,6 +3421,18 @@ void n64_rdp::write_pixel16(uint32_t curpixel, color_t& color, rdp_span_aux* use
finalcolor = (color.get_r() << 11) | (color.get_g() << 6) | (color.get_b() << 1);
}
+#if DEBUG_RDP_PIXEL
+ if (s_debug_drawing)
+ {
+ uint32_t y = curpixel / object.m_misc_state.m_fb_width;
+ uint32_t x = curpixel % object.m_misc_state.m_fb_width;
+ if (x == 157 && y == 89)
+ {
+ printf("Writing 16-bit final color: %04x\n", finalcolor);
+ }
+ }
+#endif
+
switch (object.m_other_modes.cvg_dest)
{
case 0:
@@ -3523,6 +3485,18 @@ void n64_rdp::write_pixel32(uint32_t curpixel, color_t& color, rdp_span_aux* use
finalcolor = (color.get_r() << 24) | (color.get_g() << 16) | (color.get_b() << 8);
}
+#if DEBUG_RDP_PIXEL
+ if (s_debug_drawing)
+ {
+ uint32_t y = curpixel / object.m_misc_state.m_fb_width;
+ uint32_t x = curpixel % object.m_misc_state.m_fb_width;
+ if (x == 157 && y == 89)
+ {
+ printf("Writing 32-bit final color: %08x\n", finalcolor);
+ }
+ }
+#endif
+
switch (object.m_other_modes.cvg_dest)
{
case 0:
@@ -3791,9 +3765,11 @@ void n64_rdp::span_draw_1cycle(int32_t scanline, const extent_t &extent, const r
rgbaz_correct_triangle(offx, offy, &sr, &sg, &sb, &sa, &sz, userdata, object);
rgbaz_clip(sr, sg, sb, sa, &sz, userdata);
- ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle0]))(&userdata->m_texel0_color, &userdata->m_texel0_color, sss, sst, tilenum, 0, userdata, object);
+ ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle0]))(&userdata->m_texel0_color, &userdata->m_texel0_color, sss, sst, tilenum, 0, userdata, object/*, false*/);
uint32_t t0a = userdata->m_texel0_color.get_a();
userdata->m_texel0_alpha.set(t0a, t0a, t0a, t0a);
+ userdata->m_texel1_color = userdata->m_texel0_color;
+ userdata->m_texel1_alpha = userdata->m_texel0_alpha;
const uint8_t noise = machine().rand() << 3; // Not accurate
userdata->m_noise_color.set(0, noise, noise, noise);
@@ -3831,17 +3807,132 @@ void n64_rdp::span_draw_1cycle(int32_t scanline, const extent_t &extent, const r
((this)->*(m_read_pixel[object.m_misc_state.m_fb_size]))(curpixel, userdata, object);
- if(z_compare(zbcur, zhbcur, sz, dzpix, userdata, object))
+#if DEBUG_RDP_PIXEL
+ if (s_debug_drawing)
+ {
+ //uint32_t x = curpixel % m_n64_periphs->vi_width;
+ //uint32_t y = curpixel / m_n64_periphs->vi_width;
+ //printf("%d, %d ", x, scanline);
+ if (x == 157 && scanline == 89)
+ {
+ if (true)//finalcolor == 0)
+ {
+ static const char *s_fb_format[4] = { "I", "IA", "CI", "RGBA" };
+ static const char *s_blend1a_c0[4] = { "PIXC", "MEMC", "BLENDC", "FOGC" };
+ static const char *s_blend1b_c0[4] = { "PIXA", "FOGA", "SHADEA", "ZERO" };
+ static const char *s_blend2a_c0[4] = { "PIXC", "MEMC", "BLENDC", "FOGC" };
+ static const char *s_blend2b_c0[4] = { "INVPIXA", "MEMA", "ONE", "ZERO" };
+ static const char *s_blend1a_c1[4] = { "BPIXC", "MEMC", "BLENDC", "FOGC" };
+ static const char *s_blend1b_c1[4] = { "PIXA", "FOGA", "SHADEA", "ZERO" };
+ static const char *s_blend2a_c1[4] = { "BPIXC", "MEMC", "BLENDC", "FOGC" };
+ static const char *s_blend2b_c1[4] = { "INVPIXA", "MEMA", "ONE", "ZERO" };
+ static const char *s_suba_rgb[16] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "ONE", "NOISE", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO" };
+ static const char *s_subb_rgb[16] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "KEYC", "K4", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO" };
+ static const char *s_mul_rgb[32] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "KEYS", "CombinedA", "TEX0A", "TEX1A", "PRIMA", "SHADEA", "ENVA", "LODF", "PLODF", "K5",
+ "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO" };
+ static const char *s_add_rgb[8] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "ONE", "ZERO" };
+ static const char *s_sub_a[16] = { "CombinedA", "TEX0A", "TEX1A", "PRIMA", "SHADEA", "ENVA", "ONE", "ZERO" };
+ static const char *s_mul_a[16] = { "LODF", "TEX0A", "TEX1A", "PRIMA", "SHADEA", "ENVA", "PLODF", "ZERO" };
+
+ printf("Write to %08x: %d, %d\n", curpixel, x, scanline);
+ printf("m_fb_size: %d\n", 4 << object.m_misc_state.m_fb_size);
+ printf("m_fb_format: %s\n", s_fb_format[object.m_misc_state.m_fb_format]);
+ printf("blend enable: %d\n", userdata->m_blend_enable);
+ printf("other modes:\n");
+ printf(" cycle_type: %d\n", object.m_other_modes.cycle_type);
+ printf(" persp_tex_en: %d\n", object.m_other_modes.persp_tex_en);
+ printf(" detail_tex_en: %d\n", object.m_other_modes.detail_tex_en);
+ printf(" sharpen_tex_en: %d\n", object.m_other_modes.sharpen_tex_en);
+ printf(" tex_lod_en: %d\n", object.m_other_modes.tex_lod_en);
+ printf(" en_tlut: %d\n", object.m_other_modes.en_tlut);
+ printf(" tlut_type: %d\n", object.m_other_modes.tlut_type);
+ printf(" sample_type: %d\n", object.m_other_modes.sample_type);
+ printf(" mid_texel: %d\n", object.m_other_modes.mid_texel);
+ printf(" bi_lerp0: %d\n", object.m_other_modes.bi_lerp0);
+ printf(" bi_lerp1: %d\n", object.m_other_modes.bi_lerp1);
+ printf(" convert_one: %d\n", object.m_other_modes.convert_one);
+ printf(" key_en: %d\n", object.m_other_modes.key_en);
+ printf(" rgb_dither_sel: %d\n", object.m_other_modes.rgb_dither_sel);
+ printf(" alpha_dither_sel: %d\n", object.m_other_modes.alpha_dither_sel);
+ printf(" blend_m1a_0 (A Cycle 0, 1): %s\n", s_blend1a_c0[object.m_other_modes.blend_m1a_0]);
+ printf(" blend_m1a_1 (A Cycle 1, 1): %s\n", s_blend1a_c1[object.m_other_modes.blend_m1a_1]);
+ printf(" blend_m1b_0 (B Cycle 0, 1): %s\n", s_blend1b_c0[object.m_other_modes.blend_m1b_0]);
+ printf(" blend_m1b_1 (B Cycle 1, 1): %s\n", s_blend1b_c1[object.m_other_modes.blend_m1b_1]);
+ printf(" blend_m2a_0 (A Cycle 0, 2): %s\n", s_blend2a_c0[object.m_other_modes.blend_m2a_0]);
+ printf(" blend_m2a_1 (A Cycle 1, 2): %s\n", s_blend2a_c1[object.m_other_modes.blend_m2a_1]);
+ printf(" blend_m2b_0 (B Cycle 0, 2): %s\n", s_blend2b_c0[object.m_other_modes.blend_m2b_0]);
+ printf(" blend_m2b_1 (B Cycle 1, 2): %s\n", s_blend2b_c1[object.m_other_modes.blend_m2b_1]);
+ printf(" tex_edge: %d\n", object.m_other_modes.tex_edge);
+ printf(" force_blend: %d\n", object.m_other_modes.force_blend);
+ printf(" blend_shift: %d\n", object.m_other_modes.blend_shift);
+ printf(" alpha_cvg_select: %d\n", object.m_other_modes.alpha_cvg_select);
+ printf(" cvg_times_alpha: %d\n", object.m_other_modes.cvg_times_alpha);
+ printf(" z_mode: %d\n", object.m_other_modes.z_mode);
+ printf(" cvg_dest: %d\n", object.m_other_modes.cvg_dest);
+ printf(" color_on_cvg: %d\n", object.m_other_modes.color_on_cvg);
+ printf(" image_read_en: %d\n", object.m_other_modes.image_read_en);
+ printf(" z_update_en: %d\n", object.m_other_modes.z_update_en);
+ printf(" z_compare_en: %d\n", object.m_other_modes.z_compare_en);
+ printf(" antialias_en: %d\n", object.m_other_modes.antialias_en);
+ printf(" z_source_sel: %d\n", object.m_other_modes.z_source_sel);
+ printf(" dither_alpha_en: %d\n", object.m_other_modes.dither_alpha_en);
+ printf(" alpha_compare_en: %d\n", object.m_other_modes.alpha_compare_en);
+ printf(" alpha_dither_mode: %d\n", object.m_other_modes.alpha_dither_mode);
+ printf("combine:\n");
+ printf(" RGB sub A, cycle 0: %s\n", s_suba_rgb[m_combine.sub_a_rgb0]);
+ printf(" RGB sub B, cycle 0: %s\n", s_subb_rgb[m_combine.sub_b_rgb0]);
+ printf(" RGB mul, cycle 0: %s\n", s_mul_rgb[m_combine.mul_rgb0]);
+ printf(" RGB add, cycle 0: %s\n", s_add_rgb[m_combine.add_rgb0]);
+ printf(" Alpha sub A, cycle 0: %s\n", s_sub_a[m_combine.sub_a_a0]);
+ printf(" Alpha sub B, cycle 0: %s\n", s_sub_a[m_combine.sub_b_a0]);
+ printf(" Alpha mul, cycle 0: %s\n", s_mul_a[m_combine.mul_a0]);
+ printf(" Alpha add, cycle 0: %s\n\n", s_add_rgb[m_combine.add_a0]);
+ printf(" RGB sub A, cycle 1: %s\n", s_suba_rgb[m_combine.sub_a_rgb1]);
+ printf(" RGB sub B, cycle 1: %s\n", s_subb_rgb[m_combine.sub_b_rgb1]);
+ printf(" RGB mul, cycle 1: %s\n", s_mul_rgb[m_combine.mul_rgb1]);
+ printf(" RGB add, cycle 1: %s\n", s_add_rgb[m_combine.add_rgb1]);
+ printf(" Alpha sub A, cycle 1: %s\n", s_sub_a[m_combine.sub_a_a1]);
+ printf(" Alpha sub B, cycle 1: %s\n", s_sub_a[m_combine.sub_b_a1]);
+ printf(" Alpha mul, cycle 1: %s\n", s_mul_a[m_combine.mul_a1]);
+ printf(" Alpha add, cycle 1: %s\n\n", s_add_rgb[m_combine.add_a1]);
+ printf("Texel 0: %08x\n", (uint32_t)userdata->m_texel0_color.to_rgba());
+ printf("Texel 1: %08x\n", (uint32_t)userdata->m_texel1_color.to_rgba());
+ printf("Env: %08x\n", (uint32_t)userdata->m_env_color.to_rgba());
+ printf("Prim: %08x\n", (uint32_t)userdata->m_prim_color.to_rgba());
+ printf("Mem: %08x\n", (uint32_t)userdata->m_memory_color.to_rgba());
+ printf("Shade: %08x\n", (uint32_t)userdata->m_shade_color.to_rgba());
+ printf("sargb: %08x, %08x, %08x, %08x\n", (uint32_t)sa, (uint32_t)sr, (uint32_t)sg, (uint32_t)sb);
+
+ printf("Blend index: %d\n", (userdata->m_blend_enable << 2) | blend_index);
+ int32_t cdith = 0;
+ int32_t adith = 0;
+ get_dither_values(scanline, j, &cdith, &adith, object);
+ color_t reblended_pixel;
+ ((&m_blender)->*(m_blender.blend1[(userdata->m_blend_enable << 2) | blend_index]))(reblended_pixel, cdith, adith, partialreject, sel0, userdata, object/*, true*/);
+
+ //((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle0]))(&userdata->m_texel0_color, &userdata->m_texel0_color, sss, sst, tilenum, 0, userdata, object/*, true*/);
+ }
+ }
+ }
+#endif
+
+ if (z_compare(zbcur, zhbcur, sz, dzpix, userdata, object))
{
int32_t cdith = 0;
int32_t adith = 0;
get_dither_values(scanline, j, &cdith, &adith, object);
color_t blended_pixel;
- bool rendered = ((&m_blender)->*(m_blender.blend1[(userdata->m_blend_enable << 2) | blend_index]))(blended_pixel, cdith, adith, partialreject, sel0, userdata, object);
+ bool rendered = ((&m_blender)->*(m_blender.blend1[(userdata->m_blend_enable << 2) | blend_index]))(blended_pixel, cdith, adith, partialreject, sel0, userdata, object/*, false*/);
if (rendered)
{
+#if DEBUG_RDP_PIXEL
+ if (x == 157 && scanline == 89 && s_debug_drawing)
+ {
+ printf("WRITE1: %08x\n", (uint32_t)blended_pixel.to_rgba());
+ }
+#endif
((this)->*(m_write_pixel[object.m_misc_state.m_fb_size]))(curpixel, blended_pixel, userdata, object);
if (object.m_other_modes.z_update_en)
{
@@ -4011,9 +4102,8 @@ void n64_rdp::span_draw_2cycle(int32_t scanline, const extent_t &extent, const r
rgbaz_correct_triangle(offx, offy, &sr, &sg, &sb, &sa, &sz, userdata, object);
rgbaz_clip(sr, sg, sb, sa, &sz, userdata);
- ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle0]))(&userdata->m_texel0_color, &userdata->m_texel0_color, sss, sst, tile1, 0, userdata, object);
- ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle1]))(&userdata->m_texel1_color, &userdata->m_texel0_color, sss, sst, tile2, 1, userdata, object);
- ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle1]))(&userdata->m_next_texel_color, &userdata->m_next_texel_color, sss, sst, tile2, 1, userdata, object);
+ ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle0]))(&userdata->m_texel0_color, &userdata->m_texel0_color, sss, sst, tile1, 0, userdata, object/*, false*/);
+ ((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle1]))(&userdata->m_texel1_color, &userdata->m_texel0_color, sss, sst, tile2, 1, userdata, object/*, false*/);
uint32_t t0a = userdata->m_texel0_color.get_a();
uint32_t t1a = userdata->m_texel1_color.get_a();
@@ -4049,8 +4139,10 @@ void n64_rdp::span_draw_2cycle(int32_t scanline, const extent_t &extent, const r
rgbsub_a.clamp_and_clear(0xfffffe00);
userdata->m_combined_color.set(rgbsub_a);
- userdata->m_texel0_color.set(userdata->m_texel1_color);
- userdata->m_texel1_color.set(userdata->m_next_texel_color);
+
+ rgbaint_t temp_color(userdata->m_texel0_color);
+ userdata->m_texel0_color = userdata->m_texel1_color;
+ userdata->m_texel1_color = temp_color;
uint32_t ca = userdata->m_combined_color.get_a();
userdata->m_combined_alpha.set(ca, ca, ca, ca);
@@ -4090,15 +4182,130 @@ void n64_rdp::span_draw_2cycle(int32_t scanline, const extent_t &extent, const r
((this)->*(m_read_pixel[object.m_misc_state.m_fb_size]))(curpixel, userdata, object);
+#if DEBUG_RDP_PIXEL
+ if (s_debug_drawing)
+ {
+ //uint32_t x = curpixel % m_n64_periphs->vi_width;
+ //uint32_t y = curpixel / m_n64_periphs->vi_width;
+ //printf("%d, %d ", x, scanline);
+ if (x == 157 && scanline == 89)
+ {
+ if (true)//finalcolor == 0)
+ {
+ static const char *s_fb_format[4] = { "I", "IA", "CI", "RGBA" };
+ static const char *s_blend1a_c0[4] = { "PIXC", "MEMC", "BLENDC", "FOGC" };
+ static const char *s_blend1b_c0[4] = { "PIXA", "FOGA", "SHADEA", "ZERO" };
+ static const char *s_blend2a_c0[4] = { "PIXC", "MEMC", "BLENDC", "FOGC" };
+ static const char *s_blend2b_c0[4] = { "INVPIXA", "MEMA", "ONE", "ZERO" };
+ static const char *s_blend1a_c1[4] = { "BPIXC", "MEMC", "BLENDC", "FOGC" };
+ static const char *s_blend1b_c1[4] = { "PIXA", "FOGA", "SHADEA", "ZERO" };
+ static const char *s_blend2a_c1[4] = { "BPIXC", "MEMC", "BLENDC", "FOGC" };
+ static const char *s_blend2b_c1[4] = { "INVPIXA", "MEMA", "ONE", "ZERO" };
+ static const char *s_suba_rgb[16] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "ONE", "NOISE", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO" };
+ static const char *s_subb_rgb[16] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "KEYC", "K4", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO" };
+ static const char *s_mul_rgb[32] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "KEYS", "CombinedA", "TEX0A", "TEX1A", "PRIMA", "SHADEA", "ENVA", "LODF", "PLODF", "K5",
+ "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO", "ZERO" };
+ static const char *s_add_rgb[8] = { "Combined", "TEX0C", "TEX1C", "PRIMC", "SHADEC", "ENVC", "ONE", "ZERO" };
+ static const char *s_sub_a[16] = { "CombinedA", "TEX0A", "TEX1A", "PRIMA", "SHADEA", "ENVA", "ONE", "ZERO" };
+ static const char *s_mul_a[16] = { "LODF", "TEX0A", "TEX1A", "PRIMA", "SHADEA", "ENVA", "PLODF", "ZERO" };
+
+ printf("Write to %08x: %d, %d\n", curpixel, x, scanline);
+ printf("m_fb_size: %d\n", 4 << object.m_misc_state.m_fb_size);
+ printf("m_fb_format: %s\n", s_fb_format[object.m_misc_state.m_fb_format]);
+ printf("blend enable: %d\n", userdata->m_blend_enable);
+ printf("other modes:\n");
+ printf(" cycle_type: %d\n", object.m_other_modes.cycle_type);
+ printf(" persp_tex_en: %d\n", object.m_other_modes.persp_tex_en);
+ printf(" detail_tex_en: %d\n", object.m_other_modes.detail_tex_en);
+ printf(" sharpen_tex_en: %d\n", object.m_other_modes.sharpen_tex_en);
+ printf(" tex_lod_en: %d\n", object.m_other_modes.tex_lod_en);
+ printf(" en_tlut: %d\n", object.m_other_modes.en_tlut);
+ printf(" tlut_type: %d\n", object.m_other_modes.tlut_type);
+ printf(" sample_type: %d\n", object.m_other_modes.sample_type);
+ printf(" mid_texel: %d\n", object.m_other_modes.mid_texel);
+ printf(" bi_lerp0: %d\n", object.m_other_modes.bi_lerp0);
+ printf(" bi_lerp1: %d\n", object.m_other_modes.bi_lerp1);
+ printf(" convert_one: %d\n", object.m_other_modes.convert_one);
+ printf(" key_en: %d\n", object.m_other_modes.key_en);
+ printf(" rgb_dither_sel: %d\n", object.m_other_modes.rgb_dither_sel);
+ printf(" alpha_dither_sel: %d\n", object.m_other_modes.alpha_dither_sel);
+ printf(" blend_m1a_0 (A Cycle 0, 1): %s\n", s_blend1a_c0[object.m_other_modes.blend_m1a_0]);
+ printf(" blend_m1a_1 (A Cycle 1, 1): %s\n", s_blend1a_c1[object.m_other_modes.blend_m1a_1]);
+ printf(" blend_m1b_0 (B Cycle 0, 1): %s\n", s_blend1b_c0[object.m_other_modes.blend_m1b_0]);
+ printf(" blend_m1b_1 (B Cycle 1, 1): %s\n", s_blend1b_c1[object.m_other_modes.blend_m1b_1]);
+ printf(" blend_m2a_0 (A Cycle 0, 2): %s\n", s_blend2a_c0[object.m_other_modes.blend_m2a_0]);
+ printf(" blend_m2a_1 (A Cycle 1, 2): %s\n", s_blend2a_c1[object.m_other_modes.blend_m2a_1]);
+ printf(" blend_m2b_0 (B Cycle 0, 2): %s\n", s_blend2b_c0[object.m_other_modes.blend_m2b_0]);
+ printf(" blend_m2b_1 (B Cycle 1, 2): %s\n", s_blend2b_c1[object.m_other_modes.blend_m2b_1]);
+ printf(" tex_edge: %d\n", object.m_other_modes.tex_edge);
+ printf(" force_blend: %d\n", object.m_other_modes.force_blend);
+ printf(" blend_shift: %d\n", object.m_other_modes.blend_shift);
+ printf(" alpha_cvg_select: %d\n", object.m_other_modes.alpha_cvg_select);
+ printf(" cvg_times_alpha: %d\n", object.m_other_modes.cvg_times_alpha);
+ printf(" z_mode: %d\n", object.m_other_modes.z_mode);
+ printf(" cvg_dest: %d\n", object.m_other_modes.cvg_dest);
+ printf(" color_on_cvg: %d\n", object.m_other_modes.color_on_cvg);
+ printf(" image_read_en: %d\n", object.m_other_modes.image_read_en);
+ printf(" z_update_en: %d\n", object.m_other_modes.z_update_en);
+ printf(" z_compare_en: %d\n", object.m_other_modes.z_compare_en);
+ printf(" antialias_en: %d\n", object.m_other_modes.antialias_en);
+ printf(" z_source_sel: %d\n", object.m_other_modes.z_source_sel);
+ printf(" dither_alpha_en: %d\n", object.m_other_modes.dither_alpha_en);
+ printf(" alpha_compare_en: %d\n", object.m_other_modes.alpha_compare_en);
+ printf(" alpha_dither_mode: %d\n", object.m_other_modes.alpha_dither_mode);
+ printf("combine:\n");
+ printf(" RGB sub A, cycle 0: %s\n", s_suba_rgb[m_combine.sub_a_rgb0]);
+ printf(" RGB sub B, cycle 0: %s\n", s_subb_rgb[m_combine.sub_b_rgb0]);
+ printf(" RGB mul, cycle 0: %s\n", s_mul_rgb[m_combine.mul_rgb0]);
+ printf(" RGB add, cycle 0: %s\n", s_add_rgb[m_combine.add_rgb0]);
+ printf(" Alpha sub A, cycle 0: %s\n", s_sub_a[m_combine.sub_a_a0]);
+ printf(" Alpha sub B, cycle 0: %s\n", s_sub_a[m_combine.sub_b_a0]);
+ printf(" Alpha mul, cycle 0: %s\n", s_mul_a[m_combine.mul_a0]);
+ printf(" Alpha add, cycle 0: %s\n\n", s_add_rgb[m_combine.add_a0]);
+ printf(" RGB sub A, cycle 1: %s\n", s_suba_rgb[m_combine.sub_a_rgb1]);
+ printf(" RGB sub B, cycle 1: %s\n", s_subb_rgb[m_combine.sub_b_rgb1]);
+ printf(" RGB mul, cycle 1: %s\n", s_mul_rgb[m_combine.mul_rgb1]);
+ printf(" RGB add, cycle 1: %s\n", s_add_rgb[m_combine.add_rgb1]);
+ printf(" Alpha sub A, cycle 1: %s\n", s_sub_a[m_combine.sub_a_a1]);
+ printf(" Alpha sub B, cycle 1: %s\n", s_sub_a[m_combine.sub_b_a1]);
+ printf(" Alpha mul, cycle 1: %s\n", s_mul_a[m_combine.mul_a1]);
+ printf(" Alpha add, cycle 1: %s\n\n", s_add_rgb[m_combine.add_a1]);
+ printf("Texel 0: %08x\n", (uint32_t)userdata->m_texel0_color.to_rgba());
+ printf("Texel 1: %08x\n", (uint32_t)userdata->m_texel1_color.to_rgba());
+ printf("Env: %08x\n", (uint32_t)userdata->m_env_color.to_rgba());
+ printf("Prim: %08x\n", (uint32_t)userdata->m_prim_color.to_rgba());
+ printf("Mem: %08x\n", (uint32_t)userdata->m_memory_color.to_rgba());
+ printf("Shade: %08x\n", (uint32_t)userdata->m_shade_color.to_rgba());
+ printf("sargb: %08x, %08x, %08x, %08x\n", (uint32_t)sa, (uint32_t)sr, (uint32_t)sg, (uint32_t)sb);
+
+ printf("Blend index: %d\n", (userdata->m_blend_enable << 2) | blend_index);
+ int32_t cdith = 0;
+ int32_t adith = 0;
+ get_dither_values(scanline, j, &cdith, &adith, object);
+ color_t reblended_pixel;
+ ((&m_blender)->*(m_blender.blend2[(userdata->m_blend_enable << 2) | blend_index]))(reblended_pixel, cdith, adith, partialreject, sel0, sel1, userdata, object/*, true*/);
+
+ //((m_tex_pipe).*(m_tex_pipe.m_cycle[cycle0]))(&userdata->m_texel0_color, &userdata->m_texel0_color, sss, sst, tilenum, 0, userdata, object/*, true*/);
+ }
+ }
+ }
+#endif
+
if(z_compare(zbcur, zhbcur, sz, dzpix, userdata, object))
{
get_dither_values(scanline, j, &cdith, &adith, object);
color_t blended_pixel;
- bool rendered = ((&m_blender)->*(m_blender.blend2[(userdata->m_blend_enable << 2) | blend_index]))(blended_pixel, cdith, adith, partialreject, sel0, sel1, userdata, object);
+ bool rendered = ((&m_blender)->*(m_blender.blend2[(userdata->m_blend_enable << 2) | blend_index]))(blended_pixel, cdith, adith, partialreject, sel0, sel1, userdata, object/*, false*/);
if (rendered)
{
+#if DEBUG_RDP_PIXEL
+ if (x == 157 && scanline == 89 && s_debug_drawing)
+ {
+ printf("WRITE2: %08x\n", (uint32_t)blended_pixel.to_rgba());
+ }
+#endif
((this)->*(m_write_pixel[object.m_misc_state.m_fb_size]))(curpixel, blended_pixel, userdata, object);
if (object.m_other_modes.z_update_en)
{
diff --git a/src/mame/video/n64.h b/src/mame/video/n64.h
index 9225c804b22..a40d1526dd4 100644
--- a/src/mame/video/n64.h
+++ b/src/mame/video/n64.h
@@ -127,8 +127,6 @@ class n64_rdp;
#include "video/rdpblend.h"
#include "video/rdptpipe.h"
-typedef void (*rdp_command_t)(uint64_t w1);
-
class n64_state;
class n64_rdp : public poly_manager<uint32_t, rdp_poly_state, 8>
@@ -164,24 +162,24 @@ public:
}
void process_command_list();
- uint64_t read_data(uint32_t address);
- void disassemble(char* buffer);
+ uint64_t read_data(uint32_t address);
+ void disassemble(uint64_t *cmd_buf, char* buffer);
void set_machine(running_machine& machine) { m_machine = &machine; }
void set_n64_periphs(n64_periphs* periphs) { m_n64_periphs = periphs; }
// CPU-visible registers
void set_start(uint32_t val) { m_start = val; }
- uint32_t get_start() const { return m_start; }
+ uint32_t get_start() const { return m_start; }
void set_end(uint32_t val) { m_end = val; }
- uint32_t get_end() const { return m_end; }
+ uint32_t get_end() const { return m_end; }
void set_current(uint32_t val) { m_current = val; }
- uint32_t get_current() const { return m_current; }
+ uint32_t get_current() const { return m_current; }
void set_status(uint32_t val) { m_status = val; }
- uint32_t get_status() const { return m_status; }
+ uint32_t get_status() const { return m_status; }
// Color Combiner
int32_t color_combiner_equation(int32_t a, int32_t b, int32_t c, int32_t d);
@@ -226,48 +224,39 @@ public:
bool z_compare(uint32_t zcurpixel, uint32_t dzcurpixel, uint32_t sz, uint16_t dzpix, rdp_span_aux* userdata, const rdp_poly_state &object);
// Commands
- void cmd_invalid(uint64_t w1);
- void cmd_noop(uint64_t w1);
- void cmd_triangle(uint64_t w1);
- void cmd_triangle_z(uint64_t w1);
- void cmd_triangle_t(uint64_t w1);
- void cmd_triangle_tz(uint64_t w1);
- void cmd_triangle_s(uint64_t w1);
- void cmd_triangle_sz(uint64_t w1);
- void cmd_triangle_st(uint64_t w1);
- void cmd_triangle_stz(uint64_t w1);
- void cmd_tex_rect(uint64_t w1);
- void cmd_tex_rect_flip(uint64_t w1);
- void cmd_sync_load(uint64_t w1);
- void cmd_sync_pipe(uint64_t w1);
- void cmd_sync_tile(uint64_t w1);
- void cmd_sync_full(uint64_t w1);
- void cmd_set_key_gb(uint64_t w1);
- void cmd_set_key_r(uint64_t w1);
- void cmd_set_fill_color32(uint64_t w1);
- void cmd_set_convert(uint64_t w1);
- void cmd_set_scissor(uint64_t w1);
- void cmd_set_prim_depth(uint64_t w1);
- void cmd_set_other_modes(uint64_t w1);
- void cmd_load_tlut(uint64_t w1);
- void cmd_set_tile_size(uint64_t w1);
- void cmd_load_block(uint64_t w1);
- void cmd_load_tile(uint64_t w1);
- void cmd_fill_rect(uint64_t w1);
- void cmd_set_tile(uint64_t w1);
- void cmd_set_fog_color(uint64_t w1);
- void cmd_set_blend_color(uint64_t w1);
- void cmd_set_prim_color(uint64_t w1);
- void cmd_set_env_color(uint64_t w1);
- void cmd_set_combine(uint64_t w1);
- void cmd_set_texture_image(uint64_t w1);
- void cmd_set_mask_image(uint64_t w1);
- void cmd_set_color_image(uint64_t w1);
+ void cmd_noop(uint64_t *cmd_buf);
+ void cmd_tex_rect(uint64_t *cmd_buf);
+ void cmd_tex_rect_flip(uint64_t *cmd_buf);
+ void cmd_sync_load(uint64_t *cmd_buf);
+ void cmd_sync_pipe(uint64_t *cmd_buf);
+ void cmd_sync_tile(uint64_t *cmd_buf);
+ void cmd_sync_full(uint64_t *cmd_buf);
+ void cmd_set_key_gb(uint64_t *cmd_buf);
+ void cmd_set_key_r(uint64_t *cmd_buf);
+ void cmd_set_fill_color32(uint64_t *cmd_buf);
+ void cmd_set_convert(uint64_t *cmd_buf);
+ void cmd_set_scissor(uint64_t *cmd_buf);
+ void cmd_set_prim_depth(uint64_t *cmd_buf);
+ void cmd_set_other_modes(uint64_t *cmd_buf);
+ void cmd_load_tlut(uint64_t *cmd_buf);
+ void cmd_set_tile_size(uint64_t *cmd_buf);
+ void cmd_load_block(uint64_t *cmd_buf);
+ void cmd_load_tile(uint64_t *cmd_buf);
+ void cmd_fill_rect(uint64_t *cmd_buf);
+ void cmd_set_tile(uint64_t *cmd_buf);
+ void cmd_set_fog_color(uint64_t *cmd_buf);
+ void cmd_set_blend_color(uint64_t *cmd_buf);
+ void cmd_set_prim_color(uint64_t *cmd_buf);
+ void cmd_set_env_color(uint64_t *cmd_buf);
+ void cmd_set_combine(uint64_t *cmd_buf);
+ void cmd_set_texture_image(uint64_t *cmd_buf);
+ void cmd_set_mask_image(uint64_t *cmd_buf);
+ void cmd_set_color_image(uint64_t *cmd_buf);
void rgbaz_clip(int32_t sr, int32_t sg, int32_t sb, int32_t sa, int32_t* sz, rdp_span_aux* userdata);
void rgbaz_correct_triangle(int32_t offx, int32_t offy, int32_t* r, int32_t* g, int32_t* b, int32_t* a, int32_t* z, rdp_span_aux* userdata, const rdp_poly_state &object);
- void triangle(bool shade, bool texture, bool zbuffer);
+ void triangle(uint64_t *cmd_buf, bool shade, bool texture, bool zbuffer);
void get_dither_values(int32_t x, int32_t y, int32_t* cdith, int32_t* adith, const rdp_poly_state &object);
@@ -309,7 +298,7 @@ public:
rectangle_t m_scissor;
span_base_t m_span_base;
- void draw_triangle(bool shade, bool texture, bool zbuffer, bool rect);
+ void draw_triangle(uint64_t *cmd_buf, bool shade, bool texture, bool zbuffer, bool rect);
std::unique_ptr<uint8_t[]> m_aux_buf;
uint32_t m_aux_buf_ptr;
@@ -374,9 +363,6 @@ private:
uint64_t m_cmd_data[0x800];
uint64_t m_temp_rect_data[0x800];
- int32_t m_cmd_ptr;
- int32_t m_cmd_cur;
-
uint32_t m_start;
uint32_t m_end;
uint32_t m_current;
@@ -401,7 +387,6 @@ private:
static uint8_t const s_bayer_matrix[16];
static uint8_t const s_magic_matrix[16];
- static rdp_command_t const m_commands[0x40];
static int32_t const s_rdp_command_length[];
static char const *const s_image_format[];
static char const *const s_image_size[];
diff --git a/src/mame/video/n64types.h b/src/mame/video/n64types.h
index ca9c4c28907..0f16eec4176 100644
--- a/src/mame/video/n64types.h
+++ b/src/mame/video/n64types.h
@@ -306,6 +306,7 @@ struct rdp_span_aux
uint8_t* m_tmem; /* pointer to texture cache for this polygon */
bool m_start_span;
rgbaint_t m_clamp_diff[8];
+ combine_modes_t m_combine;
};
struct z_decompress_entry_t