summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/unsp/unsp_exxx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/unsp/unsp_exxx.cpp')
-rw-r--r--src/devices/cpu/unsp/unsp_exxx.cpp48
1 files changed, 39 insertions, 9 deletions
diff --git a/src/devices/cpu/unsp/unsp_exxx.cpp b/src/devices/cpu/unsp/unsp_exxx.cpp
index 5e8f108ed52..25f754bb2e8 100644
--- a/src/devices/cpu/unsp/unsp_exxx.cpp
+++ b/src/devices/cpu/unsp/unsp_exxx.cpp
@@ -181,34 +181,64 @@ void unsp_12_device::execute_exxx_group(uint16_t op)
case 0x02:
logerror("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] & 0x0f));
+
+ m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) << (m_core->m_r[rs] & 0x01f));
+
logerror("result %04x\n", m_core->m_r[rd]);
+
return;
case 0x03:
{
// wrlshunt uses this
logerror("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]);
- uint16_t tmp = m_core->m_r[rd];
- m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) << (m_core->m_r[rs] & 0x0f));
- m_core->m_r[rd] |= tmp; // guess
+
+ 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?
+
logerror("result %04x\n", m_core->m_r[rd]);
return;
}
case 0x04:
- // smartfp loops increasing shift by 4 up to values of 28? (but regs are 16-bit?)
+ // smartfp loops increasing shift by 4 up to values of 28? (but regs are 16-bit?)
logerror("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] & 0xf));
+ m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) >> (m_core->m_r[rs] & 0x1f));
logerror("result %04x\n", m_core->m_r[rd]);
return;
case 0x05:
{
logerror("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]);
- uint16_t tmp = m_core->m_r[rd];
- m_core->m_r[rd] = (uint16_t)((m_core->m_r[rd]&0xffff) >> (m_core->m_r[rs] & 0x0f));
- m_core->m_r[rd] |= tmp; // guess
+
+ 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?
+
+
logerror("result %04x\n", m_core->m_r[rd]);
return;
}