diff options
author | mooglyguy <therealmogminer@gmail.com> | 2020-03-11 19:42:01 +0100 |
---|---|---|
committer | mooglyguy <therealmogminer@gmail.com> | 2020-03-11 19:42:01 +0100 |
commit | 166545375e9089555dfecf1db0627db1f7055b9c (patch) | |
tree | ca9d1e9e7a3eb6210f7f852895118301a6798cd9 /src/devices | |
parent | 4db634dfd908786cad140fa97a49c11a627a9019 (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.cpp | 89 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp.h | 35 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp_extended.cpp | 22 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp_exxx.cpp | 141 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp_fxxx.cpp | 96 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp_other.cpp | 13 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unspdrc.cpp | 58 |
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 |