diff options
Diffstat (limited to 'src/devices/cpu/unsp/unsp_exxx.cpp')
-rw-r--r-- | src/devices/cpu/unsp/unsp_exxx.cpp | 141 |
1 files changed, 72 insertions, 69 deletions
diff --git a/src/devices/cpu/unsp/unsp_exxx.cpp b/src/devices/cpu/unsp/unsp_exxx.cpp index 0107c1fd0c7..82593669770 100644 --- a/src/devices/cpu/unsp/unsp_exxx.cpp +++ b/src/devices/cpu/unsp/unsp_exxx.cpp @@ -9,8 +9,8 @@ #include "unspdasm.h" -#define LOG_UNSP_SHIFTS (1U << 2) #define LOG_UNSP_MULS (1U << 1) +#define LOG_UNSP_SHIFTS (1U << 2) #define VERBOSE (0) @@ -128,7 +128,7 @@ void unsp_12_device::execute_exxx_group(uint16_t op) const uint16_t opb = op & 7; m_core->m_icount -= 12; - LOGMASKED(LOG_UNSP_MULS, "%s: MUL su with %04x (signed) * %04x (unsigned) : ", machine().describe_context(), m_core->m_r[opa], m_core->m_r[opb]); + LOGMASKED(LOG_UNSP_MULS, "%s: MUL su with %04x (signed) * %04x (unsigned) (fra:%d) :\n", machine().describe_context(), m_core->m_r[opa], m_core->m_r[opb], m_core->m_fra); uint32_t lres = m_core->m_r[opa] * m_core->m_r[opb]; if (m_core->m_r[opa] & 0x8000) @@ -178,100 +178,103 @@ void unsp_12_device::execute_exxx_group(uint16_t op) switch (shift) { case 0x00: - LOGMASKED(LOG_UNSP_SHIFTS, "%s = %s asr %s\n", regs[rd], regs[rd], regs[rs]); - unimplemented_opcode(op); - return; - - case 0x01: // jak_car2 on starting a game { - LOGMASKED(LOG_UNSP_SHIFTS, "%s = %s asror %s\n", regs[rd], regs[rd], regs[rs]); - if (rd != 4) // 4 = R4 3 = R3 - the 'register bleeding' is only verified as needed between r3/r4, so bail for other regs until verified - unimplemented_opcode(op); + LOGMASKED(LOG_UNSP_SHIFTS, "%s = %s asr %s\n", regs[rd], regs[rd], regs[rs]); - uint32_t res = (uint16_t)(m_core->m_r[rd]); + uint32_t rdval = (uint16_t)(m_core->m_r[rd]); int shift = (m_core->m_r[rs] & 0x01f); - res <<= 16; + if (shift == 0) + return; - if (res & 0x80000000) + uint32_t res; + if (BIT(rd, (32 - shift))) { - res = res >> shift; - res |= (0xffffffff << (32 - shift)); - - m_core->m_r[rd] = (res >> 16); - m_core->m_r[rd - 1] |= (res & 0xffff); // register bleeding? + if (shift >= 16) + { + res = 0x0000ffff; + } + else + { + res = (rdval >> shift) | (uint16_t)(0xffff0000 >> shift); + } } else { - res = res >> shift; - m_core->m_r[rd] = (res >> 16); - m_core->m_r[rd - 1] |= (res & 0xffff); // register bleeding? + if (shift >= 16) + { + res = 0; + } + else + { + res = rdval >> shift; + } } - LOGMASKED(LOG_UNSP_SHIFTS, "result %04x\n", m_core->m_r[rd]); + LOGMASKED(LOG_UNSP_SHIFTS, "result: %08x\n", res); + m_core->m_r[rd] = res; return; } - case 0x02: - LOGMASKED(LOG_UNSP_SHIFTS, "pc:%06x: %s = %s lsl %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]); - - m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) << (m_core->m_r[rs] & 0x01f)); - - LOGMASKED(LOG_UNSP_SHIFTS, "result %04x\n", m_core->m_r[rd]); + case 0x01: // jak_car2 on starting a game + { + LOGMASKED(LOG_UNSP_SHIFTS, "%s = %s asror %s (%04x %04x)\n", regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]); + + const int32_t rdval = (int32_t)(m_core->m_r[rd] << 16); + const int shift = (m_core->m_r[rs] & 0x01f); + const uint32_t res = rdval >> shift; + m_core->m_r[REG_R3] |= (uint16_t)res; + m_core->m_r[REG_R4] |= (uint16_t)(res >> 16); + LOGMASKED(LOG_UNSP_SHIFTS, "result: %04x%04x\n", m_core->m_r[REG_R4], m_core->m_r[REG_R3]); + return; + } + case 0x02: + { + LOGMASKED(LOG_UNSP_SHIFTS, "pc:%06x: %s = %s lsl %s (%04x %04x)\n", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]); + const uint32_t rdval = (uint16_t)(m_core->m_r[rd]); + const int shift = (m_core->m_r[rs] & 0x01f); + const uint32_t res = (uint16_t)(rdval << shift); + LOGMASKED(LOG_UNSP_SHIFTS, "result: %08x\n", res); + m_core->m_r[rd] = res; return; + } case 0x03: { // wrlshunt uses this - LOGMASKED(LOG_UNSP_SHIFTS, "pc:%06x: %s = %s lslor %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]); - - if (rd != 3) // 4 = R4 3 = R3 - the 'register bleeding' is only verified as needed between r3/r4, so bail for other regs until verified - unimplemented_opcode(op); - - uint32_t res = (uint16_t)(m_core->m_r[rd]); - - res <<= (m_core->m_r[rs] & 0x01f); - - m_core->m_r[rd] = (res & 0xffff); - m_core->m_r[rd + 1] |= (res >> 16); // register bleeding? - - LOGMASKED(LOG_UNSP_SHIFTS, "result %04x\n", m_core->m_r[rd]); + LOGMASKED(LOG_UNSP_SHIFTS, "pc:%06x: %s = %s lslor %s (%04x %04x)\n", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]); + + const uint32_t rdval = m_core->m_r[rd]; + const int shift = (m_core->m_r[rs] & 0x01f); + const uint32_t res = rdval << shift; + m_core->m_r[REG_R3] = (uint16_t)res; + m_core->m_r[REG_R4] |= (uint16_t)(res >> 16); + LOGMASKED(LOG_UNSP_SHIFTS, "result: %04x%04x\n", m_core->m_r[REG_R4], m_core->m_r[REG_R3]); return; } case 0x04: - // smartfp loops increasing shift by 4 up to values of 28? (but regs are 16-bit?) - LOGMASKED(LOG_UNSP_SHIFTS, "pc:%06x: %s = %s lsr %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]); - m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) >> (m_core->m_r[rs] & 0x1f)); - LOGMASKED(LOG_UNSP_SHIFTS, "result %04x\n", m_core->m_r[rd]); + { + // smartfp loops increasing shift by 4 up to values of 28 + LOGMASKED(LOG_UNSP_SHIFTS, "pc:%06x: %s = %s lsr %s (%04x %04x)\n", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]); + + const uint32_t rdval = (uint16_t)(m_core->m_r[rd]); + const int shift = (m_core->m_r[rs] & 0x01f); + const uint32_t res = (uint16_t)(rdval >> shift); + LOGMASKED(LOG_UNSP_SHIFTS, "result: %08x\n", res); + m_core->m_r[rd] = res; return; + } case 0x05: { - LOGMASKED(LOG_UNSP_SHIFTS, "pc:%06x: %s = %s lsror %s (%04x %04x) : ", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]); - - if (rd != 4) // 4 = R4 3 = R3 - the 'register bleeding' is only verified as needed between r3/r4, so bail for other regs until verified - unimplemented_opcode(op); - - uint32_t res = (uint16_t)(m_core->m_r[rd]); - - res <<= 16; - - res = res >> (m_core->m_r[rs] & 0x01f); - - // register bleeding behavior needed (for example) in jak_cars2 nand browser when increasing upper digits of address - // TODO: check if I'm missing something becaus this doesn't really seem logical, maybe other code is meant to take care of those bits? - // (although R3/R4 are the 'MR' register used for multiply stuff, so maybe there is some logic to this?) - - // code attempts to put a 32-bit value in r4/r3 then shift it like this? - //3c990: e92a r4 = r4 lsl r2 - //3c991: e73a r3 = r3 lslor r2 - - m_core->m_r[rd] = (res >> 16); - m_core->m_r[rd - 1] |= (res & 0xffff); // register bleeding? - - - LOGMASKED(LOG_UNSP_SHIFTS, "result %04x\n", m_core->m_r[rd]); + LOGMASKED(LOG_UNSP_SHIFTS, "pc:%06x: %s = %s lsror %s (%04x %04x)\n", UNSP_LPC, regs[rd], regs[rd], regs[rs], m_core->m_r[rd], m_core->m_r[rs]); + const uint32_t rdval = m_core->m_r[rd]; + const int shift = (m_core->m_r[rs] & 0x01f); + const uint32_t res = rdval << shift; + m_core->m_r[REG_R3] |= (uint16_t)res; + m_core->m_r[REG_R4] |= (uint16_t)(res >> 16); + LOGMASKED(LOG_UNSP_SHIFTS, "result: %04x%04x\n", m_core->m_r[REG_R4], m_core->m_r[REG_R3]); return; } |