summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/rsp/rspcp2d.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/rsp/rspcp2d.cpp')
-rw-r--r--src/devices/cpu/rsp/rspcp2d.cpp3388
1 files changed, 0 insertions, 3388 deletions
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;
-}