summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices
diff options
context:
space:
mode:
author mooglyguy <therealmogminer@gmail.com>2020-03-11 19:42:01 +0100
committer mooglyguy <therealmogminer@gmail.com>2020-03-11 19:42:01 +0100
commit166545375e9089555dfecf1db0627db1f7055b9c (patch)
treeca9d1e9e7a3eb6210f7f852895118301a6798cd9 /src/devices
parent4db634dfd908786cad140fa97a49c11a627a9019 (diff)
-unsp: Various changes: [Ryan Holtz]
* Added individual members for FR status flags. * Added FR = Rd and Rd = FR opcodes. * Added Ext A6 support. * Fixed up LSR/LSROR/LSL/LSLOR/ASR/ASROR support. * Cleaned up GOTO MR. * Added Faction ON/OFF, SECBANK ON/OFF, and IRQNEST ON/OFF support. * Disabled DRC for the time being.
Diffstat (limited to 'src/devices')
-rw-r--r--src/devices/cpu/unsp/unsp.cpp89
-rw-r--r--src/devices/cpu/unsp/unsp.h35
-rw-r--r--src/devices/cpu/unsp/unsp_extended.cpp22
-rw-r--r--src/devices/cpu/unsp/unsp_exxx.cpp141
-rw-r--r--src/devices/cpu/unsp/unsp_fxxx.cpp96
-rw-r--r--src/devices/cpu/unsp/unsp_other.cpp13
-rw-r--r--src/devices/cpu/unsp/unspdrc.cpp58
7 files changed, 266 insertions, 188 deletions
diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp
index 6d0bc92c6d5..ac2f5f1bdaa 100644
--- a/src/devices/cpu/unsp/unsp.cpp
+++ b/src/devices/cpu/unsp/unsp.cpp
@@ -229,9 +229,12 @@ void unsp_device::device_start()
m_drcuml->symbol_add(&m_core->m_enable_irq, sizeof(uint32_t), "IRQE");
m_drcuml->symbol_add(&m_core->m_enable_fiq, sizeof(uint32_t), "FIQE");
m_drcuml->symbol_add(&m_core->m_fir_move, sizeof(uint32_t), "FIR_MOV");
- m_drcuml->symbol_add(&m_core->m_irq, sizeof(uint32_t), "IRQ");
- m_drcuml->symbol_add(&m_core->m_fiq, sizeof(uint32_t), "FIQ");
m_drcuml->symbol_add(&m_core->m_sb, sizeof(uint32_t), "SB");
+ m_drcuml->symbol_add(&m_core->m_aq, sizeof(uint32_t), "AQ");
+ m_drcuml->symbol_add(&m_core->m_fra, sizeof(uint32_t), "FRA");
+ m_drcuml->symbol_add(&m_core->m_bnk, sizeof(uint32_t), "BNK");
+ m_drcuml->symbol_add(&m_core->m_ine, sizeof(uint32_t), "INE");
+ m_drcuml->symbol_add(&m_core->m_pri, sizeof(uint32_t), "PRI");
m_drcuml->symbol_add(&m_core->m_icount, sizeof(m_core->m_icount), "icount");
/* initialize the front-end helper */
@@ -253,9 +256,12 @@ void unsp_device::device_start()
state_add(UNSP_IRQ_EN, "IRQE", m_core->m_enable_irq).formatstr("%1u");
state_add(UNSP_FIQ_EN, "FIQE", m_core->m_enable_fiq).formatstr("%1u");
state_add(UNSP_FIR_MOV_EN, "FIR_MOV", m_core->m_fir_move).formatstr("%1u");
- state_add(UNSP_IRQ, "IRQ", m_core->m_irq).formatstr("%1u");
- state_add(UNSP_FIQ, "FIQ", m_core->m_fiq).formatstr("%1u");
state_add(UNSP_SB, "SB", m_core->m_sb).formatstr("%1X");
+ state_add(UNSP_AQ, "AQ", m_core->m_sb).formatstr("%1u");
+ state_add(UNSP_FRA, "FRA", m_core->m_sb).formatstr("%1u");
+ state_add(UNSP_BNK, "BNK", m_core->m_sb).formatstr("%1u");
+ state_add(UNSP_INE, "INE", m_core->m_sb).formatstr("%1u");
+ state_add(UNSP_PRI, "PRI", m_core->m_sb).formatstr("%1u");
#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
state_add(UNSP_LOG_OPS,"LOG", m_log_ops).formatstr("%1u");
#endif
@@ -266,13 +272,15 @@ void unsp_device::device_start()
save_item(NAME(m_core->m_r));
save_item(NAME(m_core->m_enable_irq));
save_item(NAME(m_core->m_enable_fiq));
- save_item(NAME(m_core->m_fir_move));
save_item(NAME(m_core->m_irq));
- save_item(NAME(m_core->m_fiq));
- save_item(NAME(m_core->m_curirq));
+ save_item(NAME(m_core->m_fir_move));
save_item(NAME(m_core->m_sirq));
save_item(NAME(m_core->m_sb));
- save_item(NAME(m_core->m_saved_sb));
+ save_item(NAME(m_core->m_aq));
+ save_item(NAME(m_core->m_fra));
+ save_item(NAME(m_core->m_bnk));
+ save_item(NAME(m_core->m_ine));
+ save_item(NAME(m_core->m_pri));
set_icountptr(m_core->m_icount);
}
@@ -284,7 +292,7 @@ void unsp_20_device::device_start()
#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
int baseindex = UNSP_LOG_OPS + 1;
#else
- int baseindex = UNSP_SB + 1;
+ int baseindex = UNSP_PRI + 1;
#endif
state_add(baseindex + UNSP20_R8, "R8", m_core->m_r[UNSP20_R8+8]).formatstr("%04X");
@@ -311,8 +319,7 @@ void unsp_device::device_reset()
m_core->m_enable_irq = 0;
m_core->m_enable_fiq = 0;
m_core->m_fir_move = 1;
- m_core->m_irq = 0;
- m_core->m_fiq = 0;
+ m_core->m_pri = 8;
}
void unsp_20_device::device_reset()
@@ -429,16 +436,11 @@ uint16_t unsp_device::pop(uint32_t *reg)
inline void unsp_device::trigger_fiq()
{
- if (!m_core->m_enable_fiq || m_core->m_fiq || m_core->m_irq)
- {
+ if (!m_core->m_enable_fiq || m_core->m_fiq)
return;
- }
m_core->m_fiq = 1;
- m_core->m_saved_sb[m_core->m_irq ? 1 : 0] = m_core->m_sb;
- m_core->m_sb = m_core->m_saved_sb[2];
-
push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]);
push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]);
m_core->m_r[REG_PC] = read16(0xfff6);
@@ -448,16 +450,21 @@ inline void unsp_device::trigger_fiq()
inline void unsp_device::trigger_irq(int line)
{
- if (!m_core->m_enable_irq || m_core->m_irq || m_core->m_fiq)
+ if ((m_core->m_ine == 0 && m_core->m_irq == 1) || m_core->m_pri <= line)
return;
m_core->m_irq = 1;
- m_core->m_saved_sb[0] = m_core->m_sb;
- m_core->m_sb = m_core->m_saved_sb[1];
-
push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]);
push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]);
+ if (m_core->m_ine)
+ {
+ push(get_fr(), &m_core->m_r[REG_SP]);
+ }
+
+ if (m_core->m_ine)
+ m_core->m_pri = line;
+
m_core->m_r[REG_PC] = read16(0xfff8 + line);
m_core->m_r[REG_SR] = 0;
standard_irq_callback(UNSP_IRQ0_LINE+line);
@@ -537,7 +544,10 @@ void unsp_device::execute_run()
execute_one(op);
- check_irqs();
+ if (op != 0x9a98)
+ {
+ check_irqs();
+ }
}
}
@@ -591,3 +601,38 @@ void unsp_device::set_ds(uint16_t ds)
m_core->m_r[REG_SR] &= 0x03ff;
m_core->m_r[REG_SR] |= (ds & 0x3f) << 10;
}
+
+void unsp_device::set_fr(uint16_t fr)
+{
+ m_core->m_aq = BIT(fr, 14);
+ const uint32_t old_bank = m_core->m_bnk;
+ m_core->m_bnk = BIT(fr, 13);
+ if (m_core->m_bnk != old_bank)
+ {
+ std::swap<uint32_t>(m_core->m_r[REG_R1], m_core->m_secbank[REG_SR1]);
+ std::swap<uint32_t>(m_core->m_r[REG_R2], m_core->m_secbank[REG_SR2]);
+ std::swap<uint32_t>(m_core->m_r[REG_R3], m_core->m_secbank[REG_SR3]);
+ std::swap<uint32_t>(m_core->m_r[REG_R4], m_core->m_secbank[REG_SR4]);
+ }
+ m_core->m_fra = BIT(fr, 12);
+ m_core->m_fir_move = BIT(fr, 11);
+ m_core->m_sb = (fr >> 7) & 0xf;
+ m_core->m_enable_fiq = BIT(fr, 6);
+ m_core->m_enable_irq = BIT(fr, 5);
+ m_core->m_ine = BIT(fr, 4);
+ m_core->m_pri = fr & 0xf;
+}
+
+uint16_t unsp_device::get_fr()
+{
+ uint16_t fr = m_core->m_aq << 14;
+ fr |= m_core->m_bnk << 13;
+ fr |= m_core->m_fra << 12;
+ fr |= m_core->m_fir_move << 11;
+ fr |= m_core->m_sb << 7;
+ fr |= m_core->m_enable_fiq << 6;
+ fr |= m_core->m_enable_irq << 5;
+ fr |= m_core->m_ine << 4;
+ fr |= m_core->m_pri;
+ return fr;
+}
diff --git a/src/devices/cpu/unsp/unsp.h b/src/devices/cpu/unsp/unsp.h
index dc3ba619eaa..badc913808d 100644
--- a/src/devices/cpu/unsp/unsp.h
+++ b/src/devices/cpu/unsp/unsp.h
@@ -32,7 +32,7 @@
#define SINGLE_INSTRUCTION_MODE (0)
-#define ENABLE_UNSP_DRC (1)
+#define ENABLE_UNSP_DRC (0)
#define UNSP_LOG_OPCODES (0)
#define UNSP_LOG_REGS (0)
@@ -61,13 +61,16 @@ enum
UNSP_IRQ_EN,
UNSP_FIQ_EN,
UNSP_FIR_MOV_EN,
- UNSP_IRQ,
- UNSP_FIQ,
-#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
UNSP_SB,
+ UNSP_AQ,
+ UNSP_FRA,
+ UNSP_BNK,
+ UNSP_INE,
+#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
+ UNSP_PRI,
UNSP_LOG_OPS
#else
- UNSP_SB
+ UNSP_PRI
#endif
};
@@ -101,6 +104,9 @@ public:
void set_ds(uint16_t ds);
uint16_t get_ds();
+ void set_fr(uint16_t fr);
+ uint16_t get_fr();
+
inline void ccfunc_unimplemented();
void invalidate_cache();
@@ -152,7 +158,12 @@ protected:
REG_R4,
REG_BP,
REG_SR,
- REG_PC
+ REG_PC,
+
+ REG_SR1 = 0,
+ REG_SR2,
+ REG_SR3,
+ REG_SR4
};
/* internal compiler state */
@@ -168,15 +179,19 @@ protected:
struct internal_unsp_state
{
uint32_t m_r[16]; // required to be 32 bits due to DRC
+ uint32_t m_secbank[4];
uint32_t m_enable_irq;
uint32_t m_enable_fiq;
uint32_t m_fir_move;
- uint32_t m_irq;
uint32_t m_fiq;
- uint32_t m_curirq;
+ uint32_t m_irq;
uint32_t m_sirq;
uint32_t m_sb;
- uint32_t m_saved_sb[3];
+ uint32_t m_aq;
+ uint32_t m_fra;
+ uint32_t m_bnk;
+ uint32_t m_ine;
+ uint32_t m_pri;
uint32_t m_arg0;
uint32_t m_arg1;
@@ -375,8 +390,6 @@ protected:
virtual void device_reset() override;
private:
- uint32_t m_secondary_r[8];
-
enum
{
UNSP20_R8 = 0,
diff --git a/src/devices/cpu/unsp/unsp_extended.cpp b/src/devices/cpu/unsp/unsp_extended.cpp
index 44f2a2d263d..8a058d8f8ad 100644
--- a/src/devices/cpu/unsp/unsp_extended.cpp
+++ b/src/devices/cpu/unsp/unsp_extended.cpp
@@ -56,7 +56,6 @@ void unsp_20_device::execute_extended_group(uint16_t op)
case 0x02:
{
// register decoding could be incorrect here
-
// Ext Push/Pop
if (ximm & 0x8000)
{
@@ -313,13 +312,24 @@ void unsp_20_device::execute_extended_group(uint16_t op)
// Rx = Rx op [A6]
// A = B op C
- //uint8_t aluop = (ximm & 0xf000) >> 12;
- //uint8_t rx = (ximm & 0x0e00) >> 9;
- //uint8_t a6 = (ximm & 0x003f) >> 0;
+ uint8_t aluop = (ximm & 0xf000) >> 12;
+ uint8_t rx = (ximm & 0x0e00) >> 9;
+ uint8_t a6 = (ximm & 0x003f) >> 0;
- logerror("(Extended group 8 'Rx=Rx op [A6]' form) unimplemented ");
+ uint16_t b = m_core->m_r[rx + 8];
+ uint16_t c = read16(a6);
+
+ uint32_t storeaddr = a6; // dest address for STORE
+ uint32_t lres;
+
+ bool write = do_basic_alu_ops(aluop, lres, b, c, storeaddr, true);
+
+ if (write)
+ {
+ // A = Rx
+ m_core->m_r[rx + 8] = (uint16_t)lres;
+ }
- unimplemented_opcode(op, ximm);
return;
}
}
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;
}
diff --git a/src/devices/cpu/unsp/unsp_fxxx.cpp b/src/devices/cpu/unsp/unsp_fxxx.cpp
index 27359d8f916..dc181da3989 100644
--- a/src/devices/cpu/unsp/unsp_fxxx.cpp
+++ b/src/devices/cpu/unsp/unsp_fxxx.cpp
@@ -9,6 +9,12 @@
#include "unspdasm.h"
+#define LOG_UNSP_MULS (1U << 1)
+
+#define VERBOSE (0)
+
+#include "logmacro.h"
+
inline void unsp_device::execute_fxxx_000_group(uint16_t op)
{
// | | |
@@ -23,36 +29,29 @@ inline void unsp_device::execute_fxxx_000_group(uint16_t op)
if (((op & 0xffc0) == 0xfe00) && m_iso >= 12)
{
// ds = imm6
- int imm = op & 0x003f;
- set_ds(imm);
+ set_ds(op & 0x003f);
return;
}
else if (((op & 0xf1f8) == 0xf020) && m_iso >= 12)
{
// rx = ds
- int r = op & 0x7;
- m_core->m_r[r] = get_ds();
+ m_core->m_r[op & 0x7] = get_ds();
return;
}
else if (((op & 0xf1f8) == 0xf028) && m_iso >= 12)
{
// ds = rx
- int r = op & 0x7;
- set_ds(m_core->m_r[r]);
+ set_ds(m_core->m_r[op & 0x7]);
return;
}
else if (((op & 0xf1f8) == 0xf030) && m_iso >= 12)
{
- int r = op & 0x7;
- logerror("%s = fr\n", regs[r]);
- // unimplemented_opcode(op);
+ m_core->m_r[op & 0x7] = get_fr();
return;
}
else if (((op & 0xf1f8) == 0xf038) && m_iso >= 12)
{
- int r = op & 0x7;
- logerror("fr = %s\n", regs[r]);
- // unimplemented_opcode(op);
+ set_fr(m_core->m_r[op & 0x7]);
return;
}
@@ -60,13 +59,23 @@ inline void unsp_device::execute_fxxx_000_group(uint16_t op)
// MUL us ( signed * unsigned )
// MUL 1 1 1 1* r r r 0* 0 0 0 0 1 r r r (** = sign bits, fixed here)
- const uint16_t rd = (op >> 9) & 7;
- const uint16_t rs = op & 7;
+
+ const uint16_t opa = (op >> 9) & 7;
+ const uint16_t opb = op & 7;
m_core->m_icount -= 12;
- int32_t lres = (int32_t)(uint32_t)m_core->m_r[rd] * (int32_t)(int16_t)m_core->m_r[rs];
- m_core->m_r[REG_R4] = (uint16_t)(lres >> 16);
+
+ LOGMASKED(LOG_UNSP_MULS, "%s: MUL us with %04x (unsigned) * %04x (signed) (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[opb] & 0x8000)
+ {
+ lres -= m_core->m_r[opa] << 16;
+ }
+ m_core->m_r[REG_R4] = lres >> 16;
m_core->m_r[REG_R3] = (uint16_t)lres;
+ LOGMASKED(LOG_UNSP_MULS, "result was : %08x\n", lres);
+
return;
}
@@ -186,15 +195,10 @@ inline void unsp_device::execute_fxxx_011_group(uint16_t op)
// JMPR 1 1 1 1 1 1 1 0 1 1 - - - - - -
if (((op & 0xffc0) == 0xfec0) && m_iso >= 12)
{
- uint32_t mr = m_core->m_r[REG_R3] | ((m_core->m_r[REG_R4]) << 16);
-
m_core->m_icount -= 5;
- m_core->m_r[REG_PC] = mr & 0xffff;
+ m_core->m_r[REG_PC] = m_core->m_r[REG_R3];
m_core->m_r[REG_SR] &= 0xffc0;
- m_core->m_r[REG_SR] |=( mr>>16) & 0x3f;
-
- logerror("goto mr %08x\n", mr);
- //unimplemented_opcode(op);
+ m_core->m_r[REG_SR] |= m_core->m_r[REG_R4] & 0x3f;
return;
}
@@ -216,13 +220,13 @@ inline void unsp_device::execute_fxxx_100_group(uint16_t op)
if ((op & 0xf1f8) == 0xf108)
{
- uint32_t lres = 0;
-
const uint16_t opa = (op >> 9) & 7;
const uint16_t opb = op & 7;
+ LOGMASKED(LOG_UNSP_MULS, "%s: MUL ss with %04x (signed) * %04x (signed) (fra:%d) :\n", machine().describe_context(), m_core->m_r[opa], m_core->m_r[opb], m_core->m_fra);
+
m_core->m_icount -= 12;
- lres = m_core->m_r[opa] * m_core->m_r[opb];
+ uint32_t lres = m_core->m_r[opa] * m_core->m_r[opb];
if (m_core->m_r[opb] & 0x8000)
{
lres -= m_core->m_r[opa] << 16;
@@ -233,6 +237,9 @@ inline void unsp_device::execute_fxxx_100_group(uint16_t op)
}
m_core->m_r[REG_R4] = lres >> 16;
m_core->m_r[REG_R3] = (uint16_t)lres;
+
+ LOGMASKED(LOG_UNSP_MULS, "result was : %08x\n", lres);
+
return;
}
@@ -253,45 +260,53 @@ void unsp_12_device::execute_fxxx_101_group(uint16_t op)
// DIVQ 1 1 1 1 - - - 1 0 1 1 - - 0 1 1
// EXP 1 1 1 1 - - - 1 0 1 1 - - 1 0 0
+ m_core->m_icount -= 1; // Unknown count
+
switch (op)
{
case 0xf146: case 0xf346: case 0xf546: case 0xf746: case 0xf946: case 0xfb46: case 0xfd46: case 0xff46:
- logerror("fraction off\n");
- unimplemented_opcode(op);
+ m_core->m_fra = 0;
return;
case 0xf147: case 0xf347: case 0xf547: case 0xf747: case 0xf947: case 0xfb47: case 0xfd47: case 0xff47:
- logerror("fraction on\n");
- unimplemented_opcode(op);
+ m_core->m_fra = 1;
return;
case 0xf14a: case 0xf34a: case 0xf54a: case 0xf74a: case 0xf94a: case 0xfb4a: case 0xfd4a: case 0xff4a:
- logerror("secbank off\n");
- unimplemented_opcode(op);
+ if (m_core->m_bnk)
+ {
+ std::swap<uint32_t>(m_core->m_r[REG_R1], m_core->m_secbank[REG_SR1]);
+ std::swap<uint32_t>(m_core->m_r[REG_R2], m_core->m_secbank[REG_SR2]);
+ std::swap<uint32_t>(m_core->m_r[REG_R3], m_core->m_secbank[REG_SR3]);
+ std::swap<uint32_t>(m_core->m_r[REG_R4], m_core->m_secbank[REG_SR4]);
+ }
+ m_core->m_bnk = 0;
return;
case 0xf14b: case 0xf34b: case 0xf54b: case 0xf74b: case 0xf94b: case 0xfb4b: case 0xfd4b: case 0xff4b:
- logerror("secbank on\n");
- unimplemented_opcode(op);
+ if (m_core->m_bnk == 0)
+ {
+ std::swap<uint32_t>(m_core->m_r[REG_R1], m_core->m_secbank[REG_SR1]);
+ std::swap<uint32_t>(m_core->m_r[REG_R2], m_core->m_secbank[REG_SR2]);
+ std::swap<uint32_t>(m_core->m_r[REG_R3], m_core->m_secbank[REG_SR3]);
+ std::swap<uint32_t>(m_core->m_r[REG_R4], m_core->m_secbank[REG_SR4]);
+ }
+ m_core->m_bnk = 1;
return;
case 0xf14d: case 0xf34d: case 0xf54d: case 0xf74d: case 0xf94d: case 0xfb4d: case 0xfd4d: case 0xff4d:
- logerror("irqnest off\n");
- unimplemented_opcode(op);
+ m_core->m_ine = 0;
return;
case 0xf14f: case 0xf34f: case 0xf54f: case 0xf74f: case 0xf94f: case 0xfb4f: case 0xfd4f: case 0xff4f:
- logerror("irqnest on\n");
- unimplemented_opcode(op);
+ m_core->m_ine = 1;
return;
case 0xf144: case 0xf344: case 0xf544: case 0xf744: case 0xf944: case 0xfb44: case 0xfd44: case 0xff44:
- m_core->m_icount -= 1;
m_core->m_fir_move = 1;
return;
case 0xf145: case 0xf345: case 0xf545: case 0xf745: case 0xf945: case 0xfb45: case 0xfd45: case 0xff45:
- m_core->m_icount -= 1;
m_core->m_fir_move = 0;
return;
@@ -300,7 +315,6 @@ void unsp_12_device::execute_fxxx_101_group(uint16_t op)
case 0xf171: case 0xf371: case 0xf571: case 0xf771: case 0xf971: case 0xfb71: case 0xfd71: case 0xff71:
case 0xf179: case 0xf379: case 0xf579: case 0xf779: case 0xf979: case 0xfb79: case 0xfd79: case 0xff79:
{
- m_core->m_icount -= 1; // unknown count
uint32_t addr = m_core->m_r[REG_R3] | ((m_core->m_r[REG_R4] & 0x3f) << 16);
push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]);
push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]);
diff --git a/src/devices/cpu/unsp/unsp_other.cpp b/src/devices/cpu/unsp/unsp_other.cpp
index 2300f2a5bc0..d2ba446fbd1 100644
--- a/src/devices/cpu/unsp/unsp_other.cpp
+++ b/src/devices/cpu/unsp/unsp_other.cpp
@@ -41,23 +41,22 @@ void unsp_device::execute_remaining(const uint16_t op)
if (op == 0x9a98) // reti
{
m_core->m_icount -= 8;
+ if (m_core->m_ine)
+ {
+ set_fr(pop(&m_core->m_r[REG_SP]));
+ }
+
m_core->m_r[REG_SR] = pop(&m_core->m_r[REG_SP]);
m_core->m_r[REG_PC] = pop(&m_core->m_r[REG_SP]);
if (m_core->m_fiq)
{
m_core->m_fiq = 0;
- m_core->m_saved_sb[2] = m_core->m_sb;
- m_core->m_sb = m_core->m_saved_sb[m_core->m_irq ? 1 : 0];
}
else if (m_core->m_irq)
{
m_core->m_irq = 0;
- m_core->m_saved_sb[1] = m_core->m_sb;
- m_core->m_sb = m_core->m_saved_sb[0];
}
- m_core->m_curirq = 0;
- check_irqs();
return;
}
else // pop
@@ -257,7 +256,7 @@ void unsp_device::execute_remaining(const uint16_t op)
break;
}
- case 0x07: // Direct 8
+ case 0x07: // Direct 6
m_core->m_icount -= (opa == 7 ? 6 : 5);
r2 = op & 0x3f;
r1 = read16(r2);
diff --git a/src/devices/cpu/unsp/unspdrc.cpp b/src/devices/cpu/unsp/unspdrc.cpp
index 6a12a58a762..32011522c2e 100644
--- a/src/devices/cpu/unsp/unspdrc.cpp
+++ b/src/devices/cpu/unsp/unspdrc.cpp
@@ -414,19 +414,13 @@ void unsp_device::static_generate_trigger_fiq()
alloc_handle(*m_drcuml, m_trigger_fiq, "trigger_fiq");
UML_HANDLE(block, *m_trigger_fiq);
- UML_OR(block, I0, mem(&m_core->m_fiq), mem(&m_core->m_irq));
- UML_TEST(block, I0, 1);
- UML_RETc(block, uml::COND_NZ);
-
UML_TEST(block, mem(&m_core->m_enable_fiq), 1);
UML_RETc(block, uml::COND_Z);
- UML_MOV(block, mem(&m_core->m_fiq), 1);
+ UML_TEST(block, mem(&m_core->m_fiq), 1);
+ UML_RETc(block, uml::COND_NZ);
- UML_MOV(block, I0, mem(&m_core->m_sb));
- UML_MOV(block, I1, mem(&m_core->m_irq));
- UML_STORE(block, (void*)m_core->m_saved_sb, I1, I0, SIZE_DWORD, SCALE_x4);
- UML_MOV(block, mem(&m_core->m_sb), mem(&m_core->m_saved_sb[2]));
+ UML_MOV(block, mem(&m_core->m_fiq), 1);
UML_MOV(block, I0, mem(&m_core->m_r[REG_SP]));
@@ -455,21 +449,34 @@ void unsp_device::static_generate_trigger_irq()
/* begin generating */
drcuml_block &block(m_drcuml->begin_block(256));
+ uml::code_label skip_ine = 1;
+
/* generate a hash jump via the current mode and PC */
alloc_handle(*m_drcuml, m_trigger_irq, "trigger_irq");
UML_HANDLE(block, *m_trigger_irq);
- UML_OR(block, I0, mem(&m_core->m_fiq), mem(&m_core->m_irq));
- UML_TEST(block, I0, 1);
+ // If INE is 0 and IRQ is 1, abort
+ UML_XOR(block, I1, mem(&m_core->m_irq), 1);
+ UML_AND(block, I1, I1, mem(&m_core->m_ine));
UML_RETc(block, uml::COND_NZ);
- UML_TEST(block, mem(&m_core->m_enable_irq), 1);
- UML_RETc(block, uml::COND_Z);
+ // If INE is 0 and IRQ is 0, we have a valid IRQ
+ UML_TEST(block, mem(&m_core->m_ine), 1);
+ UML_JMPc(block, uml::COND_Z, skip_ine);
+
+ // If INE is 1 and IRQ line is < PRI, abort
+ UML_CMP(block, I0, mem(&m_core->m_pri));
+ UML_RETc(block, uml::COND_LE);
+
+ // Update our current interrupt priority
+ UML_MOV(block, mem(&m_core->m_pri), I0);
+
+ UML_LABEL(block, skip_ine);
UML_MOV(block, mem(&m_core->m_irq), 1);
- UML_MOV(block, mem(&m_core->m_saved_sb[0]), mem(&m_core->m_sb));
- UML_MOV(block, mem(&m_core->m_sb), mem(&m_core->m_saved_sb[1]));
+ UML_TEST(block, mem(&m_core->m_enable_irq), 1);
+ UML_RETc(block, uml::COND_Z);
UML_MOV(block, I0, mem(&m_core->m_r[REG_SP]));
UML_MOV(block, I1, mem(&m_core->m_r[REG_PC]));
@@ -707,8 +714,6 @@ bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler,
const uint8_t lower_op = (op1 << 4) | op0;
uml::code_label skip_branch = compiler.m_labelnum++;
- uml::code_label clear_fiq = compiler.m_labelnum++;
- uml::code_label clear_irq = compiler.m_labelnum++;
uml::code_label reti_done = compiler.m_labelnum++;
uml::code_label mul_opa_nohi = compiler.m_labelnum++;
uml::code_label mul_opb_nohi = compiler.m_labelnum++;
@@ -849,24 +854,13 @@ bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler,
UML_AND(block, mem(&m_core->m_r[REG_SP]), I0, 0x0000ffff);
UML_TEST(block, mem(&m_core->m_fiq), 1);
- UML_JMPc(block, uml::COND_NZ, clear_fiq);
- UML_TEST(block, mem(&m_core->m_irq), 1);
- UML_JMPc(block, uml::COND_NZ, clear_irq);
- UML_JMP(block, reti_done);
+ UML_MOVc(block, uml::COND_NZ, mem(&m_core->m_fiq), 0);
+ UML_JMPc(block, uml::COND_NZ, reti_done);
- UML_LABEL(block, clear_fiq);
- UML_MOV(block, mem(&m_core->m_fiq), 0);
- UML_MOV(block, mem(&m_core->m_saved_sb[2]), mem(&m_core->m_sb));
- UML_LOAD(block, mem(&m_core->m_sb), (void*)m_core->m_saved_sb, mem(&m_core->m_irq), SIZE_DWORD, SCALE_x4);
- UML_JMP(block, reti_done);
-
- UML_LABEL(block, clear_irq);
- UML_MOV(block, mem(&m_core->m_irq), 0);
- UML_MOV(block, mem(&m_core->m_saved_sb[1]), mem(&m_core->m_sb));
- UML_MOV(block, mem(&m_core->m_sb), mem(&m_core->m_saved_sb[0]));
+ UML_TEST(block, mem(&m_core->m_irq), 1);
+ UML_MOVc(block, uml::COND_NZ, mem(&m_core->m_irq), 0);
UML_LABEL(block, reti_done);
- UML_MOV(block, mem(&m_core->m_curirq), 0);
generate_branch(block, compiler, desc);
}
else // pop