-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:
mooglyguy 2020-03-11 19:42:01 +01:00
parent 4db634dfd9
commit 166545375e
7 changed files with 265 additions and 187 deletions

View File

@ -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,9 +544,12 @@ void unsp_device::execute_run()
execute_one(op);
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;
}

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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);
uint32_t rdval = (uint16_t)(m_core->m_r[rd]);
int shift = (m_core->m_r[rs] & 0x01f);
if (shift == 0)
return;
case 0x01: // jak_car2 on starting a game
uint32_t res;
if (BIT(rd, (32 - shift)))
{
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);
uint32_t res = (uint16_t)(m_core->m_r[rd]);
int shift = (m_core->m_r[rs] & 0x01f);
res <<= 16;
if (res & 0x80000000)
if (shift >= 16)
{
res = res >> shift;
res |= (0xffffffff << (32 - shift));
m_core->m_r[rd] = (res >> 16);
m_core->m_r[rd - 1] |= (res & 0xffff); // register bleeding?
res = 0x0000ffff;
}
else
{
res = res >> shift;
m_core->m_r[rd] = (res >> 16);
m_core->m_r[rd - 1] |= (res & 0xffff); // register bleeding?
res = (rdval >> shift) | (uint16_t)(0xffff0000 >> shift);
}
}
else
{
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;
}

View File

@ -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]);

View File

@ -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);

View File

@ -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