mirror of
https://github.com/holub/mame
synced 2025-07-04 09:28:51 +03:00
-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.
This commit is contained in:
parent
4db634dfd9
commit
166545375e
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 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) : ", 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]);
|
||||
|
||||
{
|
||||
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]);
|
||||
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]);
|
||||
|
||||
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]);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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);
|
||||
|
@ -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_MOVc(block, uml::COND_NZ, mem(&m_core->m_fiq), 0);
|
||||
UML_JMPc(block, uml::COND_NZ, reti_done);
|
||||
|
||||
UML_TEST(block, mem(&m_core->m_irq), 1);
|
||||
UML_JMPc(block, uml::COND_NZ, clear_irq);
|
||||
UML_JMP(block, 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_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
|
||||
|
Loading…
Reference in New Issue
Block a user