diff options
author | 2021-08-10 03:06:08 +0200 | |
---|---|---|
committer | 2021-08-09 21:06:08 -0400 | |
commit | 7fe8f9f74c8a8aca5e0ca949dafcac13504c3013 (patch) | |
tree | 3cd6d926ab025b2b965c01ff02dbfee69488abec /src | |
parent | 1fc8bf7fcd88b672f1c9ab7427d80f0356358d85 (diff) |
Assorted N64 fixes (#8415)
* -rdp: Fixed incorrect channel swapping on 32-bit resampled framebuffers. [Ryan Holtz]
* -rsp: Fixed LWV and VMOV behavior. Added reserved instructions V056, V057, V073, and VNULL. [Ryan Holtz, krom]
* -rdp: Temporarily adjusted framebuffer resampling to not exceed screen bounds in some games. [Ryan Holtz]
* -n64: Fixed SP DMA behavior based on hardware tests. [Ryan Holtz]
* -rsp: Removed unused DRC and SIMD support. General code cleanup. [Ryan Holtz]
* -n64: Pass K4 and K5 factors to threaded drawing code. Fixes black geometry in Conker's Bad Fur Day. [Ryan Holtz]
* -aleck64: Fixed compile issue with previous commits. [Ryan Holtz]
Diffstat (limited to 'src')
43 files changed, 3573 insertions, 11860 deletions
diff --git a/src/devices/cpu/rsp/clamp.h b/src/devices/cpu/rsp/clamp.h deleted file mode 100644 index 5b69b746a7d..00000000000 --- a/src/devices/cpu/rsp/clamp.h +++ /dev/null @@ -1,37 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -static inline rsp_vec_t sclamp_acc_to_mid(rsp_vec_t acc_mid, rsp_vec_t acc_hi) -{ - return _mm_packs_epi32( - _mm_unpacklo_epi16(acc_mid, acc_hi), - _mm_unpackhi_epi16(acc_mid, acc_hi) - ); -} - -static inline rsp_vec_t uclamp_acc(rsp_vec_t val, rsp_vec_t acc_mid, rsp_vec_t acc_hi, rsp_vec_t zero) -{ - rsp_vec_t hi_negative = _mm_srai_epi16(acc_hi, 15); // 0x0000 - rsp_vec_t mid_negative = _mm_srai_epi16(acc_mid, 15); // 0xffff - - // We don't have to clamp if the HI part of the - // accumulator is sign-extended down to the MD part. - rsp_vec_t hi_sign_check = _mm_cmpeq_epi16(hi_negative, acc_hi); // 0x0000 - rsp_vec_t mid_sign_check = _mm_cmpeq_epi16(hi_negative, mid_negative); // 0x0000 - rsp_vec_t clamp_mask = _mm_and_si128(mid_sign_check, hi_sign_check); // 0x0000 - - // Generate the value in the event we need to clamp. - // * hi_negative, mid_sign => xxxx - // * hi_negative, !mid_sign => 0000 - // * !hi_negative, mid_sign => FFFF - // * !hi_negative, !mid_sign => xxxx - rsp_vec_t clamped_val = _mm_cmpeq_epi16(hi_negative, zero); // 0xffff - -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - return _mm_blendv_epi8(clamped_val, val, clamp_mask); -#else - clamped_val = _mm_and_si128(clamp_mask, val); - val = _mm_andnot_si128(clamp_mask, clamped_val); - return _mm_or_si128(val, clamped_val); -#endif -} diff --git a/src/devices/cpu/rsp/rsp.cpp b/src/devices/cpu/rsp/rsp.cpp index 07deffc6e10..5d8cccff5af 100644 --- a/src/devices/cpu/rsp/rsp.cpp +++ b/src/devices/cpu/rsp/rsp.cpp @@ -9,13 +9,10 @@ #include "emu.h" #include "rsp.h" -#include "rspfe.h" -#include "rspcp2.h" -#include "rspcp2d.h" - #include "debugger.h" #include "rspdefs.h" +#include "rspdiv.h" #include "rsp_dasm.h" @@ -27,59 +24,72 @@ DEFINE_DEVICE_TYPE(RSP, rsp_device, "rsp", "Nintendo & SGI Reality Signal Proces #define SAVE_DMEM 0 #define RSP_TEST_SYNC 0 -#define PRINT_VECREG(x) osd_printf_debug("V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X\n", (x), \ - (uint16_t)VREG_S((x),0), (uint16_t)VREG_S((x),1), \ - (uint16_t)VREG_S((x),2), (uint16_t)VREG_S((x),3), \ - (uint16_t)VREG_S((x),4), (uint16_t)VREG_S((x),5), \ - (uint16_t)VREG_S((x),6), (uint16_t)VREG_S((x),7)) +#define PRINT_VECREG(x) osd_printf_debug("V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X\n", x, \ + m_v[x].w[0], m_v[x].w[1], m_v[x].w[2], m_v[x].w[3], \ + m_v[x].w[4], m_v[x].w[5], m_v[x].w[6], m_v[x].w[7]) -#define PRINT_ACCUM(x) osd_printf_debug("A%d: %08X|%08X\n", (x), \ - (uint32_t)( ( ACCUM(x) >> 32 ) & 0x00000000ffffffff ), \ - (uint32_t)( ACCUM(x) & 0x00000000ffffffff )) +#define PRINT_ACCUM(x) osd_printf_debug("A%d: %08X|%08X\n", x, (uint32_t)(m_accum[x].q >> 32), (uint32_t)m_accum[x].q); #define SIMM16 ((int32_t)(int16_t)(op)) #define UIMM16 ((uint16_t)(op)) #define UIMM26 (op & 0x03ffffff) -#define RSVAL (m_rsp_state->r[RSREG]) -#define RTVAL (m_rsp_state->r[RTREG]) -#define RDVAL (m_rsp_state->r[RDREG]) - -#define JUMP_ABS(addr) { m_nextpc = 0x04001000 | (((addr) << 2) & 0xfff); } -#define JUMP_ABS_L(addr,l) { m_nextpc = 0x04001000 | (((addr) << 2) & 0xfff); m_rsp_state->r[l] = m_rsp_state->pc + 4; } -#define JUMP_REL(offset) { m_nextpc = 0x04001000 | ((m_rsp_state->pc + ((offset) << 2)) & 0xfff); } -#define JUMP_REL_L(offset,l) { m_nextpc = 0x04001000 | ((m_rsp_state->pc + ((offset) << 2)) & 0xfff); m_rsp_state->r[l] = m_rsp_state->pc + 4; } -#define JUMP_PC(addr) { m_nextpc = 0x04001000 | ((addr) & 0xfff); } -#define JUMP_PC_L(addr,l) { m_nextpc = 0x04001000 | ((addr) & 0xfff); m_rsp_state->r[l] = m_rsp_state->pc + 4; } -#define LINK(l) { m_rsp_state->r[l] = m_rsp_state->pc + 4; } - -#define CARRY_FLAG(x) (m_vflag[CARRY][x & 7] != 0 ? 0xffff : 0) -#define COMPARE_FLAG(x) (m_vflag[COMPARE][x & 7] != 0 ? 0xffff : 0) -#define CLIP1_FLAG(x) (m_vflag[CLIP1][x & 7] != 0 ? 0xffff : 0) -#define ZERO_FLAG(x) (m_vflag[ZERO][x & 7] != 0 ? 0xffff : 0) -#define CLIP2_FLAG(x) (m_vflag[CLIP2][x & 7] != 0 ? 0xffff : 0) - -#define CLEAR_CARRY_FLAGS() { memset(m_vflag[CARRY], 0, 16); } -#define CLEAR_COMPARE_FLAGS() { memset(m_vflag[COMPARE], 0, 16); } -#define CLEAR_CLIP1_FLAGS() { memset(m_vflag[CLIP1], 0, 16); } -#define CLEAR_ZERO_FLAGS() { memset(m_vflag[ZERO], 0, 16); } -#define CLEAR_CLIP2_FLAGS() { memset(m_vflag[CLIP2], 0, 16); } - -#define SET_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0xffff; } -#define SET_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0xffff; } -#define SET_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0xffff; } -#define SET_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0xffff; } -#define SET_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0xffff; } - -#define CLEAR_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0; } -#define CLEAR_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0; } -#define CLEAR_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0; } -#define CLEAR_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0; } -#define CLEAR_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0; } - -#define ROPCODE(pc) m_pcache.read_dword(pc) +#define JUMP_ABS(addr) { m_nextpc = (addr) << 2; } +#define JUMP_ABS_L(addr,l) { m_nextpc = (addr) << 2; m_r[l] = m_pc + 4; } +#define JUMP_REL(offset) { m_nextpc = m_pc + ((offset) << 2); } +#define JUMP_REL_L(offset,l) { m_nextpc = m_pc + ((offset) << 2); m_r[l] = m_pc + 4; } +#define JUMP_PC(addr) { m_nextpc = addr; } +#define JUMP_PC_L(addr,l) { m_nextpc = addr; m_r[l] = m_pc + 4; } +#define ROPCODE(pc) m_icache.read_dword(pc & 0xfff) + +/*************************************************************************** + Helpful Vector Defines +***************************************************************************/ + +#define VDREG ((op >> 6) & 0x1f) +#define VS1REG ((op >> 11) & 0x1f) +#define VS2REG ((op >> 16) & 0x1f) +#define EL ((op >> 21) & 0xf) + +#define VREG_B(reg, offset) m_v[(reg)].b[(offset)^1] +#define W_VREG_B(reg, offset, val) (m_v[(reg)].b[(offset)^1] = val) + +#define VEC_EL_2(x,z) (vector_elements_2[(x)][(z)]) + +#define CARRY 0 +#define COMPARE 1 +#define CLIP1 2 +#define ZERO 3 +#define CLIP2 4 + +#define SLICE_H 3 +#define SLICE_M 2 +#define SLICE_L 1 +#define SLICE_LL 0 + +#define WRITEBACK_RESULT() memcpy(m_v[VDREG].s, vres, sizeof(uint16_t) * 8); + +static const int vector_elements_2[16][8] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7 }, // none + { 0, 1, 2, 3, 4, 5, 6, 7 }, // ??? + { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q + { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q + { 0, 0, 0, 0, 4, 4, 4, 4 }, // 0h + { 1, 1, 1, 1, 5, 5, 5, 5 }, // 1h + { 2, 2, 2, 2, 6, 6, 6, 6 }, // 2h + { 3, 3, 3, 3, 7, 7, 7, 7 }, // 3h + { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0 + { 1, 1, 1, 1, 1, 1, 1, 1 }, // 1 + { 2, 2, 2, 2, 2, 2, 2, 2 }, // 2 + { 3, 3, 3, 3, 3, 3, 3, 3 }, // 3 + { 4, 4, 4, 4, 4, 4, 4, 4 }, // 4 + { 5, 5, 5, 5, 5, 5, 5, 5 }, // 5 + { 6, 6, 6, 6, 6, 6, 6, 6 }, // 6 + { 7, 7, 7, 7, 7, 7, 7, 7 }, // 7 +}; /*************************************************************************** DEBUGGING @@ -103,39 +113,17 @@ DEFINE_DEVICE_TYPE(RSP, rsp_device, "rsp", "Nintendo & SGI Reality Signal Proces rsp_device::rsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : cpu_device(mconfig, RSP, tag, owner, clock) - , m_program_config("program", ENDIANNESS_BIG, 32, 32) - , m_cache(CACHE_SIZE + sizeof(internal_rsp_state)) - , m_drcuml(nullptr) -// , m_drcuml(*this, m_cache, 0, 8, 32, 2) - , m_drcfe(nullptr) - , m_drcoptions(0) - , m_cache_dirty(true) - , m_numcycles(0) - , m_format(nullptr) - , m_arg2(0) - , m_arg3(0) - , m_entry(nullptr) - , m_nocode(nullptr) - , m_out_of_cycles(nullptr) - , m_read8(nullptr) - , m_write8(nullptr) - , m_read16(nullptr) - , m_write16(nullptr) - , m_read32(nullptr) - , m_write32(nullptr) - , m_rsp_state(nullptr) + , m_imem_config("imem", ENDIANNESS_BIG, 32, 12) + , m_dmem_config("dmem", ENDIANNESS_BIG, 32, 12) , m_exec_output(nullptr) , m_sr(0) , m_step_count(0) , m_ppc(0) - , m_nextpc(0) - , m_dmem32(nullptr) - , m_dmem16(nullptr) - , m_dmem8(nullptr) - , m_imem32(nullptr) - , m_imem16(nullptr) - , m_imem8(nullptr) + , m_nextpc(0xffff) , m_debugger_temp(0) + , m_pc_temp(0) + , m_ppc_temp(0) + , m_nextpc_temp(0xffff) , m_dp_reg_r_func(*this) , m_dp_reg_w_func(*this) , m_sp_reg_r_func(*this) @@ -151,7 +139,8 @@ rsp_device::~rsp_device() device_memory_interface::space_config_vector rsp_device::memory_space_config() const { return space_config_vector { - std::make_pair(AS_PROGRAM, &m_program_config) + std::make_pair(AS_PROGRAM, &m_imem_config), + std::make_pair(AS_DATA, &m_dmem_config) }; } @@ -160,133 +149,34 @@ std::unique_ptr<util::disasm_interface> rsp_device::create_disassembler() return std::make_unique<rsp_disassembler>(); } -void rsp_device::rsp_add_imem(uint32_t *base) -{ - m_imem32 = base; - m_imem16 = (uint16_t*)base; - m_imem8 = (uint8_t*)base; -} - -void rsp_device::rsp_add_dmem(uint32_t *base) -{ - m_dmem32 = base; - m_dmem16 = (uint16_t*)base; - m_dmem8 = (uint8_t*)base; -} - -uint8_t rsp_device::DM_READ8(uint32_t address) -{ - uint8_t ret = m_dmem8[BYTE4_XOR_BE(address & 0xfff)]; - //printf("R8:%08x=%02x\n", address, ret); - return ret; -} - -uint16_t rsp_device::DM_READ16(uint32_t address) -{ - uint16_t ret; - address &= 0xfff; - ret = m_dmem8[BYTE4_XOR_BE(address)] << 8; - ret |= m_dmem8[BYTE4_XOR_BE(address + 1)]; - //printf("R16:%08x=%04x\n", address, ret); - return ret; -} - -uint32_t rsp_device::DM_READ32(uint32_t address) -{ - uint32_t ret; - address &= 0xfff; - ret = m_dmem8[BYTE4_XOR_BE(address)] << 24; - ret |= m_dmem8[BYTE4_XOR_BE(address + 1)] << 16; - ret |= m_dmem8[BYTE4_XOR_BE(address + 2)] << 8; - ret |= m_dmem8[BYTE4_XOR_BE(address + 3)]; - //printf("R32:%08x=%08x\n", address, ret); - return ret; -} - -void rsp_device::DM_WRITE8(uint32_t address, uint8_t data) -{ - address &= 0xfff; - m_dmem8[BYTE4_XOR_BE(address)] = data; - //printf("W8:%08x=%02x\n", address, data); -} - -void rsp_device::DM_WRITE16(uint32_t address, uint16_t data) +uint8_t rsp_device::read_dmem_byte(uint32_t address) { - address &= 0xfff; - m_dmem8[BYTE4_XOR_BE(address)] = data >> 8; - m_dmem8[BYTE4_XOR_BE(address + 1)] = data & 0xff; - //printf("W16:%08x=%04x\n", address, data); + return m_dcache.read_byte(address); } -void rsp_device::DM_WRITE32(uint32_t address, uint32_t data) +uint16_t rsp_device::read_dmem_word(uint32_t address) { - address &= 0xfff; - m_dmem8[BYTE4_XOR_BE(address)] = data >> 24; - m_dmem8[BYTE4_XOR_BE(address + 1)] = (data >> 16) & 0xff; - m_dmem8[BYTE4_XOR_BE(address + 2)] = (data >> 8) & 0xff; - m_dmem8[BYTE4_XOR_BE(address + 3)] = data & 0xff; - //printf("W32:%08x=%08x\n", address, data); + return m_dcache.read_word_unaligned(address); } -uint8_t rsp_device::READ8(uint32_t address) +uint32_t rsp_device::read_dmem_dword(uint32_t address) { - uint8_t ret; - address &= 0xfff; - ret = m_program.read_byte(address); - //printf("R8:%08x=%02x\n", address, ret); - return ret; + return m_dcache.read_dword_unaligned(address); } -uint16_t rsp_device::READ16(uint32_t address) +void rsp_device::write_dmem_byte(uint32_t address, uint8_t data) { - uint16_t ret; - address &= 0xfff; - - ret = (m_program.read_byte(address) << 8) | (m_program.read_byte(address + 1) & 0xff); - - //printf("R16:%08x=%04x\n", address, ret); - return ret; -} - -uint32_t rsp_device::READ32(uint32_t address) -{ - uint32_t ret; - address &= 0xfff; - - ret = (m_program.read_byte(address) << 24) | - (m_program.read_byte(address + 1) << 16) | - (m_program.read_byte(address + 2) << 8) | - (m_program.read_byte(address + 3) << 0); - - //printf("R32:%08x=%08x\n", address, ret); - return ret; + m_dcache.write_byte(address, data); } -void rsp_device::WRITE8(uint32_t address, uint8_t data) +void rsp_device::write_dmem_word(uint32_t address, uint16_t data) { - address &= 0xfff; - m_program.write_byte(address, data); - //printf("W8:%08x=%02x\n", address, data); + m_dcache.write_word_unaligned(address, data); } -void rsp_device::WRITE16(uint32_t address, uint16_t data) +void rsp_device::write_dmem_dword(uint32_t address, uint32_t data) { - address &= 0xfff; - - m_program.write_byte(address, data >> 8); - m_program.write_byte(address + 1, data & 0xff); - //printf("W16:%08x=%04x\n", address, data); -} - -void rsp_device::WRITE32(uint32_t address, uint32_t data) -{ - address &= 0xfff; - - m_program.write_byte(address, data >> 24); - m_program.write_byte(address + 1, (data >> 16) & 0xff); - m_program.write_byte(address + 2, (data >> 8) & 0xff); - m_program.write_byte(address + 3, data & 0xff); - //printf("W32:%08x=%08x\n", address, data); + m_dcache.write_dword_unaligned(address, data); } /*****************************************************************************/ @@ -353,7 +243,7 @@ void rsp_device::unimplemented_opcode(uint32_t op) for (i=0; i < 0x1000; i++) { - fputc(READ8(rsp, 0x04000000 + i), dmem); + fputc(read_dmem_byte(i), dmem); } fclose(dmem); } @@ -375,97 +265,82 @@ void rsp_device::resolve_cb() void rsp_device::device_start() { - m_isdrc = allow_drc(); - m_rsp_state = (internal_rsp_state *)m_cache.alloc_near(sizeof(internal_rsp_state)); - if (LOG_INSTRUCTION_EXECUTION) m_exec_output = fopen("rsp_execute.txt", "wt"); - space(AS_PROGRAM).cache(m_pcache); - space(AS_PROGRAM).specific(m_program); + space(AS_PROGRAM).cache(m_icache); + space(AS_PROGRAM).specific(m_imem); + space(AS_DATA).cache(m_dcache); + space(AS_DATA).specific(m_dmem); resolve_cb(); - if (m_isdrc) - m_cop2 = std::make_unique<cop2_drc>(*this, machine()); - else - m_cop2 = std::make_unique<cop2>(*this, machine()); - - m_cop2->init(); - m_cop2->start(); - - // RSP registers should power on to a random state for (int regIdx = 0; regIdx < 32; regIdx++) - m_rsp_state->r[regIdx] = 0; - - m_sr = RSP_STATUS_HALT; - m_step_count = 0; + m_r[regIdx] = 0; - /* initialize the UML generator */ - uint32_t drc_flags = 0; - m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, drc_flags, 8, 32, 2); - - /* add symbols for our stuff */ - m_drcuml->symbol_add(&m_rsp_state->pc, sizeof(m_rsp_state->pc), "pc"); - m_drcuml->symbol_add(&m_rsp_state->icount, sizeof(m_rsp_state->icount), "icount"); - for (int regnum = 0; regnum < 32; regnum++) + for(auto & elem : m_v) { - char buf[10]; - sprintf(buf, "r%d", regnum); - m_drcuml->symbol_add(&m_rsp_state->r[regnum], sizeof(m_rsp_state->r[regnum]), buf); + elem.d[0] = 0; + elem.d[1] = 0; } - m_drcuml->symbol_add(&m_rsp_state->arg0, sizeof(m_rsp_state->arg0), "arg0"); - m_drcuml->symbol_add(&m_rsp_state->arg1, sizeof(m_rsp_state->arg1), "arg1"); - m_drcuml->symbol_add(&m_arg2, sizeof(m_arg2), "arg2"); - m_drcuml->symbol_add(&m_arg3, sizeof(m_arg3), "arg3"); - m_drcuml->symbol_add(&m_numcycles, sizeof(m_numcycles), "numcycles"); - /* initialize the front-end helper */ - m_drcfe = std::make_unique<frontend>(*this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE); + m_vcarry = 0; + m_vcompare = 0; + m_vclip1 = 0; + m_vzero = 0; + m_vclip2 = 0; + + m_reciprocal_res = 0; + m_reciprocal_high = 0; + m_ideduct = 0; + m_scalar_busy = false; + m_vector_busy = false; + m_paired_busy = false; - /* compute the register parameters */ - for (int regnum = 0; regnum < 32; regnum++) + for(auto & elem : m_accum) { - m_regmap[regnum] = (regnum == 0) ? uml::parameter(0) : uml::parameter::make_memory(&m_rsp_state->r[regnum]); + elem.q = 0; } - /* mark the cache dirty so it is updated on next execute */ - m_cache_dirty = true; - - state_add( RSP_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%08X"); - state_add( RSP_R0, "R0", m_rsp_state->r[0]).formatstr("%08X"); - state_add( RSP_R1, "R1", m_rsp_state->r[1]).formatstr("%08X"); - state_add( RSP_R2, "R2", m_rsp_state->r[2]).formatstr("%08X"); - state_add( RSP_R3, "R3", m_rsp_state->r[3]).formatstr("%08X"); - state_add( RSP_R4, "R4", m_rsp_state->r[4]).formatstr("%08X"); - state_add( RSP_R5, "R5", m_rsp_state->r[5]).formatstr("%08X"); - state_add( RSP_R6, "R6", m_rsp_state->r[6]).formatstr("%08X"); - state_add( RSP_R7, "R7", m_rsp_state->r[7]).formatstr("%08X"); - state_add( RSP_R8, "R8", m_rsp_state->r[8]).formatstr("%08X"); - state_add( RSP_R9, "R9", m_rsp_state->r[9]).formatstr("%08X"); - state_add( RSP_R10, "R10", m_rsp_state->r[10]).formatstr("%08X"); - state_add( RSP_R11, "R11", m_rsp_state->r[11]).formatstr("%08X"); - state_add( RSP_R12, "R12", m_rsp_state->r[12]).formatstr("%08X"); - state_add( RSP_R13, "R13", m_rsp_state->r[13]).formatstr("%08X"); - state_add( RSP_R14, "R14", m_rsp_state->r[14]).formatstr("%08X"); - state_add( RSP_R15, "R15", m_rsp_state->r[15]).formatstr("%08X"); - state_add( RSP_R16, "R16", m_rsp_state->r[16]).formatstr("%08X"); - state_add( RSP_R17, "R17", m_rsp_state->r[17]).formatstr("%08X"); - state_add( RSP_R18, "R18", m_rsp_state->r[18]).formatstr("%08X"); - state_add( RSP_R19, "R19", m_rsp_state->r[19]).formatstr("%08X"); - state_add( RSP_R20, "R20", m_rsp_state->r[20]).formatstr("%08X"); - state_add( RSP_R21, "R21", m_rsp_state->r[21]).formatstr("%08X"); - state_add( RSP_R22, "R22", m_rsp_state->r[22]).formatstr("%08X"); - state_add( RSP_R23, "R23", m_rsp_state->r[23]).formatstr("%08X"); - state_add( RSP_R24, "R24", m_rsp_state->r[24]).formatstr("%08X"); - state_add( RSP_R25, "R25", m_rsp_state->r[25]).formatstr("%08X"); - state_add( RSP_R26, "R26", m_rsp_state->r[26]).formatstr("%08X"); - state_add( RSP_R27, "R27", m_rsp_state->r[27]).formatstr("%08X"); - state_add( RSP_R28, "R28", m_rsp_state->r[28]).formatstr("%08X"); - state_add( RSP_R29, "R29", m_rsp_state->r[29]).formatstr("%08X"); - state_add( RSP_R30, "R30", m_rsp_state->r[30]).formatstr("%08X"); - state_add( RSP_R31, "R31", m_rsp_state->r[31]).formatstr("%08X"); + m_pc = 0; + m_nextpc = 0xffff; + m_sr = RSP_STATUS_HALT; + m_step_count = 0; + + state_add( RSP_PC, "PC", m_pc).callimport().callexport().formatstr("%08X"); + state_add( RSP_R0, "R0", m_r[0]).formatstr("%08X"); + state_add( RSP_R1, "R1", m_r[1]).formatstr("%08X"); + state_add( RSP_R2, "R2", m_r[2]).formatstr("%08X"); + state_add( RSP_R3, "R3", m_r[3]).formatstr("%08X"); + state_add( RSP_R4, "R4", m_r[4]).formatstr("%08X"); + state_add( RSP_R5, "R5", m_r[5]).formatstr("%08X"); + state_add( RSP_R6, "R6", m_r[6]).formatstr("%08X"); + state_add( RSP_R7, "R7", m_r[7]).formatstr("%08X"); + state_add( RSP_R8, "R8", m_r[8]).formatstr("%08X"); + state_add( RSP_R9, "R9", m_r[9]).formatstr("%08X"); + state_add( RSP_R10, "R10", m_r[10]).formatstr("%08X"); + state_add( RSP_R11, "R11", m_r[11]).formatstr("%08X"); + state_add( RSP_R12, "R12", m_r[12]).formatstr("%08X"); + state_add( RSP_R13, "R13", m_r[13]).formatstr("%08X"); + state_add( RSP_R14, "R14", m_r[14]).formatstr("%08X"); + state_add( RSP_R15, "R15", m_r[15]).formatstr("%08X"); + state_add( RSP_R16, "R16", m_r[16]).formatstr("%08X"); + state_add( RSP_R17, "R17", m_r[17]).formatstr("%08X"); + state_add( RSP_R18, "R18", m_r[18]).formatstr("%08X"); + state_add( RSP_R19, "R19", m_r[19]).formatstr("%08X"); + state_add( RSP_R20, "R20", m_r[20]).formatstr("%08X"); + state_add( RSP_R21, "R21", m_r[21]).formatstr("%08X"); + state_add( RSP_R22, "R22", m_r[22]).formatstr("%08X"); + state_add( RSP_R23, "R23", m_r[23]).formatstr("%08X"); + state_add( RSP_R24, "R24", m_r[24]).formatstr("%08X"); + state_add( RSP_R25, "R25", m_r[25]).formatstr("%08X"); + state_add( RSP_R26, "R26", m_r[26]).formatstr("%08X"); + state_add( RSP_R27, "R27", m_r[27]).formatstr("%08X"); + state_add( RSP_R28, "R28", m_r[28]).formatstr("%08X"); + state_add( RSP_R29, "R29", m_r[29]).formatstr("%08X"); + state_add( RSP_R30, "R30", m_r[30]).formatstr("%08X"); + state_add( RSP_R31, "R31", m_r[31]).formatstr("%08X"); state_add( RSP_SR, "SR", m_sr).formatstr("%08X"); - state_add( RSP_NEXTPC, "NPC", m_debugger_temp).callimport().callexport().formatstr("%08X"); + state_add( RSP_NEXTPC, "NPC", m_nextpc).callimport().callexport().formatstr("%04X"); state_add( RSP_STEPCNT, "STEP", m_step_count).formatstr("%08X"); state_add( RSP_V0, "V0", m_debugger_temp).formatstr("%39s"); @@ -501,12 +376,12 @@ void rsp_device::device_start() state_add( RSP_V30, "V30", m_debugger_temp).formatstr("%39s"); state_add( RSP_V31, "V31", m_debugger_temp).formatstr("%39s"); - state_add( STATE_GENPC, "GENPC", m_debugger_temp).callimport().callexport().noshow(); - state_add( STATE_GENPCBASE, "CURPC", m_rsp_state->pc).noshow(); - state_add( STATE_GENFLAGS, "GENFLAGS", m_debugger_temp).formatstr("%1s").noshow(); - state_add( STATE_GENSP, "GENSP", m_rsp_state->r[31]).noshow(); + state_add( STATE_GENPC, "GENPC", m_pc).noshow(); + state_add( STATE_GENPCBASE, "CURPC", m_pc).noshow(); + state_add( STATE_GENFLAGS, "GENFLAGS", m_r[31]).formatstr("%1s").noshow(); + state_add( STATE_GENSP, "GENSP", m_r[31]).noshow(); - set_icountptr(m_rsp_state->icount); + set_icountptr(m_icount); } void rsp_device::state_import(const device_state_entry &entry) @@ -515,15 +390,15 @@ void rsp_device::state_import(const device_state_entry &entry) { case STATE_GENPC: case RSP_PC: - m_rsp_state->pc = m_debugger_temp; + m_pc = (uint16_t)m_pc_temp; break; case STATE_GENPCBASE: - m_ppc = m_debugger_temp; + m_ppc = (uint16_t)m_ppc_temp; break; case RSP_NEXTPC: - m_nextpc = m_debugger_temp; + m_nextpc = (uint16_t)m_nextpc_temp; break; } } @@ -535,15 +410,15 @@ void rsp_device::state_export(const device_state_entry &entry) { case STATE_GENPC: case RSP_PC: - m_debugger_temp = m_rsp_state->pc | 0x04000000; + m_pc_temp = m_pc; break; case STATE_GENPCBASE: - m_debugger_temp = m_ppc | 0x04000000; + m_ppc_temp = m_ppc; break; case RSP_NEXTPC: - m_debugger_temp = m_nextpc | 0x04000000; + m_nextpc_temp = m_nextpc; break; } } @@ -551,13 +426,75 @@ void rsp_device::state_export(const device_state_entry &entry) void rsp_device::state_string_export(const device_state_entry &entry, std::string &str) const { const int index = entry.index(); - if (index >= RSP_V0 && index <= RSP_V31) - { - m_cop2->state_string_export(index, str); - } - else if (index == STATE_GENFLAGS) + switch (index) { - str = ""; + case RSP_V0: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 0].w[0], m_v[ 0].w[1], m_v[ 0].w[2], m_v[ 0].w[3], m_v[ 0].w[4], m_v[ 0].w[5], m_v[ 0].w[6], m_v[ 0].w[7]); break; + case RSP_V1: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 1].w[0], m_v[ 1].w[1], m_v[ 1].w[2], m_v[ 1].w[3], m_v[ 1].w[4], m_v[ 1].w[5], m_v[ 1].w[6], m_v[ 1].w[7]); break; + case RSP_V2: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 2].w[0], m_v[ 2].w[1], m_v[ 2].w[2], m_v[ 2].w[3], m_v[ 2].w[4], m_v[ 2].w[5], m_v[ 2].w[6], m_v[ 2].w[7]); break; + case RSP_V3: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 3].w[0], m_v[ 3].w[1], m_v[ 3].w[2], m_v[ 3].w[3], m_v[ 3].w[4], m_v[ 3].w[5], m_v[ 3].w[6], m_v[ 3].w[7]); break; + case RSP_V4: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 4].w[0], m_v[ 4].w[1], m_v[ 4].w[2], m_v[ 4].w[3], m_v[ 4].w[4], m_v[ 4].w[5], m_v[ 4].w[6], m_v[ 4].w[7]); break; + case RSP_V5: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 5].w[0], m_v[ 5].w[1], m_v[ 5].w[2], m_v[ 5].w[3], m_v[ 5].w[4], m_v[ 5].w[5], m_v[ 5].w[6], m_v[ 5].w[7]); break; + case RSP_V6: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 6].w[0], m_v[ 6].w[1], m_v[ 6].w[2], m_v[ 6].w[3], m_v[ 6].w[4], m_v[ 6].w[5], m_v[ 6].w[6], m_v[ 6].w[7]); break; + case RSP_V7: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 7].w[0], m_v[ 7].w[1], m_v[ 7].w[2], m_v[ 7].w[3], m_v[ 7].w[4], m_v[ 7].w[5], m_v[ 7].w[6], m_v[ 7].w[7]); break; + case RSP_V8: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 8].w[0], m_v[ 8].w[1], m_v[ 8].w[2], m_v[ 8].w[3], m_v[ 8].w[4], m_v[ 8].w[5], m_v[ 8].w[6], m_v[ 8].w[7]); break; + case RSP_V9: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[ 9].w[0], m_v[ 9].w[1], m_v[ 9].w[2], m_v[ 9].w[3], m_v[ 9].w[4], m_v[ 9].w[5], m_v[ 9].w[6], m_v[ 9].w[7]); break; + case RSP_V10: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[10].w[0], m_v[10].w[1], m_v[10].w[2], m_v[10].w[3], m_v[10].w[4], m_v[10].w[5], m_v[10].w[6], m_v[10].w[7]); break; + case RSP_V11: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[11].w[0], m_v[11].w[1], m_v[11].w[2], m_v[11].w[3], m_v[11].w[4], m_v[11].w[5], m_v[11].w[6], m_v[11].w[7]); break; + case RSP_V12: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[12].w[0], m_v[12].w[1], m_v[12].w[2], m_v[12].w[3], m_v[12].w[4], m_v[12].w[5], m_v[12].w[6], m_v[12].w[7]); break; + case RSP_V13: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[13].w[0], m_v[13].w[1], m_v[13].w[2], m_v[13].w[3], m_v[13].w[4], m_v[13].w[5], m_v[13].w[6], m_v[13].w[7]); break; + case RSP_V14: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[14].w[0], m_v[14].w[1], m_v[14].w[2], m_v[14].w[3], m_v[14].w[4], m_v[14].w[5], m_v[14].w[6], m_v[14].w[7]); break; + case RSP_V15: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[15].w[0], m_v[15].w[1], m_v[15].w[2], m_v[15].w[3], m_v[15].w[4], m_v[15].w[5], m_v[15].w[6], m_v[15].w[7]); break; + case RSP_V16: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[16].w[0], m_v[16].w[1], m_v[16].w[2], m_v[16].w[3], m_v[16].w[4], m_v[16].w[5], m_v[16].w[6], m_v[16].w[7]); break; + case RSP_V17: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[17].w[0], m_v[17].w[1], m_v[17].w[2], m_v[17].w[3], m_v[17].w[4], m_v[17].w[5], m_v[17].w[6], m_v[17].w[7]); break; + case RSP_V18: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[18].w[0], m_v[18].w[1], m_v[18].w[2], m_v[18].w[3], m_v[18].w[4], m_v[18].w[5], m_v[18].w[6], m_v[18].w[7]); break; + case RSP_V19: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[19].w[0], m_v[19].w[1], m_v[19].w[2], m_v[19].w[3], m_v[19].w[4], m_v[19].w[5], m_v[19].w[6], m_v[19].w[7]); break; + case RSP_V20: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[20].w[0], m_v[20].w[1], m_v[20].w[2], m_v[20].w[3], m_v[20].w[4], m_v[20].w[5], m_v[20].w[6], m_v[20].w[7]); break; + case RSP_V21: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[21].w[0], m_v[21].w[1], m_v[21].w[2], m_v[21].w[3], m_v[21].w[4], m_v[21].w[5], m_v[21].w[6], m_v[21].w[7]); break; + case RSP_V22: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[22].w[0], m_v[22].w[1], m_v[22].w[2], m_v[22].w[3], m_v[22].w[4], m_v[22].w[5], m_v[22].w[6], m_v[22].w[7]); break; + case RSP_V23: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[23].w[0], m_v[23].w[1], m_v[23].w[2], m_v[23].w[3], m_v[23].w[4], m_v[23].w[5], m_v[23].w[6], m_v[23].w[7]); break; + case RSP_V24: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[24].w[0], m_v[24].w[1], m_v[24].w[2], m_v[24].w[3], m_v[24].w[4], m_v[24].w[5], m_v[24].w[6], m_v[24].w[7]); break; + case RSP_V25: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[25].w[0], m_v[25].w[1], m_v[25].w[2], m_v[25].w[3], m_v[25].w[4], m_v[25].w[5], m_v[25].w[6], m_v[25].w[7]); break; + case RSP_V26: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[26].w[0], m_v[26].w[1], m_v[26].w[2], m_v[26].w[3], m_v[26].w[4], m_v[26].w[5], m_v[26].w[6], m_v[26].w[7]); break; + case RSP_V27: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[27].w[0], m_v[27].w[1], m_v[27].w[2], m_v[27].w[3], m_v[27].w[4], m_v[27].w[5], m_v[27].w[6], m_v[27].w[7]); break; + case RSP_V28: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[28].w[0], m_v[28].w[1], m_v[28].w[2], m_v[28].w[3], m_v[28].w[4], m_v[28].w[5], m_v[28].w[6], m_v[28].w[7]); break; + case RSP_V29: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[29].w[0], m_v[29].w[1], m_v[29].w[2], m_v[29].w[3], m_v[29].w[4], m_v[29].w[5], m_v[29].w[6], m_v[29].w[7]); break; + case RSP_V30: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[30].w[0], m_v[30].w[1], m_v[30].w[2], m_v[30].w[3], m_v[30].w[4], m_v[30].w[5], m_v[30].w[6], m_v[30].w[7]); break; + case RSP_V31: + str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", m_v[31].w[0], m_v[31].w[1], m_v[31].w[2], m_v[31].w[3], m_v[31].w[4], m_v[31].w[5], m_v[31].w[6], m_v[31].w[7]); break; + case STATE_GENFLAGS: + str = ""; + break; } } @@ -582,21 +519,11 @@ void rsp_device::device_stop() #if SAVE_DMEM { int i; - FILE *dmem; -#if 0 - dmem = fopen("rsp_dmem.txt", "wt"); - - for (i=0; i < 0x1000; i+=4) - { - fprintf(dmem, "%08X: %08X\n", 0x04000000 + i, READ32(0x04000000 + i)); - } - fclose(dmem); -#endif - dmem = fopen("rsp_dmem.bin", "wb"); + FILE *dmem = fopen("rsp_dmem.bin", "wb"); for (i=0; i < 0x1000; i++) { - fputc(READ8(0x04000000 + i), dmem); + fputc(read_dmem_byte(i), dmem); } fclose(dmem); } @@ -609,70 +536,2383 @@ void rsp_device::device_stop() void rsp_device::device_reset() { - m_nextpc = ~0; + m_nextpc = 0xffff; } -void rsp_device::execute_run() +uint16_t rsp_device::SATURATE_ACCUM(int accum, int slice, uint16_t negative, uint16_t positive) { - if (m_isdrc) + if ((int16_t)m_accum[accum].w[SLICE_H] < 0) + { + if ((uint16_t)m_accum[accum].w[SLICE_H] != 0xffff) + { + return negative; + } + else + { + if ((int16_t)m_accum[accum].w[SLICE_M] >= 0) + { + return negative; + } + else + { + if (slice == 0) + { + return m_accum[accum].w[SLICE_L]; + } + else if (slice == 1) + { + return m_accum[accum].w[SLICE_M]; + } + } + } + } + else { - execute_run_drc(); - return; + if ((uint16_t)m_accum[accum].w[SLICE_H] != 0) + { + return positive; + } + else + { + if ((int16_t)m_accum[accum].w[SLICE_M] < 0) + { + return positive; + } + else + { + if (slice == 0) + { + return m_accum[accum].w[SLICE_L]; + } + else + { + return m_accum[accum].w[SLICE_M]; + } + } + } } + return 0; +} + +void rsp_device::handle_vector_ops(uint32_t op) +{ + uint16_t vres[8]; - m_rsp_state->pc = 0x4001000 | (m_rsp_state->pc & 0xfff); + // Opcode legend: + // E = VS2 element type + // S = VS1, Source vector 1 + // T = VS2, Source vector 2 + // D = Destination vector - if( m_sr & ( RSP_STATUS_HALT | RSP_STATUS_BROKE ) ) + switch (op & 0x3f) { - m_rsp_state->icount = std::min(m_rsp_state->icount, 0); + case 0x00: /* VMULF */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000000 | + // ------------------------------------------------------ + // + // Multiplies signed integer by signed integer * 2 + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].s[i]; + int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + + if (s1 == -32768 && s2 == -32768) + { + // overflow + m_accum[i].w[SLICE_H] = 0; + m_accum[i].w[SLICE_M] = -32768; + m_accum[i].w[SLICE_L] = -32768; + vres[i] = 0x7fff; + } + else + { + int64_t r = s1 * s2 * 2; + r += 0x8000; // rounding ? + m_accum[i].w[SLICE_H] = (r < 0) ? 0xffff : 0; // Sign-extend to 48-bit + m_accum[i].w[SLICE_M] = (int16_t)(r >> 16); + m_accum[i].w[SLICE_L] = (uint16_t)r; + vres[i] = m_accum[i].w[SLICE_M]; + } + } + WRITEBACK_RESULT(); + break; + } + + case 0x01: /* VMULU */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 | + // ------------------------------------------------------ + // + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].s[i]; + int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + + int64_t r = s1 * s2 * 2; + r += 0x8000; // rounding ? + + m_accum[i].w[SLICE_H] = (uint16_t)(r >> 32); + m_accum[i].w[SLICE_M] = (uint16_t)(r >> 16); + m_accum[i].w[SLICE_L] = (uint16_t)r; + + if (r < 0) + { + vres[i] = 0; + } + else if (((int16_t)m_accum[i].w[SLICE_H] ^ (int16_t)m_accum[i].w[SLICE_M]) < 0) + { + vres[i] = -1; + } + else + { + vres[i] = m_accum[i].w[SLICE_M]; + } + } + WRITEBACK_RESULT(); + break; + } + + case 0x04: /* VMUDL */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000100 | + // ------------------------------------------------------ + // + // Multiplies unsigned fraction by unsigned fraction + // Stores the higher 16 bits of the 32-bit result to accumulator + // The low slice of accumulator is stored into destination element + + for (int i = 0; i < 8; i++) + { + uint32_t s1 = m_v[VS1REG].w[i]; + uint32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + uint32_t r = s1 * s2; + + m_accum[i].w[SLICE_H] = 0; + m_accum[i].w[SLICE_M] = 0; + m_accum[i].w[SLICE_L] = (uint16_t)(r >> 16); + + vres[i] = m_accum[i].w[SLICE_L]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x05: /* VMUDM */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000101 | + // ------------------------------------------------------ + // + // Multiplies signed integer by unsigned fraction + // The result is stored into accumulator + // The middle slice of accumulator is stored into destination element + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].s[i]; + int32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)]; // not sign-extended + int32_t r = s1 * s2; + + m_accum[i].w[SLICE_H] = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit + m_accum[i].w[SLICE_M] = (int16_t)(r >> 16); + m_accum[i].w[SLICE_L] = (uint16_t)r; + + vres[i] = m_accum[i].w[SLICE_M]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x06: /* VMUDN */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 | + // ------------------------------------------------------ + // + // Multiplies unsigned fraction by signed integer + // The result is stored into accumulator + // The low slice of accumulator is stored into destination element + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].w[i]; // not sign-extended + int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + int32_t r = s1 * s2; + + m_accum[i].w[SLICE_H] = (r < 0) ? 0xffff : 0; // sign-extend to 48-bit + m_accum[i].w[SLICE_M] = (int16_t)(r >> 16); + m_accum[i].w[SLICE_L] = (uint16_t)(r); + + vres[i] = m_accum[i].w[SLICE_L]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x07: /* VMUDH */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000111 | + // ------------------------------------------------------ + // + // Multiplies signed integer by signed integer + // The result is stored into highest 32 bits of accumulator, the low slice is zero + // The highest 32 bits of accumulator is saturated into destination element + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].s[i]; + int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + int32_t r = s1 * s2; + + m_accum[i].w[SLICE_H] = (int16_t)(r >> 16); + m_accum[i].w[SLICE_M] = (uint16_t)(r); + m_accum[i].w[SLICE_L] = 0; + + if (r < -32768) r = -32768; + if (r > 32767) r = 32767; + vres[i] = (int16_t)(r); + } + WRITEBACK_RESULT(); + break; + } + + case 0x08: /* VMACF */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001000 | + // ------------------------------------------------------ + // + // Multiplies signed integer by signed integer * 2 + // The result is added to accumulator + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].s[i]; + int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + int32_t r = s1 * s2; + + uint64_t q = (uint64_t)(uint16_t)m_accum[i].w[SLICE_LL]; + q |= (((uint64_t)(uint16_t)m_accum[i].w[SLICE_L]) << 16); + q |= (((uint64_t)(uint16_t)m_accum[i].w[SLICE_M]) << 32); + q |= (((uint64_t)(uint16_t)m_accum[i].w[SLICE_H]) << 48); + + q += (int64_t)(r) << 17; + + m_accum[i].w[SLICE_LL] = (uint16_t)q; + m_accum[i].w[SLICE_L] = (uint16_t)(q >> 16); + m_accum[i].w[SLICE_M] = (uint16_t)(q >> 32); + m_accum[i].w[SLICE_H] = (uint16_t)(q >> 48); + + vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff); + } + WRITEBACK_RESULT(); + break; + } + + case 0x09: /* VMACU */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 | + // ------------------------------------------------------ + // + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].s[i]; + int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + int32_t r1 = s1 * s2; + uint32_t r2 = m_accum[i].w[SLICE_L] + ((uint16_t)r1 * 2); + uint32_t r3 = m_accum[i].w[SLICE_M] + (uint16_t)((r1 >> 16) * 2) + (uint16_t)(r2 >> 16); + + m_accum[i].w[SLICE_L] = (uint16_t)r2; + m_accum[i].w[SLICE_M] = (uint16_t)r3; + m_accum[i].w[SLICE_H] += (uint16_t)(r3 >> 16) + (uint16_t)(r1 >> 31); + + if ((int16_t)m_accum[i].w[SLICE_H] < 0) + { + vres[i] = 0; + } + else + { + if (m_accum[i].w[SLICE_H] != 0) + { + vres[i] = 0xffff; + } + else + { + if ((int16_t)m_accum[i].w[SLICE_M] < 0) + { + vres[i] = 0xffff; + } + else + { + vres[i] = m_accum[i].w[SLICE_M]; + } + } + } + } + WRITEBACK_RESULT(); + break; + } + + case 0x0c: /* VMADL */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001100 | + // ------------------------------------------------------ + // + // Multiplies unsigned fraction by unsigned fraction + // Adds the higher 16 bits of the 32-bit result to accumulator + // The low slice of accumulator is stored into destination element + + for (int i = 0; i < 8; i++) + { + uint32_t s1 = m_v[VS1REG].w[i]; + uint32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + uint32_t r1 = s1 * s2; + uint32_t r2 = m_accum[i].w[SLICE_L] + (r1 >> 16); + uint32_t r3 = m_accum[i].w[SLICE_M] + (r2 >> 16); + + m_accum[i].w[SLICE_L] = (uint16_t)r2; + m_accum[i].w[SLICE_M] = (uint16_t)r3; + m_accum[i].w[SLICE_H] += (int16_t)(r3 >> 16); + + vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff); + } + WRITEBACK_RESULT(); + break; + } + + case 0x0d: /* VMADM */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 | + // ------------------------------------------------------ + // + // Multiplies signed integer by unsigned fraction + // The result is added into accumulator + // The middle slice of accumulator is stored into destination element + + for (int i = 0; i < 8; i++) + { + uint32_t s1 = m_v[VS1REG].s[i]; + uint32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)]; // not sign-extended + uint32_t r1 = s1 * s2; + uint32_t r2 = (uint16_t)m_accum[i].w[SLICE_L] + (uint16_t)(r1); + uint32_t r3 = (uint16_t)m_accum[i].w[SLICE_M] + (r1 >> 16) + (r2 >> 16); + + m_accum[i].w[SLICE_L] = (uint16_t)r2; + m_accum[i].w[SLICE_M] = (uint16_t)r3; + m_accum[i].w[SLICE_H] += (uint16_t)(r3 >> 16); + if ((int32_t)r1 < 0) + m_accum[i].w[SLICE_H] -= 1; + + vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff); + } + WRITEBACK_RESULT(); + break; + } + + case 0x0e: /* VMADN */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 | + // ------------------------------------------------------ + // + // Multiplies unsigned fraction by signed integer + // The result is added into accumulator + // The low slice of accumulator is stored into destination element + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].w[i]; // not sign-extended + int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + + uint64_t q = (uint64_t)m_accum[i].w[SLICE_LL]; + q |= (((uint64_t)m_accum[i].w[SLICE_L]) << 16); + q |= (((uint64_t)m_accum[i].w[SLICE_M]) << 32); + q |= (((uint64_t)m_accum[i].w[SLICE_H]) << 48); + q += (int64_t)(s1*s2) << 16; + + m_accum[i].w[SLICE_LL] = (uint16_t)q; + m_accum[i].w[SLICE_L] = (uint16_t)(q >> 16); + m_accum[i].w[SLICE_M] = (uint16_t)(q >> 32); + m_accum[i].w[SLICE_H] = (uint16_t)(q >> 48); + + vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff); + } + WRITEBACK_RESULT(); + + break; + } + + case 0x0f: /* VMADH */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001111 | + // ------------------------------------------------------ + // + // Multiplies signed integer by signed integer + // The result is added into highest 32 bits of accumulator, the low slice is zero + // The highest 32 bits of accumulator is saturated into destination element + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].s[i]; + int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + + int32_t accum = (uint32_t)(uint16_t)m_accum[i].w[SLICE_M]; + accum |= ((uint32_t)((uint16_t)m_accum[i].w[SLICE_H])) << 16; + accum += s1 * s2; + + m_accum[i].w[SLICE_H] = (uint16_t)(accum >> 16); + m_accum[i].w[SLICE_M] = (uint16_t)accum; + + vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff); + } + WRITEBACK_RESULT(); + break; + } + + case 0x10: /* VADD */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010000 | + // ------------------------------------------------------ + // + // Adds two vector registers and carry flag, the result is saturated to 32767 + + // TODO: check VS2REG == VDREG + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].s[i]; + int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + int32_t r = s1 + s2 + BIT(m_vcarry, i); + + m_accum[i].w[SLICE_L] = (int16_t)r; + + if (r > 32767) r = 32767; + if (r < -32768) r = -32768; + vres[i] = (int16_t)(r); + } + m_vzero = 0; + m_vcarry = 0; + WRITEBACK_RESULT(); + break; + } + + case 0x11: /* VSUB */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010001 | + // ------------------------------------------------------ + // + // Subtracts two vector registers and carry flag, the result is saturated to -32768 + + // TODO: check VS2REG == VDREG + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].s[i]; + int32_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + int32_t r = s1 - s2 - BIT(m_vcarry, i); + + m_accum[i].w[SLICE_L] = (int16_t)r; + + if (r > 32767) r = 32767; + if (r < -32768) r = -32768; + + vres[i] = (int16_t)(r); + } + m_vzero = 0; + m_vcarry = 0; + WRITEBACK_RESULT(); + break; + } + + case 0x13: /* VABS */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010011 | + // ------------------------------------------------------ + // + // Changes the sign of source register 2 if source register 1 is negative and stores + // the result to destination register + + for (int i = 0; i < 8; i++) + { + int16_t s1 = m_v[VS1REG].s[i]; + int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + + if (s1 < 0) + { + if (s2 == -32768) + { + vres[i] = 32767; + } + else + { + vres[i] = -s2; + } + } + else if (s1 > 0) + { + vres[i] = s2; + } + else + { + vres[i] = 0; + } + + m_accum[i].w[SLICE_L] = vres[i]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x14: /* VADDC */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010100 | + // ------------------------------------------------------ + // + // Adds two vector registers, the carry out is stored into carry register + + // TODO: check VS2REG = VDREG + + m_vzero = 0; + m_vcarry = 0; + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].w[i]; + int32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + int32_t r = s1 + s2; + + vres[i] = (int16_t)r; + m_accum[i].w[SLICE_L] = (int16_t)r; + + if (r & 0xffff0000) + { + m_vcarry |= 1 << i; + } + } + WRITEBACK_RESULT(); + break; + } + + case 0x15: /* VSUBC */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010101 | + // ------------------------------------------------------ + // + // Subtracts two vector registers, the carry out is stored into carry register + + // TODO: check VS2REG = VDREG + + m_vzero = 0; + m_vcarry = 0; + + for (int i = 0; i < 8; i++) + { + int32_t s1 = m_v[VS1REG].w[i]; + int32_t s2 = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + int32_t r = s1 - s2; + + vres[i] = (int16_t)(r); + m_accum[i].w[SLICE_L] = (uint16_t)r; + + if ((uint16_t)r != 0) + { + m_vzero |= 1 << i; + } + if (r & 0xffff0000) + { + m_vcarry |= 1 << i; + } + } + WRITEBACK_RESULT(); + break; + } + + case 0x1d: /* VSAW */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 011101 | + // ------------------------------------------------------ + // + // Stores high, middle or low slice of accumulator to destination vector + + switch (EL) + { + case 0x08: // VSAWH + { + for (int i = 0; i < 8; i++) + { + m_v[VDREG].w[i] = m_accum[i].w[SLICE_H]; + } + break; + } + case 0x09: // VSAWM + { + for (int i = 0; i < 8; i++) + { + m_v[VDREG].w[i] = m_accum[i].w[SLICE_M]; + } + break; + } + case 0x0a: // VSAWL + { + for (int i = 0; i < 8; i++) + { + m_v[VDREG].w[i] = m_accum[i].w[SLICE_L]; + } + break; + } + default: + printf("RSP: VSAW: el = %d\n", EL); + break; + } + break; + } + + case 0x20: /* VLT */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100000 | + // ------------------------------------------------------ + // + // Sets compare flags if elements in VS1 are less than VS2 + // Moves the element in VS2 to destination vector + + m_vcompare = 0; + m_vclip2 = 0; + + for (int i = 0; i < 8; i++) + { + int16_t s1 = m_v[VS1REG].s[i]; + int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + if (s1 < s2) + { + m_vcompare |= 1 << i; + } + else if (s1 == s2) + { + if (BIT(m_vzero & m_vcarry, i)) + { + m_vcompare |= 1 << i; + } + } + + if (BIT(m_vcompare, i)) + { + vres[i] = s1; + } + else + { + vres[i] = s2; + } + + m_accum[i].w[SLICE_L] = vres[i]; + } + + m_vzero = 0; + m_vcarry = 0; + WRITEBACK_RESULT(); + break; + } + + case 0x21: /* VEQ */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100001 | + // ------------------------------------------------------ + // + // Sets compare flags if elements in VS1 are equal with VS2 + // Moves the element in VS2 to destination vector + + m_vcompare = 0; + m_vclip2 = 0; + + for (int i = 0; i < 8; i++) + { + int16_t s1 = m_v[VS1REG].s[i]; + int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + + if ((s1 == s2) && !BIT(m_vzero, i)) + { + m_vcompare |= 1 << i; + vres[i] = s1; + } + else + { + vres[i] = s2; + } + m_accum[i].w[SLICE_L] = vres[i]; + } + + m_vzero = 0; + m_vcarry = 0; + WRITEBACK_RESULT(); + break; + } + + case 0x22: /* VNE */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100010 | + // ------------------------------------------------------ + // + // Sets compare flags if elements in VS1 are not equal with VS2 + // Moves the element in VS2 to destination vector + + m_vcompare = 0; + m_vclip2 = 0; + + for (int i = 0; i < 8; i++) + { + int16_t s1 = m_v[VS1REG].s[i]; + int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + + if (s1 != s2 || BIT(m_vzero, i)) + { + m_vcompare |= 1 << i; + vres[i] = s1; + } + else + { + vres[i] = s2; + } + + m_accum[i].w[SLICE_L] = vres[i]; + } + + m_vzero = 0; + m_vcarry = 0; + WRITEBACK_RESULT(); + break; + } + + case 0x23: /* VGE */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100011 | + // ------------------------------------------------------ + // + // Sets compare flags if elements in VS1 are greater or equal with VS2 + // Moves the element in VS2 to destination vector + + m_vcompare = 0; + m_vclip2 = 0; + + for (int i = 0; i < 8; i++) + { + int16_t s1 = m_v[VS1REG].s[i]; + int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + + if ((s1 == s2 && (!BIT(m_vzero, i) || !BIT(m_vcarry, i))) || s1 > s2) + { + m_vcompare |= 1 << i; + vres[i] = s1; + } + else + { + vres[i] = s2; + } + + m_accum[i].w[SLICE_L] = vres[i]; + } + + m_vzero = 0; + m_vcarry = 0; + WRITEBACK_RESULT(); + break; + } + + case 0x24: /* VCL */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 | + // ------------------------------------------------------ + // + // Vector clip low + + for (int i = 0; i < 8; i++) + { + int16_t s1 = m_v[VS1REG].s[i]; + int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + + if (BIT(m_vcarry, i)) // vco_lo + { + if (BIT(m_vzero, i)) // vco_hi + { + if (BIT(m_vcompare, i)) // vcc_lo + { + m_accum[i].w[SLICE_L] = -(uint16_t)s2; + } + else + { + m_accum[i].w[SLICE_L] = s1; + } + } + else + { + if (BIT(m_vclip1, i)) // vce + { + if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) > 0x10000) + { + m_accum[i].w[SLICE_L] = s1; + m_vcompare &= ~(1 << i); + } + else + { + m_accum[i].w[SLICE_L] = -(uint16_t)s2; + m_vcompare |= 1 << i; + } + } + else + { + if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) != 0) + { + m_accum[i].w[SLICE_L] = s1; + m_vcompare &= ~(1 << i); + } + else + { + m_accum[i].w[SLICE_L] = -(uint16_t)s2; + m_vcompare |= 1 << i; + } + } + } + } + else + { + if (BIT(m_vzero, i)) // vco_hi + { + if (BIT(m_vclip2, i)) // vcc_hi + { + m_accum[i].w[SLICE_L] = s2; + } + else + { + m_accum[i].w[SLICE_L] = s1; + } + } + else + { + if (((int32_t)(uint16_t)s1 - (int32_t)(uint16_t)s2) >= 0) + { + m_accum[i].w[SLICE_L] = s2; + m_vclip2 |= 1 << i; + } + else + { + m_accum[i].w[SLICE_L] = s1; + m_vclip2 &= ~(1 << i); + } + } + } + + vres[i] = m_accum[i].w[SLICE_L]; + } + + m_vzero = 0; + m_vcarry = 0; + m_vclip1 = 0; + WRITEBACK_RESULT(); + break; + } + + case 0x25: /* VCH */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 | + // ------------------------------------------------------ + // + // Vector clip high + + m_vcarry = 0; + m_vcompare = 0; + m_vclip1 = 0; + m_vzero = 0; + m_vclip2 = 0; + uint32_t vce; + + for (int i = 0; i < 8; i++) + { + int16_t s1 = m_v[VS1REG].s[i]; + int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + + if ((s1 ^ s2) < 0) + { + vce = (s1 + s2 == -1); + m_vcarry |= 1 << i; + if (s2 < 0) + { + m_vclip2 |= 1 << i; + } + + if (s1 + s2 <= 0) + { + m_vcompare |= 1 << i; + vres[i] = -((uint16_t)s2); + } + else + { + vres[i] = s1; + } + + if (s1 + s2 != 0) + { + if (s1 != ~s2) + { + m_vzero |= 1 << i; + } + } + } + else + { + vce = 0; + if (s2 < 0) + { + m_vcompare |= 1 << i; + } + if (s1 - s2 >= 0) + { + m_vclip2 |= 1 << i; + vres[i] = s2; + } + else + { + vres[i] = s1; + } + + if ((s1 - s2) != 0) + { + if (s1 != ~s2) + { + m_vzero |= 1 << i; + } + } + } + + if (vce != 0) + { + m_vclip1 |= 1 << i; + } + + m_accum[i].w[SLICE_L] = vres[i]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x26: /* VCR */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 | + // ------------------------------------------------------ + // + // Vector clip reverse + + m_vcarry = 0; + m_vcompare = 0; + m_vclip1 = 0; + m_vzero = 0; + m_vclip2 = 0; + + for (int i = 0; i < 8; i++) + { + int16_t s1 = m_v[VS1REG].s[i]; + int16_t s2 = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + + if ((int16_t)(s1 ^ s2) < 0) + { + if (s2 < 0) + { + m_vclip2 |= 1 << i; + } + if ((s1 + s2) <= 0) + { + m_accum[i].w[SLICE_L] = ~(uint16_t)s2; + m_vcompare |= 1 << i; + } + else + { + m_accum[i].w[SLICE_L] = s1; + } + } + else + { + if (s2 < 0) + { + m_vcompare |= 1 << i; + } + if ((s1 - s2) >= 0) + { + m_accum[i].w[SLICE_L] = s2; + m_vclip2 |= 1 << i; + } + else + { + m_accum[i].w[SLICE_L] = s1; + } + } + + vres[i] = m_accum[i].w[SLICE_L]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x27: /* VMRG */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100111 | + // ------------------------------------------------------ + // + // Merges two vectors according to compare flags + + for (int i = 0; i < 8; i++) + { + if (BIT(m_vcompare, i)) + { + vres[i] = m_v[VS1REG].s[i]; + } + else + { + vres[i] = m_v[VS2REG].s[VEC_EL_2(EL, i)]; + } + + m_accum[i].w[SLICE_L] = vres[i]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x28: /* VAND */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 | + // ------------------------------------------------------ + // + // Bitwise AND of two vector registers + + for (int i = 0; i < 8; i++) + { + vres[i] = m_v[VS1REG].w[i] & m_v[VS2REG].w[VEC_EL_2(EL, i)]; + m_accum[i].w[SLICE_L] = vres[i]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x29: /* VNAND */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101001 | + // ------------------------------------------------------ + // + // Bitwise NOT AND of two vector registers + + for (int i = 0; i < 8; i++) + { + vres[i] = ~(m_v[VS1REG].w[i] & m_v[VS2REG].w[VEC_EL_2(EL, i)]); + m_accum[i].w[SLICE_L] = vres[i]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x2a: /* VOR */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101010 | + // ------------------------------------------------------ + // + // Bitwise OR of two vector registers + + for (int i = 0; i < 8; i++) + { + vres[i] = m_v[VS1REG].w[i] | m_v[VS2REG].w[VEC_EL_2(EL, i)]; + m_accum[i].w[SLICE_L] = vres[i]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x2b: /* VNOR */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101011 | + // ------------------------------------------------------ + // + // Bitwise NOT OR of two vector registers + + for (int i = 0; i < 8; i++) + { + vres[i] = ~(m_v[VS1REG].w[i] | m_v[VS2REG].w[VEC_EL_2(EL, i)]); + m_accum[i].w[SLICE_L] = vres[i]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x2c: /* VXOR */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101100 | + // ------------------------------------------------------ + // + // Bitwise XOR of two vector registers + + for (int i = 0; i < 8; i++) + { + vres[i] = m_v[VS1REG].w[i] ^ m_v[VS2REG].w[VEC_EL_2(EL, i)]; + m_accum[i].w[SLICE_L] = vres[i]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x2d: /* VNXOR */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 | + // ------------------------------------------------------ + // + // Bitwise NOT XOR of two vector registers + + for (int i = 0; i < 8; i++) + { + vres[i] = ~(m_v[VS1REG].w[i] ^ m_v[VS2REG].w[VEC_EL_2(EL, i)]); + m_accum[i].w[SLICE_L] = vres[i]; + } + WRITEBACK_RESULT(); + break; + } + + case 0x2e: /* V056 (Reserved) */ + case 0x2f: /* V057 (Reserved) */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 | + // ------------------------------------------------------ + // + // Reserved Opcode + // Appears to simply store the unsigned 16-bit sum of vector elements into low accumulator slice. + // Zeroes destination vector. + + for (int i = 0; i < 8; i++) + { + vres[i] = 0; + uint16_t e1 = m_v[VS1REG].w[i]; + uint16_t e2 = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + m_accum[i].w[SLICE_L] = e1 + e2; + } + WRITEBACK_RESULT(); + break; + } + + case 0x30: /* VRCP */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 | + // ------------------------------------------------------ + // + // Calculates reciprocal + + int32_t shifter = 0; + + int32_t rec = m_v[VS2REG].s[EL & 7]; + int32_t datainput = (rec < 0) ? (-rec) : rec; + if (datainput) + { + for (int i = 0; i < 32; i++) + { + if (datainput & (1 << ((~i) & 0x1f))) + { + shifter = i; + break; + } + } + } + else + { + shifter = 0x10; + } + + int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22; + int32_t fetchval = rsp_divtable[address]; + int32_t temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); + if (rec < 0) + { + temp = ~temp; + } + if (!rec) + { + temp = 0x7fffffff; + } + else if (rec == 0xffff8000) + { + temp = 0xffff0000; + } + rec = temp; + + m_reciprocal_res = rec; + m_dp_allowed = 0; + + m_v[VDREG].w[VS1REG & 7] = (uint16_t)(rec & 0xffff); + + for (int i = 0; i < 8; i++) + { + m_accum[i].w[SLICE_L] = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + } + break; + } + + case 0x31: /* VRCPL */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 | + // ------------------------------------------------------ + // + // Calculates reciprocal low part + + int32_t shifter = 0; + + int32_t rec = m_v[VS2REG].s[EL & 7]; + int32_t datainput = rec; + + if (m_dp_allowed) + { + rec = (rec & 0x0000ffff) | m_reciprocal_high; + datainput = rec; + + if (rec < 0) + { + if (rec < -32768) + { + datainput = ~datainput; + } + else + { + datainput = -datainput; + } + } + } + else if (datainput < 0) + { + datainput = -datainput; + + shifter = 0x10; + } + + + for (int i = 0; i < 32; i++) + { + if (datainput & (1 << ((~i) & 0x1f))) + { + shifter = i; + break; + } + } + + int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22; + int32_t fetchval = rsp_divtable[address]; + int32_t temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); + temp ^= rec >> 31; + + if (!rec) + { + temp = 0x7fffffff; + } + else if (rec == 0xffff8000) + { + temp = 0xffff0000; + } + rec = temp; + + m_reciprocal_res = rec; + m_dp_allowed = 0; + + m_v[VDREG].w[VS1REG & 7] = (uint16_t)(rec & 0xffff); + + for (int i = 0; i < 8; i++) + { + m_accum[i].w[SLICE_L] = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + } + break; + } + + case 0x32: /* VRCPH */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 | + // ------------------------------------------------------ + // + // Calculates reciprocal high part + + m_reciprocal_high = m_v[VS2REG].w[EL & 7] << 16; + m_dp_allowed = 1; + + for (int i = 0; i < 8; i++) + { + m_accum[i].w[SLICE_L] = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + } + + m_v[VDREG].s[VS1REG & 7] = (int16_t)(m_reciprocal_res >> 16); + break; + } + + case 0x33: /* VMOV */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110011 | + // ------------------------------------------------------ + // + // Moves element from vector to destination vector + + m_v[VDREG].w[VS1REG & 7] = m_v[VS2REG].w[VEC_EL_2(EL, VS1REG & 7)]; + for (int i = 0; i < 8; i++) + { + m_accum[i].w[SLICE_L] = m_v[VS2REG].w[i]; + } + break; + } + + case 0x34: /* VRSQ */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 | + // ------------------------------------------------------ + // + // Calculates reciprocal square-root + + int32_t shifter = 0; + + int32_t rec = m_v[VS2REG].s[EL & 7]; + int32_t datainput = (rec < 0) ? (-rec) : rec; + if (datainput) + { + for (int i = 0; i < 32; i++) + { + if (datainput & (1 << (~i & 0x1f))) + { + shifter = i; + break; + } + } + } + else + { + shifter = 0x10; + } + + int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22; + address = ((address | 0x200) & 0x3fe) | (shifter & 1); + + int32_t fetchval = rsp_divtable[address]; + int32_t temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); + if (rec < 0) + { + temp = ~temp; + } + if (!rec) + { + temp = 0x7fffffff; + } + else if (rec == 0xffff8000) + { + temp = 0xffff0000; + } + rec = temp; + + m_reciprocal_res = rec; + m_dp_allowed = 0; + + m_v[VDREG].w[VS1REG & 7] = (uint16_t)(rec & 0xffff); + + for (int i = 0; i < 8; i++) + { + m_accum[i].w[SLICE_L] = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + } + + break; + } + + case 0x35: /* VRSQL */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 | + // ------------------------------------------------------ + // + // Calculates reciprocal square-root low part + + int32_t shifter = 0; + int32_t rec = m_v[VS2REG].s[EL & 7]; + int32_t datainput = rec; + + if (m_dp_allowed) + { + rec = (rec & 0x0000ffff) | m_reciprocal_high; + datainput = rec; + + if (rec < 0) + { + if (rec < -32768) + { + datainput = ~datainput; + } + else + { + datainput = -datainput; + } + } + } + else if (datainput < 0) + { + datainput = -datainput; + + shifter = 0x10; + } + + if (datainput) + { + for (int i = 0; i < 32; i++) + { + if (datainput & (1 << ((~i) & 0x1f))) + { + shifter = i; + break; + } + } + } + + int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22; + address = ((address | 0x200) & 0x3fe) | (shifter & 1); + + int32_t fetchval = rsp_divtable[address]; + int32_t temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); + temp ^= rec >> 31; + + if (!rec) + { + temp = 0x7fffffff; + } + else if (rec == 0xffff8000) + { + temp = 0xffff0000; + } + rec = temp; + + m_reciprocal_res = rec; + m_dp_allowed = 0; + + m_v[VDREG].w[VS1REG & 7] = (uint16_t)(rec & 0xffff); + + for (int i = 0; i < 8; i++) + { + m_accum[i].w[SLICE_L] = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + } + + break; + } + + case 0x36: /* VRSQH */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110110 | + // ------------------------------------------------------ + // + // Calculates reciprocal square-root high part + + m_reciprocal_high = m_v[VS2REG].w[EL & 7] << 16; + m_dp_allowed = 1; + + for (int i = 0; i < 8; i++) + { + m_accum[i].w[SLICE_L] = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + } + + m_v[VDREG].s[VS1REG & 7] = (int16_t)(m_reciprocal_res >> 16); // store high part + break; + } + + case 0x37: /* VNOP */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110111 | + // ------------------------------------------------------ + // + // Vector null instruction + + break; + } + + case 0x3b: /* V073 (Reserved) */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 | + // ------------------------------------------------------ + // + // Reserved Opcode + // Appears to simply store the unsigned 16-bit sum of vector elements into low accumulator slice. + // Zeroes destination vector. + + for (int i = 0; i < 8; i++) + { + vres[i] = 0; + uint16_t e1 = m_v[VS1REG].w[i]; + uint16_t e2 = m_v[VS2REG].w[VEC_EL_2(EL, i)]; + m_accum[i].w[SLICE_L] = e1 + e2; + } + WRITEBACK_RESULT(); + break; + } + + case 0x3f: /* VNULL (Reserved) */ + { + // 31 25 24 20 15 10 5 0 + // ------------------------------------------------------ + // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 | + // ------------------------------------------------------ + // + // Reserved Opcode + // Appears to simply store the unsigned 16-bit sum of vector elements into low accumulator slice. + // Zeroes destination vector. + + for (int i = 0; i < 8; i++) + { + vres[i] = m_v[VS1REG].w[i]; + m_accum[i].w[SLICE_L] = 0; + } + WRITEBACK_RESULT(); + break; + } + + default: unimplemented_opcode(op); break; + } +} + +void rsp_device::handle_cop2(uint32_t op) +{ + switch ((op >> 21) & 0x1f) + { + case 0x00: /* MFC2 */ + { + // 31 25 20 15 10 6 0 + // --------------------------------------------------- + // | 010010 | 00000 | TTTTT | DDDDD | IIII | 0000000 | + // --------------------------------------------------- + + int el = (op >> 7) & 0xf; + uint16_t b1 = VREG_B(RDREG, (el+0) & 0xf); + uint16_t b2 = VREG_B(RDREG, (el+1) & 0xf); + if (RTREG) m_r[RTREG] = (int32_t)(int16_t)((b1 << 8) | (b2)); + break; + } + + case 0x02: /* CFC2 */ + { + // 31 25 20 15 10 0 + // ------------------------------------------------ + // | 010010 | 00010 | TTTTT | DDDDD | 00000000000 | + // ------------------------------------------------ + + if (RTREG) + { + switch (RDREG) + { + case 0: + m_r[RTREG] = (m_vzero << 8) | m_vcarry; + if (m_r[RTREG] & 0x8000) m_r[RTREG] |= 0xffff0000; + break; + case 1: + m_r[RTREG] = (m_vclip2 << 8) | m_vcompare; + if (m_r[RTREG] & 0x8000) m_r[RTREG] |= 0xffff0000; + break; + case 2: + // Anciliary clipping flags + m_r[RTREG] = m_vclip1; + break; + } + } + break; + } + + case 0x04: /* MTC2 */ + { + // 31 25 20 15 10 6 0 + // --------------------------------------------------- + // | 010010 | 00100 | TTTTT | DDDDD | IIII | 0000000 | + // --------------------------------------------------- + + int el = (op >> 7) & 0xf; + W_VREG_B(RDREG, (el+0) & 0xf, (m_r[RTREG] >> 8) & 0xff); + W_VREG_B(RDREG, (el+1) & 0xf, (m_r[RTREG] >> 0) & 0xff); + break; + } + + case 0x06: /* CTC2 */ + { + // 31 25 20 15 10 0 + // ------------------------------------------------ + // | 010010 | 00110 | TTTTT | DDDDD | 00000000000 | + // ------------------------------------------------ + + switch (RDREG) + { + case 0: + m_vcarry = (uint8_t)m_r[RTREG]; + m_vzero = (uint8_t)(m_r[RTREG] >> 8); + break; + + case 1: + m_vcompare = (uint8_t)m_r[RTREG]; + m_vclip2 = (uint8_t)(m_r[RTREG] >> 8); + break; + + case 2: + m_vclip1 = (uint8_t)m_r[RTREG]; + break; + } + break; + } + + case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: + handle_vector_ops(op); + break; + + default: + unimplemented_opcode(op); + break; + } +} + +void rsp_device::handle_lwc2(uint32_t op) +{ + int base = (op >> 21) & 0x1f; + int dest = (op >> 16) & 0x1f; + int index = (op >> 7) & 0xf; + int offset = (op & 0x7f); + offset = (offset << 25) >> 25; + + switch ((op >> 11) & 0x1f) + { + case 0x00: /* LBV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 00000 | IIII | Offset | + // -------------------------------------------------- + // + // Load 1 byte to vector byte index + + uint32_t ea = (base) ? m_r[base] + offset : offset; + VREG_B(dest, index) = read_dmem_byte(ea); + break; + } + + case 0x01: /* LSV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 00001 | IIII | Offset | + // -------------------------------------------------- + // + // Loads 2 bytes starting from vector byte index + + uint32_t ea = (base) ? m_r[base] + (offset * 2) : (offset * 2); + + for (int i = index; i < index + 2; i++) + { + VREG_B(dest, i) = read_dmem_byte(ea); + ea++; + } + break; + } + + case 0x02: /* LLV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 00010 | IIII | Offset | + // -------------------------------------------------- + // + // Loads 4 bytes starting from vector byte index + + uint32_t ea = (base) ? m_r[base] + (offset * 4) : (offset * 4); + + for (int i = index; i < index + 4; i++) + { + VREG_B(dest, i) = read_dmem_byte(ea); + ea++; + } + break; + } + + case 0x03: /* LDV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 00011 | IIII | Offset | + // -------------------------------------------------- + // + // Loads 8 bytes starting from vector byte index + + uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8); + + for (int i = index; i < index + 8; i++) + { + VREG_B(dest, i) = read_dmem_byte(ea); + ea++; + } + break; + } + + case 0x04: /* LQV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 00100 | IIII | Offset | + // -------------------------------------------------- + // + // Loads up to 16 bytes starting from vector byte index + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + + int end = index + (16 - (ea & 0xf)); + if (end > 16) end = 16; + + for (int i = index; i < end; i++) + { + VREG_B(dest, i) = read_dmem_byte(ea); + ea++; + } + break; + } + + case 0x05: /* LRV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 00101 | IIII | Offset | + // -------------------------------------------------- + // + // Stores up to 16 bytes starting from right side until 16-byte boundary + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + + index = 16 - ((ea & 0xf) - index); + ea &= ~0xf; + + for (int i = index; i < 16; i++) + { + VREG_B(dest, i) = read_dmem_byte(ea); + ea++; + } + break; + } + + case 0x06: /* LPV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 00110 | IIII | Offset | + // -------------------------------------------------- + // + // Loads a byte as the upper 8 bits of each element + + uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8); + + for (int i = 0; i < 8; i++) + { + m_v[dest].w[i] = read_dmem_byte(ea + (((16-index) + i) & 0xf)) << 8; + } + break; + } + + case 0x07: /* LUV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 00111 | IIII | Offset | + // -------------------------------------------------- + // + // Loads a byte as the bits 14-7 of each element + + uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8); + + for (int i = 0; i < 8; i++) + { + m_v[dest].w[i] = read_dmem_byte(ea + (((16-index) + i) & 0xf)) << 7; + } + break; + } + + case 0x08: /* LHV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 01000 | IIII | Offset | + // -------------------------------------------------- + // + // Loads a byte as the bits 14-7 of each element, with 2-byte stride + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + + for (int i = 0; i < 8; i++) + { + m_v[dest].w[i] = read_dmem_byte(ea + (((16-index) + (i<<1)) & 0xf)) << 7; + } + break; + } + + case 0x09: /* LFV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 01001 | IIII | Offset | + // -------------------------------------------------- + // + // Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + + // NOTE: Not sure what happens if 16-byte boundary is crossed + + int end = (index >> 1) + 4; + + for (int i = index >> 1; i < end; i++) + { + m_v[dest].w[i] = read_dmem_byte(ea) << 7; + ea += 4; + } + break; + } + + case 0x0a: /* LWV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 01010 | IIII | Offset | + // -------------------------------------------------- + // + // Intended instruction behavior: + // Loads the full 128-bit vector starting from vector byte index and wrapping to index 0 + // after byte index 15 + // + // Actual instruction behavior: + // Loads the full 128-bit vector starting from vector byte index 0. + // + // Hardware testing has proven that the vector index is ignored when executing LWV. + // By contrast, SWV will function as intended when provided an index. + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + + for (int i = 0; i < 16; i++) + { + VREG_B(dest, i) = read_dmem_byte(ea); + ea++; + } + break; + } + + case 0x0b: /* LTV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset | + // -------------------------------------------------- + // + // Loads one element to maximum of 8 vectors, while incrementing element index + + // FIXME: has a small problem with odd indices + + int32_t vs = (op >> 16) & 0x1f; + int32_t ve = vs + 8; + if (ve > 32) + ve = 32; + + if (index & 1) fatalerror("RSP: LTV: index = %d\n", index); + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + ea = ((ea + 8) & ~0xf) + (index & 1); + + for (int32_t i = vs; i < ve; i++) + { + int32_t element = ((8 - (index >> 1) + (i-vs)) << 1); + VREG_B(i, (element & 0xf)) = read_dmem_byte(ea); + VREG_B(i, ((element + 1) & 0xf)) = read_dmem_byte(ea + 1); + + ea += 2; + } + break; + } + + default: + { + unimplemented_opcode(op); + break; + } } +} + + +/*************************************************************************** + Vector Store Instructions +***************************************************************************/ + +void rsp_device::handle_swc2(uint32_t op) +{ + int base = (op >> 21) & 0x1f; + int dest = (op >> 16) & 0x1f; + int index = (op >> 7) & 0xf; + int offset = (op & 0x7f); + offset = (offset << 25) >> 25; - while (m_rsp_state->icount > 0) + switch ((op >> 11) & 0x1f) { - m_ppc = m_rsp_state->pc; - debugger_instruction_hook(m_rsp_state->pc); + case 0x00: /* SBV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset | + // -------------------------------------------------- + // + // Stores 1 byte from vector byte index + + uint32_t ea = (base) ? m_r[base] + offset : offset; + write_dmem_byte(ea, VREG_B(dest, index)); + break; + } + + case 0x01: /* SSV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset | + // -------------------------------------------------- + // + // Stores 2 bytes starting from vector byte index + + uint32_t ea = (base) ? m_r[base] + (offset * 2) : (offset * 2); + + for (int i = index; i < index + 2; i++) + { + write_dmem_byte(ea, VREG_B(dest, i)); + ea++; + } + break; + } + + case 0x02: /* SLV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset | + // -------------------------------------------------- + // + // Stores 4 bytes starting from vector byte index + + uint32_t ea = (base) ? m_r[base] + (offset * 4) : (offset * 4); + + for (int i = index; i < index + 4; i++) + { + write_dmem_byte(ea, VREG_B(dest, i)); + ea++; + } + break; + } - uint32_t op = ROPCODE(m_rsp_state->pc); - if (m_nextpc != ~0) + case 0x03: /* SDV */ { - m_rsp_state->pc = m_nextpc; - m_nextpc = ~0; + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset | + // -------------------------------------------------- + // + // Stores 8 bytes starting from vector byte index + + uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8); + + for (int i = index; i < index + 8; i++) + { + write_dmem_byte(ea, VREG_B(dest, i)); + ea++; + } + break; + } + + case 0x04: /* SQV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset | + // -------------------------------------------------- + // + // Stores up to 16 bytes starting from vector byte index until 16-byte boundary + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + int end = index + (16 - (ea & 0xf)); + + for (int i = index; i < end; i++) + { + write_dmem_byte(ea, VREG_B(dest, i & 0xf)); + ea++; + } + break; + } + + case 0x05: /* SRV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset | + // -------------------------------------------------- + // + // Stores up to 16 bytes starting from right side until 16-byte boundary + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + + int end = index + (ea & 0xf); + int o = (16 - (ea & 0xf)) & 0xf; + ea &= ~0xf; + + for (int i = index; i < end; i++) + { + write_dmem_byte(ea, VREG_B(dest, ((i + o) & 0xf))); + ea++; + } + break; + } + + case 0x06: /* SPV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset | + // -------------------------------------------------- + // + // Stores upper 8 bits of each element + + uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8); + + for (int i = index; i < index + 8; i++) + { + if ((i & 0xf) < 8) + { + write_dmem_byte(ea, VREG_B(dest, ((i & 0xf) << 1))); + } + else + { + write_dmem_byte(ea, m_v[dest].s[i & 0x7] >> 7); + } + ea++; + } + break; + } + + case 0x07: /* SUV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset | + // -------------------------------------------------- + // + // Stores bits 14-7 of each element + + uint32_t ea = (base) ? m_r[base] + (offset * 8) : (offset * 8); + + for (int i = index; i < index + 8; i++) + { + if ((i & 0xf) < 8) + { + write_dmem_byte(ea, m_v[dest].s[i & 0x7] >> 7); + } + else + { + write_dmem_byte(ea, VREG_B(dest, ((i & 0x7) << 1))); + } + ea++; + } + break; + } + + case 0x08: /* SHV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset | + // -------------------------------------------------- + // + // Stores bits 14-7 of each element, with 2-byte stride + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + + for (int i = 0; i < 8; i++) + { + uint8_t d = ((VREG_B(dest, ((index + (i << 1) + 0) & 0xf))) << 1) | + ((VREG_B(dest, ((index + (i << 1) + 1) & 0xf))) >> 7); + + write_dmem_byte(ea, d); + ea += 2; + } + break; + } + + case 0x09: /* SFV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset | + // -------------------------------------------------- + // + // Stores bits 14-7 of upper or lower quad, with 4-byte stride + + // FIXME: only works for index 0 and index 8 + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + + int eaoffset = ea & 0xf; + ea &= ~0xf; + + int end = (index >> 1) + 4; + + for (int i = index >> 1; i < end; i++) + { + write_dmem_byte(ea + (eaoffset & 0xf), m_v[dest].s[i] >> 7); + eaoffset += 4; + } + break; + } + + case 0x0a: /* SWV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset | + // -------------------------------------------------- + // + // Stores the full 128-bit vector starting from vector byte index and wrapping to index 0 + // after byte index 15 + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + + int eaoffset = ea & 0xf; + ea &= ~0xf; + + for (int i = index; i < index + 16; i++) + { + write_dmem_byte(ea + (eaoffset & 0xf), VREG_B(dest, i & 0xf)); + eaoffset++; + } + break; + } + + case 0x0b: /* STV */ + { + // 31 25 20 15 10 6 0 + // -------------------------------------------------- + // | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset | + // -------------------------------------------------- + // + // Stores one element from maximum of 8 vectors, while incrementing element index + + int32_t vs = (op >> 16) & 0x1f; + int32_t ve = vs + 8; + if (ve > 32) + ve = 32; + + int32_t element = 8 - (index >> 1); + + uint32_t ea = (base) ? m_r[base] + (offset * 16) : (offset * 16); + + int32_t eaoffset = (ea & 0xf) + (element * 2); + ea &= ~0xf; + + for (int32_t i = vs; i < ve; i++) + { + write_dmem_word(ea + (eaoffset & 0xf), m_v[i].w[element & 0x7]); + eaoffset += 2; + element++; + } + break; + } + + default: + unimplemented_opcode(op); + break; + } +} + +void rsp_device::update_scalar_op_deduction() +{ + /*if (m_paired_busy) + { + m_scalar_busy = false; + m_vector_busy = false; + m_paired_busy = false; + m_ideduct = 1; + } + else if (m_vector_busy) + { + m_scalar_busy = true; + m_paired_busy = true; + m_ideduct = 0; + } + else if (m_scalar_busy) + { + m_ideduct = 1; + } + else + { + m_scalar_busy = true; + m_ideduct = 0; + }*/ +} + +void rsp_device::update_vector_op_deduction() +{ + /*if (m_paired_busy) + { + m_scalar_busy = false; + m_vector_busy = false; + m_paired_busy = false; + m_ideduct = 1; + } + else if (m_scalar_busy) + { + m_vector_busy = true; + m_paired_busy = true; + m_ideduct = 0; + } + else if (m_vector_busy) + { + m_ideduct = 1; + } + else + { + m_vector_busy = true; + m_ideduct = 0; + }*/ +} + +void rsp_device::execute_run() +{ + if (m_sr & (RSP_STATUS_HALT | RSP_STATUS_BROKE)) + { + m_ideduct = 0; + m_scalar_busy = false; + m_vector_busy = false; + m_paired_busy = false; + m_icount = std::min(m_icount, 0); + } + + while (m_icount > 0) + { + m_ppc = m_pc; + debugger_instruction_hook(m_pc); + + uint32_t op = ROPCODE(m_pc); + if (m_nextpc != 0xffff) + { + m_pc = m_nextpc; + m_nextpc = 0xffff; } else { - m_rsp_state->pc += 4; + m_pc += 4; } switch (op >> 26) { case 0x00: /* SPECIAL */ { + update_scalar_op_deduction(); switch (op & 0x3f) { - case 0x00: /* SLL */ if (RDREG) RDVAL = (uint32_t)RTVAL << SHIFT; break; - case 0x02: /* SRL */ if (RDREG) RDVAL = (uint32_t)RTVAL >> SHIFT; break; - case 0x03: /* SRA */ if (RDREG) RDVAL = (int32_t)RTVAL >> SHIFT; break; - case 0x04: /* SLLV */ if (RDREG) RDVAL = (uint32_t)RTVAL << (RSVAL & 0x1f); break; - case 0x06: /* SRLV */ if (RDREG) RDVAL = (uint32_t)RTVAL >> (RSVAL & 0x1f); break; - case 0x07: /* SRAV */ if (RDREG) RDVAL = (int32_t)RTVAL >> (RSVAL & 0x1f); break; - case 0x08: /* JR */ JUMP_PC(RSVAL); break; - case 0x09: /* JALR */ JUMP_PC_L(RSVAL, RDREG); break; + case 0x00: /* SLL */ if (RDREG) m_r[RDREG] = m_r[RTREG] << SHIFT; break; + case 0x02: /* SRL */ if (RDREG) m_r[RDREG] = m_r[RTREG] >> SHIFT; break; + case 0x03: /* SRA */ if (RDREG) m_r[RDREG] = (int32_t)m_r[RTREG] >> SHIFT; break; + case 0x04: /* SLLV */ if (RDREG) m_r[RDREG] = m_r[RTREG] << (m_r[RSREG] & 0x1f); break; + case 0x06: /* SRLV */ if (RDREG) m_r[RDREG] = m_r[RTREG] >> (m_r[RSREG] & 0x1f); break; + case 0x07: /* SRAV */ if (RDREG) m_r[RDREG] = (int32_t)m_r[RTREG] >> (m_r[RSREG] & 0x1f); break; + case 0x08: /* JR */ JUMP_PC(m_r[RSREG]); break; + case 0x09: /* JALR */ JUMP_PC_L(m_r[RSREG], RDREG); break; case 0x0d: /* BREAK */ { + m_ideduct = 1; + m_scalar_busy = false; + m_vector_busy = false; + m_paired_busy = false; m_sp_set_status_func(0, 0x3, 0xffffffff); - m_rsp_state->icount = std::min(m_rsp_state->icount, 1); + m_icount = std::min(m_icount, 1); break; } - case 0x20: /* ADD */ if (RDREG) RDVAL = (int32_t)(RSVAL + RTVAL); break; - case 0x21: /* ADDU */ if (RDREG) RDVAL = (int32_t)(RSVAL + RTVAL); break; - case 0x22: /* SUB */ if (RDREG) RDVAL = (int32_t)(RSVAL - RTVAL); break; - case 0x23: /* SUBU */ if (RDREG) RDVAL = (int32_t)(RSVAL - RTVAL); break; - case 0x24: /* AND */ if (RDREG) RDVAL = RSVAL & RTVAL; break; - case 0x25: /* OR */ if (RDREG) RDVAL = RSVAL | RTVAL; break; - case 0x26: /* XOR */ if (RDREG) RDVAL = RSVAL ^ RTVAL; break; - case 0x27: /* NOR */ if (RDREG) RDVAL = ~(RSVAL | RTVAL); break; - case 0x2a: /* SLT */ if (RDREG) RDVAL = (int32_t)RSVAL < (int32_t)RTVAL; break; - case 0x2b: /* SLTU */ if (RDREG) RDVAL = (uint32_t)RSVAL < (uint32_t)RTVAL; break; + case 0x20: /* ADD */ if (RDREG) m_r[RDREG] = (int32_t)(m_r[RSREG] + m_r[RTREG]); break; + case 0x21: /* ADDU */ if (RDREG) m_r[RDREG] = (int32_t)(m_r[RSREG] + m_r[RTREG]); break; + case 0x22: /* SUB */ if (RDREG) m_r[RDREG] = (int32_t)(m_r[RSREG] - m_r[RTREG]); break; + case 0x23: /* SUBU */ if (RDREG) m_r[RDREG] = (int32_t)(m_r[RSREG] - m_r[RTREG]); break; + case 0x24: /* AND */ if (RDREG) m_r[RDREG] = m_r[RSREG] & m_r[RTREG]; break; + case 0x25: /* OR */ if (RDREG) m_r[RDREG] = m_r[RSREG] | m_r[RTREG]; break; + case 0x26: /* XOR */ if (RDREG) m_r[RDREG] = m_r[RSREG] ^ m_r[RTREG]; break; + case 0x27: /* NOR */ if (RDREG) m_r[RDREG] = ~(m_r[RSREG] | m_r[RTREG]); break; + case 0x2a: /* SLT */ if (RDREG) m_r[RDREG] = (int32_t)m_r[RSREG] < (int32_t)m_r[RTREG]; break; + case 0x2b: /* SLTU */ if (RDREG) m_r[RDREG] = m_r[RSREG] < m_r[RTREG]; break; default: unimplemented_opcode(op); break; } break; @@ -680,38 +2920,40 @@ void rsp_device::execute_run() case 0x01: /* REGIMM */ { + update_scalar_op_deduction(); switch (RTREG) { - case 0x00: /* BLTZ */ if ((int32_t)(RSVAL) < 0) JUMP_REL(SIMM16); break; - case 0x01: /* BGEZ */ if ((int32_t)(RSVAL) >= 0) JUMP_REL(SIMM16); break; - case 0x10: /* BLTZAL */ if ((int32_t)(RSVAL) < 0) JUMP_REL_L(SIMM16, 31); break; - case 0x11: /* BGEZAL */ if ((int32_t)(RSVAL) >= 0) JUMP_REL_L(SIMM16, 31); break; + case 0x00: /* BLTZ */ if ((int32_t)m_r[RSREG] < 0) JUMP_REL(SIMM16); break; + case 0x01: /* BGEZ */ if ((int32_t)m_r[RSREG] >= 0) JUMP_REL(SIMM16); break; + case 0x10: /* BLTZAL */ if ((int32_t)m_r[RSREG] < 0) JUMP_REL_L(SIMM16, 31); break; + case 0x11: /* BGEZAL */ if ((int32_t)m_r[RSREG] >= 0) JUMP_REL_L(SIMM16, 31); break; default: unimplemented_opcode(op); break; } break; } - case 0x02: /* J */ JUMP_ABS(UIMM26); break; - case 0x03: /* JAL */ JUMP_ABS_L(UIMM26, 31); break; - case 0x04: /* BEQ */ if (RSVAL == RTVAL) JUMP_REL(SIMM16); break; - case 0x05: /* BNE */ if (RSVAL != RTVAL) JUMP_REL(SIMM16); break; - case 0x06: /* BLEZ */ if ((int32_t)RSVAL <= 0) JUMP_REL(SIMM16); break; - case 0x07: /* BGTZ */ if ((int32_t)RSVAL > 0) JUMP_REL(SIMM16); break; - case 0x08: /* ADDI */ if (RTREG) RTVAL = (int32_t)(RSVAL + SIMM16); break; - case 0x09: /* ADDIU */ if (RTREG) RTVAL = (int32_t)(RSVAL + SIMM16); break; - case 0x0a: /* SLTI */ if (RTREG) RTVAL = (int32_t)(RSVAL) < ((int32_t)SIMM16); break; - case 0x0b: /* SLTIU */ if (RTREG) RTVAL = (uint32_t)(RSVAL) < (uint32_t)((int32_t)SIMM16); break; - case 0x0c: /* ANDI */ if (RTREG) RTVAL = RSVAL & UIMM16; break; - case 0x0d: /* ORI */ if (RTREG) RTVAL = RSVAL | UIMM16; break; - case 0x0e: /* XORI */ if (RTREG) RTVAL = RSVAL ^ UIMM16; break; - case 0x0f: /* LUI */ if (RTREG) RTVAL = UIMM16 << 16; break; + case 0x02: /* J */ update_scalar_op_deduction(); JUMP_ABS(UIMM26); break; + case 0x03: /* JAL */ update_scalar_op_deduction(); JUMP_ABS_L(UIMM26, 31); break; + case 0x04: /* BEQ */ update_scalar_op_deduction(); if (m_r[RSREG] == m_r[RTREG]) JUMP_REL(SIMM16); break; + case 0x05: /* BNE */ update_scalar_op_deduction(); if (m_r[RSREG] != m_r[RTREG]) JUMP_REL(SIMM16); break; + case 0x06: /* BLEZ */ update_scalar_op_deduction(); if ((int32_t)m_r[RSREG] <= 0) JUMP_REL(SIMM16); break; + case 0x07: /* BGTZ */ update_scalar_op_deduction(); if ((int32_t)m_r[RSREG] > 0) JUMP_REL(SIMM16); break; + case 0x08: /* ADDI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = (int32_t)m_r[RSREG] + SIMM16; break; + case 0x09: /* ADDIU */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = (int32_t)m_r[RSREG] + SIMM16; break; + case 0x0a: /* SLTI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = (int32_t)m_r[RSREG] < (int32_t)SIMM16; break; + case 0x0b: /* SLTIU */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = m_r[RSREG] < UIMM16; break; + case 0x0c: /* ANDI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = m_r[RSREG] & UIMM16; break; + case 0x0d: /* ORI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = m_r[RSREG] | UIMM16; break; + case 0x0e: /* XORI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = m_r[RSREG] ^ UIMM16; break; + case 0x0f: /* LUI */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = UIMM16 << 16; break; case 0x10: /* COP0 */ { + update_scalar_op_deduction(); switch ((op >> 21) & 0x1f) { - case 0x00: /* MFC0 */ if (RTREG) RTVAL = get_cop0_reg(RDREG); break; - case 0x04: /* MTC0 */ set_cop0_reg(RDREG, RTVAL); break; + case 0x00: /* MFC0 */ if (RTREG) m_r[RTREG] = get_cop0_reg(RDREG); break; + case 0x04: /* MTC0 */ set_cop0_reg(RDREG, m_r[RTREG]); break; default: unimplemented_opcode(op); break; } break; @@ -719,20 +2961,21 @@ void rsp_device::execute_run() case 0x12: /* COP2 */ { - m_cop2->handle_cop2(op); + update_vector_op_deduction(); + handle_cop2(op); break; } - case 0x20: /* LB */ if (RTREG) RTVAL = (int32_t)(int8_t)READ8(RSVAL + SIMM16); break; - case 0x21: /* LH */ if (RTREG) RTVAL = (int32_t)(int16_t)READ16(RSVAL + SIMM16); break; - case 0x23: /* LW */ if (RTREG) RTVAL = READ32(RSVAL + SIMM16); break; - case 0x24: /* LBU */ if (RTREG) RTVAL = (uint8_t)READ8(RSVAL + SIMM16); break; - case 0x25: /* LHU */ if (RTREG) RTVAL = (uint16_t)READ16(RSVAL + SIMM16); break; - case 0x28: /* SB */ WRITE8(RSVAL + SIMM16, RTVAL); break; - case 0x29: /* SH */ WRITE16(RSVAL + SIMM16, RTVAL); break; - case 0x2b: /* SW */ WRITE32(RSVAL + SIMM16, RTVAL); break; - case 0x32: /* LWC2 */ m_cop2->handle_lwc2(op); break; - case 0x3a: /* SWC2 */ m_cop2->handle_swc2(op); break; + case 0x20: /* LB */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = (int32_t)(int8_t)read_dmem_byte(m_r[RSREG] + SIMM16); break; + case 0x21: /* LH */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = (int32_t)(int16_t)read_dmem_word(m_r[RSREG] + SIMM16); break; + case 0x23: /* LW */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = read_dmem_dword(m_r[RSREG] + SIMM16); break; + case 0x24: /* LBU */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = read_dmem_byte(m_r[RSREG] + SIMM16); break; + case 0x25: /* LHU */ update_scalar_op_deduction(); if (RTREG) m_r[RTREG] = read_dmem_word(m_r[RSREG] + SIMM16); break; + case 0x28: /* SB */ update_scalar_op_deduction(); write_dmem_byte(m_r[RSREG] + SIMM16, m_r[RTREG]); break; + case 0x29: /* SH */ update_scalar_op_deduction(); write_dmem_word(m_r[RSREG] + SIMM16, m_r[RTREG]); break; + case 0x2b: /* SW */ update_scalar_op_deduction(); write_dmem_dword(m_r[RSREG] + SIMM16, m_r[RTREG]); break; + case 0x32: /* LWC2 */ update_scalar_op_deduction(); handle_lwc2(op); break; + case 0x3a: /* SWC2 */ update_scalar_op_deduction(); handle_swc2(op); break; default: { @@ -743,8 +2986,8 @@ void rsp_device::execute_run() if (LOG_INSTRUCTION_EXECUTION) { - int i, l; static uint32_t prev_regs[32]; + static VECTOR_REG prev_vecs[32]; rsp_disassembler rspd; std::ostringstream string; @@ -752,10 +2995,10 @@ void rsp_device::execute_run() fprintf(m_exec_output, "%08X: %s", m_ppc, string.str().c_str()); - l = string.str().size(); + int l = string.str().size(); if (l < 36) { - for (i=l; i < 36; i++) + for (int i = l; i < 36; i++) { fprintf(m_exec_output, " "); } @@ -763,26 +3006,36 @@ void rsp_device::execute_run() fprintf(m_exec_output, "| "); - for (i=0; i < 32; i++) + for (int i = 0; i < 32; i++) { - if (m_rsp_state->r[i] != prev_regs[i]) + if (m_r[i] != prev_regs[i]) { - fprintf(m_exec_output, "R%d: %08X ", i, m_rsp_state->r[i]); + fprintf(m_exec_output, "R%d: %08X ", i, m_r[i]); } - prev_regs[i] = m_rsp_state->r[i]; + prev_regs[i] = m_r[i]; } - m_cop2->log_instruction_execution(); + for (int i = 0; i < 32; i++) + { + if (m_v[i].d[0] != prev_vecs[i].d[0] || m_v[i].d[1] != prev_vecs[i].d[1]) + { + fprintf(m_exec_output, "V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X ", i, + m_v[i].w[0], m_v[i].w[1], m_v[i].w[2], m_v[i].w[3], m_v[i].w[4], m_v[i].w[5], m_v[i].w[6], m_v[i].w[7]); + } + prev_vecs[i].d[0] = m_v[i].d[0]; + prev_vecs[i].d[1] = m_v[i].d[1]; + } fprintf(m_exec_output, "\n"); } - --m_rsp_state->icount; + //m_icount -= m_ideduct; + --m_icount; - if( m_sr & RSP_STATUS_SSTEP ) + if (m_sr & RSP_STATUS_SSTEP) { - if( m_step_count ) + if (m_step_count) { m_step_count--; } @@ -792,14 +3045,13 @@ void rsp_device::execute_run() } } - if( m_sr & ( RSP_STATUS_HALT | RSP_STATUS_BROKE ) ) + if (m_sr & (RSP_STATUS_HALT | RSP_STATUS_BROKE)) { - m_rsp_state->icount = std::min(m_rsp_state->icount, 0); + m_ideduct = 0; + m_scalar_busy = false; + m_vector_busy = false; + m_paired_busy = false; + m_icount = std::min(m_icount, 0); } - /*m_cop2->dump(op); - if (((op >> 26) & 0x3f) == 0x3a) - { - m_cop2->dump_dmem(); - }*/ } } diff --git a/src/devices/cpu/rsp/rsp.h b/src/devices/cpu/rsp/rsp.h index 5383889cdd3..b33012bddda 100644 --- a/src/devices/cpu/rsp/rsp.h +++ b/src/devices/cpu/rsp/rsp.h @@ -14,9 +14,6 @@ #pragma once -#include "cpu/drcfe.h" -#include "cpu/drcuml.h" - /*************************************************************************** REGISTER ENUMERATION ***************************************************************************/ @@ -81,14 +78,9 @@ enum #define RSP_STATUS_SIGNAL6 0x2000 #define RSP_STATUS_SIGNAL7 0x4000 -#define RSPDRC_STRICT_VERIFY 0x0001 /* verify all instructions */ - - class rsp_device : public cpu_device { - class frontend; class cop2; - class cop2_drc; public: // construction/destruction @@ -102,24 +94,6 @@ public: auto sp_reg_w() { return m_sp_reg_w_func.bind(); } auto status_set() { return m_sp_set_status_func.bind(); } - void rspdrc_flush_drc_cache(); - void rspdrc_set_options(uint32_t options); - void rsp_add_dmem(uint32_t *base); - void rsp_add_imem(uint32_t *base); - - void ccfunc_read8(); - void ccfunc_read16(); - void ccfunc_read32(); - void ccfunc_write8(); - void ccfunc_write16(); - void ccfunc_write32(); - void ccfunc_get_cop0_reg(); - void ccfunc_set_cop0_reg(); - void ccfunc_sp_set_status_cb(); - void ccfunc_unimplemented(); - - uint8_t* get_dmem() { return m_dmem8; } - protected: // device-level overrides virtual void device_start() override; @@ -146,95 +120,56 @@ protected: void unimplemented_opcode(uint32_t op); - /* internal compiler state */ - struct compiler_state - { - compiler_state &operator=(compiler_state &) = delete; - - uint32_t cycles; /* accumulated cycles */ - uint8_t checkints; /* need to check interrupts before next instruction */ - uint8_t checksoftints; /* need to check software interrupts before next instruction */ - uml::code_label labelnum; /* index for local labels */ - }; - private: - address_space_config m_program_config; - - /* fast RAM info */ - struct fast_ram_info - { - offs_t start; /* start of the RAM block */ - offs_t end; /* end of the RAM block */ - bool readonly; /* true if read-only */ - void * base; /* base in memory where the RAM lives */ - }; + address_space_config m_imem_config; + address_space_config m_dmem_config; - /* core state */ - drc_cache m_cache; /* pointer to the DRC code cache */ - std::unique_ptr<drcuml_state> m_drcuml; /* DRC UML generator state */ - std::unique_ptr<frontend> m_drcfe; /* pointer to the DRC front-end state */ - uint32_t m_drcoptions; /* configurable DRC options */ - - /* internal stuff */ - uint8_t m_cache_dirty; /* true if we need to flush the cache */ - - /* parameters for subroutines */ - uint64_t m_numcycles; /* return value from gettotalcycles */ - const char * m_format; /* format string for print_debug */ - uint32_t m_arg2; /* print_debug argument 3 */ - uint32_t m_arg3; /* print_debug argument 4 */ - - /* register mappings */ - uml::parameter m_regmap[34]; /* parameter to register mappings for all 32 integer registers */ - - /* subroutines */ - uml::code_handle * m_entry; /* entry point */ - uml::code_handle * m_nocode; /* nocode exception handler */ - uml::code_handle * m_out_of_cycles; /* out of cycles exception handler */ - uml::code_handle * m_read8; /* read byte */ - uml::code_handle * m_write8; /* write byte */ - uml::code_handle * m_read16; /* read half */ - uml::code_handle * m_write16; /* write half */ - uml::code_handle * m_read32; /* read word */ - uml::code_handle * m_write32; /* write word */ - - struct internal_rsp_state - { - uint32_t pc; - uint32_t r[35]; - uint32_t arg0; - uint32_t arg1; - uint32_t jmpdest; - int icount; - }; + uint16_t m_pc; + uint32_t m_r[35]; + int m_icount; + int m_ideduct; + bool m_scalar_busy; + bool m_vector_busy; + bool m_paired_busy; - internal_rsp_state *m_rsp_state; + void update_scalar_op_deduction(); + void update_vector_op_deduction(); FILE *m_exec_output; uint32_t m_sr; uint32_t m_step_count; - uint32_t m_ppc; - uint32_t m_nextpc; + uint16_t m_ppc; + uint16_t m_nextpc; protected: - memory_access<32, 2, 0, ENDIANNESS_BIG>::cache m_pcache; - memory_access<32, 2, 0, ENDIANNESS_BIG>::specific m_program; + memory_access<12, 2, 0, ENDIANNESS_BIG>::cache m_icache; + memory_access<12, 2, 0, ENDIANNESS_BIG>::specific m_imem; + memory_access<12, 2, 0, ENDIANNESS_BIG>::cache m_dcache; + memory_access<12, 2, 0, ENDIANNESS_BIG>::specific m_dmem; private: - std::unique_ptr<cop2> m_cop2; - - uint32_t *m_dmem32; - uint16_t *m_dmem16; - uint8_t *m_dmem8; + union VECTOR_REG + { + uint64_t d[2]; + uint32_t l[4]; + uint16_t w[8]; + int16_t s[8]; + uint8_t b[16]; + }; - uint32_t *m_imem32; - uint16_t *m_imem16; - uint8_t *m_imem8; + union ACCUMULATOR_REG + { + uint64_t q; + uint32_t l[2]; + uint16_t w[4]; + }; uint32_t m_debugger_temp; - bool m_isdrc; + uint16_t m_pc_temp; + uint16_t m_ppc_temp; + uint16_t m_nextpc_temp; devcb_read32 m_dp_reg_r_func; devcb_write32 m_dp_reg_w_func; @@ -242,42 +177,40 @@ private: devcb_write32 m_sp_reg_w_func; devcb_write32 m_sp_set_status_func; - uint8_t READ8(uint32_t address); - uint16_t READ16(uint32_t address); - uint32_t READ32(uint32_t address); - void WRITE8(uint32_t address, uint8_t data); - void WRITE16(uint32_t address, uint16_t data); - void WRITE32(uint32_t address, uint32_t data); + uint8_t read_dmem_byte(uint32_t address); + uint16_t read_dmem_word(uint32_t address); + uint32_t read_dmem_dword(uint32_t address); + void write_dmem_byte(uint32_t address, uint8_t data); + void write_dmem_word(uint32_t address, uint16_t data); + void write_dmem_dword(uint32_t address, uint32_t data); uint32_t get_cop0_reg(int reg); void set_cop0_reg(int reg, uint32_t data); - void load_fast_iregs(drcuml_block &block); - void save_fast_iregs(drcuml_block &block); - uint8_t DM_READ8(uint32_t address); - uint16_t DM_READ16(uint32_t address); - uint32_t DM_READ32(uint32_t address); - void DM_WRITE8(uint32_t address, uint8_t data); - void DM_WRITE16(uint32_t address, uint16_t data); - void DM_WRITE32(uint32_t address, uint32_t data); void rspcom_init(); - void execute_run_drc(); - void code_flush_cache(); - void code_compile_block(offs_t pc); - void static_generate_entry_point(); - void static_generate_nocode_handler(); - void static_generate_out_of_cycles(); - void static_generate_memory_accessor(int size, int iswrite, const char *name, uml::code_handle *&handleptr); - void generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception); - void generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); - void generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); - void generate_delay_slot_and_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t linkreg); - void generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); - bool generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); - bool generate_special(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); - bool generate_regimm(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); - bool generate_cop0(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); - void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op); -}; + // COP2 (vectors) + uint16_t SATURATE_ACCUM(int accum, int slice, uint16_t negative, uint16_t positive); + + uint16_t m_vres[8]; + VECTOR_REG m_v[32]; + ACCUMULATOR_REG m_accum[8]; + uint8_t m_vcarry; + uint8_t m_vcompare; + uint8_t m_vclip1; + uint8_t m_vzero; + uint8_t m_vclip2; + + int32_t m_reciprocal_res; + uint32_t m_reciprocal_high; + int32_t m_dp_allowed; + + void handle_cop2(uint32_t op); + void handle_lwc2(uint32_t op); + void handle_swc2(uint32_t op); + void handle_vector_ops(uint32_t op); + + uint32_t m_div_in; + uint32_t m_div_out; +}; DECLARE_DEVICE_TYPE(RSP, rsp_device) diff --git a/src/devices/cpu/rsp/rsp_dasm.cpp b/src/devices/cpu/rsp/rsp_dasm.cpp index 6db58a28f4a..84647274764 100644 --- a/src/devices/cpu/rsp/rsp_dasm.cpp +++ b/src/devices/cpu/rsp/rsp_dasm.cpp @@ -157,6 +157,8 @@ void rsp_disassembler::disasm_cop2(std::ostream &stream, uint32_t op) case 0x2b: util::stream_format(stream, "vnor %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break; case 0x2c: util::stream_format(stream, "vxor %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break; case 0x2d: util::stream_format(stream, "vnxor %s, %s, %s%s", vreg[dest], vreg[s1], vreg[s2], element[el]); break; + case 0x2e: util::stream_format(stream, "v056 %s, %s[%c]", vreg[dest], vreg[s2], element2[el][s1 & 7]); break; + case 0x2f: util::stream_format(stream, "v057 %s, %s[%c]", vreg[dest], vreg[s2], element2[el][s1 & 7]); break; case 0x30: util::stream_format(stream, "vrcp %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break; case 0x31: util::stream_format(stream, "vrcpl %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break; case 0x32: util::stream_format(stream, "vrcph %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break; @@ -165,6 +167,8 @@ void rsp_disassembler::disasm_cop2(std::ostream &stream, uint32_t op) case 0x35: util::stream_format(stream, "vrsql %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break; case 0x36: util::stream_format(stream, "vrsqh %s[%d], %s[%c]", vreg[dest], s1 & 7, vreg[s2], element2[el][7-(s1 & 7)]); break; case 0x37: util::stream_format(stream, "vnop"); break; + case 0x3b: util::stream_format(stream, "v073 %s, %s[%c]", vreg[dest], vreg[s2], element2[el][s1 & 7]); break; + case 0x3f: util::stream_format(stream, "vnull"); break; default: util::stream_format(stream, "??? (VECTOR OP)"); break; } break; diff --git a/src/devices/cpu/rsp/rspcp2.cpp b/src/devices/cpu/rsp/rspcp2.cpp deleted file mode 100644 index 3180d7103f6..00000000000 --- a/src/devices/cpu/rsp/rspcp2.cpp +++ /dev/null @@ -1,4223 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz,Tyler J. Stachecki -/*************************************************************************** - - rspcp2.c - - Universal machine language-based Nintendo/SGI RSP COP2 emulator. - Written by Ryan Holtz of the MAME team. - -***************************************************************************/ - -#include "emu.h" -#include "rspcp2.h" - -#include "rsp.h" -#include "rspdefs.h" - - -#if USE_SIMD -#include <emmintrin.h> - -const rsp_device::cop2::vec_helpers_t rsp_device::cop2::m_vec_helpers = { - { 0 }, - { // logic_mask - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff } - }, - { // vrsq_mask_table - { 0xffff, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0xffff, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0xffff, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0xffff, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0xffff, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0xffff, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0xffff, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0xffff } - }, - { // shuffle_keys - { 0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e }, /* -- */ - { 0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e }, /* -- */ - - { 0x0100, 0x0100, 0x0504, 0x0504, 0x0908, 0x0908, 0x0d0c, 0x0d0c }, /* 0q */ - { 0x0302, 0x0302, 0x0706, 0x0706, 0x0b0a, 0x0b0a, 0x0f0e, 0x0f0e }, /* 1q */ - - { 0x0100, 0x0100, 0x0100, 0x0100, 0x0908, 0x0908, 0x0908, 0x0908 }, /* 0h */ - { 0x0302, 0x0302, 0x0302, 0x0302, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a }, /* 1h */ - { 0x0504, 0x0504, 0x0504, 0x0504, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c }, /* 2h */ - { 0x0706, 0x0706, 0x0706, 0x0706, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e }, /* 3h */ - - { 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100 }, /* 0w */ - { 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302, 0x0302 }, /* 1w */ - { 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504, 0x0504 }, /* 2w */ - { 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706, 0x0706 }, /* 3w */ - { 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908, 0x0908 }, /* 4w */ - { 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a, 0x0b0a }, /* 5w */ - { 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c, 0x0d0c }, /* 6w */ - { 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e, 0x0f0e } /* 7w */ - }, - { // sll_b2l_keys - { 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c }, - { 0x8003, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d }, - { 0x8080, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e }, - { 0x8080, 0x8003, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f }, - - { 0x8080, 0x8080, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908 }, - { 0x8080, 0x8080, 0x8003, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09 }, - { 0x8080, 0x8080, 0x8080, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a }, - { 0x8080, 0x8080, 0x8080, 0x8003, 0x0201, 0x0007, 0x0605, 0x040b }, - - { 0x8080, 0x8080, 0x8080, 0x8080, 0x0302, 0x0100, 0x0706, 0x0504 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8003, 0x0201, 0x0007, 0x0605 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0302, 0x0100, 0x0706 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8003, 0x0201, 0x0007 }, - - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0302, 0x0100 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8003, 0x0201 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0302 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8003 }, - }, - { // sll_l2b_keys - { 0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a, 0x0d0c, 0x0f0e }, - { 0x0201, 0x8003, 0x0605, 0x0007, 0x0a09, 0x040b, 0x0e0d, 0x080f }, - { 0x0302, 0x8080, 0x0706, 0x0100, 0x0b0a, 0x0504, 0x0f0e, 0x0908 }, - { 0x8003, 0x8080, 0x0007, 0x0201, 0x040b, 0x0605, 0x080f, 0x0a09 }, - - { 0x8080, 0x8080, 0x0100, 0x0302, 0x0504, 0x0706, 0x0908, 0x0b0a }, - { 0x8080, 0x8080, 0x0201, 0x8003, 0x0605, 0x0007, 0x0a09, 0x040b }, - { 0x8080, 0x8080, 0x0302, 0x8080, 0x0706, 0x0100, 0x0b0a, 0x0504 }, - { 0x8080, 0x8080, 0x8003, 0x8080, 0x0007, 0x0201, 0x040b, 0x0605 }, - - { 0x8080, 0x8080, 0x8080, 0x8080, 0x0100, 0x0302, 0x0504, 0x0706 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x0201, 0x8003, 0x0605, 0x0007 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x0302, 0x8080, 0x0706, 0x0100 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8003, 0x8080, 0x0007, 0x0201 }, - - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0100, 0x0302 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0201, 0x8003 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x0302, 0x8080 }, - { 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8003, 0x8080 }, - }, - { // srl_b2l_keys - { 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c }, - { 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c80 }, - { 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x8080 }, - { 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c80, 0x8080 }, - - { 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x8080, 0x8080 }, - { 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c80, 0x8080, 0x8080 }, - { 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x8080, 0x8080, 0x8080 }, - { 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c80, 0x8080, 0x8080, 0x8080 }, - - { 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x8080, 0x8080, 0x8080, 0x8080 }, - { 0x0a09, 0x080f, 0x0e0d, 0x0c80, 0x8080, 0x8080, 0x8080, 0x8080 }, - { 0x0908, 0x0f0e, 0x0d0c, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 }, - { 0x080f, 0x0e0d, 0x0c80, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 }, - - { 0x0f0e, 0x0d0c, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 }, - { 0x0e0d, 0x0c80, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 }, - { 0x0d0c, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 }, - { 0x0c80, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080 }, - }, - { // ror_b2l_keys - { 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c }, - { 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c03 }, - { 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302 }, - { 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c03, 0x0201 }, - - { 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100 }, - { 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c03, 0x0201, 0x0007 }, - { 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706 }, - { 0x040b, 0x0a09, 0x080f, 0x0e0d, 0x0c03, 0x0201, 0x0007, 0x0605 }, - - { 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504 }, - { 0x0a09, 0x080f, 0x0e0d, 0x0c03, 0x0201, 0x0007, 0x0605, 0x040b }, - { 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a }, - { 0x080f, 0x0e0d, 0x0c03, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09 }, - - { 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908 }, - { 0x0e0d, 0x0c03, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f }, - { 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e }, - { 0x0c03, 0x0201, 0x0007, 0x0605, 0x040b, 0x0a09, 0x080f, 0x0e0d }, - }, - { // rol_l2b_keys - { 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c }, - { 0x0003, 0x0e01, 0x0407, 0x0205, 0x080b, 0x0609, 0x0c0f, 0x0a0d }, - { 0x0100, 0x0f0e, 0x0504, 0x0302, 0x0908, 0x0706, 0x0d0c, 0x0b0a }, - { 0x0e01, 0x0c0f, 0x0205, 0x0003, 0x0609, 0x0407, 0x0a0d, 0x080b }, - - { 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908 }, - { 0x0c0f, 0x0a0d, 0x0003, 0x0e01, 0x0407, 0x0205, 0x080b, 0x0609 }, - { 0x0d0c, 0x0b0a, 0x0100, 0x0f0e, 0x0504, 0x0302, 0x0908, 0x0706 }, - { 0x0a0d, 0x080b, 0x0e01, 0x0c0f, 0x0205, 0x0003, 0x0609, 0x0407 }, - - { 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504 }, - { 0x080b, 0x0609, 0x0c0f, 0x0a0d, 0x0003, 0x0e01, 0x0407, 0x0205 }, - { 0x0908, 0x0706, 0x0d0c, 0x0b0a, 0x0100, 0x0f0e, 0x0504, 0x0302 }, - { 0x0609, 0x0407, 0x0a0d, 0x080b, 0x0e01, 0x0c0f, 0x0205, 0x0003 }, - - { 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100 }, - { 0x0407, 0x0205, 0x080b, 0x0609, 0x0c0f, 0x0a0d, 0x0003, 0x0e01 }, - { 0x0504, 0x0302, 0x0908, 0x0706, 0x0d0c, 0x0b0a, 0x0100, 0x0f0e }, - { 0x0205, 0x0003, 0x0609, 0x0407, 0x0a0d, 0x080b, 0x0e01, 0x0c0f }, - }, - { // ror_l2b_keys - { 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c }, - { 0x0205, 0x0003, 0x0609, 0x0407, 0x0a0d, 0x080b, 0x0e01, 0x0c0f }, - { 0x0504, 0x0302, 0x0908, 0x0706, 0x0d0c, 0x0b0a, 0x0100, 0x0f0e }, - { 0x0407, 0x0205, 0x080b, 0x0609, 0x0c0f, 0x0a0d, 0x0003, 0x0e01 }, - - { 0x0706, 0x0504, 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100 }, - { 0x0609, 0x0407, 0x0a0d, 0x080b, 0x0e01, 0x0c0f, 0x0205, 0x0003 }, - { 0x0908, 0x0706, 0x0d0c, 0x0b0a, 0x0100, 0x0f0e, 0x0504, 0x0302 }, - { 0x080b, 0x0609, 0x0c0f, 0x0a0d, 0x0003, 0x0e01, 0x0407, 0x0205 }, - - { 0x0b0a, 0x0908, 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504 }, - { 0x0a0d, 0x080b, 0x0e01, 0x0c0f, 0x0205, 0x0003, 0x0609, 0x0407 }, - { 0x0d0c, 0x0b0a, 0x0100, 0x0f0e, 0x0504, 0x0302, 0x0908, 0x0706 }, - { 0x0c0f, 0x0a0d, 0x0003, 0x0e01, 0x0407, 0x0205, 0x080b, 0x0609 }, - - { 0x0f0e, 0x0d0c, 0x0302, 0x0100, 0x0706, 0x0504, 0x0b0a, 0x0908 }, - { 0x0e01, 0x0c0f, 0x0205, 0x0003, 0x0609, 0x0407, 0x0a0d, 0x080b }, - { 0x0100, 0x0f0e, 0x0504, 0x0302, 0x0908, 0x0706, 0x0d0c, 0x0b0a }, - { 0x0003, 0x0e01, 0x0407, 0x0205, 0x080b, 0x0609, 0x0c0f, 0x0a0d }, - }, - { // qr_lut - { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }, - { 0xffff, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }, - { 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }, - { 0xff00, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff }, - - { 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff}, - { 0x0000, 0x0000, 0xffff, 0xff00, 0xffff, 0xffff, 0xffff, 0xffff }, - { 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff }, - { 0x0000, 0x0000, 0xff00, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff }, - - { 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff }, - { 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xff00, 0xffff, 0xffff }, - { 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0xffff, 0xffff }, - { 0x0000, 0x0000, 0x0000, 0x0000, 0xff00, 0x0000, 0xffff, 0xffff }, - - { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff }, - { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xff00 }, - { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000 }, - { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xff00, 0x0000 } - }, - { // bdls_lut - mask to denote which part of the vector to load/store. - { 0x0000, 0xff00, 0x0000, 0x0000 }, // B - { 0x0000, 0xffff, 0x0000, 0x0000 }, // S - { 0xffff, 0xffff, 0x0000, 0x0000 }, // L - { 0xffff, 0xffff, 0xffff, 0xffff } // D - }, - { // word_reverse - 0x0203, 0x0001, 0x0607, 0x0405, 0x0a0b, 0x0809, 0x0e0f, 0x0c0d - } -}; - -#if !(defined(__SSSE3__) || defined(_MSC_VER)) -// TODO: Highly optimized. More of a stopgap measure. -static inline rsp_vec_t sse2_pshufb(rsp_vec_t v, const uint16_t *keys) -{ - uint8_t dest[16]; - uint8_t temp[16]; - - _mm_storeu_si128((rsp_vec_t *) temp, v); - - for (uint32_t j = 0; j < 8; j++) - { - uint16_t key = keys[j]; - uint8_t key_hi = key >> 8; - uint8_t key_lo = key >> 0; - - dest[(j << 1) + 1] = key_hi == 0x80 ? 0x00 : temp[key_hi]; - dest[(j << 1) + 0] = key_lo == 0x80 ? 0x00 : temp[key_lo]; - } - - return _mm_loadu_si128((rsp_vec_t *) dest); -} - -rsp_vec_t rsp_device::cop2::vec_load_and_shuffle_operand(const uint16_t* src, uint32_t element) -{ - if (element >= 8) // element => 0w ... 7w - { - uint16_t word_lo; - - memcpy(&word_lo, src + (element - 8), sizeof(word_lo)); - uint64_t dword = word_lo | ((uint32_t) word_lo << 16); - - return _mm_shuffle_epi32(_mm_loadl_epi64((rsp_vec_t*) &dword), _MM_SHUFFLE(0,0,0,0)); - } - else if (element >= 4) // element => 0h ... 3h - { - uint16_t word_lo; - uint16_t word_hi; - - memcpy(&word_hi, src + element - 0, sizeof(word_hi)); - memcpy(&word_lo, src + element - 4, sizeof(word_lo)); - uint64_t dword = word_lo | ((uint32_t) word_hi << 16); - - rsp_vec_t v = _mm_loadl_epi64((rsp_vec_t*) &dword); - v = _mm_shufflelo_epi16(v, _MM_SHUFFLE(1,1,0,0)); - return _mm_shuffle_epi32(v, _MM_SHUFFLE(1,1,0,0)); - } - else if (element >= 2) // element => 0q ... 1q - { - rsp_vec_t v = vec_load_unshuffled_operand(src); - - if (element == 2) { - v = _mm_shufflelo_epi16(v, _MM_SHUFFLE(3,3,1,1)); - v = _mm_shufflehi_epi16(v, _MM_SHUFFLE(3,3,1,1)); - } - else - { - v = _mm_shufflelo_epi16(v, _MM_SHUFFLE(2,2,0,0)); - v = _mm_shufflehi_epi16(v, _MM_SHUFFLE(2,2,0,0)); - } - - return v; - } - - return vec_load_unshuffled_operand(src); -} -#else -rsp_vec_t rsp_device::cop2::vec_load_and_shuffle_operand(const uint16_t* src, uint32_t element) -{ - rsp_vec_t operand = _mm_load_si128((rsp_vec_t*) src); - rsp_vec_t key = _mm_load_si128((rsp_vec_t*) m_vec_helpers.shuffle_keys[element]); - - return _mm_shuffle_epi8(operand, key); -} -#endif -// -// SSSE3+ accelerated loads for group I. Byteswap big-endian to 2-byte -// little-endian vector. Start at vector element offset, discarding any -// wraparound as necessary. -// -// TODO: Reverse-engineer what happens when loads to vector elements must -// wraparound. Do we just discard the data, as below, or does the -// data effectively get rotated around the edge of the vector? -// -void rsp_device::cop2::vec_load_group1(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm) -{ - uint32_t offset = addr & 0x7; - uint32_t ror = offset - element; - - // Always load in 8-byte chunks to emulate wraparound. - rsp_vec_t data; - if (offset) { - uint32_t aligned_addr_lo = addr & ~0x7; - uint32_t aligned_addr_hi = (aligned_addr_lo + 8) & 0xFFF; - - data = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_lo)); - rsp_vec_t temp = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_hi)); - data = _mm_unpacklo_epi64(data, temp); - } - else - { - data = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + addr)); - } - - // Shift the DQM up to the point where we mux in the data. -#if !(defined(__SSSE3__) || defined(_MSC_VER)) - dqm = sse2_pshufb(dqm, m_vec_helpers.sll_b2l_keys[element]); -#else - rsp_vec_t ekey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.sll_b2l_keys[element])); - dqm = _mm_shuffle_epi8(dqm, ekey); -#endif - - // Align the data to the DQM so we can mask it in. -#if !(defined(__SSSE3__) || defined(_MSC_VER)) - data = sse2_pshufb(data, m_vec_helpers.ror_b2l_keys[ror & 0xF]); -#else - ekey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.ror_b2l_keys[ror & 0xF])); - data = _mm_shuffle_epi8(data, ekey); -#endif - - // Mask and mux in the data. -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - reg = _mm_blendv_epi8(reg, data, dqm); -#else - data = _mm_and_si128(dqm, data); - reg = _mm_andnot_si128(dqm, reg); - reg = _mm_or_si128(data, reg); -#endif - - _mm_store_si128((rsp_vec_t *) regp, reg); -} - -// -// SSSE3+ accelerated loads for group II. -// -// TODO: Reverse-engineer what happens when loads to vector elements must -// wraparound. Do we just discard the data, as below, or does the -// data effectively get rotated around the edge of the vector? -// -// TODO: Reverse-engineer what happens when element != 0. -// -void rsp_device::cop2::vec_load_group2(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type) { - uint32_t offset = addr & 0x7; - rsp_vec_t data; - - // Always load in 8-byte chunks to emulate wraparound. - if (offset) { - uint32_t aligned_addr_lo = addr & ~0x7; - uint32_t aligned_addr_hi = (aligned_addr_lo + 8) & 0xFFF; - uint64_t datalow, datahigh; - - memcpy(&datalow, m_rsp.get_dmem() + aligned_addr_lo, sizeof(datalow)); - memcpy(&datahigh, m_rsp.get_dmem() + aligned_addr_hi, sizeof(datahigh)); - - // TODO: Test for endian issues? - datahigh >>= ((8 - offset) << 3); - datalow <<= (offset << 3); - datalow = datahigh | datalow; - - data = _mm_loadl_epi64((rsp_vec_t *) &datalow); - } - else - { - data = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + addr)); - } - - // "Unpack" the data. - rsp_vec_t zero = _mm_setzero_si128(); - data = _mm_unpacklo_epi8(zero, data); - - if (request_type != RSP_MEM_REQUEST_PACK) - { - data = _mm_srli_epi16(data, 1); - } - - data = _mm_shufflehi_epi16(data, _MM_SHUFFLE(0, 1, 2, 3)); - data = _mm_shufflelo_epi16(data, _MM_SHUFFLE(0, 1, 2, 3)); - - _mm_store_si128((rsp_vec_t *) regp, data); -} - -// -// SSSE3+ accelerated loads for group IV. Byteswap big-endian to 2-byte -// little-endian vector. Stop loading at quadword boundaries. -// -// TODO: Reverse-engineer what happens when loads from vector elements -// must wraparound (i.e., the address offset is small, starting -// element is large). -// -void rsp_device::cop2::vec_load_group4(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type) -{ - uint32_t aligned_addr = addr & 0xFF0; - uint32_t offset = addr & 0xF; - static uint32_t call_count = 0; - - rsp_vec_t data = _mm_load_si128((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr)); - - uint32_t ror; - if (request_type == RSP_MEM_REQUEST_QUAD) - { - ror = 16 - element + offset; - } - else - { - // TODO: How is this adjusted for LRV when e != 0? - dqm = _mm_cmpeq_epi8(_mm_setzero_si128(), dqm); - ror = 16 - offset; - } - -#if !(defined(__SSSE3__) || defined(_MSC_VER)) - data = sse2_pshufb(data, m_vec_helpers.ror_b2l_keys[ror & 0xF]); - dqm = sse2_pshufb(dqm, m_vec_helpers.ror_b2l_keys[ror & 0xF]); -#else - rsp_vec_t dkey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.ror_b2l_keys[ror & 0xF])); - data = _mm_shuffle_epi8(data, dkey); - dqm = _mm_shuffle_epi8(dqm, dkey); -#endif - - // Mask and mux in the data. -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - data = _mm_blendv_epi8(reg, data, dqm); -#else - data = _mm_and_si128(dqm, data); - reg = _mm_andnot_si128(dqm, reg); - data = _mm_or_si128(data, reg); -#endif - - _mm_store_si128((rsp_vec_t *) regp, data); - - call_count++; -} - -// -// SSE3+ accelerated stores for group I. Byteswap 2-byte little-endian -// vector back to big-endian. Start at vector element offset, wrapping -// around the edge of the vector as necessary. -// -// TODO: Reverse-engineer what happens when stores from vector elements -// must wraparound. Do we just stop storing the data, or do we -// continue storing from the front of the vector, as below? -// -void rsp_device::cop2::vec_store_group1(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm) -{ - uint32_t offset = addr & 0x7; - uint32_t ror = element - offset; - - // Shift the DQM up to the point where we mux in the data. -#if !(defined(__SSSE3__) || defined(_MSC_VER)) - dqm = sse2_pshufb(dqm, m_vec_helpers.sll_l2b_keys[offset]); -#else - rsp_vec_t ekey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.sll_l2b_keys[offset])); - dqm = _mm_shuffle_epi8(dqm, ekey); -#endif - - // Rotate the reg to align with the DQM. -#if !(defined(__SSSE3__) || defined(_MSC_VER)) - reg = sse2_pshufb(reg, m_vec_helpers.ror_l2b_keys[ror & 0xF]); -#else - ekey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.ror_l2b_keys[ror & 0xF])); - reg = _mm_shuffle_epi8(reg, ekey); -#endif - - // Always load in 8-byte chunks to emulate wraparound. - rsp_vec_t data; - if (offset) - { - uint32_t aligned_addr_lo = addr & ~0x7; - uint32_t aligned_addr_hi = (aligned_addr_lo + 8) & 0xFFF; - - data = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_lo)); - rsp_vec_t temp = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_hi)); - data = _mm_unpacklo_epi64(data, temp); - - // Mask and mux in the data. -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - data = _mm_blendv_epi8(data, reg, dqm); -#else - data = _mm_andnot_si128(dqm, data); - reg = _mm_and_si128(dqm, reg); - data = _mm_or_si128(data, reg); -#endif - - _mm_storel_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_lo), data); - - data = _mm_srli_si128(data, 8); - _mm_storel_epi64((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr_hi), data); - } - else - { - data = _mm_loadl_epi64((rsp_vec_t *) (m_rsp.get_dmem() + addr)); - - // Mask and mux in the data. -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - data = _mm_blendv_epi8(data, reg, dqm); -#else - data = _mm_andnot_si128(dqm, data); - reg = _mm_and_si128(dqm, reg); - data = _mm_or_si128(data, reg); -#endif - - _mm_storel_epi64((rsp_vec_t *) (m_rsp.get_dmem() + addr), data); - } -} - -// -// SSE3+ accelerated stores for group II. Byteswap 2-byte little-endian -// vector back to big-endian. Start at vector element offset, wrapping -// around the edge of the vector as necessary. -// -// TODO: Reverse-engineer what happens when stores from vector elements -// must wraparound. Do we just stop storing the data, or do we -// continue storing from the front of the vector, as below? -// -// TODO: Reverse-engineer what happens when element != 0. -// -void rsp_device::cop2::vec_store_group2(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type) { - // "Pack" the data. - if (request_type != RSP_MEM_REQUEST_PACK) - { - reg = _mm_slli_epi16(reg, 1); - } - - reg = _mm_srai_epi16(reg, 8); - reg = _mm_packs_epi16(reg, reg); - -#if !(defined(__SSSE3__) || defined(_MSC_VER)) - reg = sse2_pshufb(reg, m_vec_helpers.word_reverse); -#else - rsp_vec_t dkey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.word_reverse)); - reg = _mm_shuffle_epi8(reg, dkey); -#endif - - // TODO: Always store in 8-byte chunks to emulate wraparound. - _mm_storel_epi64((rsp_vec_t *) (m_rsp.get_dmem() + addr), reg); -} - -// -// SSE3+ accelerated stores for group IV. Byteswap 2-byte little-endian -// vector back to big-endian. Stop storing at quadword boundaries. -// -void rsp_device::cop2::vec_store_group4(uint32_t addr, uint32_t element, uint16_t *regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type) { - uint32_t aligned_addr = addr & 0xFF0; - uint32_t offset = addr & 0xF; - uint32_t rol = offset; - - rsp_vec_t data = _mm_load_si128((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr)); - - if (request_type == RSP_MEM_REQUEST_QUAD) - { - rol -= element; - } - else - { - // TODO: How is this adjusted for SRV when e != 0? - dqm = _mm_cmpeq_epi8(_mm_setzero_si128(), dqm); - } - -#if !(defined(__SSSE3__) || defined(_MSC_VER)) - reg = sse2_pshufb(reg, m_vec_helpers.rol_l2b_keys[rol & 0xF]); -#else - rsp_vec_t ekey = _mm_load_si128((rsp_vec_t *) (m_vec_helpers.rol_l2b_keys[rol & 0xF])); - reg = _mm_shuffle_epi8(reg, ekey); -#endif - - // Mask and mux out the data, write. -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - data = _mm_blendv_epi8(data, reg, dqm); -#else - reg = _mm_and_si128(dqm, reg); - data = _mm_andnot_si128(dqm, data); - data = _mm_or_si128(data, reg); -#endif - - _mm_store_si128((rsp_vec_t *) (m_rsp.get_dmem() + aligned_addr), data); -} -#endif - -/*************************************************************************** - Helpful Defines -***************************************************************************/ - -#define VDREG ((op >> 6) & 0x1f) -#define VS1REG ((op >> 11) & 0x1f) -#define VS2REG ((op >> 16) & 0x1f) -#define EL ((op >> 21) & 0xf) - -#define RSVAL (m_rsp.m_rsp_state->r[RSREG]) -#define RTVAL (m_rsp.m_rsp_state->r[RTREG]) -#define RDVAL (m_rsp.m_rsp_state->r[RDREG]) - -#define VREG_B(reg, offset) m_v[(reg)].b[(offset)^1] -#define VREG_S(reg, offset) m_v[(reg)].s[(offset)] -#define VREG_L(reg, offset) m_v[(reg)].l[(offset)] - -#define R_VREG_B(reg, offset) m_v[(reg)].b[(offset)^1] -#define R_VREG_S(reg, offset) (int16_t)m_v[(reg)].s[(offset)] -#define R_VREG_L(reg, offset) m_v[(reg)].l[(offset)] - -#define W_VREG_B(reg, offset, val) (m_v[(reg)].b[(offset)^1] = val) -#define W_VREG_S(reg, offset, val) (m_v[(reg)].s[(offset)] = val) -#define W_VREG_L(reg, offset, val) (m_v[(reg)].l[(offset)] = val) - -#define VEC_EL_2(x,z) (vector_elements_2[(x)][(z)]) - -#define CARRY 0 -#define COMPARE 1 -#define CLIP1 2 -#define ZERO 3 -#define CLIP2 4 - -#define ACCUM(x) m_accum[x].q -#define ACCUM_H(x) (uint16_t)m_accum[x].w[3] -#define ACCUM_M(x) (uint16_t)m_accum[x].w[2] -#define ACCUM_L(x) (uint16_t)m_accum[x].w[1] -#define ACCUM_LL(x) (uint16_t)m_accum[x].w[0] - -#define SET_ACCUM_H(v, x) m_accum[x].w[3] = v; -#define SET_ACCUM_M(v, x) m_accum[x].w[2] = v; -#define SET_ACCUM_L(v, x) m_accum[x].w[1] = v; -#define SET_ACCUM_LL(v, x) m_accum[x].w[0] = v; - -#define CARRY_FLAG(x) (m_vflag[CARRY][x & 7] != 0 ? 0xffff : 0) -#define COMPARE_FLAG(x) (m_vflag[COMPARE][x & 7] != 0 ? 0xffff : 0) -#define CLIP1_FLAG(x) (m_vflag[CLIP1][x & 7] != 0 ? 0xffff : 0) -#define ZERO_FLAG(x) (m_vflag[ZERO][x & 7] != 0 ? 0xffff : 0) -#define CLIP2_FLAG(x) (m_vflag[CLIP2][x & 7] != 0 ? 0xffff : 0) - -#define CLEAR_CARRY_FLAGS() { memset(m_vflag[CARRY], 0, 16); } -#define CLEAR_COMPARE_FLAGS() { memset(m_vflag[COMPARE], 0, 16); } -#define CLEAR_CLIP1_FLAGS() { memset(m_vflag[CLIP1], 0, 16); } -#define CLEAR_ZERO_FLAGS() { memset(m_vflag[ZERO], 0, 16); } -#define CLEAR_CLIP2_FLAGS() { memset(m_vflag[CLIP2], 0, 16); } - -#define SET_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0xffff; } -#define SET_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0xffff; } -#define SET_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0xffff; } -#define SET_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0xffff; } -#define SET_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0xffff; } - -#define CLEAR_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0; } -#define CLEAR_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0; } -#define CLEAR_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0; } -#define CLEAR_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0; } -#define CLEAR_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0; } - -#define WRITEBACK_RESULT() { \ - VREG_S(VDREG, 0) = m_vres[0]; \ - VREG_S(VDREG, 1) = m_vres[1]; \ - VREG_S(VDREG, 2) = m_vres[2]; \ - VREG_S(VDREG, 3) = m_vres[3]; \ - VREG_S(VDREG, 4) = m_vres[4]; \ - VREG_S(VDREG, 5) = m_vres[5]; \ - VREG_S(VDREG, 6) = m_vres[6]; \ - VREG_S(VDREG, 7) = m_vres[7]; \ -} - -#if !USE_SIMD -static const int vector_elements_2[16][8] = -{ - { 0, 1, 2, 3, 4, 5, 6, 7 }, // none - { 0, 1, 2, 3, 4, 5, 6, 7 }, // ??? - { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q - { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q - { 0, 0, 0, 0, 4, 4, 4, 4 }, // 0h - { 1, 1, 1, 1, 5, 5, 5, 5 }, // 1h - { 2, 2, 2, 2, 6, 6, 6, 6 }, // 2h - { 3, 3, 3, 3, 7, 7, 7, 7 }, // 3h - { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0 - { 1, 1, 1, 1, 1, 1, 1, 1 }, // 1 - { 2, 2, 2, 2, 2, 2, 2, 2 }, // 2 - { 3, 3, 3, 3, 3, 3, 3, 3 }, // 3 - { 4, 4, 4, 4, 4, 4, 4, 4 }, // 4 - { 5, 5, 5, 5, 5, 5, 5, 5 }, // 5 - { 6, 6, 6, 6, 6, 6, 6, 6 }, // 6 - { 7, 7, 7, 7, 7, 7, 7, 7 }, // 7 -}; -#endif - -rsp_device::cop2::cop2(rsp_device &rsp, running_machine &machine) - : m_rsp(rsp) - , m_machine(machine) - , m_reciprocal_res(0) - , m_reciprocal_high(0) - , m_dp_allowed(0) -{ - memset(m_vres, 0, sizeof(m_vres)); - memset(m_v, 0, sizeof(m_v)); - memset(m_vflag, 0, sizeof(m_vflag)); - memset(m_accum, 0, sizeof(m_accum)); -#if USE_SIMD - memset(&m_acc, 0, sizeof(m_acc)); - memset(&m_flags, 0, sizeof(aligned_rsp_2vect_t) * 3); - m_div_out = 0; - m_div_in = 0; -#endif - m_rspcop2_state = (internal_rspcop2_state *)rsp.m_cache.alloc_near(sizeof(internal_rspcop2_state)); -} - -rsp_device::cop2::~cop2() -{ -} - -void rsp_device::cop2::init() -{ - CLEAR_CARRY_FLAGS(); - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP1_FLAGS(); - CLEAR_ZERO_FLAGS(); - CLEAR_CLIP2_FLAGS(); -} - -void rsp_device::cop2::start() -{ - for(auto & elem : m_v) - { - elem.d[0] = 0; - elem.d[1] = 0; - } - - CLEAR_CARRY_FLAGS(); - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP1_FLAGS(); - CLEAR_ZERO_FLAGS(); - CLEAR_CLIP2_FLAGS(); - m_reciprocal_res = 0; - m_reciprocal_high = 0; - - // Accumulators do not power on to a random state - for(auto & elem : m_accum) - { - elem.q = 0; - } -} - -void rsp_device::cop2::state_string_export(const int index, std::string &str) const -{ - switch (index) - { - case RSP_V0: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 0, 0), (uint16_t)VREG_S( 0, 1), (uint16_t)VREG_S( 0, 2), (uint16_t)VREG_S( 0, 3), (uint16_t)VREG_S( 0, 4), (uint16_t)VREG_S( 0, 5), (uint16_t)VREG_S( 0, 6), (uint16_t)VREG_S( 0, 7)); - break; - case RSP_V1: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 1, 0), (uint16_t)VREG_S( 1, 1), (uint16_t)VREG_S( 1, 2), (uint16_t)VREG_S( 1, 3), (uint16_t)VREG_S( 1, 4), (uint16_t)VREG_S( 1, 5), (uint16_t)VREG_S( 1, 6), (uint16_t)VREG_S( 1, 7)); - break; - case RSP_V2: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 2, 0), (uint16_t)VREG_S( 2, 1), (uint16_t)VREG_S( 2, 2), (uint16_t)VREG_S( 2, 3), (uint16_t)VREG_S( 2, 4), (uint16_t)VREG_S( 2, 5), (uint16_t)VREG_S( 2, 6), (uint16_t)VREG_S( 2, 7)); - break; - case RSP_V3: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 3, 0), (uint16_t)VREG_S( 3, 1), (uint16_t)VREG_S( 3, 2), (uint16_t)VREG_S( 3, 3), (uint16_t)VREG_S( 3, 4), (uint16_t)VREG_S( 3, 5), (uint16_t)VREG_S( 3, 6), (uint16_t)VREG_S( 3, 7)); - break; - case RSP_V4: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 4, 0), (uint16_t)VREG_S( 4, 1), (uint16_t)VREG_S( 4, 2), (uint16_t)VREG_S( 4, 3), (uint16_t)VREG_S( 4, 4), (uint16_t)VREG_S( 4, 5), (uint16_t)VREG_S( 4, 6), (uint16_t)VREG_S( 4, 7)); - break; - case RSP_V5: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 5, 0), (uint16_t)VREG_S( 5, 1), (uint16_t)VREG_S( 5, 2), (uint16_t)VREG_S( 5, 3), (uint16_t)VREG_S( 5, 4), (uint16_t)VREG_S( 5, 5), (uint16_t)VREG_S( 5, 6), (uint16_t)VREG_S( 5, 7)); - break; - case RSP_V6: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 6, 0), (uint16_t)VREG_S( 6, 1), (uint16_t)VREG_S( 6, 2), (uint16_t)VREG_S( 6, 3), (uint16_t)VREG_S( 6, 4), (uint16_t)VREG_S( 6, 5), (uint16_t)VREG_S( 6, 6), (uint16_t)VREG_S( 6, 7)); - break; - case RSP_V7: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 7, 0), (uint16_t)VREG_S( 7, 1), (uint16_t)VREG_S( 7, 2), (uint16_t)VREG_S( 7, 3), (uint16_t)VREG_S( 7, 4), (uint16_t)VREG_S( 7, 5), (uint16_t)VREG_S( 7, 6), (uint16_t)VREG_S( 7, 7)); - break; - case RSP_V8: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 8, 0), (uint16_t)VREG_S( 8, 1), (uint16_t)VREG_S( 8, 2), (uint16_t)VREG_S( 8, 3), (uint16_t)VREG_S( 8, 4), (uint16_t)VREG_S( 8, 5), (uint16_t)VREG_S( 8, 6), (uint16_t)VREG_S( 8, 7)); - break; - case RSP_V9: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 9, 0), (uint16_t)VREG_S( 9, 1), (uint16_t)VREG_S( 9, 2), (uint16_t)VREG_S( 9, 3), (uint16_t)VREG_S( 9, 4), (uint16_t)VREG_S( 9, 5), (uint16_t)VREG_S( 9, 6), (uint16_t)VREG_S( 9, 7)); - break; - case RSP_V10: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(10, 0), (uint16_t)VREG_S(10, 1), (uint16_t)VREG_S(10, 2), (uint16_t)VREG_S(10, 3), (uint16_t)VREG_S(10, 4), (uint16_t)VREG_S(10, 5), (uint16_t)VREG_S(10, 6), (uint16_t)VREG_S(10, 7)); - break; - case RSP_V11: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(11, 0), (uint16_t)VREG_S(11, 1), (uint16_t)VREG_S(11, 2), (uint16_t)VREG_S(11, 3), (uint16_t)VREG_S(11, 4), (uint16_t)VREG_S(11, 5), (uint16_t)VREG_S(11, 6), (uint16_t)VREG_S(11, 7)); - break; - case RSP_V12: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(12, 0), (uint16_t)VREG_S(12, 1), (uint16_t)VREG_S(12, 2), (uint16_t)VREG_S(12, 3), (uint16_t)VREG_S(12, 4), (uint16_t)VREG_S(12, 5), (uint16_t)VREG_S(12, 6), (uint16_t)VREG_S(12, 7)); - break; - case RSP_V13: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(13, 0), (uint16_t)VREG_S(13, 1), (uint16_t)VREG_S(13, 2), (uint16_t)VREG_S(13, 3), (uint16_t)VREG_S(13, 4), (uint16_t)VREG_S(13, 5), (uint16_t)VREG_S(13, 6), (uint16_t)VREG_S(13, 7)); - break; - case RSP_V14: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(14, 0), (uint16_t)VREG_S(14, 1), (uint16_t)VREG_S(14, 2), (uint16_t)VREG_S(14, 3), (uint16_t)VREG_S(14, 4), (uint16_t)VREG_S(14, 5), (uint16_t)VREG_S(14, 6), (uint16_t)VREG_S(14, 7)); - break; - case RSP_V15: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(15, 0), (uint16_t)VREG_S(15, 1), (uint16_t)VREG_S(15, 2), (uint16_t)VREG_S(15, 3), (uint16_t)VREG_S(15, 4), (uint16_t)VREG_S(15, 5), (uint16_t)VREG_S(15, 6), (uint16_t)VREG_S(15, 7)); - break; - case RSP_V16: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(16, 0), (uint16_t)VREG_S(16, 1), (uint16_t)VREG_S(16, 2), (uint16_t)VREG_S(16, 3), (uint16_t)VREG_S(16, 4), (uint16_t)VREG_S(16, 5), (uint16_t)VREG_S(16, 6), (uint16_t)VREG_S(16, 7)); - break; - case RSP_V17: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(17, 0), (uint16_t)VREG_S(17, 1), (uint16_t)VREG_S(17, 2), (uint16_t)VREG_S(17, 3), (uint16_t)VREG_S(17, 4), (uint16_t)VREG_S(17, 5), (uint16_t)VREG_S(17, 6), (uint16_t)VREG_S(17, 7)); - break; - case RSP_V18: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(18, 0), (uint16_t)VREG_S(18, 1), (uint16_t)VREG_S(18, 2), (uint16_t)VREG_S(18, 3), (uint16_t)VREG_S(18, 4), (uint16_t)VREG_S(18, 5), (uint16_t)VREG_S(18, 6), (uint16_t)VREG_S(18, 7)); - break; - case RSP_V19: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(19, 0), (uint16_t)VREG_S(19, 1), (uint16_t)VREG_S(19, 2), (uint16_t)VREG_S(19, 3), (uint16_t)VREG_S(19, 4), (uint16_t)VREG_S(19, 5), (uint16_t)VREG_S(19, 6), (uint16_t)VREG_S(19, 7)); - break; - case RSP_V20: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(20, 0), (uint16_t)VREG_S(20, 1), (uint16_t)VREG_S(20, 2), (uint16_t)VREG_S(20, 3), (uint16_t)VREG_S(20, 4), (uint16_t)VREG_S(20, 5), (uint16_t)VREG_S(20, 6), (uint16_t)VREG_S(20, 7)); - break; - case RSP_V21: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(21, 0), (uint16_t)VREG_S(21, 1), (uint16_t)VREG_S(21, 2), (uint16_t)VREG_S(21, 3), (uint16_t)VREG_S(21, 4), (uint16_t)VREG_S(21, 5), (uint16_t)VREG_S(21, 6), (uint16_t)VREG_S(21, 7)); - break; - case RSP_V22: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(22, 0), (uint16_t)VREG_S(22, 1), (uint16_t)VREG_S(22, 2), (uint16_t)VREG_S(22, 3), (uint16_t)VREG_S(22, 4), (uint16_t)VREG_S(22, 5), (uint16_t)VREG_S(22, 6), (uint16_t)VREG_S(22, 7)); - break; - case RSP_V23: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(23, 0), (uint16_t)VREG_S(23, 1), (uint16_t)VREG_S(23, 2), (uint16_t)VREG_S(23, 3), (uint16_t)VREG_S(23, 4), (uint16_t)VREG_S(23, 5), (uint16_t)VREG_S(23, 6), (uint16_t)VREG_S(23, 7)); - break; - case RSP_V24: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(24, 0), (uint16_t)VREG_S(24, 1), (uint16_t)VREG_S(24, 2), (uint16_t)VREG_S(24, 3), (uint16_t)VREG_S(24, 4), (uint16_t)VREG_S(24, 5), (uint16_t)VREG_S(24, 6), (uint16_t)VREG_S(24, 7)); - break; - case RSP_V25: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(25, 0), (uint16_t)VREG_S(25, 1), (uint16_t)VREG_S(25, 2), (uint16_t)VREG_S(25, 3), (uint16_t)VREG_S(25, 4), (uint16_t)VREG_S(25, 5), (uint16_t)VREG_S(25, 6), (uint16_t)VREG_S(25, 7)); - break; - case RSP_V26: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(26, 0), (uint16_t)VREG_S(26, 1), (uint16_t)VREG_S(26, 2), (uint16_t)VREG_S(26, 3), (uint16_t)VREG_S(26, 4), (uint16_t)VREG_S(26, 5), (uint16_t)VREG_S(26, 6), (uint16_t)VREG_S(26, 7)); - break; - case RSP_V27: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(27, 0), (uint16_t)VREG_S(27, 1), (uint16_t)VREG_S(27, 2), (uint16_t)VREG_S(27, 3), (uint16_t)VREG_S(27, 4), (uint16_t)VREG_S(27, 5), (uint16_t)VREG_S(27, 6), (uint16_t)VREG_S(27, 7)); - break; - case RSP_V28: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(28, 0), (uint16_t)VREG_S(28, 1), (uint16_t)VREG_S(28, 2), (uint16_t)VREG_S(28, 3), (uint16_t)VREG_S(28, 4), (uint16_t)VREG_S(28, 5), (uint16_t)VREG_S(28, 6), (uint16_t)VREG_S(28, 7)); - break; - case RSP_V29: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(29, 0), (uint16_t)VREG_S(29, 1), (uint16_t)VREG_S(29, 2), (uint16_t)VREG_S(29, 3), (uint16_t)VREG_S(29, 4), (uint16_t)VREG_S(29, 5), (uint16_t)VREG_S(29, 6), (uint16_t)VREG_S(29, 7)); - break; - case RSP_V30: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(30, 0), (uint16_t)VREG_S(30, 1), (uint16_t)VREG_S(30, 2), (uint16_t)VREG_S(30, 3), (uint16_t)VREG_S(30, 4), (uint16_t)VREG_S(30, 5), (uint16_t)VREG_S(30, 6), (uint16_t)VREG_S(30, 7)); - break; - case RSP_V31: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(31, 0), (uint16_t)VREG_S(31, 1), (uint16_t)VREG_S(31, 2), (uint16_t)VREG_S(31, 3), (uint16_t)VREG_S(31, 4), (uint16_t)VREG_S(31, 5), (uint16_t)VREG_S(31, 6), (uint16_t)VREG_S(31, 7)); - break; - } -} - -/*************************************************************************** - Vector Load Instructions -***************************************************************************/ - -void rsp_device::cop2::handle_lwc2(uint32_t op) -{ - int base = (op >> 21) & 0x1f; -#if !USE_SIMD - int i, end; - uint32_t ea; - int dest = (op >> 16) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - offset |= 0xffffffc0; -#endif - - switch ((op >> 11) & 0x1f) - { - case 0x00: /* LBV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 00000 | IIII | Offset | - // -------------------------------------------------- - // - // Load 1 byte to vector byte index - - //printf("LBV "); -#if USE_SIMD - vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset; - VREG_B(dest, index) = m_rsp.READ8(ea); -#endif - // - break; - } - case 0x01: /* LSV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 00001 | IIII | Offset | - // -------------------------------------------------- - // - // Loads 2 bytes starting from vector byte index - - //printf("LSV "); -#if USE_SIMD - vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 2) : (offset * 2); - - end = index + 2; - - for (i=index; i < end; i++) - { - VREG_B(dest, i) = m_rsp.READ8(ea); - ea++; - } -#endif - // - break; - } - case 0x02: /* LLV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 00010 | IIII | Offset | - // -------------------------------------------------- - // - // Loads 4 bytes starting from vector byte index - - //printf("LLV "); -#if USE_SIMD - vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 4) : (offset * 4); - - end = index + 4; - - for (i=index; i < end; i++) - { - VREG_B(dest, i) = m_rsp.READ8(ea); - ea++; - } -#endif - // - break; - } - case 0x03: /* LDV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 00011 | IIII | Offset | - // -------------------------------------------------- - // - // Loads 8 bytes starting from vector byte index - - //printf("LDV "); -#if USE_SIMD - vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - - end = index + 8; - - for (i=index; i < end; i++) - { - VREG_B(dest, i) = m_rsp.READ8(ea); - ea++; - } -#endif - // - break; - } - case 0x04: /* LQV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 00100 | IIII | Offset | - // -------------------------------------------------- - // - // Loads up to 16 bytes starting from vector byte index - - //printf("LQV "); -#if USE_SIMD - vec_lqrv_sqrv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - end = index + (16 - (ea & 0xf)); - if (end > 16) end = 16; - - for (i=index; i < end; i++) - { - VREG_B(dest, i) = m_rsp.READ8(ea); - ea++; - } -#endif - // - break; - } - case 0x05: /* LRV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 00101 | IIII | Offset | - // -------------------------------------------------- - // - // Stores up to 16 bytes starting from right side until 16-byte boundary - - //printf("LRV "); -#if USE_SIMD - vec_lqrv_sqrv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - index = 16 - ((ea & 0xf) - index); - end = 16; - ea &= ~0xf; - - for (i=index; i < end; i++) - { - VREG_B(dest, i) = m_rsp.READ8(ea); - ea++; - } -#endif - // - break; - } - case 0x06: /* LPV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 00110 | IIII | Offset | - // -------------------------------------------------- - // - // Loads a byte as the upper 8 bits of each element - - //printf("LPV "); -#if USE_SIMD - vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - - for (i=0; i < 8; i++) - { - VREG_S(dest, i) = m_rsp.READ8(ea + (((16-index) + i) & 0xf)) << 8; - } -#endif - // - break; - } - case 0x07: /* LUV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 00111 | IIII | Offset | - // -------------------------------------------------- - // - // Loads a byte as the bits 14-7 of each element - - //printf("LUV "); -#if USE_SIMD - vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - - for (i=0; i < 8; i++) - { - VREG_S(dest, i) = m_rsp.READ8(ea + (((16-index) + i) & 0xf)) << 7; - } -#endif - // - break; - } - case 0x08: /* LHV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 01000 | IIII | Offset | - // -------------------------------------------------- - // - // Loads a byte as the bits 14-7 of each element, with 2-byte stride - - //printf("LHV "); -#if USE_SIMD - vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - for (i=0; i < 8; i++) - { - VREG_S(dest, i) = m_rsp.READ8(ea + (((16-index) + (i<<1)) & 0xf)) << 7; - } -#endif - // - break; - } - case 0x09: /* LFV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 01001 | IIII | Offset | - // -------------------------------------------------- - // - // Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride - - //printf("LFV "); -#if USE_SIMD - vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - // not sure what happens if 16-byte boundary is crossed... - - end = (index >> 1) + 4; - - for (i=index >> 1; i < end; i++) - { - VREG_S(dest, i) = m_rsp.READ8(ea) << 7; - ea += 4; - } -#endif - // - break; - } - case 0x0a: /* LWV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 01010 | IIII | Offset | - // -------------------------------------------------- - // - // Loads the full 128-bit vector starting from vector byte index and wrapping to index 0 - // after byte index 15 - - //printf("LWV "); -#if USE_SIMD -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - end = (16 - index) + 16; - - for (i=(16 - index); i < end; i++) - { - VREG_B(dest, i & 0xf) = m_rsp.READ8(ea); - ea += 4; - } -#endif - // - break; - } - case 0x0b: /* LTV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset | - // -------------------------------------------------- - // - // Loads one element to maximum of 8 vectors, while incrementing element index - - // FIXME: has a small problem with odd indices - - //printf("LTV "); -#if 0 -#else - int32_t index = (op >> 7) & 0xf; - int32_t offset = (op & 0x7f); - if (offset & 0x40) - offset |= 0xffffffc0; - - int32_t vs = (op >> 16) & 0x1f; - int32_t ve = vs + 8; - if (ve > 32) - ve = 32; - - int32_t element; - - if (index & 1) fatalerror("RSP: LTV: index = %d\n", index); - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - ea = ((ea + 8) & ~0xf) + (index & 1); - for (int32_t i = vs; i < ve; i++) - { - element = ((8 - (index >> 1) + (i-vs)) << 1); - VREG_B(i, (element & 0xf)) = m_rsp.READ8(ea); - VREG_B(i, ((element + 1) & 0xf)) = m_rsp.READ8(ea + 1); - - ea += 2; - } -#endif - // - break; - } - - default: - { - m_rsp.unimplemented_opcode(op); - break; - } - } -} - - -/*************************************************************************** - Vector Store Instructions -***************************************************************************/ - -void rsp_device::cop2::handle_swc2(uint32_t op) -{ - int base = (op >> 21) & 0x1f; -#if !USE_SIMD - int i, end; - int eaoffset; - uint32_t ea; - int dest = (op >> 16) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - offset |= 0xffffffc0; -#endif - - switch ((op >> 11) & 0x1f) - { - case 0x00: /* SBV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset | - // -------------------------------------------------- - // - // Stores 1 byte from vector byte index - - //printf("SBV "); -#if USE_SIMD - vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset; - m_rsp.WRITE8(ea, VREG_B(dest, index)); -#endif - // - break; - } - case 0x01: /* SSV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset | - // -------------------------------------------------- - // - // Stores 2 bytes starting from vector byte index - - //printf("SSV "); -#if USE_SIMD - vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 2) : (offset * 2); - - end = index + 2; - - for (i=index; i < end; i++) - { - m_rsp.WRITE8(ea, VREG_B(dest, i)); - ea++; - } -#endif - // - break; - } - case 0x02: /* SLV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset | - // -------------------------------------------------- - // - // Stores 4 bytes starting from vector byte index - - //printf("SLV "); -#if USE_SIMD - vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 4) : (offset * 4); - - end = index + 4; - - for (i=index; i < end; i++) - { - m_rsp.WRITE8(ea, VREG_B(dest, i)); - ea++; - } -#endif - // - break; - } - case 0x03: /* SDV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset | - // -------------------------------------------------- - // - // Stores 8 bytes starting from vector byte index - - //printf("SDV "); -#if USE_SIMD - vec_lbdlsv_sbdlsv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - - end = index + 8; - - for (i=index; i < end; i++) - { - m_rsp.WRITE8(ea, VREG_B(dest, i)); - ea++; - } -#endif - // - break; - } - case 0x04: /* SQV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset | - // -------------------------------------------------- - // - // Stores up to 16 bytes starting from vector byte index until 16-byte boundary - - //printf("SQV "); -#if USE_SIMD - vec_lqrv_sqrv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - end = index + (16 - (ea & 0xf)); - - for (i=index; i < end; i++) - { - m_rsp.WRITE8(ea, VREG_B(dest, i & 0xf)); - ea++; - } -#endif - // - break; - } - case 0x05: /* SRV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset | - // -------------------------------------------------- - // - // Stores up to 16 bytes starting from right side until 16-byte boundary - - //printf("SRV "); -#if USE_SIMD - vec_lqrv_sqrv(op, m_rsp.m_rsp_state->r[base]); -#else - int o; - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - end = index + (ea & 0xf); - o = (16 - (ea & 0xf)) & 0xf; - ea &= ~0xf; - - for (i=index; i < end; i++) - { - m_rsp.WRITE8(ea, VREG_B(dest, ((i + o) & 0xf))); - ea++; - } -#endif - // - break; - } - case 0x06: /* SPV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset | - // -------------------------------------------------- - // - // Stores upper 8 bits of each element - - //printf("SPV "); -#if USE_SIMD - vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - end = index + 8; - - for (i=index; i < end; i++) - { - if ((i & 0xf) < 8) - { - m_rsp.WRITE8(ea, VREG_B(dest, ((i & 0xf) << 1))); - } - else - { - m_rsp.WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7); - } - ea++; - } -#endif - // - break; - } - case 0x07: /* SUV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset | - // -------------------------------------------------- - // - // Stores bits 14-7 of each element - - //printf("SUV "); -#if USE_SIMD - vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - end = index + 8; - - for (i=index; i < end; i++) - { - if ((i & 0xf) < 8) - { - m_rsp.WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7); - } - else - { - m_rsp.WRITE8(ea, VREG_B(dest, ((i & 0x7) << 1))); - } - ea++; - } -#endif - // - break; - } - case 0x08: /* SHV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset | - // -------------------------------------------------- - // - // Stores bits 14-7 of each element, with 2-byte stride - - //printf("SHV "); -#if USE_SIMD - vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - for (i=0; i < 8; i++) - { - uint8_t d = ((VREG_B(dest, ((index + (i << 1) + 0) & 0xf))) << 1) | - ((VREG_B(dest, ((index + (i << 1) + 1) & 0xf))) >> 7); - - m_rsp.WRITE8(ea, d); - ea += 2; - } -#endif - // - break; - } - case 0x09: /* SFV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset | - // -------------------------------------------------- - // - // Stores bits 14-7 of upper or lower quad, with 4-byte stride - - // FIXME: only works for index 0 and index 8 - - //printf("SFV "); -#if USE_SIMD - vec_lfhpuv_sfhpuv(op, m_rsp.m_rsp_state->r[base]); -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - eaoffset = ea & 0xf; - ea &= ~0xf; - - end = (index >> 1) + 4; - - for (i=index >> 1; i < end; i++) - { - m_rsp.WRITE8(ea + (eaoffset & 0xf), VREG_S(dest, i) >> 7); - eaoffset += 4; - } -#endif - // - break; - } - case 0x0a: /* SWV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset | - // -------------------------------------------------- - // - // Stores the full 128-bit vector starting from vector byte index and wrapping to index 0 - // after byte index 15 - - //printf("SWV "); -#if USE_SIMD -#else - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - eaoffset = ea & 0xf; - ea &= ~0xf; - - end = index + 16; - - for (i=index; i < end; i++) - { - m_rsp.WRITE8(ea + (eaoffset & 0xf), VREG_B(dest, i & 0xf)); - eaoffset++; - } -#endif - // - break; - } - case 0x0b: /* STV */ - { - // 31 25 20 15 10 6 0 - // -------------------------------------------------- - // | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset | - // -------------------------------------------------- - // - // Stores one element from maximum of 8 vectors, while incrementing element index - - //printf("STV "); -#if 0 -#else - int32_t index = (op >> 7) & 0xf; - int32_t offset = (op & 0x7f); - if (offset & 0x40) - offset |= 0xffffffc0; - - int32_t vs = (op >> 16) & 0x1f; - int32_t ve = vs + 8; - if (ve > 32) - ve = 32; - - int32_t element = 8 - (index >> 1); - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - int32_t eaoffset = (ea & 0xf) + (element * 2); - ea &= ~0xf; - - for (int32_t i = vs; i < ve; i++) - { - m_rsp.WRITE16(ea + (eaoffset & 0xf), VREG_S(i, element & 0x7)); - eaoffset += 2; - element++; - } -#endif - // - break; - } - - default: - { - m_rsp.unimplemented_opcode(op); - break; - } - } -} - -/*************************************************************************** - Vector Accumulator Helpers -***************************************************************************/ - -uint16_t rsp_device::cop2::SATURATE_ACCUM(int accum, int slice, uint16_t negative, uint16_t positive) -{ - if ((int16_t)ACCUM_H(accum) < 0) - { - if ((uint16_t)(ACCUM_H(accum)) != 0xffff) - { - return negative; - } - else - { - if ((int16_t)ACCUM_M(accum) >= 0) - { - return negative; - } - else - { - if (slice == 0) - { - return ACCUM_L(accum); - } - else if (slice == 1) - { - return ACCUM_M(accum); - } - } - } - } - else - { - if ((uint16_t)(ACCUM_H(accum)) != 0) - { - return positive; - } - else - { - if ((int16_t)ACCUM_M(accum) < 0) - { - return positive; - } - else - { - if (slice == 0) - { - return ACCUM_L(accum); - } - else - { - return ACCUM_M(accum); - } - } - } - } - return 0; -} - - -/*************************************************************************** - Vector Opcodes -***************************************************************************/ - -void rsp_device::cop2::handle_vector_ops(uint32_t op) -{ -#if !USE_SIMD - int i; -#endif - - // Opcode legend: - // E = VS2 element type - // S = VS1, Source vector 1 - // T = VS2, Source vector 2 - // D = Destination vector - - switch (op & 0x3f) - { - case 0x00: /* VMULF */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000000 | - // ------------------------------------------------------ - // - // Multiplies signed integer by signed integer * 2 - - //printf("MULF "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo, acc_mid, acc_hi; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmulf_vmulu(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i=0; i < 8; i++) - { - int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i); - int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - - if (s1 == -32768 && s2 == -32768) - { - // overflow - SET_ACCUM_H(0, i); - SET_ACCUM_M(-32768, i); - SET_ACCUM_L(-32768, i); - m_vres[i] = 0x7fff; - } - else - { - int64_t r = s1 * s2 * 2; - r += 0x8000; // rounding ? - SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit - SET_ACCUM_M((int16_t)(r >> 16), i); - SET_ACCUM_L((uint16_t)(r), i); - m_vres[i] = ACCUM_M(i); - } - } - WRITEBACK_RESULT(); -#endif - // - break; - - } - - case 0x01: /* VMULU */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 | - // ------------------------------------------------------ - // - - //printf("MULU "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo, acc_mid, acc_hi; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmulf_vmulu(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i=0; i < 8; i++) - { - int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i); - int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - - int64_t r = s1 * s2 * 2; - r += 0x8000; // rounding ? - - SET_ACCUM_H((uint16_t)(r >> 32), i); - SET_ACCUM_M((uint16_t)(r >> 16), i); - SET_ACCUM_L((uint16_t)(r), i); - - if (r < 0) - { - m_vres[i] = 0; - } - else if (((int16_t)(ACCUM_H(i)) ^ (int16_t)(ACCUM_M(i))) < 0) - { - m_vres[i] = -1; - } - else - { - m_vres[i] = ACCUM_M(i); - } - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x04: /* VMUDL */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000100 | - // ------------------------------------------------------ - // - // Multiplies unsigned fraction by unsigned fraction - // Stores the higher 16 bits of the 32-bit result to accumulator - // The low slice of accumulator is stored into destination element - - //printf("MUDL "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo, acc_mid, acc_hi; - - acc_lo = read_acc_lo(acc); - acc_mid = read_acc_mid(acc); - acc_hi = read_acc_hi(acc); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmadl_vmudl(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i=0; i < 8; i++) - { - uint32_t s1 = (uint32_t)(uint16_t)VREG_S(VS1REG, i); - uint32_t s2 = (uint32_t)(uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - uint32_t r = s1 * s2; - - SET_ACCUM_H(0, i); - SET_ACCUM_M(0, i); - SET_ACCUM_L((uint16_t)(r >> 16), i); - - m_vres[i] = ACCUM_L(i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x05: /* VMUDM */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000101 | - // ------------------------------------------------------ - // - // Multiplies signed integer by unsigned fraction - // The result is stored into accumulator - // The middle slice of accumulator is stored into destination element - - //printf("MUDM "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo, acc_mid, acc_hi; - - acc_lo = read_acc_lo(acc); - acc_mid = read_acc_mid(acc); - acc_hi = read_acc_hi(acc); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmadm_vmudm(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i=0; i < 8; i++) - { - int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i); - int32_t s2 = (uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); // not sign-extended - int32_t r = s1 * s2; - - SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit - SET_ACCUM_M((int16_t)(r >> 16), i); - SET_ACCUM_L((uint16_t)(r), i); - - m_vres[i] = ACCUM_M(i); - } - WRITEBACK_RESULT(); -#endif - // - break; - - } - - case 0x06: /* VMUDN */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 | - // ------------------------------------------------------ - // - // Multiplies unsigned fraction by signed integer - // The result is stored into accumulator - // The low slice of accumulator is stored into destination element - - //printf("MUDN "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo = read_acc_lo(acc); - rsp_vec_t acc_mid = read_acc_mid(acc); - rsp_vec_t acc_hi = read_acc_hi(acc); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmadn_vmudn(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i=0; i < 8; i++) - { - int32_t s1 = (uint16_t)VREG_S(VS1REG, i); // not sign-extended - int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - int32_t r = s1 * s2; - - SET_ACCUM_H((r < 0) ? 0xffff : 0, i); // sign-extend to 48-bit - SET_ACCUM_M((int16_t)(r >> 16), i); - SET_ACCUM_L((uint16_t)(r), i); - - m_vres[i] = ACCUM_L(i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x07: /* VMUDH */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000111 | - // ------------------------------------------------------ - // - // Multiplies signed integer by signed integer - // The result is stored into highest 32 bits of accumulator, the low slice is zero - // The highest 32 bits of accumulator is saturated into destination element - - //printf("MUDH "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo, acc_mid, acc_hi; - - acc_lo = read_acc_lo(acc); - acc_mid = read_acc_mid(acc); - acc_hi = read_acc_hi(acc); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmadh_vmudh(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i=0; i < 8; i++) - { - int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i); - int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - int32_t r = s1 * s2; - - SET_ACCUM_H((int16_t)(r >> 16), i); - SET_ACCUM_M((uint16_t)(r), i); - SET_ACCUM_L(0, i); - - if (r < -32768) r = -32768; - if (r > 32767) r = 32767; - m_vres[i] = (int16_t)(r); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x08: /* VMACF */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001000 | - // ------------------------------------------------------ - // - // Multiplies signed integer by signed integer * 2 - // The result is added to accumulator - - //printf("MACF "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo, acc_mid, acc_hi; - - acc_lo = read_acc_lo(acc); - acc_mid = read_acc_mid(acc); - acc_hi = read_acc_hi(acc); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmacf_vmacu(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i=0; i < 8; i++) - { - int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i); - int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - int32_t r = s1 * s2; - - uint64_t q = (uint64_t)(uint16_t)ACCUM_LL(i); - q |= (((uint64_t)(uint16_t)ACCUM_L(i)) << 16); - q |= (((uint64_t)(uint16_t)ACCUM_M(i)) << 32); - q |= (((uint64_t)(uint16_t)ACCUM_H(i)) << 48); - - q += (int64_t)(r) << 17; - - SET_ACCUM_LL((uint16_t)q, i); - SET_ACCUM_L((uint16_t)(q >> 16), i); - SET_ACCUM_M((uint16_t)(q >> 32), i); - SET_ACCUM_H((uint16_t)(q >> 48), i); - - m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - case 0x09: /* VMACU */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 | - // ------------------------------------------------------ - // - - //printf("MACU "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo, acc_mid, acc_hi; - - acc_lo = read_acc_lo(acc); - acc_mid = read_acc_mid(acc); - acc_hi = read_acc_hi(acc); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmacf_vmacu(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i = 0; i < 8; i++) - { - int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i); - int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - int32_t r1 = s1 * s2; - uint32_t r2 = (uint16_t)ACCUM_L(i) + ((uint16_t)(r1) * 2); - uint32_t r3 = (uint16_t)ACCUM_M(i) + (uint16_t)((r1 >> 16) * 2) + (uint16_t)(r2 >> 16); - - SET_ACCUM_L((uint16_t)(r2), i); - SET_ACCUM_M((uint16_t)(r3), i); - SET_ACCUM_H(ACCUM_H(i) + (uint16_t)(r3 >> 16) + (uint16_t)(r1 >> 31), i); - - if ((int16_t)ACCUM_H(i) < 0) - { - m_vres[i] = 0; - } - else - { - if (ACCUM_H(i) != 0) - { - m_vres[i] = 0xffff; - } - else - { - if ((int16_t)ACCUM_M(i) < 0) - { - m_vres[i] = 0xffff; - } - else - { - m_vres[i] = ACCUM_M(i); - } - } - } - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x0c: /* VMADL */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001100 | - // ------------------------------------------------------ - // - // Multiplies unsigned fraction by unsigned fraction - // Adds the higher 16 bits of the 32-bit result to accumulator - // The low slice of accumulator is stored into destination element - - //printf("MADL "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo, acc_mid, acc_hi; - - acc_lo = read_acc_lo(acc); - acc_mid = read_acc_mid(acc); - acc_hi = read_acc_hi(acc); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmadl_vmudl(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i = 0; i < 8; i++) - { - uint32_t s1 = (uint32_t)(uint16_t)VREG_S(VS1REG, i); - uint32_t s2 = (uint32_t)(uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - uint32_t r1 = s1 * s2; - uint32_t r2 = (uint16_t)ACCUM_L(i) + (r1 >> 16); - uint32_t r3 = (uint16_t)ACCUM_M(i) + (r2 >> 16); - - SET_ACCUM_L((uint16_t)(r2), i); - SET_ACCUM_M((uint16_t)(r3), i); - SET_ACCUM_H(ACCUM_H(i) + (int16_t)(r3 >> 16), i); - - m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x0d: /* VMADM */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 | - // ------------------------------------------------------ - // - // Multiplies signed integer by unsigned fraction - // The result is added into accumulator - // The middle slice of accumulator is stored into destination element - - //printf("MADM "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo, acc_mid, acc_hi; - - acc_lo = read_acc_lo(acc); - acc_mid = read_acc_mid(acc); - acc_hi = read_acc_hi(acc); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmadm_vmudm(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i=0; i < 8; i++) - { - uint32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i); - uint32_t s2 = (uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); // not sign-extended - uint32_t r1 = s1 * s2; - uint32_t r2 = (uint16_t)ACCUM_L(i) + (uint16_t)(r1); - uint32_t r3 = (uint16_t)ACCUM_M(i) + (r1 >> 16) + (r2 >> 16); - - SET_ACCUM_L((uint16_t)(r2), i); - SET_ACCUM_M((uint16_t)(r3), i); - SET_ACCUM_H(ACCUM_H(i) + (uint16_t)(r3 >> 16), i); - if ((int32_t)(r1) < 0) - SET_ACCUM_H(ACCUM_H(i) - 1, i); - - m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x0e: /* VMADN */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001110 | - // ------------------------------------------------------ - // - // Multiplies unsigned fraction by signed integer - // The result is added into accumulator - // The low slice of accumulator is stored into destination element - - //printf("MADN "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo, acc_mid, acc_hi; - - acc_lo = read_acc_lo(acc); - acc_mid = read_acc_mid(acc); - acc_hi = read_acc_hi(acc); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmadn_vmudn(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i=0; i < 8; i++) - { - int32_t s1 = (uint16_t)VREG_S(VS1REG, i); // not sign-extended - int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - - uint64_t q = (uint64_t)ACCUM_LL(i); - q |= (((uint64_t)ACCUM_L(i)) << 16); - q |= (((uint64_t)ACCUM_M(i)) << 32); - q |= (((uint64_t)ACCUM_H(i)) << 48); - q += (int64_t)(s1*s2) << 16; - - SET_ACCUM_LL((uint16_t)q, i); - SET_ACCUM_L((uint16_t)(q >> 16), i); - SET_ACCUM_M((uint16_t)(q >> 32), i); - SET_ACCUM_H((uint16_t)(q >> 48), i); - - m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff); - } - WRITEBACK_RESULT(); - -#endif - // - break; - } - - case 0x0f: /* VMADH */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001111 | - // ------------------------------------------------------ - // - // Multiplies signed integer by signed integer - // The result is added into highest 32 bits of accumulator, the low slice is zero - // The highest 32 bits of accumulator is saturated into destination element - - //printf("MADH "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t acc_lo, acc_mid, acc_hi; - - acc_lo = read_acc_lo(acc); - acc_mid = read_acc_mid(acc); - acc_hi = read_acc_hi(acc); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmadh_vmudh(op, vs, vt_shuffle, vec_zero(), &acc_lo, &acc_mid, &acc_hi); - - write_acc_lo(acc, acc_lo); - write_acc_mid(acc, acc_mid); - write_acc_hi(acc, acc_hi); -#else - for (i = 0; i < 8; i++) - { - int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i); - int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - - int32_t accum = (uint32_t)(uint16_t)ACCUM_M(i); - accum |= ((uint32_t)((uint16_t)ACCUM_H(i))) << 16; - accum += s1 * s2; - - SET_ACCUM_H((uint16_t)(accum >> 16), i); - SET_ACCUM_M((uint16_t)accum, i); - - m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff); - } - WRITEBACK_RESULT(); - -#endif - // - break; - } - - case 0x10: /* VADD */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010000 | - // ------------------------------------------------------ - // - // Adds two vector registers and carry flag, the result is saturated to 32767 - - // TODO: check VS2REG == VDREG - - //printf("ADD "); -#if USE_SIMD - rsp_vec_t acc_lo; - uint16_t *acc = m_acc.s; - rsp_vec_t carry = read_vco_lo(m_flags[RSP_VCO].s); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vadd(vs, vt_shuffle, carry, &acc_lo); - - write_vco_hi(m_flags[RSP_VCO].s, vec_zero()); - write_vco_lo(m_flags[RSP_VCO].s, vec_zero()); - write_acc_lo(acc, acc_lo); -#else - for (i=0; i < 8; i++) - { - int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i); - int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - int32_t r = s1 + s2 + (CARRY_FLAG(i) != 0 ? 1 : 0); - - SET_ACCUM_L((int16_t)(r), i); - - if (r > 32767) r = 32767; - if (r < -32768) r = -32768; - m_vres[i] = (int16_t)(r); - } - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x11: /* VSUB */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010001 | - // ------------------------------------------------------ - // - // Subtracts two vector registers and carry flag, the result is saturated to -32768 - - // TODO: check VS2REG == VDREG - - //printf("SUB "); -#if USE_SIMD - rsp_vec_t acc_lo; - uint16_t *acc = m_acc.s; - rsp_vec_t carry = read_vco_lo(m_flags[RSP_VCO].s); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vsub(vs, vt_shuffle, carry, &acc_lo); - - write_vco_hi(m_flags[RSP_VCO].s, vec_zero()); - write_vco_lo(m_flags[RSP_VCO].s, vec_zero()); - write_acc_lo(acc, acc_lo); -#else - for (i = 0; i < 8; i++) - { - int32_t s1 = (int32_t)(int16_t)VREG_S(VS1REG, i); - int32_t s2 = (int32_t)(int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - int32_t r = s1 - s2 - (CARRY_FLAG(i) != 0 ? 1 : 0); - - SET_ACCUM_L((int16_t)(r), i); - - if (r > 32767) r = 32767; - if (r < -32768) r = -32768; - - m_vres[i] = (int16_t)(r); - } - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x13: /* VABS */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010011 | - // ------------------------------------------------------ - // - // Changes the sign of source register 2 if source register 1 is negative and stores - // the result to destination register - - //printf("ABS "); -#if USE_SIMD - rsp_vec_t acc_lo; - uint16_t *acc = m_acc.s; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vabs(vs, vt_shuffle, vec_zero(), &acc_lo); - - write_acc_lo(acc, acc_lo); -#else - for (i=0; i < 8; i++) - { - int16_t s1 = (int16_t)VREG_S(VS1REG, i); - int16_t s2 = (int16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - - if (s1 < 0) - { - if (s2 == -32768) - { - m_vres[i] = 32767; - } - else - { - m_vres[i] = -s2; - } - } - else if (s1 > 0) - { - m_vres[i] = s2; - } - else - { - m_vres[i] = 0; - } - - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x14: /* VADDC */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010100 | - // ------------------------------------------------------ - // - // Adds two vector registers, the carry out is stored into carry register - - // TODO: check VS2REG = VDREG - - //printf("ADDC "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t sn; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vaddc(vs, vt_shuffle, vec_zero(), &sn); - - write_vco_hi(m_flags[RSP_VCO].s, vec_zero()); - write_vco_lo(m_flags[RSP_VCO].s, sn); - write_acc_lo(acc, m_v[VDREG].v); -#else - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - - for (i=0; i < 8; i++) - { - int32_t s1 = (uint32_t)(uint16_t)VREG_S(VS1REG, i); - int32_t s2 = (uint32_t)(uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - int32_t r = s1 + s2; - - m_vres[i] = (int16_t)(r); - SET_ACCUM_L((int16_t)(r), i); - - if (r & 0xffff0000) - { - SET_CARRY_FLAG(i); - } - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x15: /* VSUBC */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010101 | - // ------------------------------------------------------ - // - // Subtracts two vector registers, the carry out is stored into carry register - - // TODO: check VS2REG = VDREG - - //printf("SUBC "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t eq, sn; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vsubc(vs, vt_shuffle, vec_zero(), &eq, &sn); - - write_vco_hi(m_flags[RSP_VCO].s, eq); - write_vco_lo(m_flags[RSP_VCO].s, sn); - write_acc_lo(acc, m_v[VDREG].v); -#else - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - - for (i=0; i < 8; i++) - { - int32_t s1 = (uint32_t)(uint16_t)VREG_S(VS1REG, i); - int32_t s2 = (uint32_t)(uint16_t)VREG_S(VS2REG, VEC_EL_2(EL, i)); - int32_t r = s1 - s2; - - m_vres[i] = (int16_t)(r); - SET_ACCUM_L((uint16_t)(r), i); - - if ((uint16_t)(r) != 0) - { - SET_ZERO_FLAG(i); - } - if (r & 0xffff0000) - { - SET_CARRY_FLAG(i); - } - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x1d: /* VSAW */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 011101 | - // ------------------------------------------------------ - // - // Stores high, middle or low slice of accumulator to destination vector - - //printf("SAW "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - switch (EL) - { - case 8: - m_v[VDREG].v = read_acc_hi(acc); - break; - case 9: - m_v[VDREG].v = read_acc_mid(acc); - break; - case 10: - m_v[VDREG].v = read_acc_lo(acc); - break; - - default: - m_v[VDREG].v = _mm_setzero_si128(); - break; - } -#else - switch (EL) - { - case 0x08: // VSAWH - { - for (i=0; i < 8; i++) - { - VREG_S(VDREG, i) = ACCUM_H(i); - } - break; - } - case 0x09: // VSAWM - { - for (i=0; i < 8; i++) - { - VREG_S(VDREG, i) = ACCUM_M(i); - } - break; - } - case 0x0a: // VSAWL - { - for (i=0; i < 8; i++) - { - VREG_S(VDREG, i) = ACCUM_L(i); - } - break; - } - default: //fatalerror("RSP: VSAW: el = %d\n", EL);//??????? - printf("RSP: VSAW: el = %d\n", EL);//??? ??? - exit(0); - } -#endif - // - break; - } - - case 0x20: /* VLT */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100000 | - // ------------------------------------------------------ - // - // Sets compare flags if elements in VS1 are less than VS2 - // Moves the element in VS2 to destination vector - - //printf("LT "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t le; - - rsp_vec_t eq = read_vco_hi(m_flags[RSP_VCO].s); - rsp_vec_t sign = read_vco_lo(m_flags[RSP_VCO].s); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_veq_vge_vlt_vne(op, vs, vt_shuffle, vec_zero(), &le, eq, sign); - - write_vcc_hi(m_flags[RSP_VCC].s, vec_zero()); - write_vcc_lo(m_flags[RSP_VCC].s, le); - write_vco_hi(m_flags[RSP_VCO].s, vec_zero()); - write_vco_lo(m_flags[RSP_VCO].s, vec_zero()); - write_acc_lo(acc, m_v[VDREG].v); -#else - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP2_FLAGS(); - - for (i=0; i < 8; i++) - { - int16_t s1, s2; - s1 = VREG_S(VS1REG, i); - s2 = VREG_S(VS2REG, VEC_EL_2(EL, i)); - if (s1 < s2) - { - SET_COMPARE_FLAG(i); - } - else if (s1 == s2) - { - if (ZERO_FLAG(i) != 0 && CARRY_FLAG(i) != 0) - { - SET_COMPARE_FLAG(i); - } - } - - if (COMPARE_FLAG(i) != 0) - { - m_vres[i] = s1; - } - else - { - m_vres[i] = s2; - } - - SET_ACCUM_L(m_vres[i], i); - } - - CLEAR_CARRY_FLAGS(); - CLEAR_ZERO_FLAGS(); - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x21: /* VEQ */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100001 | - // ------------------------------------------------------ - // - // Sets compare flags if elements in VS1 are equal with VS2 - // Moves the element in VS2 to destination vector - - //printf("EQ "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t le; - - rsp_vec_t eq = read_vco_hi(m_flags[RSP_VCO].s); - rsp_vec_t sign = read_vco_lo(m_flags[RSP_VCO].s); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_veq_vge_vlt_vne(op, vs, vt_shuffle, vec_zero(), &le, eq, sign); - - write_vcc_hi(m_flags[RSP_VCC].s, vec_zero()); - write_vcc_lo(m_flags[RSP_VCC].s, le); - write_vco_hi(m_flags[RSP_VCO].s, vec_zero()); - write_vco_lo(m_flags[RSP_VCO].s, vec_zero()); - write_acc_lo(acc, m_v[VDREG].v); -#else - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP2_FLAGS(); - - for (i = 0; i < 8; i++) - { - int16_t s1 = VREG_S(VS1REG, i); - int16_t s2 = VREG_S(VS2REG, VEC_EL_2(EL, i)); - - if ((s1 == s2) && ZERO_FLAG(i) == 0) - { - SET_COMPARE_FLAG(i); - m_vres[i] = s1; - } - else - { - m_vres[i] = s2; - } - SET_ACCUM_L(m_vres[i], i); - } - - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x22: /* VNE */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100010 | - // ------------------------------------------------------ - // - // Sets compare flags if elements in VS1 are not equal with VS2 - // Moves the element in VS2 to destination vector - - //printf("NE "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t le; - - rsp_vec_t eq = read_vco_hi(m_flags[RSP_VCO].s); - rsp_vec_t sign = read_vco_lo(m_flags[RSP_VCO].s); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_veq_vge_vlt_vne(op, vs, vt_shuffle, vec_zero(), &le, eq, sign); - - write_vcc_hi(m_flags[RSP_VCC].s, vec_zero()); - write_vcc_lo(m_flags[RSP_VCC].s, le); - write_vco_hi(m_flags[RSP_VCO].s, vec_zero()); - write_vco_lo(m_flags[RSP_VCO].s, vec_zero()); - write_acc_lo(acc, m_v[VDREG].v); -#else - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP2_FLAGS(); - - for (i = 0; i < 8; i++) - { - int16_t s1 = VREG_S(VS1REG, i); - int16_t s2 = VREG_S(VS2REG, VEC_EL_2(EL, i)); - - if (s1 != s2 || ZERO_FLAG(i) != 0) - { - SET_COMPARE_FLAG(i); - m_vres[i] = s1; - } - else - { - m_vres[i] = s2; - } - - SET_ACCUM_L(m_vres[i], i); - } - - CLEAR_CARRY_FLAGS(); - CLEAR_ZERO_FLAGS(); - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x23: /* VGE */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100011 | - // ------------------------------------------------------ - // - // Sets compare flags if elements in VS1 are greater or equal with VS2 - // Moves the element in VS2 to destination vector - - //printf("GE "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t le; - - rsp_vec_t eq = read_vco_hi(m_flags[RSP_VCO].s); - rsp_vec_t sign = read_vco_lo(m_flags[RSP_VCO].s); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_veq_vge_vlt_vne(op, vs, vt_shuffle, vec_zero(), &le, eq, sign); - - write_vcc_hi(m_flags[RSP_VCC].s, vec_zero()); - write_vcc_lo(m_flags[RSP_VCC].s, le); - write_vco_hi(m_flags[RSP_VCO].s, vec_zero()); - write_vco_lo(m_flags[RSP_VCO].s, vec_zero()); - write_acc_lo(acc, m_v[VDREG].v); -#else - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP2_FLAGS(); - - for (i=0; i < 8; i++) - { - int16_t s1 = VREG_S(VS1REG, i); - int16_t s2 = VREG_S(VS2REG, VEC_EL_2(EL, i)); - - if ((s1 == s2 && (ZERO_FLAG(i) == 0 || CARRY_FLAG(i) == 0)) || s1 > s2) - { - SET_COMPARE_FLAG(i); - m_vres[i] = s1; - } - else - { - m_vres[i] = s2; - } - - SET_ACCUM_L(m_vres[i], i); - } - - CLEAR_CARRY_FLAGS(); - CLEAR_ZERO_FLAGS(); - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x24: /* VCL */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 | - // ------------------------------------------------------ - // - // Vector clip low - - //printf("CL "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - - rsp_vec_t ge = read_vcc_hi(m_flags[RSP_VCC].s); - rsp_vec_t le = read_vcc_lo(m_flags[RSP_VCC].s); - rsp_vec_t eq = read_vco_hi(m_flags[RSP_VCO].s); - rsp_vec_t sign = read_vco_lo(m_flags[RSP_VCO].s); - rsp_vec_t vce = read_vce(m_flags[RSP_VCE].s); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - m_v[VDREG].v = vec_vcl(vs, vt_shuffle, vec_zero(), &ge, &le, eq, sign, vce); - - write_vcc_hi(m_flags[RSP_VCC].s, ge); - write_vcc_lo(m_flags[RSP_VCC].s, le); - write_vco_hi(m_flags[RSP_VCO].s, vec_zero()); - write_vco_lo(m_flags[RSP_VCO].s, vec_zero()); - write_vce(m_flags[RSP_VCE].s, vec_zero()); - write_acc_lo(acc, m_v[VDREG].v); -#else - for (i = 0; i < 8; i++) - { - int16_t s1 = VREG_S(VS1REG, i); - int16_t s2 = VREG_S(VS2REG, VEC_EL_2(EL, i)); - - if (CARRY_FLAG(i) != 0) // vco_lo - { - if (ZERO_FLAG(i) != 0) // vco_hi - { - if (COMPARE_FLAG(i) != 0) // vcc_lo - { - SET_ACCUM_L(-(uint16_t)s2, i); - } - else - { - SET_ACCUM_L(s1, i); - } - } - else - { - if (CLIP1_FLAG(i) != 0) // vce - { - if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) > 0x10000) - { - SET_ACCUM_L(s1, i); - CLEAR_COMPARE_FLAG(i); - } - else - { - SET_ACCUM_L(-((uint16_t)s2), i); - SET_COMPARE_FLAG(i); - } - } - else - { - if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) != 0) - { - SET_ACCUM_L(s1, i); - CLEAR_COMPARE_FLAG(i); - } - else - { - SET_ACCUM_L(-((uint16_t)s2), i); - SET_COMPARE_FLAG(i); - } - } - } - } - else - { - if (ZERO_FLAG(i) != 0) // vco_hi - { - if (CLIP2_FLAG(i) != 0) // vcc_hi - { - SET_ACCUM_L(s2, i); - } - else - { - SET_ACCUM_L(s1, i); - } - } - else - { - if (((int32_t)(uint16_t)s1 - (int32_t)(uint16_t)s2) >= 0) - { - SET_ACCUM_L(s2, i); - SET_CLIP2_FLAG(i); - } - else - { - SET_ACCUM_L(s1, i); - CLEAR_CLIP2_FLAG(i); - } - } - } - - m_vres[i] = ACCUM_L(i); - } - CLEAR_CARRY_FLAGS(); // vco_lo - CLEAR_ZERO_FLAGS(); // vco_hi - CLEAR_CLIP1_FLAGS(); // vce - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x25: /* VCH */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 | - // ------------------------------------------------------ - // - // Vector clip high - - //printf("CH "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t ge, le, sign, eq, vce; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vch(vs, vt_shuffle, vec_zero(), &ge, &le, &eq, &sign, &vce); - - write_vcc_hi(m_flags[RSP_VCC].s, ge); - write_vcc_lo(m_flags[RSP_VCC].s, le); - write_vco_hi(m_flags[RSP_VCO].s, eq); - write_vco_lo(m_flags[RSP_VCO].s, sign); - write_vce(m_flags[RSP_VCE].s, vce); - write_acc_lo(acc, m_v[VDREG].v); -#else - CLEAR_CARRY_FLAGS(); - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP1_FLAGS(); - CLEAR_ZERO_FLAGS(); - CLEAR_CLIP2_FLAGS(); - uint32_t vce; - - for (i=0; i < 8; i++) - { - int16_t s1 = VREG_S(VS1REG, i); - int16_t s2 = VREG_S(VS2REG, VEC_EL_2(EL, i)); - - if ((s1 ^ s2) < 0) - { - vce = (s1 + s2 == -1); - SET_CARRY_FLAG(i); - if (s2 < 0) - { - SET_CLIP2_FLAG(i); - } - - if (s1 + s2 <= 0) - { - SET_COMPARE_FLAG(i); - m_vres[i] = -((uint16_t)s2); - } - else - { - m_vres[i] = s1; - } - - if (s1 + s2 != 0) - { - if (s1 != ~s2) - { - SET_ZERO_FLAG(i); - } - } - } - else - { - vce = 0; - if (s2 < 0) - { - SET_COMPARE_FLAG(i); - } - if (s1 - s2 >= 0) - { - SET_CLIP2_FLAG(i); - m_vres[i] = s2; - } - else - { - m_vres[i] = s1; - } - - if ((s1 - s2) != 0) - { - if (s1 != ~s2) - { - SET_ZERO_FLAG(i); - } - } - } - if (vce != 0) - { - SET_CLIP1_FLAG(i); - } - - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x26: /* VCR */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 | - // ------------------------------------------------------ - // - // Vector clip reverse - - //printf("CR "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t ge, le; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vcr(vs, vt_shuffle, vec_zero(), &ge, &le); - - write_vcc_hi(m_flags[RSP_VCC].s, ge); - write_vcc_lo(m_flags[RSP_VCC].s, le); - write_vco_hi(m_flags[RSP_VCO].s, vec_zero()); - write_vco_lo(m_flags[RSP_VCO].s, vec_zero()); - write_vce(m_flags[RSP_VCE].s, vec_zero()); - write_acc_lo(acc, m_v[VDREG].v); -#else - CLEAR_CARRY_FLAGS(); - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP1_FLAGS(); - CLEAR_ZERO_FLAGS(); - CLEAR_CLIP2_FLAGS(); - - for (i=0; i < 8; i++) - { - int16_t s1 = VREG_S(VS1REG, i); - int16_t s2 = VREG_S(VS2REG, VEC_EL_2(EL, i)); - - if ((int16_t)(s1 ^ s2) < 0) - { - if (s2 < 0) - { - SET_CLIP2_FLAG(i); - } - if ((s1 + s2) <= 0) - { - SET_ACCUM_L(~((uint16_t)s2), i); - SET_COMPARE_FLAG(i); - } - else - { - SET_ACCUM_L(s1, i); - } - } - else - { - if (s2 < 0) - { - SET_COMPARE_FLAG(i); - } - if ((s1 - s2) >= 0) - { - SET_ACCUM_L(s2, i); - SET_CLIP2_FLAG(i); - } - else - { - SET_ACCUM_L(s1, i); - } - } - - m_vres[i] = ACCUM_L(i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x27: /* VMRG */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100111 | - // ------------------------------------------------------ - // - // Merges two vectors according to compare flags - - //printf("MRG "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - rsp_vec_t le = read_vcc_lo(m_flags[RSP_VCC].s); - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vmrg(vs, vt_shuffle, le); - - write_vco_hi(m_flags[RSP_VCO].s, vec_zero()); - write_vco_lo(m_flags[RSP_VCO].s, vec_zero()); - write_acc_lo(acc, m_v[VDREG].v); -#else - for (i = 0; i < 8; i++) - { - if (COMPARE_FLAG(i) != 0) - { - m_vres[i] = VREG_S(VS1REG, i); - } - else - { - m_vres[i] = VREG_S(VS2REG, VEC_EL_2(EL, i)); - } - - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - case 0x28: /* VAND */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 | - // ------------------------------------------------------ - // - // Bitwise AND of two vector registers - - //printf("AND "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vand_vnand(op, vs, vt_shuffle); - - write_acc_lo(acc, m_v[VDREG].v); -#else - for (i = 0; i < 8; i++) - { - m_vres[i] = VREG_S(VS1REG, i) & VREG_S(VS2REG, VEC_EL_2(EL, i)); - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - case 0x29: /* VNAND */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101001 | - // ------------------------------------------------------ - // - // Bitwise NOT AND of two vector registers - - //printf("NAND "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vand_vnand(op, vs, vt_shuffle); - - write_acc_lo(acc, m_v[VDREG].v); -#else - for (i = 0; i < 8; i++) - { - m_vres[i] = ~((VREG_S(VS1REG, i) & VREG_S(VS2REG, VEC_EL_2(EL, i)))); - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - case 0x2a: /* VOR */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101010 | - // ------------------------------------------------------ - // - // Bitwise OR of two vector registers - - //printf("OR "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vor_vnor(op, vs, vt_shuffle); - - write_acc_lo(acc, m_v[VDREG].v); -#else - for (i = 0; i < 8; i++) - { - m_vres[i] = VREG_S(VS1REG, i) | VREG_S(VS2REG, VEC_EL_2(EL, i)); - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - case 0x2b: /* VNOR */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101011 | - // ------------------------------------------------------ - // - // Bitwise NOT OR of two vector registers - - //printf("NOR "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vor_vnor(op, vs, vt_shuffle); - - write_acc_lo(acc, m_v[VDREG].v); -#else - for (i=0; i < 8; i++) - { - m_vres[i] = ~((VREG_S(VS1REG, i) | VREG_S(VS2REG, VEC_EL_2(EL, i)))); - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - case 0x2c: /* VXOR */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101100 | - // ------------------------------------------------------ - // - // Bitwise XOR of two vector registers - - //printf("XOR "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vxor_vnxor(op, vs, vt_shuffle); - - write_acc_lo(acc, m_v[VDREG].v); -#else - for (i=0; i < 8; i++) - { - m_vres[i] = VREG_S(VS1REG, i) ^ VREG_S(VS2REG, VEC_EL_2(EL, i)); - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - case 0x2d: /* VNXOR */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 | - // ------------------------------------------------------ - // - // Bitwise NOT XOR of two vector registers - - //printf("NXOR "); -#if USE_SIMD - uint16_t *acc = m_acc.s; - - rsp_vec_t vs = vec_load_unshuffled_operand(m_v[VS1REG].s); - rsp_vec_t vt_shuffle = vec_load_and_shuffle_operand(m_v[VS2REG].s, EL); - - m_v[VDREG].v = vec_vxor_vnxor(op, vs, vt_shuffle); - - write_acc_lo(acc, m_v[VDREG].v); -#else - for (i=0; i < 8; i++) - { - m_vres[i] = ~((VREG_S(VS1REG, i) ^ VREG_S(VS2REG, VEC_EL_2(EL, i)))); - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -#endif - // - break; - } - - case 0x30: /* VRCP */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 | - // ------------------------------------------------------ - // - // Calculates reciprocal - - //printf("RCP "); -#if USE_SIMD - write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL)); - - int32_t dp = op & m_dp_flag; - m_dp_flag = 0; - - m_v[VDREG].v = vec_vrcp_vrsq(op, dp, VS2REG, EL, VDREG, VS1REG); -#else - int32_t shifter = 0; - - int32_t rec = (int16_t)(VREG_S(VS2REG, EL & 7)); - int32_t datainput = (rec < 0) ? (-rec) : rec; - if (datainput) - { - for (i = 0; i < 32; i++) - { - if (datainput & (1 << ((~i) & 0x1f))) - { - shifter = i; - break; - } - } - } - else - { - shifter = 0x10; - } - - int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22; - int32_t fetchval = rsp_divtable[address]; - int32_t temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); - if (rec < 0) - { - temp = ~temp; - } - if (!rec) - { - temp = 0x7fffffff; - } - else if (rec == 0xffff8000) - { - temp = 0xffff0000; - } - rec = temp; - - m_reciprocal_res = rec; - m_dp_allowed = 0; - - VREG_S(VDREG, VS1REG & 7) = (uint16_t)(rec & 0xffff); - - for (i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i); - } - - -#endif - // - break; - } - - case 0x31: /* VRCPL */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 | - // ------------------------------------------------------ - // - // Calculates reciprocal low part - - //printf("RCPL "); -#if USE_SIMD - write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL)); - - int32_t dp = op & m_dp_flag; - m_dp_flag = 0; - - m_v[VDREG].v = vec_vrcp_vrsq(op, dp, VS2REG, EL, VDREG, VS1REG); -#else - int32_t shifter = 0; - - int32_t rec = (int16_t)VREG_S(VS2REG, EL & 7); - int32_t datainput = rec; - - if (m_dp_allowed) - { - rec = (rec & 0x0000ffff) | m_reciprocal_high; - datainput = rec; - - if (rec < 0) - { - if (rec < -32768) - { - datainput = ~datainput; - } - else - { - datainput = -datainput; - } - } - } - else if (datainput < 0) - { - datainput = -datainput; - - shifter = 0x10; - } - - - for (i = 0; i < 32; i++) - { - if (datainput & (1 << ((~i) & 0x1f))) - { - shifter = i; - break; - } - } - - int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22; - int32_t fetchval = rsp_divtable[address]; - int32_t temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); - temp ^= rec >> 31; - - if (!rec) - { - temp = 0x7fffffff; - } - else if (rec == 0xffff8000) - { - temp = 0xffff0000; - } - rec = temp; - - m_reciprocal_res = rec; - m_dp_allowed = 0; - - VREG_S(VDREG, VS1REG & 7) = (uint16_t)(rec & 0xffff); - - for (i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i); - } - -#endif - // - break; - } - - case 0x32: /* VRCPH */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 | - // ------------------------------------------------------ - // - // Calculates reciprocal high part - - //printf("RCPH "); -#if USE_SIMD - write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL)); - - m_dp_flag = 1; - - m_v[VDREG].v = vec_vdivh(VS2REG, EL, VDREG, VS1REG); -#else - m_reciprocal_high = (VREG_S(VS2REG, EL & 7)) << 16; - m_dp_allowed = 1; - - for (i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i); - } - - VREG_S(VDREG, VS1REG & 7) = (int16_t)(m_reciprocal_res >> 16); - -#endif - // - break; - } - - case 0x33: /* VMOV */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110011 | - // ------------------------------------------------------ - // - // Moves element from vector to destination vector - - //printf("MOV "); -#if USE_SIMD - write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL)); - m_v[VDREG].v = vec_vmov(VS2REG, EL, VDREG, VS1REG); -#else - VREG_S(VDREG, VS1REG & 7) = VREG_S(VS2REG, EL & 7); - for (i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i); - } -#endif - // - break; - } - - case 0x34: /* VRSQ */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 | - // ------------------------------------------------------ - // - // Calculates reciprocal square-root - - //printf("RSQ "); -#if USE_SIMD - write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL)); - - int32_t dp = op & m_dp_flag; - m_dp_flag = 0; - - m_v[VDREG].v = vec_vrcp_vrsq(op, dp, VS2REG, EL, VDREG, VS1REG); -#else - int32_t shifter = 0; - - int32_t rec = (int16_t)(VREG_S(VS2REG, EL & 7)); - int32_t datainput = (rec < 0) ? (-rec) : rec; - if (datainput) - { - for (i = 0; i < 32; i++) - { - if (datainput & (1 << ((~i) & 0x1f)))//?.?.??? 31 - i - { - shifter = i; - break; - } - } - } - else - { - shifter = 0x10; - } - - int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22; - address = ((address | 0x200) & 0x3fe) | (shifter & 1); - - int32_t fetchval = rsp_divtable[address]; - int32_t temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); - if (rec < 0) - { - temp = ~temp; - } - if (!rec) - { - temp = 0x7fffffff; - } - else if (rec == 0xffff8000) - { - temp = 0xffff0000; - } - rec = temp; - - m_reciprocal_res = rec; - m_dp_allowed = 0; - - VREG_S(VDREG, VS1REG & 7) = (uint16_t)(rec & 0xffff); - - for (i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i); - } - -#endif - // - break; - } - - case 0x35: /* VRSQL */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 | - // ------------------------------------------------------ - // - // Calculates reciprocal square-root low part - - //printf("RSQL "); -#if USE_SIMD - write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL)); - - int32_t dp = op & m_dp_flag; - m_dp_flag = 0; - - m_v[VDREG].v = vec_vrcp_vrsq(op, dp, VS2REG, EL, VDREG, VS1REG); -#else - int32_t shifter = 0; - int32_t rec = (int16_t)VREG_S(VS2REG, EL & 7); - int32_t datainput = rec; - - if (m_dp_allowed) - { - rec = (rec & 0x0000ffff) | m_reciprocal_high; - datainput = rec; - - if (rec < 0) - { - if (rec < -32768) - { - datainput = ~datainput; - } - else - { - datainput = -datainput; - } - } - } - else if (datainput < 0) - { - datainput = -datainput; - - shifter = 0x10; - } - - if (datainput) - { - for (i = 0; i < 32; i++) - { - if (datainput & (1 << ((~i) & 0x1f))) - { - shifter = i; - break; - } - } - } - - int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22; - address = ((address | 0x200) & 0x3fe) | (shifter & 1); - - int32_t fetchval = rsp_divtable[address]; - int32_t temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); - temp ^= rec >> 31; - - if (!rec) - { - temp = 0x7fffffff; - } - else if (rec == 0xffff8000) - { - temp = 0xffff0000; - } - rec = temp; - - m_reciprocal_res = rec; - m_dp_allowed = 0; - - VREG_S(VDREG, VS1REG & 7) = (uint16_t)(rec & 0xffff); - - for (i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i); - } - -#endif - // - break; - } - - case 0x36: /* VRSQH */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110110 | - // ------------------------------------------------------ - // - // Calculates reciprocal square-root high part - - //printf("RSQH "); -#if USE_SIMD - write_acc_lo(m_acc.s, vec_load_and_shuffle_operand(m_v[VS2REG].s, EL)); - - m_dp_flag = 1; - - m_v[VDREG].v = vec_vdivh(VS2REG, EL, VDREG, VS1REG); -#else - m_reciprocal_high = (VREG_S(VS2REG, EL & 7)) << 16; - m_dp_allowed = 1; - - for (i=0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i); - } - - VREG_S(VDREG, VS1REG & 7) = (int16_t)(m_reciprocal_res >> 16); // store high part -#endif - // - break; - } - - case 0x37: /* VNOP */ - { - // 31 25 24 20 15 10 5 0 - // ------------------------------------------------------ - // | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110111 | - // ------------------------------------------------------ - // - // Vector null instruction - - //printf("NOP "); - break; - } - - default: m_rsp.unimplemented_opcode(op); break; - } -} - -/*************************************************************************** - Vector Flag Reading/Writing -***************************************************************************/ - -void rsp_device::cop2::handle_cop2(uint32_t op) -{ - switch ((op >> 21) & 0x1f) - { - case 0x00: /* MFC2 */ - { - // 31 25 20 15 10 6 0 - // --------------------------------------------------- - // | 010010 | 00000 | TTTTT | DDDDD | IIII | 0000000 | - // --------------------------------------------------- - // - //printf("MFC2 "); - int el = (op >> 7) & 0xf; - uint16_t b1 = VREG_B(RDREG, (el+0) & 0xf); - uint16_t b2 = VREG_B(RDREG, (el+1) & 0xf); - if (RTREG) RTVAL = (int32_t)(int16_t)((b1 << 8) | (b2)); - break; - } - - case 0x02: /* CFC2 */ - { - // 31 25 20 15 10 0 - // ------------------------------------------------ - // | 010010 | 00010 | TTTTT | DDDDD | 00000000000 | - // ------------------------------------------------ - // - //printf("CFC2 "); - if (RTREG) - { -#if USE_SIMD - int32_t src = RDREG & 3; - if (src == 3) { - src = 2; - } - RTVAL = get_flags(m_flags[src].s); -#else - switch(RDREG) - { - case 0: - RTVAL = ((CARRY_FLAG(0) & 1) << 0) | - ((CARRY_FLAG(1) & 1) << 1) | - ((CARRY_FLAG(2) & 1) << 2) | - ((CARRY_FLAG(3) & 1) << 3) | - ((CARRY_FLAG(4) & 1) << 4) | - ((CARRY_FLAG(5) & 1) << 5) | - ((CARRY_FLAG(6) & 1) << 6) | - ((CARRY_FLAG(7) & 1) << 7) | - ((ZERO_FLAG(0) & 1) << 8) | - ((ZERO_FLAG(1) & 1) << 9) | - ((ZERO_FLAG(2) & 1) << 10) | - ((ZERO_FLAG(3) & 1) << 11) | - ((ZERO_FLAG(4) & 1) << 12) | - ((ZERO_FLAG(5) & 1) << 13) | - ((ZERO_FLAG(6) & 1) << 14) | - ((ZERO_FLAG(7) & 1) << 15); - if (RTVAL & 0x8000) RTVAL |= 0xffff0000; - break; - case 1: - RTVAL = ((COMPARE_FLAG(0) & 1) << 0) | - ((COMPARE_FLAG(1) & 1) << 1) | - ((COMPARE_FLAG(2) & 1) << 2) | - ((COMPARE_FLAG(3) & 1) << 3) | - ((COMPARE_FLAG(4) & 1) << 4) | - ((COMPARE_FLAG(5) & 1) << 5) | - ((COMPARE_FLAG(6) & 1) << 6) | - ((COMPARE_FLAG(7) & 1) << 7) | - ((CLIP2_FLAG(0) & 1) << 8) | - ((CLIP2_FLAG(1) & 1) << 9) | - ((CLIP2_FLAG(2) & 1) << 10) | - ((CLIP2_FLAG(3) & 1) << 11) | - ((CLIP2_FLAG(4) & 1) << 12) | - ((CLIP2_FLAG(5) & 1) << 13) | - ((CLIP2_FLAG(6) & 1) << 14) | - ((CLIP2_FLAG(7) & 1) << 15); - if (RTVAL & 0x8000) RTVAL |= 0xffff0000; - break; - case 2: - // Anciliary clipping flags - RTVAL = ((CLIP1_FLAG(0) & 1) << 0) | - ((CLIP1_FLAG(1) & 1) << 1) | - ((CLIP1_FLAG(2) & 1) << 2) | - ((CLIP1_FLAG(3) & 1) << 3) | - ((CLIP1_FLAG(4) & 1) << 4) | - ((CLIP1_FLAG(5) & 1) << 5) | - ((CLIP1_FLAG(6) & 1) << 6) | - ((CLIP1_FLAG(7) & 1) << 7); - } -#endif - } - break; - } - - case 0x04: /* MTC2 */ - { - // 31 25 20 15 10 6 0 - // --------------------------------------------------- - // | 010010 | 00100 | TTTTT | DDDDD | IIII | 0000000 | - // --------------------------------------------------- - // - //printf("MTC2 "); - int el = (op >> 7) & 0xf; - W_VREG_B(RDREG, (el+0) & 0xf, (RTVAL >> 8) & 0xff); - W_VREG_B(RDREG, (el+1) & 0xf, (RTVAL >> 0) & 0xff); - break; - } - - case 0x06: /* CTC2 */ - { - // 31 25 20 15 10 0 - // ------------------------------------------------ - // | 010010 | 00110 | TTTTT | DDDDD | 00000000000 | - // ------------------------------------------------ - // - switch(RDREG) - { -#if USE_SIMD - case 0: - case 1: - case 2: - uint16_t r0 = (RTVAL & (1 << 0)) ? 0xffff : 0; - uint16_t r1 = (RTVAL & (1 << 1)) ? 0xffff : 0; - uint16_t r2 = (RTVAL & (1 << 2)) ? 0xffff : 0; - uint16_t r3 = (RTVAL & (1 << 3)) ? 0xffff : 0; - uint16_t r4 = (RTVAL & (1 << 4)) ? 0xffff : 0; - uint16_t r5 = (RTVAL & (1 << 5)) ? 0xffff : 0; - uint16_t r6 = (RTVAL & (1 << 6)) ? 0xffff : 0; - uint16_t r7 = (RTVAL & (1 << 7)) ? 0xffff : 0; - m_flags[RDREG].__align[0] = _mm_set_epi16(r7, r6, r5, r4, r3, r2, r1, r0); - r0 = (RTVAL & (1 << 8)) ? 0xffff : 0; - r1 = (RTVAL & (1 << 9)) ? 0xffff : 0; - r2 = (RTVAL & (1 << 10)) ? 0xffff : 0; - r3 = (RTVAL & (1 << 11)) ? 0xffff : 0; - r4 = (RTVAL & (1 << 12)) ? 0xffff : 0; - r5 = (RTVAL & (1 << 13)) ? 0xffff : 0; - r6 = (RTVAL & (1 << 14)) ? 0xffff : 0; - r7 = (RTVAL & (1 << 15)) ? 0xffff : 0; - m_flags[RDREG].__align[1] = _mm_set_epi16(r7, r6, r5, r4, r3, r2, r1, r0); - break; -#else - case 0: - CLEAR_CARRY_FLAGS(); - CLEAR_ZERO_FLAGS(); - if (RTVAL & (1 << 0)) { SET_CARRY_FLAG(0); } - if (RTVAL & (1 << 1)) { SET_CARRY_FLAG(1); } - if (RTVAL & (1 << 2)) { SET_CARRY_FLAG(2); } - if (RTVAL & (1 << 3)) { SET_CARRY_FLAG(3); } - if (RTVAL & (1 << 4)) { SET_CARRY_FLAG(4); } - if (RTVAL & (1 << 5)) { SET_CARRY_FLAG(5); } - if (RTVAL & (1 << 6)) { SET_CARRY_FLAG(6); } - if (RTVAL & (1 << 7)) { SET_CARRY_FLAG(7); } - if (RTVAL & (1 << 8)) { SET_ZERO_FLAG(0); } - if (RTVAL & (1 << 9)) { SET_ZERO_FLAG(1); } - if (RTVAL & (1 << 10)) { SET_ZERO_FLAG(2); } - if (RTVAL & (1 << 11)) { SET_ZERO_FLAG(3); } - if (RTVAL & (1 << 12)) { SET_ZERO_FLAG(4); } - if (RTVAL & (1 << 13)) { SET_ZERO_FLAG(5); } - if (RTVAL & (1 << 14)) { SET_ZERO_FLAG(6); } - if (RTVAL & (1 << 15)) { SET_ZERO_FLAG(7); } - break; - - case 1: - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP2_FLAGS(); - if (RTVAL & (1 << 0)) { SET_COMPARE_FLAG(0); } - if (RTVAL & (1 << 1)) { SET_COMPARE_FLAG(1); } - if (RTVAL & (1 << 2)) { SET_COMPARE_FLAG(2); } - if (RTVAL & (1 << 3)) { SET_COMPARE_FLAG(3); } - if (RTVAL & (1 << 4)) { SET_COMPARE_FLAG(4); } - if (RTVAL & (1 << 5)) { SET_COMPARE_FLAG(5); } - if (RTVAL & (1 << 6)) { SET_COMPARE_FLAG(6); } - if (RTVAL & (1 << 7)) { SET_COMPARE_FLAG(7); } - if (RTVAL & (1 << 8)) { SET_CLIP2_FLAG(0); } - if (RTVAL & (1 << 9)) { SET_CLIP2_FLAG(1); } - if (RTVAL & (1 << 10)) { SET_CLIP2_FLAG(2); } - if (RTVAL & (1 << 11)) { SET_CLIP2_FLAG(3); } - if (RTVAL & (1 << 12)) { SET_CLIP2_FLAG(4); } - if (RTVAL & (1 << 13)) { SET_CLIP2_FLAG(5); } - if (RTVAL & (1 << 14)) { SET_CLIP2_FLAG(6); } - if (RTVAL & (1 << 15)) { SET_CLIP2_FLAG(7); } - break; - - case 2: - CLEAR_CLIP1_FLAGS(); - if (RTVAL & (1 << 0)) { SET_CLIP1_FLAG(0); } - if (RTVAL & (1 << 1)) { SET_CLIP1_FLAG(1); } - if (RTVAL & (1 << 2)) { SET_CLIP1_FLAG(2); } - if (RTVAL & (1 << 3)) { SET_CLIP1_FLAG(3); } - if (RTVAL & (1 << 4)) { SET_CLIP1_FLAG(4); } - if (RTVAL & (1 << 5)) { SET_CLIP1_FLAG(5); } - if (RTVAL & (1 << 6)) { SET_CLIP1_FLAG(6); } - if (RTVAL & (1 << 7)) { SET_CLIP1_FLAG(7); } - break; -#endif - } - break; - } - - case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: - case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: - { - //printf("V"); - handle_vector_ops(op); - break; - } - - default: - m_rsp.unimplemented_opcode(op); - break; - } - //dump(op); -} - -inline void rsp_device::cop2::mfc2() -{ - uint32_t op = m_rspcop2_state->op; - int el = (op >> 7) & 0xf; - - uint16_t b1 = VREG_B(VS1REG, (el+0) & 0xf); - uint16_t b2 = VREG_B(VS1REG, (el+1) & 0xf); - if (RTREG) RTVAL = (int32_t)(int16_t)((b1 << 8) | (b2)); -} - -inline void rsp_device::cop2::cfc2() -{ - uint32_t op = m_rspcop2_state->op; - if (RTREG) - { - switch(RDREG) - { - case 0: - RTVAL = ((CARRY_FLAG(0) & 1) << 0) | - ((CARRY_FLAG(1) & 1) << 1) | - ((CARRY_FLAG(2) & 1) << 2) | - ((CARRY_FLAG(3) & 1) << 3) | - ((CARRY_FLAG(4) & 1) << 4) | - ((CARRY_FLAG(5) & 1) << 5) | - ((CARRY_FLAG(6) & 1) << 6) | - ((CARRY_FLAG(7) & 1) << 7) | - ((ZERO_FLAG(0) & 1) << 8) | - ((ZERO_FLAG(1) & 1) << 9) | - ((ZERO_FLAG(2) & 1) << 10) | - ((ZERO_FLAG(3) & 1) << 11) | - ((ZERO_FLAG(4) & 1) << 12) | - ((ZERO_FLAG(5) & 1) << 13) | - ((ZERO_FLAG(6) & 1) << 14) | - ((ZERO_FLAG(7) & 1) << 15); - if (RTVAL & 0x8000) RTVAL |= 0xffff0000; - break; - case 1: - RTVAL = ((COMPARE_FLAG(0) & 1) << 0) | - ((COMPARE_FLAG(1) & 1) << 1) | - ((COMPARE_FLAG(2) & 1) << 2) | - ((COMPARE_FLAG(3) & 1) << 3) | - ((COMPARE_FLAG(4) & 1) << 4) | - ((COMPARE_FLAG(5) & 1) << 5) | - ((COMPARE_FLAG(6) & 1) << 6) | - ((COMPARE_FLAG(7) & 1) << 7) | - ((CLIP2_FLAG(0) & 1) << 8) | - ((CLIP2_FLAG(1) & 1) << 9) | - ((CLIP2_FLAG(2) & 1) << 10) | - ((CLIP2_FLAG(3) & 1) << 11) | - ((CLIP2_FLAG(4) & 1) << 12) | - ((CLIP2_FLAG(5) & 1) << 13) | - ((CLIP2_FLAG(6) & 1) << 14) | - ((CLIP2_FLAG(7) & 1) << 15); - if (RTVAL & 0x8000) RTVAL |= 0xffff0000; - break; - case 2: - RTVAL = ((CLIP1_FLAG(0) & 1) << 0) | - ((CLIP1_FLAG(1) & 1) << 1) | - ((CLIP1_FLAG(2) & 1) << 2) | - ((CLIP1_FLAG(3) & 1) << 3) | - ((CLIP1_FLAG(4) & 1) << 4) | - ((CLIP1_FLAG(5) & 1) << 5) | - ((CLIP1_FLAG(6) & 1) << 6) | - ((CLIP1_FLAG(7) & 1) << 7); - break; - } - } -} - -inline void rsp_device::cop2::mtc2() -{ - uint32_t op = m_rspcop2_state->op; - int el = (op >> 7) & 0xf; - VREG_B(VS1REG, (el+0) & 0xf) = (RTVAL >> 8) & 0xff; - VREG_B(VS1REG, (el+1) & 0xf) = (RTVAL >> 0) & 0xff; -} - -inline void rsp_device::cop2::ctc2() -{ - uint32_t op = m_rspcop2_state->op; - switch(RDREG) - { - case 0: - CLEAR_CARRY_FLAGS(); - CLEAR_ZERO_FLAGS(); - m_vflag[0][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0; - m_vflag[0][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0; - m_vflag[0][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0; - m_vflag[0][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0; - m_vflag[0][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0; - m_vflag[0][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0; - m_vflag[0][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0; - m_vflag[0][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0; - if (RTVAL & (1 << 0)) { SET_CARRY_FLAG(0); } - if (RTVAL & (1 << 1)) { SET_CARRY_FLAG(1); } - if (RTVAL & (1 << 2)) { SET_CARRY_FLAG(2); } - if (RTVAL & (1 << 3)) { SET_CARRY_FLAG(3); } - if (RTVAL & (1 << 4)) { SET_CARRY_FLAG(4); } - if (RTVAL & (1 << 5)) { SET_CARRY_FLAG(5); } - if (RTVAL & (1 << 6)) { SET_CARRY_FLAG(6); } - if (RTVAL & (1 << 7)) { SET_CARRY_FLAG(7); } - m_vflag[3][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0; - m_vflag[3][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0; - m_vflag[3][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0; - m_vflag[3][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0; - m_vflag[3][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0; - m_vflag[3][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0; - m_vflag[3][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0; - m_vflag[3][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0; - if (RTVAL & (1 << 8)) { SET_ZERO_FLAG(0); } - if (RTVAL & (1 << 9)) { SET_ZERO_FLAG(1); } - if (RTVAL & (1 << 10)) { SET_ZERO_FLAG(2); } - if (RTVAL & (1 << 11)) { SET_ZERO_FLAG(3); } - if (RTVAL & (1 << 12)) { SET_ZERO_FLAG(4); } - if (RTVAL & (1 << 13)) { SET_ZERO_FLAG(5); } - if (RTVAL & (1 << 14)) { SET_ZERO_FLAG(6); } - if (RTVAL & (1 << 15)) { SET_ZERO_FLAG(7); } - break; - case 1: - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP2_FLAGS(); - m_vflag[1][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0; - m_vflag[1][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0; - m_vflag[1][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0; - m_vflag[1][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0; - m_vflag[1][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0; - m_vflag[1][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0; - m_vflag[1][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0; - m_vflag[1][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0; - if (RTVAL & (1 << 0)) { SET_COMPARE_FLAG(0); } - if (RTVAL & (1 << 1)) { SET_COMPARE_FLAG(1); } - if (RTVAL & (1 << 2)) { SET_COMPARE_FLAG(2); } - if (RTVAL & (1 << 3)) { SET_COMPARE_FLAG(3); } - if (RTVAL & (1 << 4)) { SET_COMPARE_FLAG(4); } - if (RTVAL & (1 << 5)) { SET_COMPARE_FLAG(5); } - if (RTVAL & (1 << 6)) { SET_COMPARE_FLAG(6); } - if (RTVAL & (1 << 7)) { SET_COMPARE_FLAG(7); } - m_vflag[4][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0; - m_vflag[4][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0; - m_vflag[4][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0; - m_vflag[4][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0; - m_vflag[4][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0; - m_vflag[4][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0; - m_vflag[4][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0; - m_vflag[4][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0; - if (RTVAL & (1 << 8)) { SET_CLIP2_FLAG(0); } - if (RTVAL & (1 << 9)) { SET_CLIP2_FLAG(1); } - if (RTVAL & (1 << 10)) { SET_CLIP2_FLAG(2); } - if (RTVAL & (1 << 11)) { SET_CLIP2_FLAG(3); } - if (RTVAL & (1 << 12)) { SET_CLIP2_FLAG(4); } - if (RTVAL & (1 << 13)) { SET_CLIP2_FLAG(5); } - if (RTVAL & (1 << 14)) { SET_CLIP2_FLAG(6); } - if (RTVAL & (1 << 15)) { SET_CLIP2_FLAG(7); } - break; - case 2: - CLEAR_CLIP1_FLAGS(); - m_vflag[2][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0; - m_vflag[2][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0; - m_vflag[2][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0; - m_vflag[2][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0; - m_vflag[2][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0; - m_vflag[2][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0; - m_vflag[2][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0; - m_vflag[2][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0; - if (RTVAL & (1 << 0)) { SET_CLIP1_FLAG(0); } - if (RTVAL & (1 << 1)) { SET_CLIP1_FLAG(1); } - if (RTVAL & (1 << 2)) { SET_CLIP1_FLAG(2); } - if (RTVAL & (1 << 3)) { SET_CLIP1_FLAG(3); } - if (RTVAL & (1 << 4)) { SET_CLIP1_FLAG(4); } - if (RTVAL & (1 << 5)) { SET_CLIP1_FLAG(5); } - if (RTVAL & (1 << 6)) { SET_CLIP1_FLAG(6); } - if (RTVAL & (1 << 7)) { SET_CLIP1_FLAG(7); } - break; - } -} - -void rsp_device::cop2::log_instruction_execution() -{ - static VECTOR_REG prev_vecs[32]; - - for (int i = 0; i < 32; i++) - { - if (m_v[i].d[0] != prev_vecs[i].d[0] || m_v[i].d[1] != prev_vecs[i].d[1]) - { - fprintf(m_rsp.m_exec_output, "V%d: %04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X ", i, - (uint16_t)VREG_S(i,0), (uint16_t)VREG_S(i,1), (uint16_t)VREG_S(i,2), (uint16_t)VREG_S(i,3), (uint16_t)VREG_S(i,4), (uint16_t)VREG_S(i,5), (uint16_t)VREG_S(i,6), (uint16_t)VREG_S(i,7)); - } - prev_vecs[i].d[0] = m_v[i].d[0]; - prev_vecs[i].d[1] = m_v[i].d[1]; - } -} - -void rsp_device::cop2::dump(uint32_t op) -{ - printf("%08x ", op); - for (int i = 0; i < 32; i++) - { - printf("%08x ", m_rsp.m_rsp_state->r[i]); - } - printf("\n"); - - for (int i = 0; i < 32; i++) - { - printf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", VREG_B(i, 0), VREG_B(i, 1), VREG_B(i, 2), VREG_B(i, 3), VREG_B(i, 4), VREG_B(i, 5), VREG_B(i, 6), VREG_B(i, 7), VREG_B(i, 8), VREG_B(i, 9), VREG_B(i, 10), VREG_B(i, 11), VREG_B(i, 12), VREG_B(i, 13), VREG_B(i, 14), VREG_B(i, 15)); - } - -#if USE_SIMD - printf("acc_h: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_acc.s[0], m_acc.s[1], m_acc.s[2], m_acc.s[3], m_acc.s[4], m_acc.s[5], m_acc.s[6], m_acc.s[7]); - printf("acc_m: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_acc.s[8], m_acc.s[9], m_acc.s[10], m_acc.s[11], m_acc.s[12], m_acc.s[13], m_acc.s[14], m_acc.s[15]); - printf("acc_l: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_acc.s[16], m_acc.s[17], m_acc.s[18], m_acc.s[19], m_acc.s[20], m_acc.s[21], m_acc.s[22], m_acc.s[23]); - printf("vcc_hi: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_flags[RSP_VCC].s[0], m_flags[RSP_VCC].s[1], m_flags[RSP_VCC].s[2], m_flags[RSP_VCC].s[3], m_flags[RSP_VCC].s[4], m_flags[RSP_VCC].s[5], m_flags[RSP_VCC].s[6], m_flags[RSP_VCC].s[7]); - printf("vcc_lo: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_flags[RSP_VCC].s[8], m_flags[RSP_VCC].s[9], m_flags[RSP_VCC].s[10], m_flags[RSP_VCC].s[11], m_flags[RSP_VCC].s[12], m_flags[RSP_VCC].s[13], m_flags[RSP_VCC].s[14], m_flags[RSP_VCC].s[15]); - printf("vco_hi: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_flags[RSP_VCO].s[0], m_flags[RSP_VCO].s[1], m_flags[RSP_VCO].s[2], m_flags[RSP_VCO].s[3], m_flags[RSP_VCO].s[4], m_flags[RSP_VCO].s[5], m_flags[RSP_VCO].s[6], m_flags[RSP_VCO].s[7]); - printf("vco_lo: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_flags[RSP_VCO].s[8], m_flags[RSP_VCO].s[9], m_flags[RSP_VCO].s[10], m_flags[RSP_VCO].s[11], m_flags[RSP_VCO].s[12], m_flags[RSP_VCO].s[13], m_flags[RSP_VCO].s[14], m_flags[RSP_VCO].s[15]); - printf("vce: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_flags[RSP_VCE].s[0], m_flags[RSP_VCE].s[1], m_flags[RSP_VCE].s[2], m_flags[RSP_VCE].s[3], m_flags[RSP_VCE].s[4], m_flags[RSP_VCE].s[5], m_flags[RSP_VCE].s[6], m_flags[RSP_VCE].s[7]); -#else - printf("acc_h: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", ACCUM_H(0), ACCUM_H(1), ACCUM_H(2), ACCUM_H(3), ACCUM_H(4), ACCUM_H(5), ACCUM_H(6), ACCUM_H(7)); - printf("acc_m: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", ACCUM_M(0), ACCUM_M(1), ACCUM_M(2), ACCUM_M(3), ACCUM_M(4), ACCUM_M(5), ACCUM_M(6), ACCUM_M(7)); - printf("acc_l: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", ACCUM_L(0), ACCUM_L(1), ACCUM_L(2), ACCUM_L(3), ACCUM_L(4), ACCUM_L(5), ACCUM_L(6), ACCUM_L(7)); - printf("vcc_hi: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_vflag[4][0], m_vflag[4][1], m_vflag[4][2], m_vflag[4][3], m_vflag[4][4], m_vflag[4][5], m_vflag[4][6], m_vflag[4][7]); - printf("vcc_lo: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_vflag[1][0], m_vflag[1][1], m_vflag[1][2], m_vflag[1][3], m_vflag[1][4], m_vflag[1][5], m_vflag[1][6], m_vflag[1][7]); - printf("vco_hi: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_vflag[3][0], m_vflag[3][1], m_vflag[3][2], m_vflag[3][3], m_vflag[3][4], m_vflag[3][5], m_vflag[3][6], m_vflag[3][7]); - printf("vco_lo: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_vflag[0][0], m_vflag[0][1], m_vflag[0][2], m_vflag[0][3], m_vflag[0][4], m_vflag[0][5], m_vflag[0][6], m_vflag[0][7]); - printf("vce: %04x|%04x|%04x|%04x|%04x|%04x|%04x|%04x\n", m_vflag[2][0], m_vflag[2][1], m_vflag[2][2], m_vflag[2][3], m_vflag[2][4], m_vflag[2][5], m_vflag[2][6], m_vflag[2][7]); -#endif -} - -void rsp_device::cop2::dump_dmem() -{ - uint8_t* dmem = m_rsp.get_dmem(); - printf("\n"); - for (int i = 0; i < 0x1000; i += 32) - { - printf("%04x: ", i); - for (int j = 0; j < 32; j++) - { - printf("%02x ", dmem[i + j]); - } - printf("\n"); - } - printf("\n"); -} diff --git a/src/devices/cpu/rsp/rspcp2.h b/src/devices/cpu/rsp/rspcp2.h deleted file mode 100644 index 7e374e71ae3..00000000000 --- a/src/devices/cpu/rsp/rspcp2.h +++ /dev/null @@ -1,395 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz,Tyler J. Stachecki -/*************************************************************************** - - rspcp2.h - - Interface file for Reality Signal Processor (RSP) vector extensions. - -***************************************************************************/ -#ifndef MAME_CPU_RSP_RSPCP2_H -#define MAME_CPU_RSP_RSPCP2_H - -#pragma once - -#include "rsp.h" -#include "rspdiv.h" -#include "cpu/drcuml.h" - -#define SIMD_OFF (1) - -#if (defined(__SSE2__) || defined(__SSE3__) || defined(__SSSE3__) || defined(__SSE4_1__) || defined(__SSE4_2__)) -#define SSE_AVAILABLE (1) -#else -#define SSE_AVAILABLE (0) -#endif - -#if (SSE_AVAILABLE || defined(_MSC_VER)) && defined(PTR64) && !SIMD_OFF -#define USE_SIMD (1) -#else -#define USE_SIMD (0) -#endif - -#if USE_SIMD - -#ifdef _MSC_VER -#define __align16 __declspec(align(16)) -#else -#define __align16 __attribute__((aligned(16))) -#endif - -#if (defined(__SSE4_2__) || defined(_MSC_VER)) -#include <nmmintrin.h> -#elif (defined(__SSE4_1__) || defined(_MSC_VER)) -#include <smmintrin.h> -#elif (defined(__SSSE3__) || defined(_MSC_VER)) -#include <tmmintrin.h> -#elif (defined(__SSE3__ ) || defined(_MSC_VER)) -#include <pmmintrin.h> -#else -#include <emmintrin.h> -#endif - -typedef __m128i rsp_vec_t; -#endif - -union VECTOR_REG -{ - uint64_t d[2]; - uint32_t l[4]; - uint16_t s[8]; - uint8_t b[16]; -#if USE_SIMD - rsp_vec_t v; -#endif -}; - -union ACCUMULATOR_REG -{ - uint64_t q; - uint32_t l[2]; - uint16_t w[4]; -}; - -struct compiler_state; - -class rsp_device::cop2 -{ - friend class rsp_device; - -public: - cop2(rsp_device &rsp, running_machine &machine); - -protected: - virtual void init(); - virtual void start(); - - virtual bool generate_cop2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) { return true; } - virtual bool generate_lwc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) { return true; } - virtual bool generate_swc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) { return true; } - - virtual void state_string_export(const int index, std::string &str) const; - -public: - virtual ~cop2(); - - virtual void lbv() { } - virtual void lsv() { } - virtual void llv() { } - virtual void ldv() { } - virtual void lqv() { } - virtual void lrv() { } - virtual void lpv() { } - virtual void luv() { } - virtual void lhv() { } - virtual void lfv() { } - virtual void lwv() { } - virtual void ltv() { } - virtual void sbv() { } - virtual void ssv() { } - virtual void slv() { } - virtual void sdv() { } - virtual void sqv() { } - virtual void srv() { } - virtual void spv() { } - virtual void suv() { } - virtual void shv() { } - virtual void sfv() { } - virtual void swv() { } - virtual void stv() { } - virtual void vmulf() { } - virtual void vmulu() { } - virtual void vmudl() { } - virtual void vmudm() { } - virtual void vmudn() { } - virtual void vmudh() { } - virtual void vmacf() { } - virtual void vmacu() { } - virtual void vmadl() { } - virtual void vmadm() { } - virtual void vmadn() { } - virtual void vmadh() { } - virtual void vadd() { } - virtual void vsub() { } - virtual void vabs() { } - virtual void vaddc() { } - virtual void vsubc() { } - virtual void vaddb() { } - virtual void vsaw() { } - virtual void vlt() { } - virtual void veq() { } - virtual void vne() { } - virtual void vge() { } - virtual void vcl() { } - virtual void vch() { } - virtual void vcr() { } - virtual void vmrg() { } - virtual void vand() { } - virtual void vnand() { } - virtual void vor() { } - virtual void vnor() { } - virtual void vxor() { } - virtual void vnxor() { } - virtual void vrcp() { } - virtual void vrcpl() { } - virtual void vrcph() { } - virtual void vmov() { } - virtual void vrsql() { } - virtual void vrsqh() { } - virtual void vrsq() { } - virtual void mfc2(); - virtual void cfc2(); - virtual void mtc2(); - virtual void ctc2(); - - virtual void handle_cop2(uint32_t op); - - void log_instruction_execution(); - virtual void cfunc_unimplemented_opcode() { } - - void dump(uint32_t op); - void dump_dmem(); - -protected: - virtual bool generate_vector_opcode(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) { return true; } - - uint16_t SATURATE_ACCUM(int accum, int slice, uint16_t negative, uint16_t positive); - - // Data that needs to be stored close to the generated DRC code - struct internal_rspcop2_state - { - uint32_t op; - }; - - internal_rspcop2_state *m_rspcop2_state; - rsp_device& m_rsp; - running_machine& m_machine; - uint32_t m_vres[8]; /* used for temporary vector results */ - -#if USE_SIMD - __align16 VECTOR_REG m_v[32]; -#else - VECTOR_REG m_v[32]; -#endif - ACCUMULATOR_REG m_accum[8]; - uint16_t m_vflag[6][8]; - - int32_t m_reciprocal_res; - uint32_t m_reciprocal_high; - int32_t m_dp_allowed; - -#if USE_SIMD - enum rsp_flags_t { - RSP_VCO = 0, - RSP_VCC = 1, - RSP_VCE = 2 - }; - - enum rsp_acc_t { - RSP_ACC_LO = 16, - RSP_ACC_MD = 8, - RSP_ACC_HI = 0, - }; - - enum rsp_mem_request_type { - RSP_MEM_REQUEST_NONE, - RSP_MEM_REQUEST_INT_MEM, - RSP_MEM_REQUEST_VECTOR, - RSP_MEM_REQUEST_FOURTH, - RSP_MEM_REQUEST_HALF, - RSP_MEM_REQUEST_PACK, - RSP_MEM_REQUEST_QUAD, - RSP_MEM_REQUEST_REST, - RSP_MEM_REQUEST_UPACK - }; - - union aligned_rsp_1vect_t { - rsp_vec_t __align; - uint16_t s[8]; - }; - - union aligned_rsp_2vect_t { - rsp_vec_t __align[2]; - uint16_t s[16]; - }; - - union aligned_rsp_3vect_t { - rsp_vec_t __align[3]; - uint16_t s[24]; - }; - - __align16 aligned_rsp_1vect_t m_vdqm; - __align16 aligned_rsp_2vect_t m_flags[3]; - __align16 aligned_rsp_3vect_t m_acc; - uint32_t m_dp_flag; - - typedef struct - { - rsp_vec_t dummy_for_alignment; - const uint16_t logic_mask[2][8]; - const uint16_t vrsq_mask_table[8][8]; - const uint16_t shuffle_keys[16][8]; - const uint16_t sll_b2l_keys[16][8]; - const uint16_t sll_l2b_keys[16][8]; - const uint16_t srl_b2l_keys[16][8]; - const uint16_t ror_b2l_keys[16][8]; - const uint16_t rol_l2b_keys[16][8]; - const uint16_t ror_l2b_keys[16][8]; - const uint16_t qr_lut[16][8]; - const uint16_t bdls_lut[4][4]; - const uint16_t word_reverse[8]; - } vec_helpers_t; - - static const vec_helpers_t m_vec_helpers; - - rsp_vec_t vec_load_and_shuffle_operand(const uint16_t* src, uint32_t element); - static inline uint32_t sign_extend_6(int32_t i) { - return ((i << (32 - 7)) >> (32 - 7)) & 0xfff; - } - static inline rsp_vec_t vec_load_unshuffled_operand(const void* src) - { - return _mm_load_si128((rsp_vec_t*) src); - } - static inline void vec_write_operand(uint16_t* dest, rsp_vec_t src) - { - _mm_store_si128((rsp_vec_t*) dest, src); - } - static inline rsp_vec_t read_acc_lo(const uint16_t* acc) - { - return vec_load_unshuffled_operand(acc + sizeof(rsp_vec_t)); - } - static inline rsp_vec_t read_acc_mid(const uint16_t* acc) - { - return vec_load_unshuffled_operand(acc + (sizeof(rsp_vec_t) >> 1)); - } - static inline rsp_vec_t read_acc_hi(const void* acc) - { - return vec_load_unshuffled_operand(acc); - } - static inline rsp_vec_t read_vcc_lo(const uint16_t *vcc) - { - return vec_load_unshuffled_operand(vcc + (sizeof(rsp_vec_t) >> 1)); - } - static inline rsp_vec_t read_vcc_hi(const uint16_t *vcc) - { - return vec_load_unshuffled_operand(vcc); - } - static inline rsp_vec_t read_vco_lo(const uint16_t *vco) - { - return vec_load_unshuffled_operand(vco + (sizeof(rsp_vec_t) >> 1)); - } - static inline rsp_vec_t read_vco_hi(const uint16_t *vco) - { - return vec_load_unshuffled_operand(vco); - } - static inline rsp_vec_t read_vce(const uint16_t *vce) - { - return vec_load_unshuffled_operand(vce + (sizeof(rsp_vec_t) >> 1)); - } - static inline void write_acc_lo(uint16_t *acc, rsp_vec_t acc_lo) - { - return vec_write_operand(acc + sizeof(rsp_vec_t), acc_lo); - } - static inline void write_acc_mid(uint16_t *acc, rsp_vec_t acc_mid) - { - return vec_write_operand(acc + (sizeof(rsp_vec_t) >> 1), acc_mid); - } - static inline void write_acc_hi(uint16_t *acc, rsp_vec_t acc_hi) - { - return vec_write_operand(acc, acc_hi); - } - static inline void write_vcc_lo(uint16_t *vcc, rsp_vec_t vcc_lo) - { - return vec_write_operand(vcc + (sizeof(rsp_vec_t) >> 1), vcc_lo); - } - static inline void write_vcc_hi(uint16_t *vcc, rsp_vec_t vcc_hi) - { - return vec_write_operand(vcc, vcc_hi); - } - static inline void write_vco_lo(uint16_t *vcc, rsp_vec_t vco_lo) - { - return vec_write_operand(vcc + (sizeof(rsp_vec_t) >> 1), vco_lo); - } - static inline void write_vco_hi(uint16_t *vcc, rsp_vec_t vco_hi) - { - return vec_write_operand(vcc, vco_hi); - } - static inline void write_vce(uint16_t *vce, rsp_vec_t vce_r) - { - return vec_write_operand(vce + (sizeof(rsp_vec_t) >> 1), vce_r); - } - - static inline int16_t get_flags(const uint16_t *flags) - { - return _mm_movemask_epi8(_mm_packs_epi16(_mm_load_si128((rsp_vec_t*) (flags + (sizeof(rsp_vec_t) >> 1))), _mm_load_si128((rsp_vec_t*) flags))); - } - - static inline rsp_vec_t vec_zero() - { - return _mm_setzero_si128(); - } - - void vec_load_group1(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm); - void vec_load_group2(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type); - void vec_load_group4(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type); - void vec_store_group1(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm); - void vec_store_group2(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type); - void vec_store_group4(uint32_t addr, uint32_t element, uint16_t* regp, rsp_vec_t reg, rsp_vec_t dqm, rsp_mem_request_type request_type); - -#include "clamp.h" -#include "vabs.h" -#include "vadd.h" -#include "vaddc.h" -#include "vand.h" -#include "vch.h" -#include "vcmp.h" -#include "vcl.h" -#include "vcr.h" -#include "vdivh.h" -#include "vmac.h" -#include "vmov.h" -#include "vmrg.h" -#include "vmul.h" -#include "vmulh.h" -#include "vmull.h" -#include "vmulm.h" -#include "vmuln.h" -#include "vor.h" -#include "vrcpsq.h" -#include "vrsq.h" -#include "vsub.h" -#include "vsubc.h" -#include "vxor.h" -#include "vldst.h" -#endif - -private: - void handle_lwc2(uint32_t op); - void handle_swc2(uint32_t op); - void handle_vector_ops(uint32_t op); - - uint32_t m_div_in; - uint32_t m_div_out; -}; - -#endif // MAME_CPU_RSP_RSPCP2_H diff --git a/src/devices/cpu/rsp/rspcp2d.cpp b/src/devices/cpu/rsp/rspcp2d.cpp deleted file mode 100644 index a77ab072cab..00000000000 --- a/src/devices/cpu/rsp/rspcp2d.cpp +++ /dev/null @@ -1,3388 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/*************************************************************************** - - rspcp2d.c - - Universal machine language-based Nintendo/SGI RSP COP2 emulator. - Written by Ryan Holtz - -***************************************************************************/ - -#include "emu.h" -#include "rspcp2d.h" - -#include "rsp_dasm.h" - -#include "cpu/drcfe.h" -#include "cpu/drcuml.h" -#include "cpu/drcumlsh.h" - -#include "rspdefs.h" - - -/*************************************************************************** - Helpful Defines -***************************************************************************/ - -#define VDREG ((op >> 6) & 0x1f) -#define VS1REG ((op >> 11) & 0x1f) -#define VS2REG ((op >> 16) & 0x1f) -#define EL ((op >> 21) & 0xf) - -#define RSVAL (m_rsp.m_rsp_state->r[RSREG]) -#define RTVAL (m_rsp.m_rsp_state->r[RTREG]) -#define RDVAL (m_rsp.m_rsp_state->r[RDREG]) - -#define VREG_B(reg, offset) m_v[(reg)].b[(offset)^1] -#define W_VREG_S(reg, offset) m_v[(reg)].s[(offset)] -#define VREG_S(reg, offset) (int16_t)m_v[(reg)].s[(offset)] - -#define VEC_EL_2(x,z) (vector_elements_2[(x)][(z)]) - -#define ACCUM(x) m_accum[x].q - -#define CARRY 0 -#define COMPARE 1 -#define CLIP1 2 -#define ZERO 3 -#define CLIP2 4 - -#define ACCUM_H(x) (uint16_t)m_accum[x].w[3] -#define ACCUM_M(x) (uint16_t)m_accum[x].w[2] -#define ACCUM_L(x) (uint16_t)m_accum[x].w[1] -#define ACCUM_LL(x) (uint16_t)m_accum[x].w[0] -#define ACCUM(x) m_accum[x].q - -#define SET_ACCUM_H(v, x) m_accum[x].w[3] = v; -#define SET_ACCUM_M(v, x) m_accum[x].w[2] = v; -#define SET_ACCUM_L(v, x) m_accum[x].w[1] = v; -#define SET_ACCUM_LL(v, x) m_accum[x].w[0] = v; -#define SET_ACCUM(v, x) m_accum[x].q = v; - -#define GET_VS1(out, i) out = VREG_S(vs1reg, i) -#define GET_VS2(out, i) out = VREG_S(vs2reg, VEC_EL_2(el, i)) - -#define CARRY_FLAG(x) (m_vflag[CARRY][x & 7] != 0 ? 0xffff : 0) -#define COMPARE_FLAG(x) (m_vflag[COMPARE][x & 7] != 0 ? 0xffff : 0) -#define CLIP1_FLAG(x) (m_vflag[CLIP1][x & 7] != 0 ? 0xffff : 0) -#define ZERO_FLAG(x) (m_vflag[ZERO][x & 7] != 0 ? 0xffff : 0) -#define CLIP2_FLAG(x) (m_vflag[CLIP2][x & 7] != 0 ? 0xffff : 0) - -#define CLEAR_CARRY_FLAGS() { memset(m_vflag[CARRY], 0, 16); } -#define CLEAR_COMPARE_FLAGS() { memset(m_vflag[COMPARE], 0, 16); } -#define CLEAR_CLIP1_FLAGS() { memset(m_vflag[CLIP1], 0, 16); } -#define CLEAR_ZERO_FLAGS() { memset(m_vflag[ZERO], 0, 16); } -#define CLEAR_CLIP2_FLAGS() { memset(m_vflag[CLIP2], 0, 16); } - -#define SET_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0xffff; } -#define SET_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0xffff; } -#define SET_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0xffff; } -#define SET_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0xffff; } -#define SET_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0xffff; } - -#define CLEAR_CARRY_FLAG(x) { m_vflag[CARRY][x & 7] = 0; } -#define CLEAR_COMPARE_FLAG(x) { m_vflag[COMPARE][x & 7] = 0; } -#define CLEAR_CLIP1_FLAG(x) { m_vflag[CLIP1][x & 7] = 0; } -#define CLEAR_ZERO_FLAG(x) { m_vflag[ZERO][x & 7] = 0; } -#define CLEAR_CLIP2_FLAG(x) { m_vflag[CLIP2][x & 7] = 0; } - -#define CACHE_VALUES() \ - const int op = m_rspcop2_state->op; \ - const int vdreg = VDREG; \ - const int vs1reg = VS1REG; \ - const int vs2reg = VS2REG; \ - const int el = EL; - -#define WRITEBACK_RESULT() { \ - W_VREG_S(vdreg, 0) = m_vres[0]; \ - W_VREG_S(vdreg, 1) = m_vres[1]; \ - W_VREG_S(vdreg, 2) = m_vres[2]; \ - W_VREG_S(vdreg, 3) = m_vres[3]; \ - W_VREG_S(vdreg, 4) = m_vres[4]; \ - W_VREG_S(vdreg, 5) = m_vres[5]; \ - W_VREG_S(vdreg, 6) = m_vres[6]; \ - W_VREG_S(vdreg, 7) = m_vres[7]; \ -} - -static const int vector_elements_2[16][8] = -{ - { 0, 1, 2, 3, 4, 5, 6, 7 }, // none - { 0, 1, 2, 3, 4, 5, 6, 7 }, // ??? - { 0, 0, 2, 2, 4, 4, 6, 6 }, // 0q - { 1, 1, 3, 3, 5, 5, 7, 7 }, // 1q - { 0, 0, 0, 0, 4, 4, 4, 4 }, // 0h - { 1, 1, 1, 1, 5, 5, 5, 5 }, // 1h - { 2, 2, 2, 2, 6, 6, 6, 6 }, // 2h - { 3, 3, 3, 3, 7, 7, 7, 7 }, // 3h - { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0 - { 1, 1, 1, 1, 1, 1, 1, 1 }, // 1 - { 2, 2, 2, 2, 2, 2, 2, 2 }, // 2 - { 3, 3, 3, 3, 3, 3, 3, 3 }, // 3 - { 4, 4, 4, 4, 4, 4, 4, 4 }, // 4 - { 5, 5, 5, 5, 5, 5, 5, 5 }, // 5 - { 6, 6, 6, 6, 6, 6, 6, 6 }, // 6 - { 7, 7, 7, 7, 7, 7, 7, 7 }, // 7 -}; - -void rsp_device::cop2_drc::cfunc_unimplemented_opcode() -{ - const uint32_t ppc = m_rsp.m_ppc; - if ((m_machine.debug_flags & DEBUG_FLAG_ENABLED) != 0) - { - rsp_disassembler rspd; - std::ostringstream stream; - rspd.dasm_one(stream, ppc, m_rspcop2_state->op); - const std::string stream_string = stream.str(); - osd_printf_debug("%08X: %s\n", ppc, stream_string); - } - fatalerror("RSP: unknown opcode %02X (%08X) at %08X\n", m_rspcop2_state->op >> 26, m_rspcop2_state->op, ppc); -} - -void rsp_device::cop2_drc::state_string_export(const int index, std::string &str) const -{ - switch (index) - { - case RSP_V0: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 0, 0), (uint16_t)VREG_S( 0, 1), (uint16_t)VREG_S( 0, 2), (uint16_t)VREG_S( 0, 3), (uint16_t)VREG_S( 0, 4), (uint16_t)VREG_S( 0, 5), (uint16_t)VREG_S( 0, 6), (uint16_t)VREG_S( 0, 7)); - break; - case RSP_V1: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 1, 0), (uint16_t)VREG_S( 1, 1), (uint16_t)VREG_S( 1, 2), (uint16_t)VREG_S( 1, 3), (uint16_t)VREG_S( 1, 4), (uint16_t)VREG_S( 1, 5), (uint16_t)VREG_S( 1, 6), (uint16_t)VREG_S( 1, 7)); - break; - case RSP_V2: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 2, 0), (uint16_t)VREG_S( 2, 1), (uint16_t)VREG_S( 2, 2), (uint16_t)VREG_S( 2, 3), (uint16_t)VREG_S( 2, 4), (uint16_t)VREG_S( 2, 5), (uint16_t)VREG_S( 2, 6), (uint16_t)VREG_S( 2, 7)); - break; - case RSP_V3: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 3, 0), (uint16_t)VREG_S( 3, 1), (uint16_t)VREG_S( 3, 2), (uint16_t)VREG_S( 3, 3), (uint16_t)VREG_S( 3, 4), (uint16_t)VREG_S( 3, 5), (uint16_t)VREG_S( 3, 6), (uint16_t)VREG_S( 3, 7)); - break; - case RSP_V4: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 4, 0), (uint16_t)VREG_S( 4, 1), (uint16_t)VREG_S( 4, 2), (uint16_t)VREG_S( 4, 3), (uint16_t)VREG_S( 4, 4), (uint16_t)VREG_S( 4, 5), (uint16_t)VREG_S( 4, 6), (uint16_t)VREG_S( 4, 7)); - break; - case RSP_V5: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 5, 0), (uint16_t)VREG_S( 5, 1), (uint16_t)VREG_S( 5, 2), (uint16_t)VREG_S( 5, 3), (uint16_t)VREG_S( 5, 4), (uint16_t)VREG_S( 5, 5), (uint16_t)VREG_S( 5, 6), (uint16_t)VREG_S( 5, 7)); - break; - case RSP_V6: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 6, 0), (uint16_t)VREG_S( 6, 1), (uint16_t)VREG_S( 6, 2), (uint16_t)VREG_S( 6, 3), (uint16_t)VREG_S( 6, 4), (uint16_t)VREG_S( 6, 5), (uint16_t)VREG_S( 6, 6), (uint16_t)VREG_S( 6, 7)); - break; - case RSP_V7: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 7, 0), (uint16_t)VREG_S( 7, 1), (uint16_t)VREG_S( 7, 2), (uint16_t)VREG_S( 7, 3), (uint16_t)VREG_S( 7, 4), (uint16_t)VREG_S( 7, 5), (uint16_t)VREG_S( 7, 6), (uint16_t)VREG_S( 7, 7)); - break; - case RSP_V8: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 8, 0), (uint16_t)VREG_S( 8, 1), (uint16_t)VREG_S( 8, 2), (uint16_t)VREG_S( 8, 3), (uint16_t)VREG_S( 8, 4), (uint16_t)VREG_S( 8, 5), (uint16_t)VREG_S( 8, 6), (uint16_t)VREG_S( 8, 7)); - break; - case RSP_V9: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S( 9, 0), (uint16_t)VREG_S( 9, 1), (uint16_t)VREG_S( 9, 2), (uint16_t)VREG_S( 9, 3), (uint16_t)VREG_S( 9, 4), (uint16_t)VREG_S( 9, 5), (uint16_t)VREG_S( 9, 6), (uint16_t)VREG_S( 9, 7)); - break; - case RSP_V10: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(10, 0), (uint16_t)VREG_S(10, 1), (uint16_t)VREG_S(10, 2), (uint16_t)VREG_S(10, 3), (uint16_t)VREG_S(10, 4), (uint16_t)VREG_S(10, 5), (uint16_t)VREG_S(10, 6), (uint16_t)VREG_S(10, 7)); - break; - case RSP_V11: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(11, 0), (uint16_t)VREG_S(11, 1), (uint16_t)VREG_S(11, 2), (uint16_t)VREG_S(11, 3), (uint16_t)VREG_S(11, 4), (uint16_t)VREG_S(11, 5), (uint16_t)VREG_S(11, 6), (uint16_t)VREG_S(11, 7)); - break; - case RSP_V12: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(12, 0), (uint16_t)VREG_S(12, 1), (uint16_t)VREG_S(12, 2), (uint16_t)VREG_S(12, 3), (uint16_t)VREG_S(12, 4), (uint16_t)VREG_S(12, 5), (uint16_t)VREG_S(12, 6), (uint16_t)VREG_S(12, 7)); - break; - case RSP_V13: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(13, 0), (uint16_t)VREG_S(13, 1), (uint16_t)VREG_S(13, 2), (uint16_t)VREG_S(13, 3), (uint16_t)VREG_S(13, 4), (uint16_t)VREG_S(13, 5), (uint16_t)VREG_S(13, 6), (uint16_t)VREG_S(13, 7)); - break; - case RSP_V14: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(14, 0), (uint16_t)VREG_S(14, 1), (uint16_t)VREG_S(14, 2), (uint16_t)VREG_S(14, 3), (uint16_t)VREG_S(14, 4), (uint16_t)VREG_S(14, 5), (uint16_t)VREG_S(14, 6), (uint16_t)VREG_S(14, 7)); - break; - case RSP_V15: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(15, 0), (uint16_t)VREG_S(15, 1), (uint16_t)VREG_S(15, 2), (uint16_t)VREG_S(15, 3), (uint16_t)VREG_S(15, 4), (uint16_t)VREG_S(15, 5), (uint16_t)VREG_S(15, 6), (uint16_t)VREG_S(15, 7)); - break; - case RSP_V16: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(16, 0), (uint16_t)VREG_S(16, 1), (uint16_t)VREG_S(16, 2), (uint16_t)VREG_S(16, 3), (uint16_t)VREG_S(16, 4), (uint16_t)VREG_S(16, 5), (uint16_t)VREG_S(16, 6), (uint16_t)VREG_S(16, 7)); - break; - case RSP_V17: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(17, 0), (uint16_t)VREG_S(17, 1), (uint16_t)VREG_S(17, 2), (uint16_t)VREG_S(17, 3), (uint16_t)VREG_S(17, 4), (uint16_t)VREG_S(17, 5), (uint16_t)VREG_S(17, 6), (uint16_t)VREG_S(17, 7)); - break; - case RSP_V18: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(18, 0), (uint16_t)VREG_S(18, 1), (uint16_t)VREG_S(18, 2), (uint16_t)VREG_S(18, 3), (uint16_t)VREG_S(18, 4), (uint16_t)VREG_S(18, 5), (uint16_t)VREG_S(18, 6), (uint16_t)VREG_S(18, 7)); - break; - case RSP_V19: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(19, 0), (uint16_t)VREG_S(19, 1), (uint16_t)VREG_S(19, 2), (uint16_t)VREG_S(19, 3), (uint16_t)VREG_S(19, 4), (uint16_t)VREG_S(19, 5), (uint16_t)VREG_S(19, 6), (uint16_t)VREG_S(19, 7)); - break; - case RSP_V20: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(20, 0), (uint16_t)VREG_S(20, 1), (uint16_t)VREG_S(20, 2), (uint16_t)VREG_S(20, 3), (uint16_t)VREG_S(20, 4), (uint16_t)VREG_S(20, 5), (uint16_t)VREG_S(20, 6), (uint16_t)VREG_S(20, 7)); - break; - case RSP_V21: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(21, 0), (uint16_t)VREG_S(21, 1), (uint16_t)VREG_S(21, 2), (uint16_t)VREG_S(21, 3), (uint16_t)VREG_S(21, 4), (uint16_t)VREG_S(21, 5), (uint16_t)VREG_S(21, 6), (uint16_t)VREG_S(21, 7)); - break; - case RSP_V22: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(22, 0), (uint16_t)VREG_S(22, 1), (uint16_t)VREG_S(22, 2), (uint16_t)VREG_S(22, 3), (uint16_t)VREG_S(22, 4), (uint16_t)VREG_S(22, 5), (uint16_t)VREG_S(22, 6), (uint16_t)VREG_S(22, 7)); - break; - case RSP_V23: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(23, 0), (uint16_t)VREG_S(23, 1), (uint16_t)VREG_S(23, 2), (uint16_t)VREG_S(23, 3), (uint16_t)VREG_S(23, 4), (uint16_t)VREG_S(23, 5), (uint16_t)VREG_S(23, 6), (uint16_t)VREG_S(23, 7)); - break; - case RSP_V24: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(24, 0), (uint16_t)VREG_S(24, 1), (uint16_t)VREG_S(24, 2), (uint16_t)VREG_S(24, 3), (uint16_t)VREG_S(24, 4), (uint16_t)VREG_S(24, 5), (uint16_t)VREG_S(24, 6), (uint16_t)VREG_S(24, 7)); - break; - case RSP_V25: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(25, 0), (uint16_t)VREG_S(25, 1), (uint16_t)VREG_S(25, 2), (uint16_t)VREG_S(25, 3), (uint16_t)VREG_S(25, 4), (uint16_t)VREG_S(25, 5), (uint16_t)VREG_S(25, 6), (uint16_t)VREG_S(25, 7)); - break; - case RSP_V26: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(26, 0), (uint16_t)VREG_S(26, 1), (uint16_t)VREG_S(26, 2), (uint16_t)VREG_S(26, 3), (uint16_t)VREG_S(26, 4), (uint16_t)VREG_S(26, 5), (uint16_t)VREG_S(26, 6), (uint16_t)VREG_S(26, 7)); - break; - case RSP_V27: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(27, 0), (uint16_t)VREG_S(27, 1), (uint16_t)VREG_S(27, 2), (uint16_t)VREG_S(27, 3), (uint16_t)VREG_S(27, 4), (uint16_t)VREG_S(27, 5), (uint16_t)VREG_S(27, 6), (uint16_t)VREG_S(27, 7)); - break; - case RSP_V28: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(28, 0), (uint16_t)VREG_S(28, 1), (uint16_t)VREG_S(28, 2), (uint16_t)VREG_S(28, 3), (uint16_t)VREG_S(28, 4), (uint16_t)VREG_S(28, 5), (uint16_t)VREG_S(28, 6), (uint16_t)VREG_S(28, 7)); - break; - case RSP_V29: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(29, 0), (uint16_t)VREG_S(29, 1), (uint16_t)VREG_S(29, 2), (uint16_t)VREG_S(29, 3), (uint16_t)VREG_S(29, 4), (uint16_t)VREG_S(29, 5), (uint16_t)VREG_S(29, 6), (uint16_t)VREG_S(29, 7)); - break; - case RSP_V30: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(30, 0), (uint16_t)VREG_S(30, 1), (uint16_t)VREG_S(30, 2), (uint16_t)VREG_S(30, 3), (uint16_t)VREG_S(30, 4), (uint16_t)VREG_S(30, 5), (uint16_t)VREG_S(30, 6), (uint16_t)VREG_S(30, 7)); - break; - case RSP_V31: - str = string_format("%04X|%04X|%04X|%04X|%04X|%04X|%04X|%04X", (uint16_t)VREG_S(31, 0), (uint16_t)VREG_S(31, 1), (uint16_t)VREG_S(31, 2), (uint16_t)VREG_S(31, 3), (uint16_t)VREG_S(31, 4), (uint16_t)VREG_S(31, 5), (uint16_t)VREG_S(31, 6), (uint16_t)VREG_S(31, 7)); - break; - } -} - - -/*************************************************************************** - Vector Load Instructions -***************************************************************************/ - -// LBV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 00000 | IIII | Offset | -// -------------------------------------------------- -// -// Load 1 byte to vector byte index - -void rsp_device::cop2_drc::lbv() -{ - uint32_t op = m_rspcop2_state->op; - - uint32_t ea; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset; - VREG_B(dest, index) = m_rsp.DM_READ8(ea); -} - - -// LSV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 00001 | IIII | Offset | -// -------------------------------------------------- -// -// Loads 2 bytes starting from vector byte index - -void rsp_device::cop2_drc::lsv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 2) : (offset * 2); - int end = index + 2; - for (int i = index; i < end; i++) - { - VREG_B(dest, i) = m_rsp.DM_READ8(ea); - ea++; - } -} - - -// LLV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 00010 | IIII | Offset | -// -------------------------------------------------- -// -// Loads 4 bytes starting from vector byte index - -void rsp_device::cop2_drc::llv() -{ - uint32_t op = m_rspcop2_state->op; - uint32_t ea; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 4) : (offset * 4); - - int end = index + 4; - - for (int i = index; i < end; i++) - { - VREG_B(dest, i) = m_rsp.DM_READ8(ea); - ea++; - } -} - - -// LDV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 00011 | IIII | Offset | -// -------------------------------------------------- -// -// Loads 8 bytes starting from vector byte index - -void rsp_device::cop2_drc::ldv() -{ - uint32_t op = m_rspcop2_state->op; - uint32_t ea; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - - int end = index + 8; - - for (int i = index; i < end; i++) - { - VREG_B(dest, i) = m_rsp.DM_READ8(ea); - ea++; - } -} - - -// LQV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 00100 | IIII | Offset | -// -------------------------------------------------- -// -// Loads up to 16 bytes starting from vector byte index - -void rsp_device::cop2_drc::lqv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - int end = 16 - (ea & 0xf); - if (end > 16) end = 16; - - for (int i = 0; i < end; i++) - { - VREG_B(dest, i) = m_rsp.DM_READ8(ea); - ea++; - } -} - - -// LRV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 00101 | IIII | Offset | -// -------------------------------------------------- -// -// Stores up to 16 bytes starting from right side until 16-byte boundary - -void rsp_device::cop2_drc::lrv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - index = 16 - ((ea & 0xf) - index); - ea &= ~0xf; - - for (int i = index; i < 16; i++) - { - VREG_B(dest, i) = m_rsp.DM_READ8(ea); - ea++; - } -} - - -// LPV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 00110 | IIII | Offset | -// -------------------------------------------------- -// -// Loads a byte as the upper 8 bits of each element - -void rsp_device::cop2_drc::lpv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - - for (int i = 0; i < 8; i++) - { - W_VREG_S(dest, i) = m_rsp.DM_READ8(ea + (((16-index) + i) & 0xf)) << 8; - } -} - - -// LUV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 00111 | IIII | Offset | -// -------------------------------------------------- -// -// Loads a byte as the bits 14-7 of each element - -void rsp_device::cop2_drc::luv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - - for (int i = 0; i < 8; i++) - { - W_VREG_S(dest, i) = m_rsp.DM_READ8(ea + (((16-index) + i) & 0xf)) << 7; - } -} - - -// LHV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 01000 | IIII | Offset | -// -------------------------------------------------- -// -// Loads a byte as the bits 14-7 of each element, with 2-byte stride - -void rsp_device::cop2_drc::lhv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - for (int i = 0; i < 8; i++) - { - W_VREG_S(dest, i) = m_rsp.DM_READ8(ea + (((16-index) + (i<<1)) & 0xf)) << 7; - } -} - - -// LFV -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 01001 | IIII | Offset | -// -------------------------------------------------- -// -// Loads a byte as the bits 14-7 of upper or lower quad, with 4-byte stride - -void rsp_device::cop2_drc::lfv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - // not sure what happens if 16-byte boundary is crossed... - - int end = (index >> 1) + 4; - - for (int i = index >> 1; i < end; i++) - { - W_VREG_S(dest, i) = m_rsp.DM_READ8(ea) << 7; - ea += 4; - } -} - - -// LWV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 01010 | IIII | Offset | -// -------------------------------------------------- -// -// Loads the full 128-bit vector starting from vector byte index and wrapping to index 0 -// after byte index 15 - -void rsp_device::cop2_drc::lwv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - int end = (16 - index) + 16; - - for (int i = (16 - index); i < end; i++) - { - VREG_B(dest, i & 0xf) = m_rsp.DM_READ8(ea); - ea += 4; - } -} - - -// LTV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 110010 | BBBBB | TTTTT | 01011 | IIII | Offset | -// -------------------------------------------------- -// -// Loads one element to maximum of 8 vectors, while incrementing element index - -void rsp_device::cop2_drc::ltv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - - // FIXME: has a small problem with odd indices - - int vs = dest; - int ve = dest + 8; - if (ve > 32) - { - ve = 32; - } - - int element; - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - ea = ((ea + 8) & ~0xf) + (index & 1); - for (int i = vs; i < ve; i++) - { - element = (8 - (index >> 1) + (i - vs)) << 1; - VREG_B(i, (element & 0xf)) = m_rsp.DM_READ8(ea); - VREG_B(i, ((element + 1) & 0xf)) = m_rsp.DM_READ8(ea + 1); - ea += 2; - } -} - - -bool rsp_device::cop2_drc::generate_lwc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) -{ - uint32_t op = desc->opptr.l[0]; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - switch ((op >> 11) & 0x1f) - { - case 0x00: /* LBV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_lbv, this); - return true; - - case 0x01: /* LSV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_lsv, this); - return true; - - case 0x02: /* LLV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_llv, this); - return true; - - case 0x03: /* LDV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_ldv, this); - return true; - - case 0x04: /* LQV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_lqv, this); - return true; - - case 0x05: /* LRV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_lrv, this); - return true; - - case 0x06: /* LPV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_lpv, this); - return true; - - case 0x07: /* LUV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_luv, this); - return true; - - case 0x08: /* LHV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_lhv, this); - return true; - - case 0x09: /* LFV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_lfv, this); - return true; - - case 0x0a: /* LWV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_lwv, this); - return true; - - case 0x0b: /* LTV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [m_rspcop2_state->op],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_ltv, this); - return true; - - default: - return false; - } -} - - -/*************************************************************************** - Vector Store Instructions -***************************************************************************/ - -// SBV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 00000 | IIII | Offset | -// -------------------------------------------------- -// -// Stores 1 byte from vector byte index - -void rsp_device::cop2_drc::sbv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + offset : offset; - m_rsp.DM_WRITE8(ea, VREG_B(dest, index)); -} - - -// SSV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 00001 | IIII | Offset | -// -------------------------------------------------- -// -// Stores 2 bytes starting from vector byte index - -void rsp_device::cop2_drc::ssv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 2) : (offset * 2); - - int end = index + 2; - for (int i = index; i < end; i++) - { - m_rsp.DM_WRITE8(ea, VREG_B(dest, i)); - ea++; - } -} - - -// SLV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 00010 | IIII | Offset | -// -------------------------------------------------- -// -// Stores 4 bytes starting from vector byte index - -void rsp_device::cop2_drc::slv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 4) : (offset * 4); - - int end = index + 4; - for (int i = index; i < end; i++) - { - m_rsp.DM_WRITE8(ea, VREG_B(dest, i)); - ea++; - } -} - - -// SDV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 00011 | IIII | Offset | -// -------------------------------------------------- -// -// Stores 8 bytes starting from vector byte index - -void rsp_device::cop2_drc::sdv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - - int end = index + 8; - for (int i = index; i < end; i++) - { - m_rsp.DM_WRITE8(ea, VREG_B(dest, i)); - ea++; - } -} - - -// SQV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 00100 | IIII | Offset | -// -------------------------------------------------- -// -// Stores up to 16 bytes starting from vector byte index until 16-byte boundary - -void rsp_device::cop2_drc::sqv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - int end = index + (16 - (ea & 0xf)); - for (int i=index; i < end; i++) - { - m_rsp.DM_WRITE8(ea, VREG_B(dest, i & 0xf)); - ea++; - } -} - - -// SRV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 00101 | IIII | Offset | -// -------------------------------------------------- -// -// Stores up to 16 bytes starting from right side until 16-byte boundary - -void rsp_device::cop2_drc::srv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - - int end = index + (ea & 0xf); - int o = (16 - (ea & 0xf)) & 0xf; - ea &= ~0xf; - - for (int i = index; i < end; i++) - { - m_rsp.DM_WRITE8(ea, VREG_B(dest, ((i + o) & 0xf))); - ea++; - } -} - - -// SPV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 00110 | IIII | Offset | -// -------------------------------------------------- -// -// Stores upper 8 bits of each element - -void rsp_device::cop2_drc::spv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - int end = index + 8; - for (int i=index; i < end; i++) - { - if ((i & 0xf) < 8) - { - m_rsp.DM_WRITE8(ea, VREG_B(dest, (i & 0xf) << 1)); - } - else - { - m_rsp.DM_WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7); - } - ea++; - } -} - - -// SUV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 00111 | IIII | Offset | -// -------------------------------------------------- -// -// Stores bits 14-7 of each element - -void rsp_device::cop2_drc::suv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 8) : (offset * 8); - int end = index + 8; - for (int i=index; i < end; i++) - { - if ((i & 0xf) < 8) - { - m_rsp.DM_WRITE8(ea, VREG_S(dest, (i & 0x7)) >> 7); - } - else - { - m_rsp.DM_WRITE8(ea, VREG_B(dest, ((i & 0x7) << 1))); - } - ea++; - } -} - - -// SHV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 01000 | IIII | Offset | -// -------------------------------------------------- -// -// Stores bits 14-7 of each element, with 2-byte stride - -void rsp_device::cop2_drc::shv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - for (int i=0; i < 8; i++) - { - int element = index + (i << 1); - uint8_t d = (VREG_B(dest, (element & 0xf)) << 1) | - (VREG_B(dest, ((element + 1) & 0xf)) >> 7); - m_rsp.DM_WRITE8(ea, d); - ea += 2; - } -} - - -// SFV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 01001 | IIII | Offset | -// -------------------------------------------------- -// -// Stores bits 14-7 of upper or lower quad, with 4-byte stride - -void rsp_device::cop2_drc::sfv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - int eaoffset = ea & 0xf; - ea &= ~0xf; - - int end = (index >> 1) + 4; - - for (int i = index>>1; i < end; i++) - { - m_rsp.DM_WRITE8(ea + (eaoffset & 0xf), VREG_S(dest, i) >> 7); - eaoffset += 4; - } -} - - -// SWV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 01010 | IIII | Offset | -// -------------------------------------------------- -// -// Stores the full 128-bit vector starting from vector byte index and wrapping to index 0 -// after byte index 15 - -void rsp_device::cop2_drc::swv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - int eaoffset = ea & 0xf; - ea &= ~0xf; - - int end = index + 16; - for (int i = index; i < end; i++) - { - m_rsp.DM_WRITE8(ea + (eaoffset & 0xf), VREG_B(dest, i & 0xf)); - eaoffset++; - } -} - - -// STV -// -// 31 25 20 15 10 6 0 -// -------------------------------------------------- -// | 111010 | BBBBB | TTTTT | 01011 | IIII | Offset | -// -------------------------------------------------- -// -// Stores one element from maximum of 8 vectors, while incrementing element index - -void rsp_device::cop2_drc::stv() -{ - uint32_t op = m_rspcop2_state->op; - int dest = (op >> 16) & 0x1f; - int base = (op >> 21) & 0x1f; - int index = (op >> 7) & 0xf; - int offset = (op & 0x7f); - - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - int vs = dest; - int ve = dest + 8; - if (ve > 32) - { - ve = 32; - } - - int element = 8 - (index >> 1); - - uint32_t ea = (base) ? m_rsp.m_rsp_state->r[base] + (offset * 16) : (offset * 16); - int eaoffset = (ea & 0xf) + (element * 2); - ea &= ~0xf; - - for (int i = vs; i < ve; i++) - { - m_rsp.DM_WRITE16(ea + (eaoffset & 0xf), VREG_S(i, element & 0x7)); - eaoffset += 2; - element++; - } -} - -bool rsp_device::cop2_drc::generate_swc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) -{ - uint32_t op = desc->opptr.l[0]; - int offset = (op & 0x7f); - if (offset & 0x40) - { - offset |= 0xffffffc0; - } - - switch ((op >> 11) & 0x1f) - { - case 0x00: /* SBV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_sbv, this); - return true; - - case 0x01: /* SSV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_ssv, this); - return true; - - case 0x02: /* SLV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_slv, this); - return true; - - case 0x03: /* SDV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_sdv, this); - return true; - - case 0x04: /* SQV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_sqv, this); - return true; - - case 0x05: /* SRV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_srv, this); - return true; - - case 0x06: /* SPV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_spv, this); - return true; - - case 0x07: /* SUV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_suv, this); - return true; - - case 0x08: /* SHV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_shv, this); - return true; - - case 0x09: /* SFV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_sfv, this); - return true; - - case 0x0a: /* SWV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_swv, this); - return true; - - case 0x0b: /* STV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_stv, this); - return true; - - default: - m_rsp.unimplemented_opcode(op); - return false; - } - - return true; -} - - -/*************************************************************************** - Vector Opcodes -***************************************************************************/ - -// VMULF -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000000 | -// ------------------------------------------------------ -// -// Multiplies signed integer by signed integer * 2 - -void rsp_device::cop2_drc::vmulf() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (int32_t)(int16_t)w1; - int32_t s2 = (int32_t)(int16_t)w2; - - if (s1 == -32768 && s2 == -32768) - { - // overflow - ACCUM(i) = s64(0x0000800080000000U); - m_vres[i] = 0x7fff; - } - else - { - ACCUM(i) = (int64_t)(s1 * s2 * 2 + 0x8000) << 16; // rounding? - m_vres[i] = ACCUM_M(i); - } - } - WRITEBACK_RESULT(); -} - - -// VMULU -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000001 | -// ------------------------------------------------------ -// - -void rsp_device::cop2_drc::vmulu() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (int32_t)(int16_t)w1; - int32_t s2 = (int32_t)(int16_t)w2; - - int64_t r = s1 * s2 * 2 + 0x8000; // rounding? - - ACCUM(i) = r << 16; - - if (r < 0) - { - m_vres[i] = 0; - } - else if (((int16_t)(ACCUM_H(i)) ^ (int16_t)(ACCUM_M(i))) < 0) - { - m_vres[i] = -1; - } - else - { - m_vres[i] = ACCUM_M(i); - } - } - WRITEBACK_RESULT(); -} - - -// VMUDL -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001101 | -// ------------------------------------------------------ -// -// Multiplies signed integer by unsigned fraction -// The result is added into accumulator -// The middle slice of accumulator is stored into destination element - -void rsp_device::cop2_drc::vmudl() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - uint32_t s1 = (uint32_t)(uint16_t)w1; - uint32_t s2 = (uint32_t)(uint16_t)w2; - - ACCUM(i) = s1 * s2; - - m_vres[i] = ACCUM_L(i); - } - WRITEBACK_RESULT(); -} - - -// VMUDM -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000101 | -// ------------------------------------------------------ -// -// Multiplies signed integer by unsigned fraction -// The result is stored into accumulator -// The middle slice of accumulator is stored into destination element - -void rsp_device::cop2_drc::vmudm() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (int32_t)(int16_t)w1; - int32_t s2 = (uint16_t)w2; - - ACCUM(i) = (int64_t)(s1 * s2) << 16; - - m_vres[i] = ACCUM_M(i); - } - WRITEBACK_RESULT(); -} - - -// VMUDN -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000110 | -// ------------------------------------------------------ -// -// Multiplies unsigned fraction by signed integer -// The result is stored into accumulator -// The low slice of accumulator is stored into destination element - -void rsp_device::cop2_drc::vmudn() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (uint16_t)w1; - int32_t s2 = (int32_t)(int16_t)w2; - - int32_t r = s1 * s2; - - ACCUM(i) = (int64_t)(s1 * s2) << 16; - - m_vres[i] = (uint16_t)(r); - } - WRITEBACK_RESULT(); -} - - -// VMUDH -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 000111 | -// ------------------------------------------------------ -// -// Multiplies signed integer by signed integer -// The result is stored into highest 32 bits of accumulator, the low slice is zero -// The highest 32 bits of accumulator is saturated into destination element - -void rsp_device::cop2_drc::vmudh() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (int32_t)(int16_t)w1; - int32_t s2 = (int32_t)(int16_t)w2; - - int32_t r = s1 * s2; - - ACCUM(i) = (int64_t)r << 32; - - if (r < -32768) r = -32768; - if (r > 32767) r = 32767; - m_vres[i] = (int16_t)(r); - } - WRITEBACK_RESULT(); -} - - -// VMACF -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001000 | -// ------------------------------------------------------ -// - -void rsp_device::cop2_drc::vmacf() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (int32_t)(int16_t)w1; - int32_t s2 = (int32_t)(int16_t)w2; - - ACCUM(i) += (int64_t)(s1 * s2 * 2) << 16; - - m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff); - } - WRITEBACK_RESULT(); -} - - -// VMACU -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001001 | -// ------------------------------------------------------ -// - -void rsp_device::cop2_drc::vmacu() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (int32_t)(int16_t)w1; - int32_t s2 = (int32_t)(int16_t)w2; - - ACCUM(i) += (int64_t)(s1 * s2 * 2) << 16; - - if ((int16_t)ACCUM_H(i) < 0) - { - m_vres[i] = 0; - } - else - { - if (ACCUM_H(i) != 0) - { - m_vres[i] = (int16_t)0xffff; - } - else - { - if ((int16_t)ACCUM_M(i) < 0) - { - m_vres[i] = (int16_t)0xffff; - } - else - { - m_vres[i] = ACCUM_M(i); - } - } - } - } - WRITEBACK_RESULT(); -} - - -// VMADL -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001100 | -// ------------------------------------------------------ -// -// Multiplies unsigned fraction by unsigned fraction -// Adds the higher 16 bits of the 32-bit result to accumulator -// The low slice of accumulator is stored into destination element - -void rsp_device::cop2_drc::vmadl() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - uint32_t s1 = w1; - uint32_t s2 = w2; - - ACCUM(i) += (s1 * s2) & 0xffff0000; - - m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff); - } - WRITEBACK_RESULT(); -} - - -// VMADM -// - -void rsp_device::cop2_drc::vmadm() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - uint32_t s1 = (int32_t)(int16_t)w1; - uint32_t s2 = (uint16_t)w2; - - ACCUM(i) += (int64_t)(int32_t)(s1 * s2) << 16; - - m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff); - } - WRITEBACK_RESULT(); -} - - -// VMADN -// - -void rsp_device::cop2_drc::vmadn() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (uint16_t)w1; - int32_t s2 = (int32_t)(int16_t)w2; - - ACCUM(i) += (int64_t)(s1 * s2) << 16; - - m_vres[i] = SATURATE_ACCUM(i, 0, 0x0000, 0xffff); - } - WRITEBACK_RESULT(); -} - - -// VMADH -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 001111 | -// ------------------------------------------------------ -// -// Multiplies signed integer by signed integer -// The result is added into highest 32 bits of accumulator, the low slice is zero -// The highest 32 bits of accumulator is saturated into destination element - -void rsp_device::cop2_drc::vmadh() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - int16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (int32_t)(int16_t)w1; - int32_t s2 = (int32_t)(int16_t)w2; - - ACCUM(i) += (int64_t)(s1 * s2) << 32; - - m_vres[i] = SATURATE_ACCUM(i, 1, 0x8000, 0x7fff); - } - WRITEBACK_RESULT(); -} - - -// VADD -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010000 | -// ------------------------------------------------------ -// -// Adds two vector registers and carry flag, the result is saturated to 32767 - -void rsp_device::cop2_drc::vadd() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - int16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (int32_t)(int16_t)w1; - int32_t s2 = (int32_t)(int16_t)w2; - int32_t r = s1 + s2 + (((CARRY_FLAG(i)) != 0) ? 1 : 0); - - SET_ACCUM_L((int16_t)(r), i); - - if (r > 32767) r = 32767; - if (r < -32768) r = -32768; - m_vres[i] = (int16_t)(r); - } - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - WRITEBACK_RESULT(); -} - - -// VSUB -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010001 | -// ------------------------------------------------------ -// -// Subtracts two vector registers and carry flag, the result is saturated to -32768 -// TODO: check VS2REG == VDREG - -void rsp_device::cop2_drc::vsub() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - int16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (int32_t)(int16_t)w1; - int32_t s2 = (int32_t)(int16_t)w2; - int32_t r = s1 - s2 - (((CARRY_FLAG(i)) != 0) ? 1 : 0); - - SET_ACCUM_L((int16_t)(r), i); - - if (r > 32767) r = 32767; - if (r < -32768) r = -32768; - - m_vres[i] = (int16_t)(r); - } - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - WRITEBACK_RESULT(); -} - - -// VABS -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010011 | -// ------------------------------------------------------ -// -// Changes the sign of source register 2 if source register 1 is negative and stores the result to destination register - -void rsp_device::cop2_drc::vabs() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - int16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - - if (s1 < 0) - { - if (s2 == -32768) - { - m_vres[i] = 32767; - } - else - { - m_vres[i] = -s2; - } - } - else if (s1 > 0) - { - m_vres[i] = s2; - } - else - { - m_vres[i] = 0; - } - - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -} - - -// VADDC -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010100 | -// ------------------------------------------------------ -// -// Adds two vector registers, the carry out is stored into carry register -// TODO: check VS2REG = VDREG - -void rsp_device::cop2_drc::vaddc() -{ - CACHE_VALUES(); - - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - - for (int i = 0; i < 8; i++) - { - int16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (uint32_t)(uint16_t)w1; - int32_t s2 = (uint32_t)(uint16_t)w2; - int32_t r = s1 + s2; - - m_vres[i] = (int16_t)(r); - SET_ACCUM_L((int16_t)r, i); - - if (r & 0xffff0000) - { - SET_CARRY_FLAG(i); - } - } - WRITEBACK_RESULT(); -} - - -// VSUBC -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010101 | -// ------------------------------------------------------ -// -// Subtracts two vector registers, the carry out is stored into carry register -// TODO: check VS2REG = VDREG - -void rsp_device::cop2_drc::vsubc() -{ - CACHE_VALUES(); - - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - - for (int i = 0; i < 8; i++) - { - int16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - int32_t s1 = (uint32_t)(uint16_t)w1; - int32_t s2 = (uint32_t)(uint16_t)w2; - int32_t r = s1 - s2; - - m_vres[i] = (int16_t)(r); - SET_ACCUM_L((uint16_t)r, i); - - if ((uint16_t)(r) != 0) - { - SET_ZERO_FLAG(i); - } - if (r & 0xffff0000) - { - SET_CARRY_FLAG(i); - } - } - WRITEBACK_RESULT(); -} - - -// VADDB -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010110 | -// ------------------------------------------------------ -// -// Adds two vector registers bytewise with rounding - -void rsp_device::cop2_drc::vaddb() -{ - CACHE_VALUES(); - const int round = (el == 0) ? 0 : (1 << (el - 1)); - - for (int i = 0; i < 8; i++) - { - uint16_t w1, w2; - GET_VS1(w1, i); - GET_VS2(w2, i); - - uint8_t hb1 = w1 >> 8; - uint8_t lb1 = w1 & 0xff; - uint8_t hb2 = w2 >> 8; - uint8_t lb2 = w2 & 0xff; - - uint16_t hs = hb1 + hb2 + round; - uint16_t ls = lb1 + lb2 + round; - - SET_ACCUM_L((hs << 8) | ls, i); - - hs >>= EL; - if (hs > 255) - { - hs = 255; - } - - ls >>= EL; - if (ls > 255) - { - ls = 255; - } - - m_vres[i] = 0; // VD writeback disabled on production hardware - // m_vres[i] = (hs << 8) | ls; - } - WRITEBACK_RESULT(); -} - - -// VSAW -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 011101 | -// ------------------------------------------------------ -// -// Stores high, middle or low slice of accumulator to destination vector - -void rsp_device::cop2_drc::vsaw() -{ - const int op = m_rspcop2_state->op; - const int vdreg = VDREG; - const int el = EL; - - switch (el) - { - case 0x08: // VSAWH - for (int i = 0; i < 8; i++) - { - W_VREG_S(vdreg, i) = ACCUM_H(i); - } - break; - case 0x09: // VSAWM - for (int i = 0; i < 8; i++) - { - W_VREG_S(vdreg, i) = ACCUM_M(i); - } - break; - case 0x0a: // VSAWL - for (int i = 0; i < 8; i++) - { - W_VREG_S(vdreg, i) = ACCUM_L(i); - } - break; - default: // Unsupported - { - for (int i = 0; i < 8; i++) - { - W_VREG_S(vdreg, i) = 0; - } - } - } -} - - -// VLT -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100000 | -// ------------------------------------------------------ -// -// Sets compare flags if elements in VS1 are less than VS2 -// Moves the element in VS2 to destination vector - -void rsp_device::cop2_drc::vlt() -{ - CACHE_VALUES(); - - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP2_FLAGS(); - - for (int i = 0; i < 8; i++) - { - int16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - - if (s1 < s2) - { - SET_COMPARE_FLAG(i); - } - else if (s1 == s2) - { - if (ZERO_FLAG(i) != 0 && CARRY_FLAG(i) != 0) - { - SET_COMPARE_FLAG(i); - } - } - - if (COMPARE_FLAG(i) != 0) - { - m_vres[i] = s1; - } - else - { - m_vres[i] = s2; - } - - SET_ACCUM_L(m_vres[i], i); - } - - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - WRITEBACK_RESULT(); -} - - -// VEQ -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100001 | -// ------------------------------------------------------ -// -// Sets compare flags if elements in VS1 are equal with VS2 -// Moves the element in VS2 to destination vector - -void rsp_device::cop2_drc::veq() -{ - CACHE_VALUES(); - - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP2_FLAGS(); - - for (int i = 0; i < 8; i++) - { - int16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - - if ((s1 == s2) && ZERO_FLAG(i) == 0) - { - SET_COMPARE_FLAG(i); - m_vres[i] = s1; - } - else - { - m_vres[i] = s2; - } - - SET_ACCUM_L(m_vres[i], i); - } - - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - WRITEBACK_RESULT(); -} - - -// VNE -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100010 | -// ------------------------------------------------------ -// -// Sets compare flags if elements in VS1 are not equal with VS2 -// Moves the element in VS2 to destination vector - -void rsp_device::cop2_drc::vne() -{ - CACHE_VALUES(); - - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP2_FLAGS(); - - for (int i = 0; i < 8; i++) - { - int16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - - if (s1 != s2 || ZERO_FLAG(i) != 0) - { - SET_COMPARE_FLAG(i); - m_vres[i] = s1; - } - else - { - m_vres[i] = s2; - } - - SET_ACCUM_L(m_vres[i], i); - } - - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - WRITEBACK_RESULT(); -} - - -// VGE -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100011 | -// ------------------------------------------------------ -// -// Sets compare flags if elements in VS1 are greater or equal with VS2 -// Moves the element in VS2 to destination vector - -void rsp_device::cop2_drc::vge() -{ - CACHE_VALUES(); - - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP2_FLAGS(); - - for (int i = 0; i < 8; i++) - { - int16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - if ((s1 == s2 && (ZERO_FLAG(i) == 0 || CARRY_FLAG(i) == 0)) || s1 > s2) - { - SET_COMPARE_FLAG(i); - m_vres[i] = s1; - } - else - { - m_vres[i] = s2; - } - - SET_ACCUM_L(m_vres[i], i); - } - - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - WRITEBACK_RESULT(); -} - - -// VCL -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100100 | -// ------------------------------------------------------ -// -// Vector clip low - -void rsp_device::cop2_drc::vcl() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - int16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - - if (CARRY_FLAG(i) != 0) - { - if (ZERO_FLAG(i) != 0) - { - if (COMPARE_FLAG(i) != 0) - { - SET_ACCUM_L(-(uint16_t)s2, i); - } - else - { - SET_ACCUM_L(s1, i); - } - } - else - { - if (CLIP1_FLAG(i) != 0) - { - if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) > 0x10000) - { - SET_ACCUM_L(s1, i); - CLEAR_COMPARE_FLAG(i); - } - else - { - SET_ACCUM_L(-((uint16_t)s2), i); - SET_COMPARE_FLAG(i); - } - } - else - { - if (((uint32_t)(uint16_t)(s1) + (uint32_t)(uint16_t)(s2)) != 0) - { - SET_ACCUM_L(s1, i); - CLEAR_COMPARE_FLAG(i); - } - else - { - SET_ACCUM_L(-((uint16_t)s2), i); - SET_COMPARE_FLAG(i); - } - } - } - } - else - { - if (ZERO_FLAG(i) != 0) - { - if (CLIP2_FLAG(i) != 0) - { - SET_ACCUM_L(s2, i); - } - else - { - SET_ACCUM_L(s1, i); - } - } - else - { - if (((int32_t)(uint16_t)s1 - (int32_t)(uint16_t)s2) >= 0) - { - SET_ACCUM_L(s2, i); - SET_CLIP2_FLAG(i); - } - else - { - SET_ACCUM_L(s1, i); - CLEAR_CLIP2_FLAG(i); - } - } - } - m_vres[i] = ACCUM_L(i); - } - CLEAR_ZERO_FLAGS(); - CLEAR_CARRY_FLAGS(); - CLEAR_CLIP1_FLAGS(); - WRITEBACK_RESULT(); -} - - -// VCH -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100101 | -// ------------------------------------------------------ -// -// Vector clip high - -void rsp_device::cop2_drc::vch() -{ - CACHE_VALUES(); - - CLEAR_CARRY_FLAGS(); - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP1_FLAGS(); - CLEAR_ZERO_FLAGS(); - CLEAR_CLIP2_FLAGS(); - - uint32_t vce; - for (int i = 0; i < 8; i++) - { - int16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - - if ((s1 ^ s2) < 0) - { - vce = (s1 + s2 == -1); - SET_CARRY_FLAG(i); - if (s2 < 0) - { - SET_CLIP2_FLAG(i); - } - - if ((s1 + s2) <= 0) - { - SET_COMPARE_FLAG(i); - m_vres[i] = -((uint16_t)s2); - } - else - { - m_vres[i] = s1; - } - - if ((s1 + s2) != 0 && s1 != ~s2) - { - SET_ZERO_FLAG(i); - } - }//sign - else - { - vce = 0; - if (s2 < 0) - { - SET_COMPARE_FLAG(i); - } - if ((s1 - s2) >= 0) - { - SET_CLIP2_FLAG(i); - m_vres[i] = s2; - } - else - { - m_vres[i] = s1; - } - - if ((s1 - s2) != 0 && s1 != ~s2) - { - SET_ZERO_FLAG(i); - } - } - if (vce) - { - SET_CLIP1_FLAG(i); - } - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -} - - -// VCR -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100110 | -// ------------------------------------------------------ -// -// Vector clip reverse - -void rsp_device::cop2_drc::vcr() -{ - CACHE_VALUES(); - - CLEAR_CARRY_FLAGS(); - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP1_FLAGS(); - CLEAR_ZERO_FLAGS(); - CLEAR_CLIP2_FLAGS(); - - for (int i = 0; i < 8; i++) - { - int16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - - if ((int16_t)(s1 ^ s2) < 0) - { - if (s2 < 0) - { - SET_CLIP2_FLAG(i); - } - if ((s1 + s2) <= 0) - { - SET_ACCUM_L(~((uint16_t)s2), i); - SET_COMPARE_FLAG(i); - } - else - { - SET_ACCUM_L(s1, i); - } - } - else - { - if (s2 < 0) - { - SET_COMPARE_FLAG(i); - } - if ((s1 - s2) >= 0) - { - SET_ACCUM_L(s2, i); - SET_CLIP2_FLAG(i); - } - else - { - SET_ACCUM_L(s1, i); - } - } - - m_vres[i] = ACCUM_L(i); - } - WRITEBACK_RESULT(); -} - - -// VMRG -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 100111 | -// ------------------------------------------------------ -// -// Merges two vectors according to compare flags - -void rsp_device::cop2_drc::vmrg() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - int16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - if (COMPARE_FLAG(i) != 0) - { - m_vres[i] = s1; - } - else - { - m_vres[i] = s2; - } - - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -} - - -// VAND -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101000 | -// ------------------------------------------------------ -// -// Bitwise AND of two vector registers - -void rsp_device::cop2_drc::vand() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - m_vres[i] = s1 & s2; - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -} - - -// VNAND -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101001 | -// ------------------------------------------------------ -// -// Bitwise NOT AND of two vector registers - -void rsp_device::cop2_drc::vnand() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - m_vres[i] = ~((s1 & s2)); - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -} - - -// VOR -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101010 | -// ------------------------------------------------------ -// -// Bitwise OR of two vector registers - -void rsp_device::cop2_drc::vor() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - m_vres[i] = s1 | s2; - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -} - - -// VNOR -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101011 | -// ------------------------------------------------------ -// -// Bitwise NOT OR of two vector registers - -void rsp_device::cop2_drc::vnor() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - m_vres[i] = ~(s1 | s2); - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -} - - -// VXOR -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101100 | -// ------------------------------------------------------ -// -// Bitwise XOR of two vector registers - -void rsp_device::cop2_drc::vxor() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - m_vres[i] = s1 ^ s2; - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -} - - -// VNXOR -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 101101 | -// ------------------------------------------------------ -// -// Bitwise NOT XOR of two vector registers - -void rsp_device::cop2_drc::vnxor() -{ - CACHE_VALUES(); - - for (int i = 0; i < 8; i++) - { - uint16_t s1, s2; - GET_VS1(s1, i); - GET_VS2(s2, i); - m_vres[i] = ~(s1 ^ s2); - SET_ACCUM_L(m_vres[i], i); - } - WRITEBACK_RESULT(); -} - - -// VRCP -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110000 | -// ------------------------------------------------------ -// -// Calculates reciprocal - -void rsp_device::cop2_drc::vrcp() -{ - CACHE_VALUES(); - - int32_t shifter = 0; - int32_t rec = (int16_t)(VREG_S(vs2reg, el & 7)); - int32_t datainput = (rec < 0) ? (-rec) : rec; - if (datainput) - { - for (int i = 0; i < 32; i++) - { - if (datainput & (1 << ((~i) & 0x1f))) - { - shifter = i; - break; - } - } - } - else - { - shifter = 0x10; - } - - int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22; - int32_t fetchval = rsp_divtable[address]; - int32_t temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); - if (rec < 0) - { - temp = ~temp; - } - if (!rec) - { - temp = 0x7fffffff; - } - else if (rec == 0xffff8000) - { - temp = 0xffff0000; - } - rec = temp; - - m_reciprocal_res = rec; - m_dp_allowed = 0; - - W_VREG_S(vdreg, vs1reg & 7) = (uint16_t)rec; - for (int i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(vs2reg, VEC_EL_2(el, i)), i); - } -} - - -// VRCPL -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110001 | -// ------------------------------------------------------ -// -// Calculates reciprocal low part - -void rsp_device::cop2_drc::vrcpl() -{ - CACHE_VALUES(); - - int32_t shifter = 0; - int32_t rec = (int16_t)VREG_S(vs2reg, el & 7); - int32_t datainput = rec; - - if (m_dp_allowed) - { - rec = (rec & 0x0000ffff) | m_reciprocal_high; - datainput = rec; - - if (rec < 0) - { - if (rec < -32768) - { - datainput = ~datainput; - } - else - { - datainput = -datainput; - } - } - } - else if (datainput < 0) - { - datainput = -datainput; - - shifter = 0x10; - } - - if (datainput) - { - for (int i = 0; i < 32; i++) - { - if (datainput & (1 << ((~i) & 0x1f))) - { - shifter = i; - break; - } - } - } - - uint32_t address = (datainput << shifter) >> 22; - int32_t fetchval = rsp_divtable[address & 0x1ff]; - int32_t temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); - temp ^= rec >> 31; - - if (!rec) - { - temp = 0x7fffffff; - } - else if (rec == 0xffff8000) - { - temp = 0xffff0000; - } - rec = temp; - - m_reciprocal_res = rec; - m_dp_allowed = 0; - - W_VREG_S(vdreg, vs1reg & 7) = (uint16_t)rec; - - for (int i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(vs2reg, VEC_EL_2(el, i)), i); - } -} - - -// VRCPH -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110010 | -// ------------------------------------------------------ -// -// Calculates reciprocal high part - -void rsp_device::cop2_drc::vrcph() -{ - CACHE_VALUES(); - - m_reciprocal_high = (VREG_S(vs2reg, el & 7)) << 16; - m_dp_allowed = 1; - - for (int i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(vs2reg, VEC_EL_2(el, i)), i); - } - - W_VREG_S(vdreg, vs1reg & 7) = (int16_t)(m_reciprocal_res >> 16); -} - - -// VMOV -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110011 | -// ------------------------------------------------------ -// -// Moves element from vector to destination vector - -void rsp_device::cop2_drc::vmov() -{ - CACHE_VALUES(); - - W_VREG_S(vdreg, vs1reg & 7) = VREG_S(vs2reg, el & 7); - for (int i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(vs2reg, VEC_EL_2(el, i)), i); - } -} - - -// VRSQ -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 | -// ------------------------------------------------------ -// -// Calculates reciprocal square-root - -void rsp_device::cop2_drc::vrsq() -{ - CACHE_VALUES(); - - int32_t shifter = 0; - int32_t rec = (int16_t)VREG_S(vs2reg, el & 7); - int32_t datainput = (rec < 0) ? (-rec) : (rec); - - if (rec < 0) - { - if (rec < -32768) - { - datainput = ~datainput; - } - else - { - datainput = -datainput; - } - } - - if (datainput) - { - for (int i = 0; i < 32; i++) - { - if (datainput & (1 << ((~i) & 0x1f))) - { - shifter = i; - break; - } - } - } - else - { - shifter = 0; - } - - int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22; - address = ((address | 0x200) & 0x3fe) | (shifter & 1); - - int32_t fetchval = rsp_divtable[address]; - int32_t temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); - if (rec < 0) - { - temp = ~temp; - } - if (!rec) - { - temp = 0x7fffffff; - } - else if (rec == 0xffff8000) - { - temp = 0xffff0000; - } - rec = temp; - - if (rec < 0) - { - if (m_dp_allowed) - { - if (rec < -32768) - { - datainput = ~datainput; - } - else - { - datainput = -datainput; - } - } - else - { - datainput = -datainput; - } - } - - if (datainput) - { - for (int i = 0; i < 32; i++) - { - if (datainput & (1 << ((~i) & 0x1f))) - { - shifter = i; - break; - } - } - } - else - { - shifter = 0; - } - - address = ((datainput << shifter) & 0x7fc00000) >> 22; - address = ((address | 0x200) & 0x3fe) | (shifter & 1); - - fetchval = rsp_divtable[address]; - temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); - if (rec < 0) - { - temp = ~temp; - } - if (!rec) - { - temp = 0x7fff; - } - else if (rec == 0xffff8000) - { - temp = 0x0000; - } - rec = temp; - - W_VREG_S(vdreg, vs1reg & 7) = (uint16_t)rec; - for (int i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(vs2reg, VEC_EL_2(el, i)), i); - } -} - - -// VRSQL -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110101 | -// ------------------------------------------------------ -// -// Calculates reciprocal square-root low part - -void rsp_device::cop2_drc::vrsql() -{ - CACHE_VALUES(); - - int32_t shifter = 0; - int32_t rec = (int16_t)VREG_S(vs2reg, el & 7); - int32_t datainput = rec; - - if (m_dp_allowed) - { - rec = (rec & 0x0000ffff) | m_reciprocal_high; - datainput = rec; - - if (rec < 0) - { - if (rec < -32768) - { - datainput = ~datainput; - } - else - { - datainput = -datainput; - } - } - } - else if (datainput < 0) - { - datainput = -datainput; - - shifter = 0x10; - } - - if (datainput) - { - for (int i = 0; i < 32; i++) - { - if (datainput & (1 << ((~i) & 0x1f))) - { - shifter = i; - break; - } - } - } - - int32_t address = ((datainput << shifter) & 0x7fc00000) >> 22; - address = ((address | 0x200) & 0x3fe) | (shifter & 1); - - int32_t fetchval = rsp_divtable[address]; - int32_t temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); - temp ^= rec >> 31; - - if (!rec) - { - temp = 0x7fffffff; - } - else if (rec == 0xffff8000) - { - temp = 0xffff0000; - } - rec = temp; - - m_reciprocal_res = rec; - m_dp_allowed = 0; - - W_VREG_S(vdreg, vs1reg & 7) = (uint16_t)(rec & 0xffff); - for (int i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(vs2reg, VEC_EL_2(el, i)), i); - } -} - - -// VRSQH -// -// 31 25 24 20 15 10 5 0 -// ------------------------------------------------------ -// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110110 | -// ------------------------------------------------------ -// -// Calculates reciprocal square-root high part - -void rsp_device::cop2_drc::vrsqh() -{ - CACHE_VALUES(); - - m_reciprocal_high = (VREG_S(vs2reg, el & 7)) << 16; - m_dp_allowed = 1; - - for (int i = 0; i < 8; i++) - { - SET_ACCUM_L(VREG_S(vs2reg, VEC_EL_2(el, i)), i); - } - - W_VREG_S(vdreg, vs1reg & 7) = (int16_t)(m_reciprocal_res >> 16); // store high part -} - - -/*------------------------------------------------- - generate_vector_opcode - generate code for a - vector opcode --------------------------------------------------*/ - -bool rsp_device::cop2_drc::generate_vector_opcode(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) -{ - uint32_t op = desc->opptr.l[0]; - // Opcode legend: - // E = VS2 element type - // S = VS1, Source vector 1 - // T = VS2, Source vector 2 - // D = Destination vector - - switch (op & 0x3f) - { - case 0x00: /* VMULF */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmulf, this); - return true; - - case 0x01: /* VMULU */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmulu, this); - return true; - - case 0x04: /* VMUDL */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmudl, this); - return true; - - case 0x05: /* VMUDM */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmudm, this); - return true; - - case 0x06: /* VMUDN */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmudn, this); - return true; - - case 0x07: /* VMUDH */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmudh, this); - return true; - - case 0x08: /* VMACF */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmacf, this); - return true; - - case 0x09: /* VMACU */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmacu, this); - return true; - - case 0x0c: /* VMADL */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmadl, this); - return true; - - case 0x0d: /* VMADM */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmadm, this); - return true; - - case 0x0e: /* VMADN */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmadn, this); - return true; - - case 0x0f: /* VMADH */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmadh, this); - return true; - - case 0x10: /* VADD */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vadd, this); - return true; - - case 0x11: /* VSUB */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vsub, this); - return true; - - case 0x13: /* VABS */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vabs, this); - return true; - - case 0x14: /* VADDC */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vaddc, this); - return true; - - case 0x15: /* VSUBC */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vsubc, this); - return true; - - case 0x16: /* VADDB */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vaddb, this); - return true; - - case 0x17: /* VSUBB (reserved, functionally identical to VADDB) */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vaddb, this); - return true; - - case 0x18: /* VACCB (reserved, functionally identical to VADDB) */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vaddb, this); - return true; - - case 0x19: /* VSUCB (reserved, functionally identical to VADDB) */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vaddb, this); - return true; - - case 0x1d: /* VSAW */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vsaw, this); - return true; - - case 0x20: /* VLT */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vlt, this); - return true; - - case 0x21: /* VEQ */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_veq, this); - return true; - - case 0x22: /* VNE */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vne, this); - return true; - - case 0x23: /* VGE */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vge, this); - return true; - - case 0x24: /* VCL */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vcl, this); - return true; - - case 0x25: /* VCH */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vch, this); - return true; - - case 0x26: /* VCR */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vcr, this); - return true; - - case 0x27: /* VMRG */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmrg, this); - return true; - - case 0x28: /* VAND */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vand, this); - return true; - - case 0x29: /* VNAND */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vnand, this); - return true; - - case 0x2a: /* VOR */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vor, this); - return true; - - case 0x2b: /* VNOR */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vnor, this); - return true; - - case 0x2c: /* VXOR */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vxor, this); - return true; - - case 0x2d: /* VNXOR */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vnxor, this); - return true; - - case 0x30: /* VRCP */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vrcp, this); - return true; - - case 0x31: /* VRCPL */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vrcpl, this); - return true; - - case 0x32: /* VRCPH */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vrcph, this); - return true; - - case 0x33: /* VMOV */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vmov, this); - return true; - - case 0x34: /* VRSQ */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vrsq, this); - return true; - - case 0x35: /* VRSQL */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vrsql, this); - return true; - - case 0x36: /* VRSQH */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_vrsqh, this); - return true; - - case 0x37: /* VNOP */ - case 0x3F: /* VNULL */ - return true; - - default: - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::unimplemented_opcode, &m_rsp); - return false; - } -} - - -/*************************************************************************** - Vector Flag Reading/Writing -***************************************************************************/ - -void rsp_device::cop2_drc::mfc2() -{ - uint32_t op = m_rspcop2_state->op; - int el = (op >> 7) & 0xf; - - uint16_t b1 = VREG_B(VS1REG, (el+0) & 0xf); - uint16_t b2 = VREG_B(VS1REG, (el+1) & 0xf); - if (RTREG) RTVAL = (int32_t)(int16_t)((b1 << 8) | (b2)); -} - -void rsp_device::cop2_drc::cfc2() -{ - uint32_t op = m_rspcop2_state->op; - if (RTREG) - { - switch(RDREG) - { - case 0: - RTVAL = ((CARRY_FLAG(0) & 1) << 0) | - ((CARRY_FLAG(1) & 1) << 1) | - ((CARRY_FLAG(2) & 1) << 2) | - ((CARRY_FLAG(3) & 1) << 3) | - ((CARRY_FLAG(4) & 1) << 4) | - ((CARRY_FLAG(5) & 1) << 5) | - ((CARRY_FLAG(6) & 1) << 6) | - ((CARRY_FLAG(7) & 1) << 7) | - ((ZERO_FLAG(0) & 1) << 8) | - ((ZERO_FLAG(1) & 1) << 9) | - ((ZERO_FLAG(2) & 1) << 10) | - ((ZERO_FLAG(3) & 1) << 11) | - ((ZERO_FLAG(4) & 1) << 12) | - ((ZERO_FLAG(5) & 1) << 13) | - ((ZERO_FLAG(6) & 1) << 14) | - ((ZERO_FLAG(7) & 1) << 15); - if (RTVAL & 0x8000) RTVAL |= 0xffff0000; - break; - case 1: - RTVAL = ((COMPARE_FLAG(0) & 1) << 0) | - ((COMPARE_FLAG(1) & 1) << 1) | - ((COMPARE_FLAG(2) & 1) << 2) | - ((COMPARE_FLAG(3) & 1) << 3) | - ((COMPARE_FLAG(4) & 1) << 4) | - ((COMPARE_FLAG(5) & 1) << 5) | - ((COMPARE_FLAG(6) & 1) << 6) | - ((COMPARE_FLAG(7) & 1) << 7) | - ((CLIP2_FLAG(0) & 1) << 8) | - ((CLIP2_FLAG(1) & 1) << 9) | - ((CLIP2_FLAG(2) & 1) << 10) | - ((CLIP2_FLAG(3) & 1) << 11) | - ((CLIP2_FLAG(4) & 1) << 12) | - ((CLIP2_FLAG(5) & 1) << 13) | - ((CLIP2_FLAG(6) & 1) << 14) | - ((CLIP2_FLAG(7) & 1) << 15); - if (RTVAL & 0x8000) RTVAL |= 0xffff0000; - break; - case 2: - RTVAL = ((CLIP1_FLAG(0) & 1) << 0) | - ((CLIP1_FLAG(1) & 1) << 1) | - ((CLIP1_FLAG(2) & 1) << 2) | - ((CLIP1_FLAG(3) & 1) << 3) | - ((CLIP1_FLAG(4) & 1) << 4) | - ((CLIP1_FLAG(5) & 1) << 5) | - ((CLIP1_FLAG(6) & 1) << 6) | - ((CLIP1_FLAG(7) & 1) << 7); - break; - } - } -} - - -void rsp_device::cop2_drc::mtc2() -{ - uint32_t op = m_rspcop2_state->op; - int el = (op >> 7) & 0xf; - VREG_B(VS1REG, (el+0) & 0xf) = (RTVAL >> 8) & 0xff; - VREG_B(VS1REG, (el+1) & 0xf) = (RTVAL >> 0) & 0xff; -} - - -void rsp_device::cop2_drc::ctc2() -{ - uint32_t op = m_rspcop2_state->op; - switch(RDREG) - { - case 0: - CLEAR_CARRY_FLAGS(); - CLEAR_ZERO_FLAGS(); - m_vflag[0][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0; - m_vflag[0][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0; - m_vflag[0][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0; - m_vflag[0][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0; - m_vflag[0][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0; - m_vflag[0][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0; - m_vflag[0][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0; - m_vflag[0][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0; - if (RTVAL & (1 << 0)) { SET_CARRY_FLAG(0); } - if (RTVAL & (1 << 1)) { SET_CARRY_FLAG(1); } - if (RTVAL & (1 << 2)) { SET_CARRY_FLAG(2); } - if (RTVAL & (1 << 3)) { SET_CARRY_FLAG(3); } - if (RTVAL & (1 << 4)) { SET_CARRY_FLAG(4); } - if (RTVAL & (1 << 5)) { SET_CARRY_FLAG(5); } - if (RTVAL & (1 << 6)) { SET_CARRY_FLAG(6); } - if (RTVAL & (1 << 7)) { SET_CARRY_FLAG(7); } - m_vflag[3][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0; - m_vflag[3][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0; - m_vflag[3][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0; - m_vflag[3][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0; - m_vflag[3][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0; - m_vflag[3][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0; - m_vflag[3][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0; - m_vflag[3][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0; - if (RTVAL & (1 << 8)) { SET_ZERO_FLAG(0); } - if (RTVAL & (1 << 9)) { SET_ZERO_FLAG(1); } - if (RTVAL & (1 << 10)) { SET_ZERO_FLAG(2); } - if (RTVAL & (1 << 11)) { SET_ZERO_FLAG(3); } - if (RTVAL & (1 << 12)) { SET_ZERO_FLAG(4); } - if (RTVAL & (1 << 13)) { SET_ZERO_FLAG(5); } - if (RTVAL & (1 << 14)) { SET_ZERO_FLAG(6); } - if (RTVAL & (1 << 15)) { SET_ZERO_FLAG(7); } - break; - case 1: - CLEAR_COMPARE_FLAGS(); - CLEAR_CLIP2_FLAGS(); - m_vflag[1][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0; - m_vflag[1][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0; - m_vflag[1][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0; - m_vflag[1][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0; - m_vflag[1][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0; - m_vflag[1][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0; - m_vflag[1][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0; - m_vflag[1][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0; - if (RTVAL & (1 << 0)) { SET_COMPARE_FLAG(0); } - if (RTVAL & (1 << 1)) { SET_COMPARE_FLAG(1); } - if (RTVAL & (1 << 2)) { SET_COMPARE_FLAG(2); } - if (RTVAL & (1 << 3)) { SET_COMPARE_FLAG(3); } - if (RTVAL & (1 << 4)) { SET_COMPARE_FLAG(4); } - if (RTVAL & (1 << 5)) { SET_COMPARE_FLAG(5); } - if (RTVAL & (1 << 6)) { SET_COMPARE_FLAG(6); } - if (RTVAL & (1 << 7)) { SET_COMPARE_FLAG(7); } - m_vflag[4][0] = ((RTVAL >> 8) & 1) ? 0xffff : 0; - m_vflag[4][1] = ((RTVAL >> 9) & 1) ? 0xffff : 0; - m_vflag[4][2] = ((RTVAL >> 10) & 1) ? 0xffff : 0; - m_vflag[4][3] = ((RTVAL >> 11) & 1) ? 0xffff : 0; - m_vflag[4][4] = ((RTVAL >> 12) & 1) ? 0xffff : 0; - m_vflag[4][5] = ((RTVAL >> 13) & 1) ? 0xffff : 0; - m_vflag[4][6] = ((RTVAL >> 14) & 1) ? 0xffff : 0; - m_vflag[4][7] = ((RTVAL >> 15) & 1) ? 0xffff : 0; - if (RTVAL & (1 << 8)) { SET_CLIP2_FLAG(0); } - if (RTVAL & (1 << 9)) { SET_CLIP2_FLAG(1); } - if (RTVAL & (1 << 10)) { SET_CLIP2_FLAG(2); } - if (RTVAL & (1 << 11)) { SET_CLIP2_FLAG(3); } - if (RTVAL & (1 << 12)) { SET_CLIP2_FLAG(4); } - if (RTVAL & (1 << 13)) { SET_CLIP2_FLAG(5); } - if (RTVAL & (1 << 14)) { SET_CLIP2_FLAG(6); } - if (RTVAL & (1 << 15)) { SET_CLIP2_FLAG(7); } - break; - case 2: - CLEAR_CLIP1_FLAGS(); - m_vflag[2][0] = ((RTVAL >> 0) & 1) ? 0xffff : 0; - m_vflag[2][1] = ((RTVAL >> 1) & 1) ? 0xffff : 0; - m_vflag[2][2] = ((RTVAL >> 2) & 1) ? 0xffff : 0; - m_vflag[2][3] = ((RTVAL >> 3) & 1) ? 0xffff : 0; - m_vflag[2][4] = ((RTVAL >> 4) & 1) ? 0xffff : 0; - m_vflag[2][5] = ((RTVAL >> 5) & 1) ? 0xffff : 0; - m_vflag[2][6] = ((RTVAL >> 6) & 1) ? 0xffff : 0; - m_vflag[2][7] = ((RTVAL >> 7) & 1) ? 0xffff : 0; - if (RTVAL & (1 << 0)) { SET_CLIP1_FLAG(0); } - if (RTVAL & (1 << 1)) { SET_CLIP1_FLAG(1); } - if (RTVAL & (1 << 2)) { SET_CLIP1_FLAG(2); } - if (RTVAL & (1 << 3)) { SET_CLIP1_FLAG(3); } - if (RTVAL & (1 << 4)) { SET_CLIP1_FLAG(4); } - if (RTVAL & (1 << 5)) { SET_CLIP1_FLAG(5); } - if (RTVAL & (1 << 6)) { SET_CLIP1_FLAG(6); } - if (RTVAL & (1 << 7)) { SET_CLIP1_FLAG(7); } - break; - } -} - -/*************************************************************************** - COP2 Opcode Compilation -***************************************************************************/ - -bool rsp_device::cop2_drc::generate_cop2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) -{ - uint32_t op = desc->opptr.l[0]; - uint8_t opswitch = RSREG; - - switch (opswitch) - { - case 0x00: /* MFCz */ - if (RTREG != 0) - { - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_mfc2, this); // callc mfc2 - } - return true; - - case 0x02: /* CFCz */ - if (RTREG != 0) - { - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_cfc2, this); // callc cfc2 - } - return true; - - case 0x04: /* MTCz */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_mtc2, this); // callc mtc2 - return true; - - case 0x06: /* CTCz */ - UML_MOV(block, mem(&m_rspcop2_state->op), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, &cop2_drc::cfunc_ctc2, this); // callc ctc2 - return true; - - case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: - case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: - return generate_vector_opcode(block, compiler, desc); - } - return false; -} diff --git a/src/devices/cpu/rsp/rspcp2d.h b/src/devices/cpu/rsp/rspcp2d.h deleted file mode 100644 index 09263a39cdf..00000000000 --- a/src/devices/cpu/rsp/rspcp2d.h +++ /dev/null @@ -1,179 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/*************************************************************************** - - rspcp2d.h - - Interface file for Reality Signal Processor (RSP) vector extensions - using Universal Machine Language (UML) dynamic recompilation. - -***************************************************************************/ -#ifndef MAME_CPU_RSP_RSPCP2D_H -#define MAME_CPU_RSP_RSPCP2D_H - -#pragma once - -#include "rsp.h" -#include "rspcp2.h" -#include "cpu/drcuml.h" - - -class rsp_device::cop2_drc : public rsp_device::cop2 -{ - friend class rsp_device; -public: - cop2_drc(rsp_device &rsp, running_machine &machine) : cop2(rsp, machine) { } -private: - virtual bool generate_cop2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) override; - virtual bool generate_lwc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) override; - virtual bool generate_swc2(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) override; - - virtual void state_string_export(const int index, std::string &str) const override; - - void cfunc_unimplemented_opcode() override; - - static void unimplemented_opcode(void *param) { ((cop2 *)param)->cfunc_unimplemented_opcode(); } - static void cfunc_lbv(void *param) { ((cop2 *)param)->lbv(); } - static void cfunc_lsv(void *param) { ((cop2 *)param)->lsv(); } - static void cfunc_llv(void *param) { ((cop2 *)param)->llv(); } - static void cfunc_ldv(void *param) { ((cop2 *)param)->ldv(); } - static void cfunc_lqv(void *param) { ((cop2 *)param)->lqv(); } - static void cfunc_lrv(void *param) { ((cop2 *)param)->lrv(); } - static void cfunc_lpv(void *param) { ((cop2 *)param)->lpv(); } - static void cfunc_luv(void *param) { ((cop2 *)param)->luv(); } - static void cfunc_lhv(void *param) { ((cop2 *)param)->lhv(); } - static void cfunc_lfv(void *param) { ((cop2 *)param)->lfv(); } - static void cfunc_lwv(void *param) { ((cop2 *)param)->lwv(); } - static void cfunc_ltv(void *param) { ((cop2 *)param)->ltv(); } - static void cfunc_sbv(void *param) { ((cop2 *)param)->sbv(); } - static void cfunc_ssv(void *param) { ((cop2 *)param)->ssv(); } - static void cfunc_slv(void *param) { ((cop2 *)param)->slv(); } - static void cfunc_sdv(void *param) { ((cop2 *)param)->sdv(); } - static void cfunc_sqv(void *param) { ((cop2 *)param)->sqv(); } - static void cfunc_srv(void *param) { ((cop2 *)param)->srv(); } - static void cfunc_spv(void *param) { ((cop2 *)param)->spv(); } - static void cfunc_suv(void *param) { ((cop2 *)param)->suv(); } - static void cfunc_shv(void *param) { ((cop2 *)param)->shv(); } - static void cfunc_sfv(void *param) { ((cop2 *)param)->sfv(); } - static void cfunc_swv(void *param) { ((cop2 *)param)->swv(); } - static void cfunc_stv(void *param) { ((cop2 *)param)->stv(); } - static void cfunc_vmulf(void *param) { ((cop2 *)param)->vmulf(); } - static void cfunc_vmulu(void *param) { ((cop2 *)param)->vmulu(); } - static void cfunc_vmudl(void *param) { ((cop2 *)param)->vmudl(); } - static void cfunc_vmudm(void *param) { ((cop2 *)param)->vmudm(); } - static void cfunc_vmudn(void *param) { ((cop2 *)param)->vmudn(); } - static void cfunc_vmudh(void *param) { ((cop2 *)param)->vmudh(); } - static void cfunc_vmacf(void *param) { ((cop2 *)param)->vmacf(); } - static void cfunc_vmacu(void *param) { ((cop2 *)param)->vmacu(); } - static void cfunc_vmadl(void *param) { ((cop2 *)param)->vmadl(); } - static void cfunc_vmadm(void *param) { ((cop2 *)param)->vmadm(); } - static void cfunc_vmadn(void *param) { ((cop2 *)param)->vmadn(); } - static void cfunc_vmadh(void *param) { ((cop2 *)param)->vmadh(); } - static void cfunc_vadd(void *param) { ((cop2 *)param)->vadd(); } - static void cfunc_vsub(void *param) { ((cop2 *)param)->vsub(); } - static void cfunc_vabs(void *param) { ((cop2 *)param)->vabs(); } - static void cfunc_vaddc(void *param) { ((cop2 *)param)->vaddc(); } - static void cfunc_vsubc(void *param) { ((cop2 *)param)->vsubc(); } - static void cfunc_vaddb(void *param) { ((cop2 *)param)->vaddb(); } - static void cfunc_vsaw(void *param) { ((cop2 *)param)->vsaw(); } - static void cfunc_vlt(void *param) { ((cop2 *)param)->vlt(); } - static void cfunc_veq(void *param) { ((cop2 *)param)->veq(); } - static void cfunc_vne(void *param) { ((cop2 *)param)->vne(); } - static void cfunc_vge(void *param) { ((cop2 *)param)->vge(); } - static void cfunc_vcl(void *param) { ((cop2 *)param)->vcl(); } - static void cfunc_vch(void *param) { ((cop2 *)param)->vch(); } - static void cfunc_vcr(void *param) { ((cop2 *)param)->vcr(); } - static void cfunc_vmrg(void *param) { ((cop2 *)param)->vmrg(); } - static void cfunc_vand(void *param) { ((cop2 *)param)->vand(); } - static void cfunc_vnand(void *param) { ((cop2 *)param)->vnand(); } - static void cfunc_vor(void *param) { ((cop2 *)param)->vor(); } - static void cfunc_vnor(void *param) { ((cop2 *)param)->vnor(); } - static void cfunc_vxor(void *param) { ((cop2 *)param)->vxor(); } - static void cfunc_vnxor(void *param) { ((cop2 *)param)->vnxor(); } - static void cfunc_vrcp(void *param) { ((cop2 *)param)->vrcp(); } - static void cfunc_vrcpl(void *param) { ((cop2 *)param)->vrcpl(); } - static void cfunc_vrcph(void *param) { ((cop2 *)param)->vrcph(); } - static void cfunc_vmov(void *param) { ((cop2 *)param)->vmov(); } - static void cfunc_vrsq(void *param) { ((cop2 *)param)->vrsq(); } - static void cfunc_vrsql(void *param) { ((cop2 *)param)->vrsql(); } - static void cfunc_vrsqh(void *param) { ((cop2 *)param)->vrsqh(); } - static void cfunc_mfc2(void *param) { ((cop2 *)param)->mfc2(); } - static void cfunc_cfc2(void *param) { ((cop2 *)param)->cfc2(); } - static void cfunc_mtc2(void *param) { ((cop2 *)param)->mtc2(); } - static void cfunc_ctc2(void *param) { ((cop2 *)param)->ctc2(); } - -public: - virtual void lbv() override; - virtual void lsv() override; - virtual void llv() override; - virtual void ldv() override; - virtual void lqv() override; - virtual void lrv() override; - virtual void lpv() override; - virtual void luv() override; - virtual void lhv() override; - virtual void lfv() override; - virtual void lwv() override; - virtual void ltv() override; - virtual void sbv() override; - virtual void ssv() override; - virtual void slv() override; - virtual void sdv() override; - virtual void sqv() override; - virtual void srv() override; - virtual void spv() override; - virtual void suv() override; - virtual void shv() override; - virtual void sfv() override; - virtual void swv() override; - virtual void stv() override; - virtual void vmulf() override; - virtual void vmulu() override; - virtual void vmudl() override; - virtual void vmudm() override; - virtual void vmudn() override; - virtual void vmudh() override; - virtual void vmacf() override; - virtual void vmacu() override; - virtual void vmadl() override; - virtual void vmadm() override; - virtual void vmadn() override; - virtual void vmadh() override; - virtual void vadd() override; - virtual void vsub() override; - virtual void vabs() override; - virtual void vaddc() override; - virtual void vsubc() override; - virtual void vaddb() override; - virtual void vsaw() override; - virtual void vlt() override; - virtual void veq() override; - virtual void vne() override; - virtual void vge() override; - virtual void vcl() override; - virtual void vch() override; - virtual void vcr() override; - virtual void vmrg() override; - virtual void vand() override; - virtual void vnand() override; - virtual void vor() override; - virtual void vnor() override; - virtual void vxor() override; - virtual void vnxor() override; - virtual void vrcp() override; - virtual void vrcpl() override; - virtual void vrcph() override; - virtual void vmov() override; - virtual void vrsql() override; - virtual void vrsqh() override; - virtual void vrsq() override; - virtual void mfc2() override; - virtual void cfc2() override; - virtual void mtc2() override; - virtual void ctc2() override; - -private: - virtual bool generate_vector_opcode(drcuml_block &block, rsp_device::compiler_state &compiler, const opcode_desc *desc) override; -}; - -#endif // MAME_CPU_RSP_RSPCP2D_H diff --git a/src/devices/cpu/rsp/rspdrc.cpp b/src/devices/cpu/rsp/rspdrc.cpp deleted file mode 100644 index d2e89b4a77a..00000000000 --- a/src/devices/cpu/rsp/rspdrc.cpp +++ /dev/null @@ -1,1279 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/*************************************************************************** - - rspdrc.c - - Universal machine language-based Nintendo/SGI RSP emulator. - Written by Ryan Holtz - SIMD versions of vector multiplication opcodes provided by Marathon Man - of the CEN64 team. - -**************************************************************************** - - Future improvements/changes: - - * Confer with Aaron Giles about adding a memory hash-based caching - system and static recompilation for maximum overhead minimization - -***************************************************************************/ - -#include "emu.h" -#include "rsp.h" -#include "rsp_dasm.h" - -#include "rspfe.h" -#include "rspcp2.h" -#include "cpu/drcfe.h" -#include "cpu/drcuml.h" -#include "cpu/drcumlsh.h" - -#include "debugger.h" - -#include "rspdefs.h" - - -/*************************************************************************** - CONSTANTS -***************************************************************************/ - -/* map variables */ -#define MAPVAR_PC M0 -#define MAPVAR_CYCLES M1 - -/* exit codes */ -#define EXECUTE_OUT_OF_CYCLES 0 -#define EXECUTE_MISSING_CODE 1 -#define EXECUTE_UNMAPPED_CODE 2 -#define EXECUTE_RESET_CACHE 3 - - - -/*************************************************************************** - Macros -***************************************************************************/ - -#define R32(reg) m_regmap[reg] - -/*************************************************************************** - Inline Functions -***************************************************************************/ - -/*------------------------------------------------- - epc - compute the exception PC from a - descriptor --------------------------------------------------*/ - -static inline uint32_t epc(const opcode_desc *desc) -{ - return ((desc->flags & OPFLAG_IN_DELAY_SLOT) ? (desc->pc - 3) : desc->pc) | 0x1000; -} - - -/*------------------------------------------------- - alloc_handle - allocate a handle if not - already allocated --------------------------------------------------*/ - -static inline void alloc_handle(drcuml_state &drcuml, uml::code_handle *&handleptr, const char *name) -{ - if (!handleptr) - handleptr = drcuml.handle_alloc(name); -} - - -/*------------------------------------------------- - load_fast_iregs - load any fast integer - registers --------------------------------------------------*/ - -inline void rsp_device::load_fast_iregs(drcuml_block &block) -{ - int regnum; - - for (regnum = 0; regnum < std::size(m_regmap); regnum++) - if (m_regmap[regnum].is_int_register()) - UML_MOV(block, ireg(m_regmap[regnum].ireg() - REG_I0), mem(&m_rsp_state->r[regnum])); -} - - -/*------------------------------------------------- - save_fast_iregs - save any fast integer - registers --------------------------------------------------*/ - -inline void rsp_device::save_fast_iregs(drcuml_block &block) -{ - int regnum; - - for (regnum = 0; regnum < std::size(m_regmap); regnum++) - if (m_regmap[regnum].is_int_register()) - UML_MOV(block, mem(&m_rsp_state->r[regnum]), ireg(m_regmap[regnum].ireg() - REG_I0)); -} - -/*************************************************************************** - CORE CALLBACKS -***************************************************************************/ - -inline void rsp_device::ccfunc_read8() -{ - m_rsp_state->arg0 = DM_READ8(m_rsp_state->arg0); -} - -static void cfunc_read8(void *param) -{ - ((rsp_device *)param)->ccfunc_read8(); -} - -inline void rsp_device::ccfunc_read16() -{ - m_rsp_state->arg0 = DM_READ16(m_rsp_state->arg0); -} - -static void cfunc_read16(void *param) -{ - ((rsp_device *)param)->ccfunc_read16(); -} - -inline void rsp_device::ccfunc_read32() -{ - m_rsp_state->arg0 = DM_READ32(m_rsp_state->arg0); -} - -static void cfunc_read32(void *param) -{ - ((rsp_device *)param)->ccfunc_read32(); -} - -inline void rsp_device::ccfunc_write8() -{ - DM_WRITE8(m_rsp_state->arg0, m_rsp_state->arg1); -} - -static void cfunc_write8(void *param) -{ - ((rsp_device *)param)->ccfunc_write8(); -} - -inline void rsp_device::ccfunc_write16() -{ - DM_WRITE16(m_rsp_state->arg0, m_rsp_state->arg1); -} - -static void cfunc_write16(void *param) -{ - ((rsp_device *)param)->ccfunc_write16(); -} - -inline void rsp_device::ccfunc_write32() -{ - DM_WRITE32(m_rsp_state->arg0, m_rsp_state->arg1); -} - -static void cfunc_write32(void *param) -{ - ((rsp_device *)param)->ccfunc_write32(); -} - -/*****************************************************************************/ - -/*------------------------------------------------- - rspdrc_set_options - configure DRC options --------------------------------------------------*/ - -void rsp_device::rspdrc_set_options(uint32_t options) -{ - if (!allow_drc()) return; - m_drcoptions = options; -} - - -inline void rsp_device::ccfunc_get_cop0_reg() -{ - int reg = m_rsp_state->arg0; - int dest = m_rsp_state->arg1; - - if (reg >= 0 && reg < 8) - { - if(dest) - { - m_rsp_state->r[dest] = m_sp_reg_r_func(reg, 0xffffffff); - } - } - else if (reg >= 8 && reg < 16) - { - if(dest) - { - m_rsp_state->r[dest] = m_dp_reg_r_func(reg - 8, 0xffffffff); - } - } - else - { - fatalerror("RSP: cfunc_get_cop0_reg: %d\n", reg); - } -} - -static void cfunc_get_cop0_reg(void *param) -{ - ((rsp_device *)param)->ccfunc_get_cop0_reg(); -} - -inline void rsp_device::ccfunc_set_cop0_reg() -{ - int reg = m_rsp_state->arg0; - uint32_t data = m_rsp_state->arg1; - - if (reg >= 0 && reg < 8) - { - m_sp_reg_w_func(reg, data, 0xffffffff); - } - else if (reg >= 8 && reg < 16) - { - m_dp_reg_w_func(reg - 8, data, 0xffffffff); - } - else - { - fatalerror("RSP: set_cop0_reg: %d, %08X\n", reg, data); - } -} - -static void cfunc_set_cop0_reg(void *param) -{ - ((rsp_device *)param)->ccfunc_set_cop0_reg(); -} - -/*****************************************************************************/ - -void rsp_device::rspcom_init() -{ -} - -inline void rsp_device::ccfunc_sp_set_status_cb() -{ - m_sp_set_status_func(0, m_rsp_state->arg0, 0xffffffff); -} - -void cfunc_sp_set_status_cb(void *param) -{ - ((rsp_device *)param)->ccfunc_sp_set_status_cb(); -} - -void rsp_device::execute_run_drc() -{ - int execute_result; - - /* reset the cache if dirty */ - if (m_cache_dirty) - code_flush_cache(); - m_cache_dirty = false; - - /* execute */ - do - { - if( m_sr & ( RSP_STATUS_HALT | RSP_STATUS_BROKE ) ) - { - m_rsp_state->icount = std::min(m_rsp_state->icount, 0); - break; - } - - /* run as much as we can */ - execute_result = m_drcuml->execute(*m_entry); - - /* if we need to recompile, do it */ - if (execute_result == EXECUTE_MISSING_CODE) - { - code_compile_block(m_rsp_state->pc); - } - else if (execute_result == EXECUTE_UNMAPPED_CODE) - { - fatalerror("Attempted to execute unmapped code at PC=%08X\n", m_rsp_state->pc); - } - else if (execute_result == EXECUTE_RESET_CACHE) - { - code_flush_cache(); - } - } while (execute_result != EXECUTE_OUT_OF_CYCLES); -} - -/*************************************************************************** - CACHE MANAGEMENT -***************************************************************************/ - -/*------------------------------------------------- - rspdrc_flush_drc_cache - outward-facing - accessor to code_flush_cache --------------------------------------------------*/ - -void rsp_device::rspdrc_flush_drc_cache() -{ - if (!allow_drc()) return; - m_cache_dirty = true; -} - -/*------------------------------------------------- - code_flush_cache - flush the cache and - regenerate static code --------------------------------------------------*/ - -void rsp_device::code_flush_cache() -{ - /* empty the transient cache contents */ - m_drcuml->reset(); - - try - { - /* generate the entry point and out-of-cycles handlers */ - static_generate_entry_point(); - static_generate_nocode_handler(); - static_generate_out_of_cycles(); - - /* add subroutines for memory accesses */ - static_generate_memory_accessor(1, false, "read8", m_read8); - static_generate_memory_accessor(1, true, "write8", m_write8); - static_generate_memory_accessor(2, false, "read16", m_read16); - static_generate_memory_accessor(2, true, "write16", m_write16); - static_generate_memory_accessor(4, false, "read32", m_read32); - static_generate_memory_accessor(4, true, "write32", m_write32); - } - catch (drcuml_block::abort_compilation &) - { - fatalerror("Unable to generate static RSP code\n"); - } -} - - -/*------------------------------------------------- - code_compile_block - compile a block of the - given mode at the specified pc --------------------------------------------------*/ - -void rsp_device::code_compile_block(offs_t pc) -{ - compiler_state compiler = { 0 }; - const opcode_desc *seqhead, *seqlast; - const opcode_desc *desclist; - int override = false; - - g_profiler.start(PROFILER_DRC_COMPILE); - - /* get a description of this sequence */ - desclist = m_drcfe->describe_code(pc); - - bool succeeded = false; - while (!succeeded) - { - try - { - /* start the block */ - drcuml_block &block(m_drcuml->begin_block(4096)); - - /* loop until we get through all instruction sequences */ - for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next()) - { - const opcode_desc *curdesc; - uint32_t nextpc; - - /* add a code log entry */ - if (m_drcuml->logging()) - block.append_comment("-------------------------"); // comment - - /* determine the last instruction in this sequence */ - for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next()) - if (seqlast->flags & OPFLAG_END_SEQUENCE) - break; - assert(seqlast != nullptr); - - /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */ - if (override || !m_drcuml->hash_exists(0, seqhead->pc)) - UML_HASH(block, 0, seqhead->pc); // hash mode,pc - - /* if we already have a hash, and this is the first sequence, assume that we */ - /* are recompiling due to being out of sync and allow future overrides */ - else if (seqhead == desclist) - { - override = true; - UML_HASH(block, 0, seqhead->pc); // hash mode,pc - } - - /* otherwise, redispatch to that fixed PC and skip the rest of the processing */ - else - { - UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc - UML_HASHJMP(block, 0, seqhead->pc, *m_nocode); - // hashjmp <0>,seqhead->pc,nocode - continue; - } - - /* validate this code block if we're not pointing into ROM */ - if (m_program.space().get_write_ptr(seqhead->physpc) != nullptr) - generate_checksum_block(block, compiler, seqhead, seqlast); - - /* label this instruction, if it may be jumped to locally */ - if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET) - UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc - - /* iterate over instructions in the sequence and compile them */ - for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next()) - generate_sequence_instruction(block, compiler, curdesc); - - /* if we need to return to the start, do it */ - if (seqlast->flags & OPFLAG_RETURN_TO_START) - nextpc = pc; - - /* otherwise we just go to the next instruction */ - else - nextpc = seqlast->pc + (seqlast->skipslots + 1) * 4; - - /* count off cycles and go there */ - generate_update_cycles(block, compiler, nextpc, true); // <subtract cycles> - - /* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */ - if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc) - UML_HASHJMP(block, 0, nextpc, *m_nocode); // hashjmp <mode>,nextpc,nocode - } - - /* end the sequence */ - block.end(); - g_profiler.stop(); - succeeded = true; - } - catch (drcuml_block::abort_compilation &) - { - code_flush_cache(); - } - } -} - -/*************************************************************************** - C FUNCTION CALLBACKS -***************************************************************************/ - -/*------------------------------------------------- - cfunc_unimplemented - handler for - unimplemented opcdes --------------------------------------------------*/ - -inline void rsp_device::ccfunc_unimplemented() -{ - uint32_t opcode = m_rsp_state->arg0; - fatalerror("PC=%08X: Unimplemented op %08X (%02X,%02X)\n", m_rsp_state->pc, opcode, opcode >> 26, opcode & 0x3f); -} - -static void cfunc_unimplemented(void *param) -{ - ((rsp_device *)param)->ccfunc_unimplemented(); -} - -/*------------------------------------------------- - cfunc_fatalerror - a generic fatalerror call --------------------------------------------------*/ - -#ifdef UNUSED_CODE -static void cfunc_fatalerror(void *param) -{ - fatalerror("fatalerror\n"); -} -#endif - - -/*************************************************************************** - STATIC CODEGEN -***************************************************************************/ - -/*------------------------------------------------- - ferate_entry_point - generate a - static entry point --------------------------------------------------*/ - -void rsp_device::static_generate_entry_point() -{ - /* begin generating */ - drcuml_block &block(m_drcuml->begin_block(20)); - - /* forward references */ - alloc_handle(*m_drcuml, m_nocode, "nocode"); - - alloc_handle(*m_drcuml, m_entry, "entry"); - UML_HANDLE(block, *m_entry); // handle entry - - /* load fast integer registers */ - load_fast_iregs(block); - - /* generate a hash jump via the current mode and PC */ - UML_HASHJMP(block, 0, mem(&m_rsp_state->pc), *m_nocode); // hashjmp <mode>,<pc>,nocode - block.end(); -} - - -/*------------------------------------------------- - static_generate_nocode_handler - generate an - exception handler for "out of code" --------------------------------------------------*/ - -void rsp_device::static_generate_nocode_handler() -{ - /* begin generating */ - drcuml_block &block(m_drcuml->begin_block(10)); - - /* generate a hash jump via the current mode and PC */ - alloc_handle(*m_drcuml, m_nocode, "nocode"); - UML_HANDLE(block, *m_nocode); // handle nocode - UML_GETEXP(block, I0); // getexp i0 - UML_MOV(block, mem(&m_rsp_state->pc), I0); // mov [pc],i0 - save_fast_iregs(block); - UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE - - block.end(); -} - - -/*------------------------------------------------- - static_generate_out_of_cycles - generate an - out of cycles exception handler --------------------------------------------------*/ - -void rsp_device::static_generate_out_of_cycles() -{ - /* begin generating */ - drcuml_block &block(m_drcuml->begin_block(10)); - - /* generate a hash jump via the current mode and PC */ - alloc_handle(*m_drcuml, m_out_of_cycles, "out_of_cycles"); - UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles - UML_GETEXP(block, I0); // getexp i0 - UML_MOV(block, mem(&m_rsp_state->pc), I0); // mov <pc>,i0 - save_fast_iregs(block); - UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES - - block.end(); -} - -/*------------------------------------------------------------------ - static_generate_memory_accessor -------------------------------------------------------------------*/ - -void rsp_device::static_generate_memory_accessor(int size, int iswrite, const char *name, uml::code_handle *&handleptr) -{ - /* on entry, address is in I0; data for writes is in I1 */ - /* on exit, read result is in I0 */ - /* routine trashes I0-I1 */ - - /* begin generating */ - drcuml_block &block(m_drcuml->begin_block(1024)); - - /* add a global entry for this */ - alloc_handle(*m_drcuml, handleptr, name); - UML_HANDLE(block, *handleptr); // handle *handleptr - - // write: - if (iswrite) - { - if (size == 1) - { - UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address - UML_MOV(block, mem(&m_rsp_state->arg1), I1); // mov [arg1],i1 ; data - UML_CALLC(block, cfunc_write8, this); // callc cfunc_write8 - } - else if (size == 2) - { - UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address - UML_MOV(block, mem(&m_rsp_state->arg1), I1); // mov [arg1],i1 ; data - UML_CALLC(block, cfunc_write16, this); // callc cfunc_write16 - } - else if (size == 4) - { - UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address - UML_MOV(block, mem(&m_rsp_state->arg1), I1); // mov [arg1],i1 ; data - UML_CALLC(block, cfunc_write32, this); // callc cfunc_write32 - } - } - else - { - if (size == 1) - { - UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address - UML_CALLC(block, cfunc_read8, this); // callc read8 - UML_MOV(block, I0, mem(&m_rsp_state->arg0)); // mov i0,[arg0],i0 ; result - } - else if (size == 2) - { - UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address - UML_CALLC(block, cfunc_read16, this); // callc cfunc_read16 - UML_MOV(block, I0, mem(&m_rsp_state->arg0)); // mov i0,[arg0],i0 ; result - } - else if (size == 4) - { - UML_MOV(block, mem(&m_rsp_state->arg0), I0); // mov [arg0],i0 ; address - UML_CALLC(block, cfunc_read32, this); // callc cfunc_read32 - UML_MOV(block, I0, mem(&m_rsp_state->arg0)); // mov i0,[arg0],i0 ; result - } - } - UML_RET(block); - - block.end(); -} - - - -/*************************************************************************** - CODE GENERATION -***************************************************************************/ - -/*------------------------------------------------- - generate_update_cycles - generate code to - subtract cycles from the icount and generate - an exception if out --------------------------------------------------*/ -void rsp_device::generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception) -{ - /* account for cycles */ - if (compiler.cycles > 0) - { - UML_SUB(block, mem(&m_rsp_state->icount), mem(&m_rsp_state->icount), MAPVAR_CYCLES); // sub icount,icount,cycles - UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0 - UML_EXHc(block, COND_S, *m_out_of_cycles, param); - } - compiler.cycles = 0; -} - -/*------------------------------------------------- - generate_checksum_block - generate code to - validate a sequence of opcodes --------------------------------------------------*/ - -void rsp_device::generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast) -{ - const opcode_desc *curdesc; - if (m_drcuml->logging()) - { - block.append_comment("[Validation for %08X]", seqhead->pc | 0x1000); // comment - } - /* loose verify or single instruction: just compare and fail */ - if (!(m_drcoptions & RSPDRC_STRICT_VERIFY) || seqhead->next() == nullptr) - { - if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) - { - uint32_t sum = seqhead->opptr.l[0]; - void *base = m_pcache.read_ptr(seqhead->physpc | 0x1000); - UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword - - if (seqhead->delay.first() != nullptr && seqhead->physpc != seqhead->delay.first()->physpc) - { - base = m_pcache.read_ptr((seqhead->delay.first()->physpc & 0x00000fff) | 0x1000); - assert(base != nullptr); - UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword - UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - - sum += seqhead->delay.first()->opptr.l[0]; - } - - UML_CMP(block, I0, sum); // cmp i0,opptr[0] - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc - } - } - - /* full verification; sum up everything */ - else - { - uint32_t sum = 0; - void *base = m_pcache.read_ptr(seqhead->physpc | 0x1000); - UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword - sum += seqhead->opptr.l[0]; - for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next()) - if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) - { - base = m_pcache.read_ptr(curdesc->physpc | 0x1000); - assert(base != nullptr); - UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword - UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - sum += curdesc->opptr.l[0]; - - if (curdesc->delay.first() != nullptr && (curdesc == seqlast || (curdesc->next() != nullptr && curdesc->next()->physpc != curdesc->delay.first()->physpc))) - { - base = m_pcache.read_ptr((curdesc->delay.first()->physpc & 0x00000fff) | 0x1000); - assert(base != nullptr); - UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword - UML_ADD(block, I0, I0, I1); // add i0,i0,i1 - - sum += curdesc->delay.first()->opptr.l[0]; - } - } - UML_CMP(block, I0, sum); // cmp i0,sum - UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc - } -} - - -/*------------------------------------------------- - generate_sequence_instruction - generate code - for a single instruction in a sequence --------------------------------------------------*/ - -void rsp_device::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) -{ - offs_t expc; - - /* add an entry for the log */ - if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) - log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]); - - /* set the PC map variable */ - expc = (desc->flags & OPFLAG_IN_DELAY_SLOT) ? desc->pc - 3 : desc->pc; - UML_MAPVAR(block, MAPVAR_PC, expc); // mapvar PC,expc - - /* accumulate total cycles */ - compiler.cycles += desc->cycles; - - /* update the icount map variable */ - UML_MAPVAR(block, MAPVAR_CYCLES, compiler.cycles); // mapvar CYCLES,compiler.cycles - - /* if we are debugging, call the debugger */ - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) - { - UML_MOV(block, mem(&m_rsp_state->pc), desc->pc); // mov [pc],desc->pc - save_fast_iregs(block); - UML_DEBUG(block, desc->pc); // debug desc->pc - } - - /* if we hit an unmapped address, fatal error */ -#if 0 - if (desc->flags & OPFLAG_COMPILER_UNMAPPED) - { - UML_MOV(block, mem(&m_rsp_state->pc), desc->pc); // mov [pc],desc->pc - save_fast_iregs(block); - UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE - } -#endif - - /* otherwise, unless this is a virtual no-op, it's a regular instruction */ - /*else*/ if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) - { - /* compile the instruction */ - if (!generate_opcode(block, compiler, desc)) - { - UML_MOV(block, mem(&m_rsp_state->pc), desc->pc); // mov [pc],desc->pc - UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l - UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented - } - } -} - -/*------------------------------------------------------------------ - generate_branch -------------------------------------------------------------------*/ - -void rsp_device::generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) -{ - compiler_state compiler_temp(compiler); - - /* update the cycles and jump through the hash table to the target */ - if (desc->targetpc != BRANCH_TARGET_DYNAMIC) - { - generate_update_cycles(block, compiler_temp, desc->targetpc, true); // <subtract cycles> - if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) - UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc - else - UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp <mode>,desc->targetpc,nocode - } - else - { - generate_update_cycles(block, compiler_temp, uml::mem(&m_rsp_state->jmpdest), true); // <subtract cycles> - UML_HASHJMP(block, 0, mem(&m_rsp_state->jmpdest), *m_nocode); // hashjmp <mode>,<rsreg>,nocode - } -} - -/*------------------------------------------------------------------ - generate_delay_slot_and_branch -------------------------------------------------------------------*/ - -void rsp_device::generate_delay_slot_and_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t linkreg) -{ - compiler_state compiler_temp(compiler); - uint32_t op = desc->opptr.l[0]; - - /* fetch the target register if dynamic, in case it is modified by the delay slot */ - if (desc->targetpc == BRANCH_TARGET_DYNAMIC) - { - UML_AND(block, mem(&m_rsp_state->jmpdest), R32(RSREG), 0x00000fff); - UML_OR(block, mem(&m_rsp_state->jmpdest), mem(&m_rsp_state->jmpdest), 0x1000); - } - - /* set the link if needed -- before the delay slot */ - if (linkreg != 0) - { - UML_MOV(block, R32(linkreg), (int32_t)((desc->pc + 8) & 0x0000fff)); // mov <linkreg>,desc->pc + 8 - } - - /* compile the delay slot using temporary compiler state */ - assert(desc->delay.first() != nullptr); - generate_sequence_instruction(block, compiler_temp, desc->delay.first()); // <next instruction> - - generate_branch(block, compiler, desc); - - /* update the label */ - compiler.labelnum = compiler_temp.labelnum; - - /* reset the mapvar to the current cycles and account for skipped slots */ - compiler.cycles += desc->skipslots; - UML_MAPVAR(block, MAPVAR_CYCLES, compiler.cycles); // mapvar CYCLES,compiler.cycles -} - -bool rsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) -{ - int in_delay_slot = ((desc->flags & OPFLAG_IN_DELAY_SLOT) != 0); - uint32_t op = desc->opptr.l[0]; - uint8_t opswitch = op >> 26; - uml::code_label skip; - - switch (opswitch) - { - /* ----- sub-groups ----- */ - - case 0x00: /* SPECIAL - MIPS I */ - return generate_special(block, compiler, desc); - - case 0x01: /* REGIMM - MIPS I */ - return generate_regimm(block, compiler, desc); - - /* ----- jumps and branches ----- */ - - case 0x02: /* J - MIPS I */ - generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp> - return true; - - case 0x03: /* JAL - MIPS I */ - generate_delay_slot_and_branch(block, compiler, desc, 31); // <next instruction + hashjmp> - return true; - - case 0x04: /* BEQ - MIPS I */ - UML_CMP(block, R32(RSREG), R32(RTREG)); // cmp <rsreg>,<rtreg> - UML_JMPc(block, COND_NE, skip = compiler.labelnum++); // jmp skip,NE - generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp> - UML_LABEL(block, skip); // skip: - return true; - - case 0x05: /* BNE - MIPS I */ - UML_CMP(block, R32(RSREG), R32(RTREG)); // dcmp <rsreg>,<rtreg> - UML_JMPc(block, COND_E, skip = compiler.labelnum++); // jmp skip,E - generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp> - UML_LABEL(block, skip); // skip: - return true; - - case 0x06: /* BLEZ - MIPS I */ - if (RSREG != 0) - { - UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0 - UML_JMPc(block, COND_G, skip = compiler.labelnum++); // jmp skip,G - generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp> - UML_LABEL(block, skip); // skip: - } - else - generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp> - return true; - - case 0x07: /* BGTZ - MIPS I */ - UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0 - UML_JMPc(block, COND_LE, skip = compiler.labelnum++); // jmp skip,LE - generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp> - UML_LABEL(block, skip); // skip: - return true; - - - /* ----- immediate arithmetic ----- */ - - case 0x0f: /* LUI - MIPS I */ - if (RTREG != 0) - UML_MOV(block, R32(RTREG), SIMMVAL << 16); // dmov <rtreg>,SIMMVAL << 16 - return true; - - case 0x08: /* ADDI - MIPS I */ - case 0x09: /* ADDIU - MIPS I */ - if (RTREG != 0) - { - UML_ADD(block, R32(RTREG), R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL,V - } - return true; - - case 0x0a: /* SLTI - MIPS I */ - if (RTREG != 0) - { - UML_CMP(block, R32(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL - UML_SETc(block, COND_L, R32(RTREG)); // dset <rtreg>,l - } - return true; - - case 0x0b: /* SLTIU - MIPS I */ - if (RTREG != 0) - { - UML_CMP(block, R32(RSREG), SIMMVAL); // dcmp <rsreg>,SIMMVAL - UML_SETc(block, COND_B, R32(RTREG)); // dset <rtreg>,b - } - return true; - - - case 0x0c: /* ANDI - MIPS I */ - if (RTREG != 0) - UML_AND(block, R32(RTREG), R32(RSREG), UIMMVAL); // dand <rtreg>,<rsreg>,UIMMVAL - return true; - - case 0x0d: /* ORI - MIPS I */ - if (RTREG != 0) - UML_OR(block, R32(RTREG), R32(RSREG), UIMMVAL); // dor <rtreg>,<rsreg>,UIMMVAL - return true; - - case 0x0e: /* XORI - MIPS I */ - if (RTREG != 0) - UML_XOR(block, R32(RTREG), R32(RSREG), UIMMVAL); // dxor <rtreg>,<rsreg>,UIMMVAL - return true; - - /* ----- memory load operations ----- */ - - case 0x20: /* LB - MIPS I */ - UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL - UML_CALLH(block, *m_read8); // callh read8 - if (RTREG != 0) - UML_SEXT(block, R32(RTREG), I0, SIZE_BYTE); // dsext <rtreg>,i0,byte - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 4, true); - return true; - - case 0x21: /* LH - MIPS I */ - UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL - UML_CALLH(block, *m_read16); // callh read16 - if (RTREG != 0) - UML_SEXT(block, R32(RTREG), I0, SIZE_WORD); // dsext <rtreg>,i0,word - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 4, true); - return true; - - case 0x23: /* LW - MIPS I */ - UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL - UML_CALLH(block, *m_read32); // callh read32 - if (RTREG != 0) - UML_MOV(block, R32(RTREG), I0); - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 4, true); - return true; - - case 0x24: /* LBU - MIPS I */ - UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL - UML_CALLH(block, *m_read8); // callh read8 - if (RTREG != 0) - UML_AND(block, R32(RTREG), I0, 0xff); // dand <rtreg>,i0,0xff - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 4, true); - return true; - - case 0x25: /* LHU - MIPS I */ - UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL - UML_CALLH(block, *m_read16); // callh read16 - if (RTREG != 0) - UML_AND(block, R32(RTREG), I0, 0xffff); // dand <rtreg>,i0,0xffff - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 4, true); - return true; - - case 0x32: /* LWC2 - MIPS I */ - return m_cop2->generate_lwc2(block, compiler, desc); - - - /* ----- memory store operations ----- */ - - case 0x28: /* SB - MIPS I */ - UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL - UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg> - UML_CALLH(block, *m_write8); // callh write8 - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 4, true); - return true; - - case 0x29: /* SH - MIPS I */ - UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL - UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg> - UML_CALLH(block, *m_write16); // callh write16 - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 4, true); - return true; - - case 0x2b: /* SW - MIPS I */ - UML_ADD(block, I0, R32(RSREG), SIMMVAL); // add i0,<rsreg>,SIMMVAL - UML_MOV(block, I1, R32(RTREG)); // mov i1,<rtreg> - UML_CALLH(block, *m_write32); // callh write32 - if (!in_delay_slot) - generate_update_cycles(block, compiler, desc->pc + 4, true); - return true; - - case 0x3a: /* SWC2 - MIPS I */ - return m_cop2->generate_swc2(block, compiler, desc); - - /* ----- coprocessor instructions ----- */ - - case 0x10: /* COP0 - MIPS I */ - return generate_cop0(block, compiler, desc); - - case 0x12: /* COP2 - MIPS I */ - return m_cop2->generate_cop2(block, compiler, desc); - - - /* ----- unimplemented/illegal instructions ----- */ - - //default: /* ??? */ invalid_instruction(op); break; - } - - return false; -} - - -/*------------------------------------------------- - generate_special - compile opcodes in the - 'SPECIAL' group --------------------------------------------------*/ - -bool rsp_device::generate_special(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) -{ - uint32_t op = desc->opptr.l[0]; - uint8_t opswitch = op & 63; - //uml::code_label skip; - - switch (opswitch) - { - /* ----- shift instructions ----- */ - - case 0x00: /* SLL - MIPS I */ - if (RDREG != 0) - { - UML_SHL(block, R32(RDREG), R32(RTREG), SHIFT); - } - return true; - - case 0x02: /* SRL - MIPS I */ - if (RDREG != 0) - { - UML_SHR(block, R32(RDREG), R32(RTREG), SHIFT); - } - return true; - - case 0x03: /* SRA - MIPS I */ - if (RDREG != 0) - { - UML_SAR(block, R32(RDREG), R32(RTREG), SHIFT); - } - return true; - - case 0x04: /* SLLV - MIPS I */ - if (RDREG != 0) - { - UML_SHL(block, R32(RDREG), R32(RTREG), R32(RSREG)); - } - return true; - - case 0x06: /* SRLV - MIPS I */ - if (RDREG != 0) - { - UML_SHR(block, R32(RDREG), R32(RTREG), R32(RSREG)); - } - return true; - - case 0x07: /* SRAV - MIPS I */ - if (RDREG != 0) - { - UML_SAR(block, R32(RDREG), R32(RTREG), R32(RSREG)); - } - return true; - - /* ----- basic arithmetic ----- */ - - case 0x20: /* ADD - MIPS I */ - case 0x21: /* ADDU - MIPS I */ - if (RDREG != 0) - { - UML_ADD(block, R32(RDREG), R32(RSREG), R32(RTREG)); - } - return true; - - case 0x22: /* SUB - MIPS I */ - case 0x23: /* SUBU - MIPS I */ - if (RDREG != 0) - { - UML_SUB(block, R32(RDREG), R32(RSREG), R32(RTREG)); - } - return true; - - /* ----- basic logical ops ----- */ - - case 0x24: /* AND - MIPS I */ - if (RDREG != 0) - { - UML_AND(block, R32(RDREG), R32(RSREG), R32(RTREG)); // dand <rdreg>,<rsreg>,<rtreg> - } - return true; - - case 0x25: /* OR - MIPS I */ - if (RDREG != 0) - { - UML_OR(block, R32(RDREG), R32(RSREG), R32(RTREG)); // dor <rdreg>,<rsreg>,<rtreg> - } - return true; - - case 0x26: /* XOR - MIPS I */ - if (RDREG != 0) - { - UML_XOR(block, R32(RDREG), R32(RSREG), R32(RTREG)); // dxor <rdreg>,<rsreg>,<rtreg> - } - return true; - - case 0x27: /* NOR - MIPS I */ - if (RDREG != 0) - { - UML_OR(block, I0, R32(RSREG), R32(RTREG)); // dor i0,<rsreg>,<rtreg> - UML_XOR(block, R32(RDREG), I0, (uint64_t)~0); // dxor <rdreg>,i0,~0 - } - return true; - - - /* ----- basic comparisons ----- */ - - case 0x2a: /* SLT - MIPS I */ - if (RDREG != 0) - { - UML_CMP(block, R32(RSREG), R32(RTREG)); // dcmp <rsreg>,<rtreg> - UML_SETc(block, COND_L, R32(RDREG)); // dset <rdreg>,l - } - return true; - - case 0x2b: /* SLTU - MIPS I */ - if (RDREG != 0) - { - UML_CMP(block, R32(RSREG), R32(RTREG)); // dcmp <rsreg>,<rtreg> - UML_SETc(block, COND_B, R32(RDREG)); // dset <rdreg>,b - } - return true; - - - /* ----- jumps and branches ----- */ - - case 0x08: /* JR - MIPS I */ - generate_delay_slot_and_branch(block, compiler, desc, 0); // <next instruction + hashjmp> - return true; - - case 0x09: /* JALR - MIPS I */ - generate_delay_slot_and_branch(block, compiler, desc, RDREG); // <next instruction + hashjmp> - return true; - - - /* ----- system calls ----- */ - - case 0x0d: /* BREAK - MIPS I */ - UML_MOV(block, mem(&m_rsp_state->arg0), 3); // mov [arg0],3 - UML_CALLC(block, cfunc_sp_set_status_cb, this); // callc cfunc_sp_set_status_cb - UML_MOV(block, mem(&m_rsp_state->icount), 0); // mov icount, #0 - UML_MOV(block, mem(&m_rsp_state->jmpdest), desc->targetpc); - - generate_branch(block, compiler, desc); - - UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); - return true; - } - return false; -} - - - -/*------------------------------------------------- - generate_regimm - compile opcodes in the - 'REGIMM' group --------------------------------------------------*/ - -bool rsp_device::generate_regimm(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) -{ - uint32_t op = desc->opptr.l[0]; - uint8_t opswitch = RTREG; - uml::code_label skip; - - switch (opswitch) - { - case 0x00: /* BLTZ */ - case 0x10: /* BLTZAL */ - if (RSREG != 0) - { - UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0 - UML_JMPc(block, COND_GE, skip = compiler.labelnum++); // jmp skip,GE - generate_delay_slot_and_branch(block, compiler, desc, (opswitch & 0x10) ? 31 : 0); - // <next instruction + hashjmp> - UML_LABEL(block, skip); // skip: - } - return true; - - case 0x01: /* BGEZ */ - case 0x11: /* BGEZAL */ - if (RSREG != 0) - { - UML_CMP(block, R32(RSREG), 0); // dcmp <rsreg>,0 - UML_JMPc(block, COND_L, skip = compiler.labelnum++); // jmp skip,L - generate_delay_slot_and_branch(block, compiler, desc, (opswitch & 0x10) ? 31 : 0); - // <next instruction + hashjmp> - UML_LABEL(block, skip); // skip: - } - else - generate_delay_slot_and_branch(block, compiler, desc, (opswitch & 0x10) ? 31 : 0); - // <next instruction + hashjmp> - return true; - } - return false; -} - - -/*------------------------------------------------- - generate_cop0 - compile COP0 opcodes --------------------------------------------------*/ - -bool rsp_device::generate_cop0(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc) -{ - uint32_t op = desc->opptr.l[0]; - uint8_t opswitch = RSREG; - - switch (opswitch) - { - case 0x00: /* MFCz */ - if (RTREG != 0) - { - UML_MOV(block, mem(&m_rsp_state->arg0), RDREG); // mov [arg0],<rdreg> - UML_MOV(block, mem(&m_rsp_state->arg1), RTREG); // mov [arg1],<rtreg> - UML_CALLC(block, cfunc_get_cop0_reg, this); // callc cfunc_get_cop0_reg - if(RDREG == 2) - { - generate_update_cycles(block, compiler, uml::mem(&m_rsp_state->pc), true); - UML_HASHJMP(block, 0, mem(&m_rsp_state->pc), *m_nocode); - } - } - return true; - - case 0x04: /* MTCz */ - UML_MOV(block, mem(&m_rsp_state->arg0), RDREG); // mov [arg0],<rdreg> - UML_MOV(block, mem(&m_rsp_state->arg1), R32(RTREG)); // mov [arg1],rtreg - UML_CALLC(block, cfunc_set_cop0_reg, this); // callc cfunc_set_cop0_reg - return true; - } - - return false; -} - -/*************************************************************************** - CODE LOGGING HELPERS -***************************************************************************/ - -/*------------------------------------------------- - log_add_disasm_comment - add a comment - including disassembly of a RSP instruction --------------------------------------------------*/ - -void rsp_device::log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op) -{ - if (m_drcuml->logging()) - { - rsp_disassembler rspd; - std::ostringstream buffer; - rspd.dasm_one(buffer, pc, op); - block.append_comment("%08X: %s", pc, buffer.str()); // comment - } -} diff --git a/src/devices/cpu/rsp/rspfe.cpp b/src/devices/cpu/rsp/rspfe.cpp deleted file mode 100644 index 83778386a0e..00000000000 --- a/src/devices/cpu/rsp/rspfe.cpp +++ /dev/null @@ -1,307 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/*************************************************************************** - - rspfe.c - - Front-end for RSP recompiler - -***************************************************************************/ - -#include "emu.h" -#include "rspfe.h" - -#include "rspdefs.h" - - -//************************************************************************** -// RSP FRONTEND -//************************************************************************** - -//------------------------------------------------- -// rsp_device::frontend - constructor -//------------------------------------------------- - -rsp_device::frontend::frontend(rsp_device &rsp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence) - : drc_frontend(rsp, window_start, window_end, max_sequence), m_rsp(rsp) -{ -} - - -//------------------------------------------------- -// describe - build a description of a single -// instruction -//------------------------------------------------- - -bool rsp_device::frontend::describe(opcode_desc &desc, const opcode_desc *prev) -{ - uint32_t op, opswitch; - - // fetch the opcode - op = desc.opptr.l[0] = m_rsp.m_pcache.read_dword((desc.physpc & 0x00000fff) | 0x1000); - - // all instructions are 4 bytes and default to a single cycle each - desc.length = 4; - desc.cycles = 1; - - // parse the instruction - opswitch = op >> 26; - switch (opswitch) - { - case 0x00: // SPECIAL - return describe_special(op, desc); - - case 0x01: // REGIMM - return describe_regimm(op, desc); - - case 0x10: // COP0 - return describe_cop0(op, desc); - - case 0x12: // COP2 - return describe_cop2(op, desc); - - case 0x02: // J - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000; - desc.delayslots = 1; - return true; - - case 0x03: // JAL - desc.regout[0] |= REGFLAG_R(31); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = ((LIMMVAL << 2) & 0x00000fff) | 0x1000; - desc.delayslots = 1; - return true; - - case 0x04: // BEQ - case 0x05: // BNE - if ((opswitch == 0x04 || opswitch == 0x14) && RSREG == RTREG) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - else - { - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; - } - desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000; - desc.delayslots = 1; - desc.skipslots = (opswitch & 0x10) ? 1 : 0; - return true; - - case 0x06: // BLEZ - case 0x07: // BGTZ - if ((opswitch == 0x06 || opswitch == 0x16) && RSREG == 0) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - else - { - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; - } - desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000; - desc.delayslots = 1; - desc.skipslots = (opswitch & 0x10) ? 1 : 0; - return true; - - case 0x08: // ADDI - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regout[0] |= REGFLAG_R(RTREG); - return true; - - case 0x09: // ADDIU - case 0x0a: // SLTI - case 0x0b: // SLTIU - case 0x0c: // ANDI - case 0x0d: // ORI - case 0x0e: // XORI - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regout[0] |= REGFLAG_R(RTREG); - return true; - - case 0x0f: // LUI - desc.regout[0] |= REGFLAG_R(RTREG); - return true; - - case 0x20: // LB - case 0x21: // LH - case 0x23: // LW - case 0x24: // LBU - case 0x25: // LHU - case 0x27: // LWU - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regout[0] |= REGFLAG_R(RTREG); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x28: // SB - case 0x29: // SH - case 0x2b: // SW - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - - case 0x32: // LWC2 - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_READS_MEMORY; - return true; - - case 0x3a: // SWC2 - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_WRITES_MEMORY; - return true; - } - - return false; -} - - -//------------------------------------------------- -// describe_special - build a description of a -// single instruction in the 'special' group -//------------------------------------------------- - -bool rsp_device::frontend::describe_special(uint32_t op, opcode_desc &desc) -{ - switch (op & 63) - { - case 0x00: // SLL - case 0x02: // SRL - case 0x03: // SRA - desc.regin[0] |= REGFLAG_R(RTREG); - desc.regout[0] |= REGFLAG_R(RDREG); - return true; - - case 0x04: // SLLV - case 0x06: // SRLV - case 0x07: // SRAV - case 0x21: // ADDU - case 0x23: // SUBU - case 0x24: // AND - case 0x25: // OR - case 0x26: // XOR - case 0x27: // NOR - case 0x2a: // SLT - case 0x2b: // SLTU - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regout[0] |= REGFLAG_R(RDREG); - return true; - - case 0x20: // ADD - case 0x22: // SUB - desc.regin[0] |= REGFLAG_R(RSREG) | REGFLAG_R(RTREG); - desc.regout[0] |= REGFLAG_R(RDREG); - return true; - - case 0x08: // JR - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - return true; - - case 0x09: // JALR - desc.regin[0] |= REGFLAG_R(RSREG); - desc.regout[0] |= REGFLAG_R(RDREG); - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = BRANCH_TARGET_DYNAMIC; - desc.delayslots = 1; - return true; - - case 0x0d: // BREAK - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - desc.targetpc = (op >> 5) & 0x000fffff; - return true; - } - - return false; -} - - -//------------------------------------------------- -// describe_regimm - build a description of a -// single instruction in the 'regimm' group -//------------------------------------------------- - -bool rsp_device::frontend::describe_regimm(uint32_t op, opcode_desc &desc) -{ - switch (RTREG) - { - case 0x00: // BLTZ - case 0x01: // BGEZ - if (RTREG == 0x01 && RSREG == 0) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - else - { - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; - } - desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000; - desc.delayslots = 1; - desc.skipslots = (RTREG & 0x02) ? 1 : 0; - return true; - - case 0x10: // BLTZAL - case 0x11: // BGEZAL - if (RTREG == 0x11 && RSREG == 0) - desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; - else - { - desc.regin[0] |= REGFLAG_R(RSREG); - desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; - } - desc.regout[0] |= REGFLAG_R(31); - desc.targetpc = ((desc.pc + 4 + SIMMVAL * 4) & 0x00000fff) | 0x1000; - desc.delayslots = 1; - desc.skipslots = (RTREG & 0x02) ? 1 : 0; - return true; - } - - return false; -} - - -//------------------------------------------------- -// describe_cop0 - build a description of a -// single instruction in the COP0 group -//------------------------------------------------- - -bool rsp_device::frontend::describe_cop0(uint32_t op, opcode_desc &desc) -{ - switch (RSREG) - { - case 0x00: // MFCz - desc.regout[0] |= REGFLAG_R(RTREG); - return true; - - case 0x04: // MTCz - desc.regin[0] |= REGFLAG_R(RTREG); - if(RDREG == 2) // SP_RD_LEN, initiating DMA - { - desc.flags |= OPFLAG_END_SEQUENCE; - } - return true; - } - - return false; -} - -//------------------------------------------------- -// describe_cop2 - build a description of a -// single instruction in the COP2 group -//------------------------------------------------- - -bool rsp_device::frontend::describe_cop2(uint32_t op, opcode_desc &desc) -{ - switch (RSREG) - { - case 0x00: // MFCz - case 0x02: // CFCz - desc.regout[0] |= REGFLAG_R(RTREG); - return true; - - case 0x04: // MTCz - case 0x06: // CTCz - desc.regin[0] |= REGFLAG_R(RTREG); - return true; - } - - return false; -} diff --git a/src/devices/cpu/rsp/rspfe.h b/src/devices/cpu/rsp/rspfe.h deleted file mode 100644 index 5f965a96e11..00000000000 --- a/src/devices/cpu/rsp/rspfe.h +++ /dev/null @@ -1,55 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -/*************************************************************************** - - rspfe.h - - Front-end for RSP recompiler - -***************************************************************************/ -#ifndef MAME_CPU_RSP_RSPFE_H -#define MAME_CPU_RSP_RSPFE_H - -#pragma once - -#include "rsp.h" -#include "cpu/drcfe.h" - - -//************************************************************************** -// CONSTANTS -//************************************************************************** - -// register flags 0 -#define REGFLAG_R(n) (((n) == 0) ? 0 : (1 << (n))) - - - -//************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -class rsp_device::frontend : public drc_frontend -{ -public: - // construction/destruction - frontend(rsp_device &rsp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence); - -protected: - // required overrides - virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; - -private: - // internal helpers - bool describe_special(uint32_t op, opcode_desc &desc); - bool describe_regimm(uint32_t op, opcode_desc &desc); - bool describe_cop0(uint32_t op, opcode_desc &desc); - bool describe_cop2(uint32_t op, opcode_desc &desc); - - // internal state - rsp_device &m_rsp; -}; - - - -#endif // MAME_CPU_RSP_RSPFE_H diff --git a/src/devices/cpu/rsp/vabs.h b/src/devices/cpu/rsp/vabs.h deleted file mode 100644 index 273841b9610..00000000000 --- a/src/devices/cpu/rsp/vabs.h +++ /dev/null @@ -1,15 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vabs(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo) -{ - rsp_vec_t vs_zero = _mm_cmpeq_epi16(vs, zero); - rsp_vec_t sign_lt = _mm_srai_epi16(vs, 15); - rsp_vec_t vd = _mm_andnot_si128(vs_zero, vt); - - // Careful: if VT = 0x8000 and VS is negative, - // acc_lo will be 0x8000 but vd will be 0x7FFF. - vd = _mm_xor_si128(vd, sign_lt); - *acc_lo = _mm_sub_epi16(vd, sign_lt); - return _mm_subs_epi16(vd, sign_lt); -} diff --git a/src/devices/cpu/rsp/vadd.h b/src/devices/cpu/rsp/vadd.h deleted file mode 100644 index 16009e53287..00000000000 --- a/src/devices/cpu/rsp/vadd.h +++ /dev/null @@ -1,16 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vadd(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t carry, rsp_vec_t *acc_lo) -{ - // VCC uses unsaturated arithmetic. - rsp_vec_t vd = _mm_add_epi16(vs, vt); - *acc_lo = _mm_sub_epi16(vd, carry); - - // VD is the signed sum of the two sources and the carry. Since we - // have to saturate the sum of all three, we have to be clever. - rsp_vec_t minimum = _mm_min_epi16(vs, vt); - rsp_vec_t maximum = _mm_max_epi16(vs, vt); - minimum = _mm_subs_epi16(minimum, carry); - return _mm_adds_epi16(minimum, maximum); -} diff --git a/src/devices/cpu/rsp/vaddc.h b/src/devices/cpu/rsp/vaddc.h deleted file mode 100644 index 0ebd30cbd31..00000000000 --- a/src/devices/cpu/rsp/vaddc.h +++ /dev/null @@ -1,13 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vaddc(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *sn) -{ - rsp_vec_t sat_sum = _mm_adds_epu16(vs, vt); - rsp_vec_t unsat_sum = _mm_add_epi16(vs, vt); - - *sn = _mm_cmpeq_epi16(sat_sum, unsat_sum); - *sn = _mm_cmpeq_epi16(*sn, zero); - - return unsat_sum; -} diff --git a/src/devices/cpu/rsp/vand.h b/src/devices/cpu/rsp/vand.h deleted file mode 100644 index 8f638330e2a..00000000000 --- a/src/devices/cpu/rsp/vand.h +++ /dev/null @@ -1,9 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vand_vnand(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt) { - rsp_vec_t vmask = _mm_load_si128((rsp_vec_t *) m_vec_helpers.logic_mask[iw & 0x1]); - - rsp_vec_t vd = _mm_and_si128(vs, vt); - return _mm_xor_si128(vd, vmask); -} diff --git a/src/devices/cpu/rsp/vch.h b/src/devices/cpu/rsp/vch.h deleted file mode 100644 index 6abac437a2c..00000000000 --- a/src/devices/cpu/rsp/vch.h +++ /dev/null @@ -1,57 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vch(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *ge, rsp_vec_t *le, rsp_vec_t *eq, rsp_vec_t *sign, rsp_vec_t *vce) { - // sign = (vs ^ vt) < 0 - *sign = _mm_xor_si128(vs, vt); - *sign = _mm_cmplt_epi16(*sign, zero); - - // sign_negvt = sign ? -vt : vt - rsp_vec_t sign_negvt = _mm_xor_si128(vt, *sign); - sign_negvt = _mm_sub_epi16(sign_negvt, *sign); - - // Compute diff, diff_zero: - rsp_vec_t diff = _mm_sub_epi16(vs, sign_negvt); - rsp_vec_t diff_zero = _mm_cmpeq_epi16(diff, zero); - - // Compute le/ge: - rsp_vec_t vt_neg = _mm_cmplt_epi16(vt, zero); - rsp_vec_t diff_lez = _mm_cmpgt_epi16(diff, zero); - rsp_vec_t diff_gez = _mm_or_si128(diff_lez, diff_zero); - diff_lez = _mm_cmpeq_epi16(zero, diff_lez); - -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - *ge = _mm_blendv_epi8(diff_gez, vt_neg, *sign); - *le = _mm_blendv_epi8(vt_neg, diff_lez, *sign); -#else - *ge = _mm_and_si128(*sign, vt_neg); - diff_gez = _mm_andnot_si128(*sign, diff_gez); - *ge = _mm_or_si128(*ge, diff_gez); - - *le = _mm_and_si128(*sign, diff_lez); - diff_lez = _mm_andnot_si128(*sign, vt_neg); - *le = _mm_or_si128(*le, diff_lez); -#endif - - // Compute vce: - *vce = _mm_cmpeq_epi16(diff, *sign); - *vce = _mm_and_si128(*vce, *sign); - - // Compute !eq: - *eq = _mm_or_si128(diff_zero, *vce); - *eq = _mm_cmpeq_epi16(*eq, zero); - - // Compute result: -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - rsp_vec_t diff_sel_mask = _mm_blendv_epi8(*ge, *le, *sign); - return _mm_blendv_epi8(vs, sign_negvt, diff_sel_mask); -#else - diff_lez = _mm_and_si128(*sign, *le); - diff_gez = _mm_andnot_si128(*sign, *ge); - rsp_vec_t diff_sel_mask = _mm_or_si128(diff_lez, diff_gez); - - diff_lez = _mm_and_si128(diff_sel_mask, sign_negvt); - diff_gez = _mm_andnot_si128(diff_sel_mask, vs); - return _mm_or_si128(diff_lez, diff_gez); -#endif -} diff --git a/src/devices/cpu/rsp/vcl.h b/src/devices/cpu/rsp/vcl.h deleted file mode 100644 index e09a13d5a8e..00000000000 --- a/src/devices/cpu/rsp/vcl.h +++ /dev/null @@ -1,65 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vcl(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *ge, rsp_vec_t *le, rsp_vec_t eq, rsp_vec_t sign, rsp_vec_t vce) -{ - // sign_negvt = sign ? -vt : vt - rsp_vec_t sign_negvt = _mm_xor_si128(vt, sign); - sign_negvt = _mm_sub_epi16(sign_negvt, sign); - - // Compute diff, diff_zero, ncarry, and nvce: - // Note: diff = sign ? (vs + vt) : (vs - vt). - rsp_vec_t diff = _mm_sub_epi16(vs, sign_negvt); - rsp_vec_t ncarry = _mm_adds_epu16(vs, vt); - ncarry = _mm_cmpeq_epi16(diff, ncarry); - rsp_vec_t nvce = _mm_cmpeq_epi16(vce, zero); - rsp_vec_t diff_zero = _mm_cmpeq_epi16(diff, zero); - - // Compute results for if (sign && ne): - rsp_vec_t le_case1 = _mm_and_si128(diff_zero, ncarry); - le_case1 = _mm_and_si128(nvce, le_case1); - rsp_vec_t le_case2 = _mm_or_si128(diff_zero, ncarry); - le_case2 = _mm_and_si128(vce, le_case2); - rsp_vec_t le_eq = _mm_or_si128(le_case1, le_case2); - - // Compute results for if (!sign && ne): - rsp_vec_t ge_eq = _mm_subs_epu16(vt, vs); - ge_eq = _mm_cmpeq_epi16(ge_eq, zero); - - // Blend everything together. Caveat: we don't update - // the results of ge/le if ne is false, so be careful. - rsp_vec_t do_le = _mm_andnot_si128(eq, sign); -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - *le = _mm_blendv_epi8(*le, le_eq, do_le); -#else - le_eq = _mm_and_si128(do_le, le_eq); - *le = _mm_andnot_si128(do_le, *le); - *le = _mm_or_si128(le_eq, *le); -#endif - - rsp_vec_t do_ge = _mm_or_si128(sign, eq); -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - *ge = _mm_blendv_epi8(ge_eq, *ge, do_ge); -#else - *ge = _mm_and_si128(do_ge, *ge); - ge_eq = _mm_andnot_si128(do_ge, ge_eq); - *ge = _mm_or_si128(ge_eq, *ge); -#endif - - // Mux the result based on the value of sign. -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - rsp_vec_t mux_mask = _mm_blendv_epi8(*ge, *le, sign); -#else - do_le = _mm_and_si128(sign, *le); - do_ge = _mm_andnot_si128(sign, *ge); - rsp_vec_t mux_mask = _mm_or_si128(do_le, do_ge); -#endif - -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - return _mm_blendv_epi8(vs, sign_negvt, mux_mask); -#else - sign_negvt = _mm_and_si128(mux_mask, sign_negvt); - vs = _mm_andnot_si128(mux_mask, vs); - return _mm_or_si128(sign_negvt, vs); -#endif -} diff --git a/src/devices/cpu/rsp/vcmp.h b/src/devices/cpu/rsp/vcmp.h deleted file mode 100644 index 7838322d26e..00000000000 --- a/src/devices/cpu/rsp/vcmp.h +++ /dev/null @@ -1,49 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_veq_vge_vlt_vne(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *le, rsp_vec_t eq, rsp_vec_t sign) -{ - rsp_vec_t equal = _mm_cmpeq_epi16(vs, vt); - - if (iw & 0x2) // VNE & VGE - { - if (iw & 0x1) // VGE - { - rsp_vec_t gt = _mm_cmpgt_epi16(vs, vt); - rsp_vec_t equalsign = _mm_and_si128(eq, sign); - - equal = _mm_andnot_si128(equalsign, equal); - *le = _mm_or_si128(gt, equal); - } - else // VNE - { - rsp_vec_t nequal = _mm_cmpeq_epi16(equal, zero); - - *le = _mm_and_si128(eq, equal); - *le = _mm_or_si128(*le, nequal); - } - } - else // VEQ & VLT - { - if (iw & 0x1) // VEQ - { - *le = _mm_andnot_si128(eq, equal); - } - else // VLT - { - rsp_vec_t lt = _mm_cmplt_epi16(vs, vt); - - equal = _mm_and_si128(eq, equal); - equal = _mm_and_si128(sign, equal); - *le = _mm_or_si128(lt, equal); - } - } - -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - return _mm_blendv_epi8(vt, vs, *le); -#else - vs = _mm_and_si128(*le, vs); - vt = _mm_andnot_si128(*le, vt); - return _mm_or_si128(vs, vt); -#endif -} diff --git a/src/devices/cpu/rsp/vcr.h b/src/devices/cpu/rsp/vcr.h deleted file mode 100644 index 78f78c66244..00000000000 --- a/src/devices/cpu/rsp/vcr.h +++ /dev/null @@ -1,35 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vcr(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *ge, rsp_vec_t *le) { - // sign = (vs ^ vt) < 0 - rsp_vec_t sign = _mm_xor_si128(vs, vt); - sign = _mm_srai_epi16(sign, 15); - - // Compute le - rsp_vec_t diff_lez = _mm_and_si128(vs, sign); - diff_lez = _mm_add_epi16(diff_lez, vt); - *le = _mm_srai_epi16(diff_lez, 15); - - // Compute ge - rsp_vec_t diff_gez = _mm_or_si128(vs, sign); - diff_gez = _mm_min_epi16(diff_gez, vt); - *ge = _mm_cmpeq_epi16(diff_gez, vt); - - // sign_notvt = sn ? ~vt : vt - rsp_vec_t sign_notvt = _mm_xor_si128(vt, sign); - - // Compute result: -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - rsp_vec_t diff_sel_mask = _mm_blendv_epi8(*ge, *le, sign); - return _mm_blendv_epi8(vs, sign_notvt, diff_sel_mask); -#else - rsp_vec_t diff_sel_mask = _mm_sub_epi16(*le, *ge); - diff_sel_mask = _mm_and_si128(diff_sel_mask, sign); - diff_sel_mask = _mm_add_epi16(diff_sel_mask, *ge); - - zero = _mm_sub_epi16(sign_notvt, vs); - zero = _mm_and_si128(zero, diff_sel_mask); - return _mm_add_epi16(zero, vs); -#endif -} diff --git a/src/devices/cpu/rsp/vdivh.h b/src/devices/cpu/rsp/vdivh.h deleted file mode 100644 index 5bd4093f6b4..00000000000 --- a/src/devices/cpu/rsp/vdivh.h +++ /dev/null @@ -1,12 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vdivh(uint32_t src, uint32_t e, uint32_t dest, uint32_t de) -{ - // Get the element from VT. - m_div_in = m_v[src].s[e & 0x7]; - - // Write out the upper part of the result. - m_v[dest].s[de & 0x7] = m_div_out; - return vec_load_unshuffled_operand(m_v[dest].s); -} diff --git a/src/devices/cpu/rsp/vldst.h b/src/devices/cpu/rsp/vldst.h deleted file mode 100644 index fadc8be63c0..00000000000 --- a/src/devices/cpu/rsp/vldst.h +++ /dev/null @@ -1,69 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -// LBV, LDV, LLV, LSV, SBV, SDV, SLV, SSV -inline void vec_lbdlsv_sbdlsv(uint32_t iw, uint32_t rs) -{ - const uint32_t shift_and_idx = (iw >> 11) & 0x3; - rsp_vec_t dqm = _mm_loadl_epi64((rsp_vec_t *) (m_vec_helpers.bdls_lut[shift_and_idx])); - - const uint32_t addr = (rs + (sign_extend_6(iw) << shift_and_idx)) & 0xfff; - const uint32_t element = (iw >> 7) & 0xf; - uint16_t* regp = m_v[(iw >> 16) & 0x1f].s; - - if (iw >> 29 & 0x1) - { - vec_store_group1(addr, element, regp, vec_load_unshuffled_operand(regp), dqm); - } - else - { - vec_load_group1(addr, element, regp, vec_load_unshuffled_operand(regp), dqm); - } -} - -// LPV, LUV, SPV, SUV -inline void vec_lfhpuv_sfhpuv(uint32_t iw, uint32_t rs) -{ - static const enum rsp_mem_request_type fhpu_type_lut[4] = { - RSP_MEM_REQUEST_PACK, - RSP_MEM_REQUEST_UPACK, - RSP_MEM_REQUEST_HALF, - RSP_MEM_REQUEST_FOURTH - }; - - const uint32_t addr = (rs + (sign_extend_6(iw) << 3)) & 0xfff; - const uint32_t element = (iw >> 7) & 0xf; - uint16_t* regp = m_v[(iw >> 16) & 0x1f].s; - - rsp_mem_request_type request_type = fhpu_type_lut[((iw >> 11) & 0x1f) - 6]; - if ((iw >> 29) & 0x1) - { - vec_store_group2(addr, element, regp, vec_load_unshuffled_operand(regp), _mm_setzero_si128(), request_type); - } - else - { - vec_load_group2(addr, element, regp, vec_load_unshuffled_operand(regp), _mm_setzero_si128(), request_type); - } -} - -// LQV, LRV, SQV, SRV -inline void vec_lqrv_sqrv(uint32_t iw, uint32_t rs) -{ - rs &= 0xfff; - - const uint32_t addr = rs + (sign_extend_6(iw) << 4); - const uint32_t element = (iw >> 7) & 0xf; - uint16_t* regp = m_v[(iw >> 16) & 0x1f].s; - - memcpy(m_vdqm.s, m_vec_helpers.qr_lut[addr & 0xf], sizeof(m_vdqm.s)); - - rsp_mem_request_type request_type = (iw >> 11 & 0x1) ? RSP_MEM_REQUEST_REST : RSP_MEM_REQUEST_QUAD; - if ((iw >> 29) & 0x1) - { - vec_store_group4(addr, element, regp, vec_load_unshuffled_operand(regp), vec_load_unshuffled_operand(m_vdqm.s), request_type); - } - else - { - vec_load_group4(addr, element, regp, vec_load_unshuffled_operand(regp), vec_load_unshuffled_operand(m_vdqm.s), request_type); - } -} diff --git a/src/devices/cpu/rsp/vmac.h b/src/devices/cpu/rsp/vmac.h deleted file mode 100644 index ade43511daa..00000000000 --- a/src/devices/cpu/rsp/vmac.h +++ /dev/null @@ -1,57 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vmacf_vmacu(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_mid, rsp_vec_t *acc_hi) -{ - // Get the product and shift it over - // being sure to save the carries. - rsp_vec_t lo = _mm_mullo_epi16(vs, vt); - rsp_vec_t hi = _mm_mulhi_epi16(vs, vt); - - rsp_vec_t mid = _mm_slli_epi16(hi, 1); - rsp_vec_t carry = _mm_srli_epi16(lo, 15); - hi = _mm_srai_epi16(hi, 15); - mid = _mm_or_si128(mid, carry); - lo = _mm_slli_epi16(lo, 1); - - // Tricky part: start accumulating everything. - // Get/keep the carry as we'll add it in later. - rsp_vec_t overflow_mask = _mm_adds_epu16(*acc_lo, lo); - *acc_lo = _mm_add_epi16(*acc_lo, lo); - - overflow_mask = _mm_cmpeq_epi16(*acc_lo, overflow_mask); - overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero); - - // Add in the carry. If the middle portion is - // already 0xFFFF and we have a carry, we have - // to carry the all the way up to hi. - mid = _mm_sub_epi16(mid, overflow_mask); - carry = _mm_cmpeq_epi16(mid, zero); - carry = _mm_and_si128(carry, overflow_mask); - hi = _mm_sub_epi16(hi, carry); - - // Accumulate the middle portion. - overflow_mask = _mm_adds_epu16(*acc_mid, mid); - *acc_mid = _mm_add_epi16(*acc_mid, mid); - - overflow_mask = _mm_cmpeq_epi16(*acc_mid, overflow_mask); - overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero); - - // Finish up the accumulation of the... accumulator. - *acc_hi = _mm_add_epi16(*acc_hi, hi); - *acc_hi = _mm_sub_epi16(*acc_hi, overflow_mask); - - if (iw & 0x1) // VMACU - { - rsp_vec_t overflow_hi_mask = _mm_srai_epi16(*acc_hi, 15); - rsp_vec_t overflow_mid_mask = _mm_srai_epi16(*acc_mid, 15); - mid = _mm_or_si128(overflow_mid_mask, *acc_mid); - overflow_mask = _mm_cmpgt_epi16(*acc_hi, zero); - mid = _mm_andnot_si128(overflow_hi_mask, mid); - return _mm_or_si128(overflow_mask, mid); - } - else // VMACF - { - return sclamp_acc_to_mid(*acc_mid, *acc_hi); - } -} diff --git a/src/devices/cpu/rsp/vmov.h b/src/devices/cpu/rsp/vmov.h deleted file mode 100644 index 59e02e8b118..00000000000 --- a/src/devices/cpu/rsp/vmov.h +++ /dev/null @@ -1,9 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vmov(uint32_t src, uint32_t e, uint32_t dest, uint32_t de) -{ - // Get the element from VT and write out the upper part of the result. - m_v[dest].s[de & 0x7] = m_v[src].s[e & 0x7]; - return vec_load_unshuffled_operand(m_v[dest].s); -} diff --git a/src/devices/cpu/rsp/vmrg.h b/src/devices/cpu/rsp/vmrg.h deleted file mode 100644 index ab9be63ef16..00000000000 --- a/src/devices/cpu/rsp/vmrg.h +++ /dev/null @@ -1,13 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vmrg(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t le) -{ -#if (defined(__SSE4_1__) || defined(_MSC_VER)) - return _mm_blendv_epi8(vt, vs, le); -#else - vs = _mm_and_si128(le, vs); - vt = _mm_andnot_si128(le, vt); - return _mm_or_si128(vs, vt); -#endif -} diff --git a/src/devices/cpu/rsp/vmudh.h b/src/devices/cpu/rsp/vmudh.h deleted file mode 100644 index 71c3a38f4fb..00000000000 --- a/src/devices/cpu/rsp/vmudh.h +++ /dev/null @@ -1,10 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t rsp_vmudh(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t *acc_md, rsp_vec_t *acc_hi) -{ - *acc_md = _mm_mullo_epi16(vs, vt); - *acc_hi = _mm_mulhi_epi16(vs, vt); - - return sclamp_acc_to_mid(*acc_md, *acc_hi); -} diff --git a/src/devices/cpu/rsp/vmul.h b/src/devices/cpu/rsp/vmul.h deleted file mode 100644 index dc09e81768a..00000000000 --- a/src/devices/cpu/rsp/vmul.h +++ /dev/null @@ -1,39 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -// -// TODO: CHECK ME. -// - -inline rsp_vec_t vec_vmulf_vmulu(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_md, rsp_vec_t *acc_hi) -{ - rsp_vec_t lo = _mm_mullo_epi16(vs, vt); - rsp_vec_t round = _mm_cmpeq_epi16(zero, zero); - rsp_vec_t sign1 = _mm_srli_epi16(lo, 15); - lo = _mm_add_epi16(lo, lo); - round = _mm_slli_epi16(round, 15); - rsp_vec_t hi = _mm_mulhi_epi16(vs, vt); - rsp_vec_t sign2 = _mm_srli_epi16(lo, 15); - *acc_lo = _mm_add_epi16(round, lo); - sign1 = _mm_add_epi16(sign1, sign2); - - hi = _mm_slli_epi16(hi, 1); - rsp_vec_t eq = _mm_cmpeq_epi16(vs, vt); - rsp_vec_t neq = eq; - *acc_md = _mm_add_epi16(hi, sign1); - - rsp_vec_t neg = _mm_srai_epi16(*acc_md, 15); - - if (iw & 0x1) // VMULU - { - *acc_hi = _mm_andnot_si128(eq, neg); - hi =_mm_or_si128(*acc_md, neg); - return _mm_andnot_si128(*acc_hi, hi); - } - else // VMULF - { - eq = _mm_and_si128(eq, neg); - *acc_hi = _mm_andnot_si128(neq, neg); - return _mm_add_epi16(*acc_md, eq); - } -} diff --git a/src/devices/cpu/rsp/vmulh.h b/src/devices/cpu/rsp/vmulh.h deleted file mode 100644 index 6265961f5a0..00000000000 --- a/src/devices/cpu/rsp/vmulh.h +++ /dev/null @@ -1,30 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vmadh_vmudh(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_md, rsp_vec_t *acc_hi) -{ - rsp_vec_t lo = _mm_mullo_epi16(vs, vt); - rsp_vec_t hi = _mm_mulhi_epi16(vs, vt); - - if (iw & 0x8) // VMADH - { - // Tricky part: start accumulating everything. - // Get/keep the carry as we'll add it in later. - rsp_vec_t overflow_mask = _mm_adds_epu16(*acc_md, lo); - *acc_md = _mm_add_epi16(*acc_md, lo); - - overflow_mask = _mm_cmpeq_epi16(*acc_md, overflow_mask); - overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero); - - hi = _mm_sub_epi16(hi, overflow_mask); - *acc_hi = _mm_add_epi16(*acc_hi, hi); - } - else // VMUDH - { - *acc_lo = zero; - *acc_md = lo; - *acc_hi = hi; - } - - return sclamp_acc_to_mid(*acc_md, *acc_hi); -} diff --git a/src/devices/cpu/rsp/vmull.h b/src/devices/cpu/rsp/vmull.h deleted file mode 100644 index e54399b01da..00000000000 --- a/src/devices/cpu/rsp/vmull.h +++ /dev/null @@ -1,44 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vmadl_vmudl(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_md, rsp_vec_t *acc_hi) -{ - rsp_vec_t hi = _mm_mulhi_epu16(vs, vt); - - if (iw & 0x8) // VMADL - { - // Tricky part: start accumulating everything. - // Get/keep the carry as we'll add it in later. - rsp_vec_t overflow_mask = _mm_adds_epu16(*acc_lo, hi); - *acc_lo = _mm_add_epi16(*acc_lo, hi); - - overflow_mask = _mm_cmpeq_epi16(*acc_lo, overflow_mask); - overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero); - hi = _mm_sub_epi16(zero, overflow_mask); - - // Check for overflow of the upper sum. - // - // TODO: Since hi can only be {0,1}, we should - // be able to generalize this for performance. - overflow_mask = _mm_adds_epu16(*acc_md, hi); - *acc_md = _mm_add_epi16(*acc_md, hi); - - overflow_mask = _mm_cmpeq_epi16(*acc_md, overflow_mask); - overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero); - - // Finish up the accumulation of the... accumulator. - // Since the product was unsigned, only worry about - // positive overflow (i.e.: borrowing not possible). - *acc_hi = _mm_sub_epi16(*acc_hi, overflow_mask); - - return uclamp_acc(*acc_lo, *acc_md, *acc_hi, zero); - } - else // VMUDL - { - *acc_lo = hi; - *acc_md = zero; - *acc_hi = zero; - - return hi; - } -} diff --git a/src/devices/cpu/rsp/vmulm.h b/src/devices/cpu/rsp/vmulm.h deleted file mode 100644 index df76833ed0c..00000000000 --- a/src/devices/cpu/rsp/vmulm.h +++ /dev/null @@ -1,56 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vmadm_vmudm(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_md, rsp_vec_t *acc_hi) -{ - rsp_vec_t lo = _mm_mullo_epi16(vs, vt); - rsp_vec_t hi = _mm_mulhi_epu16(vs, vt); - - // What we really want to do is unsigned vs * signed vt. - // However, we have no such instructions to do so. - // - // There's a trick to "fix" an unsigned product, though: - // If vt was negative, take the upper 16-bits of the product - // and subtract vs. - rsp_vec_t sign = _mm_srai_epi16(vs, 15); - vt = _mm_and_si128(vt, sign); - hi = _mm_sub_epi16(hi, vt); - - if (iw & 0x8) // VMADM - { - // Tricky part: start accumulating everything. - // Get/keep the carry as we'll add it in later. - rsp_vec_t overflow_mask = _mm_adds_epu16(*acc_lo, lo); - *acc_lo = _mm_add_epi16(*acc_lo, lo); - - overflow_mask = _mm_cmpeq_epi16(*acc_lo, overflow_mask); - overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero); - - // This is REALLY clever. Since the product results from - // two 16-bit components, one positive and one negative, - // we don't have to worry about carrying the 1 (we can - // only borrow) past 32-bits. So we can just add it here. - hi = _mm_sub_epi16(hi, overflow_mask); - - // Check for overflow of the upper sum. - overflow_mask = _mm_adds_epu16(*acc_md, hi); - *acc_md = _mm_add_epi16(*acc_md, hi); - - overflow_mask = _mm_cmpeq_epi16(*acc_md, overflow_mask); - overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero); - - // Finish up the accumulation of the... accumulator. - *acc_hi = _mm_add_epi16(*acc_hi, _mm_srai_epi16(hi, 15)); - *acc_hi = _mm_sub_epi16(*acc_hi, overflow_mask); - - return sclamp_acc_to_mid(*acc_md, *acc_hi); - } - else // VMUDM - { - *acc_lo = lo; - *acc_md = hi; - *acc_hi = _mm_srai_epi16(hi, 15); - - return hi; - } -} diff --git a/src/devices/cpu/rsp/vmuln.h b/src/devices/cpu/rsp/vmuln.h deleted file mode 100644 index 07453b631a8..00000000000 --- a/src/devices/cpu/rsp/vmuln.h +++ /dev/null @@ -1,55 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vmadn_vmudn(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *acc_lo, rsp_vec_t *acc_md, rsp_vec_t *acc_hi) -{ - rsp_vec_t lo = _mm_mullo_epi16(vs, vt); - rsp_vec_t hi = _mm_mulhi_epu16(vs, vt); - - // What we really want to do is unsigned vs * signed vt. - // However, we have no such instructions to do so. - // - // There's a trick to "fix" an unsigned product, though: - // If vt was negative, take the upper 16-bits of the product - // and subtract vs. - rsp_vec_t sign = _mm_srai_epi16(vt, 15); - vs = _mm_and_si128(vs, sign); - hi = _mm_sub_epi16(hi, vs); - - if (iw & 0x8) // VMADN - { - // Tricky part: start accumulating everything. - // Get/keep the carry as we'll add it in later. - rsp_vec_t overflow_mask = _mm_adds_epu16(*acc_lo, lo); - *acc_lo = _mm_add_epi16(*acc_lo, lo); - - overflow_mask = _mm_cmpeq_epi16(*acc_lo, overflow_mask); - overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero); - - // This is REALLY clever. Since the product results from - // two 16-bit components, one positive and one negative, - // we don't have to worry about carrying the 1 (we can - // only borrow) past 32-bits. So we can just add it here. - hi = _mm_sub_epi16(hi, overflow_mask); - - // Check for overflow of the upper sum. - overflow_mask = _mm_adds_epu16(*acc_md, hi); - *acc_md = _mm_add_epi16(*acc_md, hi); - - overflow_mask = _mm_cmpeq_epi16(*acc_md, overflow_mask); - overflow_mask = _mm_cmpeq_epi16(overflow_mask, zero); - - // Finish up the accumulation of the... accumulator. - *acc_hi = _mm_add_epi16(*acc_hi, _mm_srai_epi16(hi, 15)); - *acc_hi = _mm_sub_epi16(*acc_hi, overflow_mask); - return uclamp_acc(*acc_lo, *acc_md, *acc_hi, zero); - } - else // VMUDN - { - *acc_lo = lo; - *acc_md = hi; - *acc_hi = _mm_srai_epi16(hi, 15); - - return lo; - } -} diff --git a/src/devices/cpu/rsp/vor.h b/src/devices/cpu/rsp/vor.h deleted file mode 100644 index 07cbb57164c..00000000000 --- a/src/devices/cpu/rsp/vor.h +++ /dev/null @@ -1,10 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vor_vnor(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt) -{ - rsp_vec_t vmask = _mm_load_si128((rsp_vec_t *) m_vec_helpers.logic_mask[iw & 0x1]); - - rsp_vec_t vd = _mm_or_si128(vs, vt); - return _mm_xor_si128(vd, vmask); -} diff --git a/src/devices/cpu/rsp/vrcpsq.h b/src/devices/cpu/rsp/vrcpsq.h deleted file mode 100644 index 4897e536193..00000000000 --- a/src/devices/cpu/rsp/vrcpsq.h +++ /dev/null @@ -1,58 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vrcp_vrsq(uint32_t iw, int32_t dp, uint32_t src, uint32_t e, uint32_t dest, uint32_t de) -{ - // Get the element from VT. - int16_t vt = m_v[src].s[e & 0x7]; - - uint32_t dp_input = ((uint32_t) m_div_in << 16) | (uint16_t) vt; - uint32_t sp_input = vt; - - int32_t input = (dp) ? dp_input : sp_input; - int32_t input_mask = input >> 31; - int32_t data = input ^ input_mask; - - if (input > -32768) - { - data -= input_mask; - } - - // Handle edge cases. - int32_t result; - if (data == 0) - { - result = 0x7fffffff; - } - else if (input == -32768) - { - result = 0xffff0000; - } - else // Main case: compute the reciprocal. - { - uint32_t shift = count_leading_zeros(data); - uint32_t idx = (((uint64_t) data << shift) & 0x7FC00000) >> 22; - - if (iw & 0x4) // VRSQ - { - idx = ((idx | 0x200) & 0x3fe) | (shift % 2); - result = rsp_divtable[idx]; - - result = ((0x10000 | result) << 14) >> ((31 - shift) >> 1); - } - else // VRCP - { - result = rsp_divtable[idx]; - - result = ((0x10000 | result) << 14) >> (31 - shift); - } - - result = result ^ input_mask; - } - - // Write out the results. - m_div_out = result >> 16; - m_v[dest].s[de & 0x7] = result; - - return vec_load_unshuffled_operand(m_v[dest].s); -} diff --git a/src/devices/cpu/rsp/vrsq.h b/src/devices/cpu/rsp/vrsq.h deleted file mode 100644 index d4bdb190fec..00000000000 --- a/src/devices/cpu/rsp/vrsq.h +++ /dev/null @@ -1,66 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -rsp_vec_t vec_vrsq(int32_t dp, uint32_t src, uint32_t e, uint32_t dest, uint32_t de) -{ - // Get the element from VT. - int16_t vt = m_v[src].s[e & 0x7]; - - uint32_t dp_input = ((uint32_t) m_div_in << 16) | (uint16_t) vt; - uint32_t sp_input = vt; - - int32_t input = (dp) ? dp_input : sp_input; - int32_t input_mask = input >> 31; - int32_t data = input ^ input_mask; - - if (input > -32768) - { - data -= input_mask; - } - - // Handle edge cases. - int32_t result; - if (data == 0) - { - result = 0x7fffffff; - } - else if (input == -32768) - { - result = 0xffff0000; - } - else // Main case: compute the reciprocal. - { - uint32_t shift = count_leading_zeros(data); - - uint32_t idx = (((uint64_t) data << shift) & 0x7fc00000) >> 22; - idx = ((idx | 0x200) & 0x3fe) | (shift % 2); - result = rsp_divtable[idx]; - - result = ((0x10000 | result) << 14) >> ((31 - shift) >> 1); - result = result ^ input_mask; - } - - // Write out the results. - m_div_out = result >> 16; - m_v[dest].s[de & 0x7] = result; - - return vec_load_unshuffled_operand(m_v[dest].s); -} - -rsp_vec_t vec_vrsqh(uint32_t src, uint32_t e, uint32_t dest, uint32_t de) -{ - int16_t elements[8]; - - // Get the element from VT. - memcpy(elements, &m_v[src], sizeof(rsp_vec_t)); - m_div_in = elements[e]; - - // Write out the upper part of the result. - rsp_vec_t vd_mask = _mm_load_si128((rsp_vec_t *) m_vec_helpers.vrsq_mask_table[de]); - rsp_vec_t vd = _mm_load_si128((rsp_vec_t *) &m_v[dest]); - vd = _mm_andnot_si128(vd_mask, vd); - - rsp_vec_t b_result = _mm_set1_epi16(m_div_out); - b_result = _mm_and_si128(vd_mask, b_result); - return _mm_or_si128(b_result, vd); -} diff --git a/src/devices/cpu/rsp/vsub.h b/src/devices/cpu/rsp/vsub.h deleted file mode 100644 index c3df93627c8..00000000000 --- a/src/devices/cpu/rsp/vsub.h +++ /dev/null @@ -1,17 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vsub(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t carry, rsp_vec_t *acc_lo) -{ - // acc_lo uses saturated arithmetic. - rsp_vec_t unsat_diff = _mm_sub_epi16(vt, carry); - rsp_vec_t sat_diff = _mm_subs_epi16(vt, carry); - - *acc_lo = _mm_sub_epi16(vs, unsat_diff); - rsp_vec_t vd = _mm_subs_epi16(vs, sat_diff); - - // VD is the signed diff of the two sources and the carry. Since we - // have to saturate the diff of all three, we have to be clever. - rsp_vec_t overflow = _mm_cmpgt_epi16(sat_diff, unsat_diff); - return _mm_adds_epi16(vd, overflow); -} diff --git a/src/devices/cpu/rsp/vsubc.h b/src/devices/cpu/rsp/vsubc.h deleted file mode 100644 index 8632b9462d9..00000000000 --- a/src/devices/cpu/rsp/vsubc.h +++ /dev/null @@ -1,14 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vsubc(rsp_vec_t vs, rsp_vec_t vt, rsp_vec_t zero, rsp_vec_t *eq, rsp_vec_t *sn) -{ - rsp_vec_t sat_udiff = _mm_subs_epu16(vs, vt); - rsp_vec_t equal = _mm_cmpeq_epi16(vs, vt); - rsp_vec_t sat_udiff_zero = _mm_cmpeq_epi16(sat_udiff, zero); - - *eq = _mm_cmpeq_epi16(equal, zero); - *sn = _mm_andnot_si128(equal, sat_udiff_zero); - - return _mm_sub_epi16(vs, vt); -} diff --git a/src/devices/cpu/rsp/vxor.h b/src/devices/cpu/rsp/vxor.h deleted file mode 100644 index 9f7f62853c5..00000000000 --- a/src/devices/cpu/rsp/vxor.h +++ /dev/null @@ -1,10 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Tyler J. Stachecki,Ryan Holtz - -inline rsp_vec_t vec_vxor_vnxor(uint32_t iw, rsp_vec_t vs, rsp_vec_t vt) -{ - rsp_vec_t vmask = _mm_load_si128((rsp_vec_t *) m_vec_helpers.logic_mask[iw & 0x1]); - - rsp_vec_t vd = _mm_xor_si128(vs, vt); - return _mm_xor_si128(vd, vmask); -} 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 |