mirror of
https://github.com/holub/mame
synced 2025-04-23 00:39:36 +03:00
-devices/cpu/unsp: Various fixes: [Ryan Holtz]
* Fixed push and pop instructions in the DRC. Fixes Wall-E. * Eliminated the use of intermediate register I7 in the DRC. * Reworked DRC timing to be fully in line with the interpreter. * Reworked DRC block checksumming to not route through the memory system. * Fixed DRC block checksumming to include all words in an opcode. Fixes V.Smile intro graphical glitches. * Increased cache size and reduced block size to reduce frequency of cache flushes and associated recompiles. * Added more verbose optional register and write logging. * Added a direct setter for IRQ lines to avoid a scheduler sync, pending merging the spg2xx_device into a unsp_device subclass. * Added direct setters/getters for the data segment as well.
This commit is contained in:
parent
b5e2e78671
commit
8f330896e2
@ -24,7 +24,7 @@
|
||||
DEFINE_DEVICE_TYPE(UNSP, unsp_device, "unsp", "SunPlus u'nSP")
|
||||
|
||||
/* size of the execution code cache */
|
||||
#define CACHE_SIZE (32 * 1024 * 1024)
|
||||
#define CACHE_SIZE (64 * 1024 * 1024)
|
||||
|
||||
unsp_device::unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: cpu_device(mconfig, UNSP, tag, owner, clock)
|
||||
@ -32,13 +32,13 @@ unsp_device::unsp_device(const machine_config &mconfig, const char *tag, device_
|
||||
, m_program(nullptr)
|
||||
, m_core(nullptr)
|
||||
, m_debugger_temp(0)
|
||||
#if UNSP_LOG_OPCODES
|
||||
#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
|
||||
, m_log_ops(0)
|
||||
#endif
|
||||
, m_cache(CACHE_SIZE + sizeof(unsp_device))
|
||||
, m_drcuml(nullptr)
|
||||
, m_drcfe(nullptr)
|
||||
, m_drcoptions(UNSP_STRICT_VERIFY)
|
||||
, m_drcoptions(0)
|
||||
, m_cache_dirty(0)
|
||||
, m_entry(nullptr)
|
||||
, m_nocode(nullptr)
|
||||
@ -78,6 +78,9 @@ uint16_t unsp_device::read16(uint32_t address)
|
||||
|
||||
void unsp_device::write16(uint32_t address, uint16_t data)
|
||||
{
|
||||
#if UNSP_LOG_REGS
|
||||
log_write(address, data);
|
||||
#endif
|
||||
m_program->write_word(address, data);
|
||||
}
|
||||
|
||||
@ -148,7 +151,7 @@ void unsp_device::device_start()
|
||||
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("%1u");
|
||||
#if UNSP_LOG_OPCODES
|
||||
#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
|
||||
state_add(UNSP_LOG_OPS,"LOG", m_log_ops).formatstr("%1u");
|
||||
#endif
|
||||
|
||||
@ -197,10 +200,20 @@ void unsp_device::device_stop()
|
||||
#if UNSP_LOG_REGS
|
||||
void unsp_device::log_regs()
|
||||
{
|
||||
if (m_log_ops == 0)
|
||||
return;
|
||||
fwrite(m_core->m_r, sizeof(uint32_t), 8, m_log_file);
|
||||
fwrite(&m_core->m_sb, sizeof(uint32_t), 1, m_log_file);
|
||||
fflush(m_log_file);
|
||||
fwrite(&m_core->m_icount, sizeof(uint32_t), 1, m_log_file);
|
||||
}
|
||||
|
||||
void unsp_device::log_write(uint32_t addr, uint32_t data)
|
||||
{
|
||||
addr |= 0x80000000;
|
||||
fwrite(&addr, sizeof(uint32_t), 1, m_log_file);
|
||||
fwrite(&data, sizeof(uint32_t), 1, m_log_file);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void unsp_device::state_string_export(const device_state_entry &entry, std::string &str) const
|
||||
@ -948,11 +961,15 @@ void unsp_device::execute_run()
|
||||
unsp_disassembler dasm;
|
||||
#endif
|
||||
|
||||
while (m_core->m_icount > 0)
|
||||
while (m_core->m_icount >= 0)
|
||||
{
|
||||
debugger_instruction_hook(UNSP_LPC);
|
||||
const uint32_t op = read16(UNSP_LPC);
|
||||
|
||||
#if UNSP_LOG_REGS
|
||||
log_regs();
|
||||
#endif
|
||||
|
||||
#if UNSP_LOG_OPCODES
|
||||
if (m_log_ops)
|
||||
{
|
||||
@ -962,10 +979,6 @@ void unsp_device::execute_run()
|
||||
}
|
||||
#endif
|
||||
|
||||
#if UNSP_LOG_REGS
|
||||
log_regs();
|
||||
#endif
|
||||
|
||||
add_lpc(1);
|
||||
|
||||
execute_one(op);
|
||||
@ -977,16 +990,26 @@ void unsp_device::execute_run()
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void unsp_device::execute_set_input(int irqline, int state)
|
||||
void unsp_device::execute_set_input(int inputnum, int state)
|
||||
{
|
||||
m_core->m_sirq &= ~(1 << irqline);
|
||||
set_state_unsynced(inputnum, state);
|
||||
}
|
||||
|
||||
uint8_t unsp_device::get_csb()
|
||||
{
|
||||
return 1 << ((UNSP_LPC >> 20) & 3);
|
||||
}
|
||||
|
||||
void unsp_device::set_state_unsynced(int inputnum, int state)
|
||||
{
|
||||
m_core->m_sirq &= ~(1 << inputnum);
|
||||
|
||||
if(!state)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (irqline)
|
||||
switch (inputnum)
|
||||
{
|
||||
case UNSP_IRQ0_LINE:
|
||||
case UNSP_IRQ1_LINE:
|
||||
@ -997,14 +1020,20 @@ void unsp_device::execute_set_input(int irqline, int state)
|
||||
case UNSP_IRQ6_LINE:
|
||||
case UNSP_IRQ7_LINE:
|
||||
case UNSP_FIQ_LINE:
|
||||
m_core->m_sirq |= (1 << irqline);
|
||||
m_core->m_sirq |= (1 << inputnum);
|
||||
break;
|
||||
case UNSP_BRK_LINE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t unsp_device::get_csb()
|
||||
uint16_t unsp_device::get_ds()
|
||||
{
|
||||
return 1 << ((UNSP_LPC >> 20) & 3);
|
||||
return (m_core->m_r[REG_SR] >> 10) & 0x3f;
|
||||
}
|
||||
|
||||
void unsp_device::set_ds(uint16_t ds)
|
||||
{
|
||||
m_core->m_r[REG_SR] &= 0x03ff;
|
||||
m_core->m_r[REG_SR] |= (ds & 0x3f) << 10;
|
||||
}
|
||||
|
@ -29,8 +29,6 @@
|
||||
#define MAPVAR_PC M0
|
||||
#define MAPVAR_CYCLES M1
|
||||
|
||||
#define UNSP_STRICT_VERIFY 0x0001 /* verify all instructions */
|
||||
|
||||
#define SINGLE_INSTRUCTION_MODE (0)
|
||||
|
||||
#define ENABLE_UNSP_DRC (1)
|
||||
@ -63,7 +61,7 @@ enum
|
||||
UNSP_FIQ_EN,
|
||||
UNSP_IRQ,
|
||||
UNSP_FIQ,
|
||||
#if UNSP_LOG_OPCODES
|
||||
#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
|
||||
UNSP_SB,
|
||||
UNSP_LOG_OPS
|
||||
#else
|
||||
@ -95,12 +93,25 @@ public:
|
||||
// construction/destruction
|
||||
unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// HACK: IRQ line state can only be modified directly by hardware on-board the SPG SoC itself.
|
||||
// Therefore, to avoid an unnecessary scheduler sync when the external spg2xx_device sets or
|
||||
// clears an interrupt line, we provide this direct accessor.
|
||||
// A more correct but longer-term solution will be to move spg2xx_device to be internal to
|
||||
// a subclass of unsp_device rather than its own standalone device.
|
||||
void set_state_unsynced(int inputnum, int state);
|
||||
|
||||
uint8_t get_csb();
|
||||
|
||||
void set_ds(uint16_t ds);
|
||||
uint16_t get_ds();
|
||||
|
||||
inline void ccfunc_unimplemented();
|
||||
void invalidate_cache();
|
||||
|
||||
#if UNSP_LOG_REGS
|
||||
void log_regs();
|
||||
void log_write(uint32_t addr, uint32_t data);
|
||||
void cfunc_log_write();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
@ -176,7 +187,6 @@ private:
|
||||
|
||||
uint32_t m_arg0;
|
||||
uint32_t m_arg1;
|
||||
uint32_t m_arg2;
|
||||
uint32_t m_jmpdest;
|
||||
|
||||
int m_icount;
|
||||
@ -191,7 +201,7 @@ private:
|
||||
internal_unsp_state *m_core;
|
||||
|
||||
uint32_t m_debugger_temp;
|
||||
#if UNSP_LOG_OPCODES
|
||||
#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
|
||||
uint32_t m_log_ops;
|
||||
#endif
|
||||
|
||||
@ -251,11 +261,9 @@ private:
|
||||
void static_generate_memory_accessor(bool iswrite, const char *name, uml::code_handle *&handleptr);
|
||||
|
||||
void generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
|
||||
void generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param);
|
||||
void generate_check_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param);
|
||||
void generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
|
||||
void generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
|
||||
void generate_push(drcuml_block &block, uint32_t sp);
|
||||
void generate_pop(drcuml_block &block, uint32_t sp);
|
||||
void generate_add_lpc(drcuml_block &block, int32_t offset);
|
||||
void generate_update_nzsc(drcuml_block &block);
|
||||
void generate_update_nz(drcuml_block &block);
|
||||
|
@ -66,10 +66,20 @@ static void cfunc_unimplemented(void *param)
|
||||
}
|
||||
|
||||
#if UNSP_LOG_REGS
|
||||
void unsp_device::cfunc_log_write()
|
||||
{
|
||||
log_write(m_core->m_arg0, m_core->m_arg1);
|
||||
}
|
||||
|
||||
static void cfunc_log_regs(void *param)
|
||||
{
|
||||
((unsp_device *)param)->log_regs();
|
||||
}
|
||||
|
||||
static void ccfunc_log_write(void *param)
|
||||
{
|
||||
((unsp_device *)param)->cfunc_log_write();
|
||||
}
|
||||
#endif
|
||||
|
||||
/***************************************************************************
|
||||
@ -140,7 +150,7 @@ void unsp_device::code_compile_block(offs_t pc)
|
||||
try
|
||||
{
|
||||
/* start the block */
|
||||
drcuml_block &block(m_drcuml->begin_block(32768));
|
||||
drcuml_block &block(m_drcuml->begin_block(1024*8));
|
||||
|
||||
/* loop until we get through all instruction sequences */
|
||||
for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next())
|
||||
@ -186,22 +196,15 @@ void unsp_device::code_compile_block(offs_t pc)
|
||||
if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET)
|
||||
UML_LABEL(block, seqhead->pc | 0x80000000);
|
||||
|
||||
UML_MOV(block, I7, 0);
|
||||
UML_CALLH(block, *m_check_interrupts);
|
||||
|
||||
/* iterate over instructions in the sequence and compile them */
|
||||
for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
|
||||
{
|
||||
generate_check_cycles(block, compiler, curdesc->pc + curdesc->length);
|
||||
generate_sequence_instruction(block, compiler, curdesc);
|
||||
UML_CALLH(block, *m_check_interrupts);
|
||||
}
|
||||
|
||||
if (seqlast->flags & OPFLAG_RETURN_TO_START) /* if we need to return to the start, do it */
|
||||
nextpc = pc;
|
||||
else /* otherwise we just go to the next instruction */
|
||||
nextpc = seqlast->pc + seqlast->length;
|
||||
|
||||
generate_update_cycles(block, compiler, nextpc);
|
||||
nextpc = seqlast->pc + seqlast->length;
|
||||
|
||||
/* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */
|
||||
if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc)
|
||||
@ -324,7 +327,14 @@ void unsp_device::static_generate_memory_accessor(bool iswrite, const char *name
|
||||
UML_HANDLE(block, *handleptr);
|
||||
|
||||
if (iswrite)
|
||||
{
|
||||
#if UNSP_LOG_REGS
|
||||
UML_MOV(block, mem(&m_core->m_arg0), I0);
|
||||
UML_MOV(block, mem(&m_core->m_arg1), I1);
|
||||
UML_CALLC(block, ccfunc_log_write, this);
|
||||
#endif
|
||||
UML_WRITE(block, I0, I1, SIZE_WORD, SPACE_PROGRAM);
|
||||
}
|
||||
else
|
||||
UML_READ(block, I1, I0, SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_RET(block);
|
||||
@ -470,17 +480,14 @@ void unsp_device::static_generate_trigger_irq()
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
generate_update_cycles - generate code to
|
||||
subtract cycles from the icount and generate
|
||||
an exception if out
|
||||
generate_check_cycles - generate code to
|
||||
generate an exception if cycles are out
|
||||
-------------------------------------------------*/
|
||||
|
||||
void unsp_device::generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param)
|
||||
void unsp_device::generate_check_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param)
|
||||
{
|
||||
UML_SUB(block, mem(&m_core->m_icount), mem(&m_core->m_icount), I7);
|
||||
UML_EXHc(block, uml::COND_Z, *m_out_of_cycles, param);
|
||||
UML_EXHc(block, uml::COND_S, *m_out_of_cycles, param);
|
||||
UML_MOV(block, I7, 0);
|
||||
UML_CMP(block, mem(&m_core->m_icount), 0);
|
||||
UML_EXHc(block, uml::COND_L, *m_out_of_cycles, param);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
@ -495,33 +502,35 @@ void unsp_device::generate_checksum_block(drcuml_block &block, compiler_state &c
|
||||
{
|
||||
block.append_comment("[Validation for %08X]", seqhead->pc);
|
||||
}
|
||||
/* loose verify or single instruction: just compare and fail */
|
||||
if (!(m_drcoptions & UNSP_STRICT_VERIFY) || seqhead->next() == nullptr)
|
||||
|
||||
/* full verification; sum up everything */
|
||||
void *memptr = m_program->get_write_ptr(seqhead->physpc);
|
||||
UML_LOAD(block, I0, memptr, 0, SIZE_WORD, SCALE_x2);
|
||||
uint32_t sum = seqhead->opptr.w[0];
|
||||
for (int i = 1; i < seqhead->length; i++)
|
||||
{
|
||||
if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
|
||||
{
|
||||
uint32_t sum = seqhead->opptr.w[0];
|
||||
UML_READ(block, I0, seqhead->physpc, SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_CMP(block, I0, sum);
|
||||
UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc);
|
||||
}
|
||||
UML_LOAD(block, I1, memptr, i, SIZE_WORD, SCALE_x2);
|
||||
UML_ADD(block, I0, I0, I1);
|
||||
sum += ((uint16_t*)memptr)[i];
|
||||
}
|
||||
else /* full verification; sum up everything */
|
||||
for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
|
||||
{
|
||||
UML_READ(block, I0, seqhead->physpc, SIZE_WORD, SPACE_PROGRAM);
|
||||
uint32_t sum = seqhead->opptr.w[0];
|
||||
for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
|
||||
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
|
||||
{
|
||||
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
|
||||
memptr = m_program->get_write_ptr(curdesc->physpc);
|
||||
UML_LOAD(block, I1, memptr, 0, SIZE_WORD, SCALE_x2);
|
||||
UML_ADD(block, I0, I0, I1);
|
||||
sum += curdesc->opptr.w[0];
|
||||
for (int i = 1; i < curdesc->length; i++)
|
||||
{
|
||||
UML_READ(block, I1, curdesc->physpc, SIZE_WORD, SPACE_PROGRAM);
|
||||
UML_LOAD(block, I1, memptr, i, SIZE_WORD, SCALE_x2);
|
||||
UML_ADD(block, I0, I0, I1);
|
||||
sum += curdesc->opptr.w[0];
|
||||
sum += ((uint16_t*)memptr)[i];
|
||||
}
|
||||
}
|
||||
UML_CMP(block, I0, sum);
|
||||
UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc);
|
||||
}
|
||||
UML_CMP(block, I0, sum);
|
||||
UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc);
|
||||
}
|
||||
|
||||
|
||||
@ -554,47 +563,17 @@ void unsp_device::generate_branch(drcuml_block &block, compiler_state &compiler,
|
||||
/* update the cycles and jump through the hash table to the target */
|
||||
if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
|
||||
{
|
||||
generate_update_cycles(block, compiler, desc->targetpc);
|
||||
UML_CALLH(block, *m_check_interrupts);
|
||||
UML_HASHJMP(block, 0, desc->targetpc, *m_nocode);
|
||||
}
|
||||
else
|
||||
{
|
||||
generate_update_cycles(block, compiler, uml::mem(&m_core->m_jmpdest));
|
||||
UML_CALLH(block, *m_check_interrupts);
|
||||
UML_HASHJMP(block, 0, mem(&m_core->m_jmpdest), *m_nocode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
generate_push - pushes a register onto a stack addressed by
|
||||
the specified register
|
||||
------------------------------------------------------------------*/
|
||||
|
||||
void unsp_device::generate_push(drcuml_block &block, uint32_t sp)
|
||||
{
|
||||
// value to push is in I1
|
||||
UML_MOV(block, I0, mem(&m_core->m_r[sp]));
|
||||
UML_CALLH(block, *m_mem_write);
|
||||
UML_SUB(block, I0, I0, 1);
|
||||
UML_AND(block, mem(&m_core->m_r[sp]), I0, 0x0000ffff);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------
|
||||
generate_pop - pops a value off a stack addressed by the
|
||||
specified register
|
||||
------------------------------------------------------------------*/
|
||||
|
||||
void unsp_device::generate_pop(drcuml_block &block, uint32_t sp)
|
||||
{
|
||||
// popped value is in I1
|
||||
UML_MOV(block, I0, mem(&m_core->m_r[sp]));
|
||||
UML_ADD(block, I0, I0, 1);
|
||||
UML_CALLH(block, *m_mem_read);
|
||||
UML_AND(block, mem(&m_core->m_r[sp]), I0, 0x0000ffff);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
generate_sequence_instruction - generate code
|
||||
for a single instruction in a sequence
|
||||
@ -721,8 +700,6 @@ bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler,
|
||||
uml::code_label shift_no_sign = compiler.m_labelnum++;
|
||||
uml::code_label no_carry = compiler.m_labelnum++;
|
||||
|
||||
UML_ADD(block, I7, I7, desc->cycles);
|
||||
|
||||
if(op0 < 0xf && opa == 0x7 && op1 < 2)
|
||||
{
|
||||
const uint32_t opimm = op & 0x3f;
|
||||
@ -793,7 +770,7 @@ bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler,
|
||||
break;
|
||||
|
||||
case 14: // JMP
|
||||
UML_ADD(block, I7, I7, 2);
|
||||
UML_SUB(block, mem(&m_core->m_icount), mem(&m_core->m_icount), 4);
|
||||
UML_MOV(block, I0, desc->targetpc);
|
||||
UML_AND(block, mem(&m_core->m_r[REG_PC]), I0, 0x0000ffff);
|
||||
generate_branch(block, compiler, desc);
|
||||
@ -802,13 +779,17 @@ bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler,
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
UML_ADD(block, I7, I7, 2);
|
||||
UML_SUB(block, mem(&m_core->m_icount), mem(&m_core->m_icount), 4);
|
||||
generate_add_lpc(block, (op1 == 0) ? opimm : (0 - opimm));
|
||||
generate_branch(block, compiler, desc);
|
||||
UML_LABEL(block, skip_branch);
|
||||
UML_SUB(block, mem(&m_core->m_icount), mem(&m_core->m_icount), 2);
|
||||
return true;
|
||||
}
|
||||
else if (lower_op == 0x2d) // Push
|
||||
|
||||
UML_SUB(block, mem(&m_core->m_icount), mem(&m_core->m_icount), desc->cycles);
|
||||
|
||||
if (lower_op == 0x2d) // Push
|
||||
{
|
||||
uint32_t r0 = opn;
|
||||
uint32_t r1 = opa;
|
||||
@ -818,10 +799,10 @@ bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler,
|
||||
UML_MOV(block, I1, mem(&m_core->m_r[r1]));
|
||||
UML_CALLH(block, *m_mem_write);
|
||||
UML_SUB(block, I0, I0, 1);
|
||||
UML_AND(block, mem(&m_core->m_r[opb]), I0, 0x0000ffff);
|
||||
r0--;
|
||||
r1--;
|
||||
}
|
||||
UML_AND(block, mem(&m_core->m_r[opb]), I0, 0x0000ffff);
|
||||
return true;
|
||||
}
|
||||
else if (lower_op == 0x29)
|
||||
@ -870,13 +851,13 @@ bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler,
|
||||
{
|
||||
r1++;
|
||||
UML_ADD(block, I0, I0, 1);
|
||||
UML_AND(block, mem(&m_core->m_r[opb]), I0, 0x0000ffff);
|
||||
UML_CALLH(block, *m_mem_read);
|
||||
UML_MOV(block, mem(&m_core->m_r[r1]), I1);
|
||||
if (r1 == REG_PC)
|
||||
do_branch = true;
|
||||
r0--;
|
||||
}
|
||||
UML_AND(block, mem(&m_core->m_r[opb]), I0, 0x0000ffff);
|
||||
if (do_branch)
|
||||
generate_branch(block, compiler, desc);
|
||||
}
|
||||
|
@ -945,7 +945,7 @@ WRITE_LINE_MEMBER(spg2xx_device::vblank)
|
||||
|
||||
void spg2xx_device::check_video_irq()
|
||||
{
|
||||
m_cpu->set_input_line(UNSP_IRQ0_LINE, (VIDEO_IRQ_STATUS & VIDEO_IRQ_ENABLE) ? ASSERT_LINE : CLEAR_LINE);
|
||||
m_cpu->set_state_unsynced(UNSP_IRQ0_LINE, (VIDEO_IRQ_STATUS & VIDEO_IRQ_ENABLE) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
|
||||
@ -1041,7 +1041,7 @@ READ16_MEMBER(spg2xx_device::io_r)
|
||||
break;
|
||||
|
||||
case 0x2f: // Data Segment
|
||||
val = m_cpu->state_int(UNSP_SR) >> 10;
|
||||
val = m_cpu->get_ds();
|
||||
LOGMASKED(LOG_SEGMENT, "io_r: Data Segment = %04x\n", val);
|
||||
break;
|
||||
|
||||
@ -1428,12 +1428,9 @@ WRITE16_MEMBER(spg2xx_device::io_w)
|
||||
}
|
||||
|
||||
case 0x2f: // Data Segment
|
||||
{
|
||||
uint16_t ds = m_cpu->state_int(UNSP_SR);
|
||||
m_cpu->set_state_int(UNSP_SR, (ds & 0x03ff) | ((data & 0x3f) << 10));
|
||||
m_cpu->set_ds(data & 0x3f);
|
||||
LOGMASKED(LOG_SEGMENT, "io_w: Data Segment = %04x\n", data);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x30: // UART Control
|
||||
{
|
||||
@ -1762,19 +1759,19 @@ void spg2xx_device::extint_w(int channel, bool state)
|
||||
void spg2xx_device::check_irqs(const uint16_t changed)
|
||||
{
|
||||
// {
|
||||
// m_cpu->set_input_line(UNSP_IRQ1_LINE, ASSERT_LINE);
|
||||
// m_cpu->set_state_unsynced(UNSP_IRQ1_LINE, ASSERT_LINE);
|
||||
// }
|
||||
|
||||
if (changed & 0x0c00) // Timer A, Timer B IRQ
|
||||
{
|
||||
LOGMASKED(LOG_IRQS, "%ssserting IRQ2 (%04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00));
|
||||
m_cpu->set_input_line(UNSP_IRQ2_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE);
|
||||
m_cpu->set_state_unsynced(UNSP_IRQ2_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
if (changed & 0x2100) // UART, ADC IRQ
|
||||
{
|
||||
LOGMASKED(LOG_UART, "%ssserting IRQ3 (%04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100));
|
||||
m_cpu->set_input_line(UNSP_IRQ3_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100) ? ASSERT_LINE : CLEAR_LINE);
|
||||
m_cpu->set_state_unsynced(UNSP_IRQ3_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x2100) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
if (changed & (AUDIO_BIS_MASK | AUDIO_BIE_MASK)) // Beat IRQ
|
||||
@ -1782,31 +1779,31 @@ void spg2xx_device::check_irqs(const uint16_t changed)
|
||||
if ((m_audio_regs[AUDIO_BEAT_COUNT] & (AUDIO_BIS_MASK | AUDIO_BIE_MASK)) == (AUDIO_BIS_MASK | AUDIO_BIE_MASK))
|
||||
{
|
||||
LOGMASKED(LOG_BEAT, "Asserting beat IRQ\n");
|
||||
m_cpu->set_input_line(UNSP_IRQ4_LINE, ASSERT_LINE);
|
||||
m_cpu->set_state_unsynced(UNSP_IRQ4_LINE, ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGMASKED(LOG_BEAT, "Clearing beat IRQ\n");
|
||||
m_cpu->set_input_line(UNSP_IRQ4_LINE, CLEAR_LINE);
|
||||
m_cpu->set_state_unsynced(UNSP_IRQ4_LINE, CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & 0x1200) // External IRQ
|
||||
{
|
||||
LOGMASKED(LOG_UART, "%ssserting IRQ5 (%04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200));
|
||||
m_cpu->set_input_line(UNSP_IRQ5_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200) ? ASSERT_LINE : CLEAR_LINE);
|
||||
m_cpu->set_state_unsynced(UNSP_IRQ5_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x1200) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
if (changed & 0x0070) // 1024Hz, 2048Hz, 4096Hz IRQ
|
||||
{
|
||||
LOGMASKED(LOG_IRQS, "%ssserting IRQ6 (%04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070));
|
||||
m_cpu->set_input_line(UNSP_IRQ6_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? ASSERT_LINE : CLEAR_LINE);
|
||||
m_cpu->set_state_unsynced(UNSP_IRQ6_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0070) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
|
||||
if (changed & 0x008b) // TMB1, TMB2, 4Hz, key change IRQ
|
||||
{
|
||||
LOGMASKED(LOG_IRQS, "%ssserting IRQ7 (%04x)\n", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? "A" : "Dea", (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b));
|
||||
m_cpu->set_input_line(UNSP_IRQ7_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? ASSERT_LINE : CLEAR_LINE);
|
||||
m_cpu->set_state_unsynced(UNSP_IRQ7_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x008b) ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user