summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/unsp/unspdrc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/unsp/unspdrc.cpp')
-rw-r--r--src/devices/cpu/unsp/unspdrc.cpp1316
1 files changed, 0 insertions, 1316 deletions
diff --git a/src/devices/cpu/unsp/unspdrc.cpp b/src/devices/cpu/unsp/unspdrc.cpp
deleted file mode 100644
index 3ee90c8c1c9..00000000000
--- a/src/devices/cpu/unsp/unspdrc.cpp
+++ /dev/null
@@ -1,1316 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-
-#include "emu.h"
-#include "unsp.h"
-#include "unspfe.h"
-#include "unspdefs.h"
-
-void unsp_device::invalidate_cache()
-{
- m_cache_dirty = true;
-}
-
-void unsp_device::execute_run_drc()
-{
- int execute_result;
-
- /* reset the cache if dirty */
- if (m_cache_dirty)
- {
- code_flush_cache();
- m_cache_dirty = false;
- }
-
-
- /* execute */
- do
- {
- /* run as much as we can */
- execute_result = m_drcuml->execute(*m_entry);
-
- /* if we need to recompile, do it */
- if (execute_result == EXECUTE_MISSING_CODE)
- {
- code_compile_block(UNSP_LPC);
- }
- else if (execute_result == EXECUTE_UNMAPPED_CODE)
- {
- fatalerror("Attempted to execute unmapped code at PC=%08X\n", UNSP_LPC);
- }
- else if (execute_result == EXECUTE_RESET_CACHE)
- {
- code_flush_cache();
- }
- } while (execute_result != EXECUTE_OUT_OF_CYCLES);
-}
-
-
-/***************************************************************************
- C FUNCTION CALLBACKS
-***************************************************************************/
-
-/*-------------------------------------------------
- cfunc_unimplemented - handler for
- unimplemented opcdes
--------------------------------------------------*/
-
-inline void unsp_device::ccfunc_unimplemented()
-{
- fatalerror("PC=%08X: Unimplemented op %04x\n", UNSP_LPC, (uint16_t)m_core->m_arg0);
-}
-
-static void cfunc_unimplemented(void *param)
-{
- ((unsp_device *)param)->ccfunc_unimplemented();
-}
-
-#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
-
-/***************************************************************************
- CACHE MANAGEMENT
-***************************************************************************/
-
-/*-------------------------------------------------
- flush_drc_cache - outward-facing accessor to
- code_flush_cache
--------------------------------------------------*/
-
-void unsp_device::flush_drc_cache()
-{
- if (!m_enable_drc)
- return;
- m_cache_dirty = true;
-}
-
-/*-------------------------------------------------
- code_flush_cache - flush the cache and
- regenerate static code
--------------------------------------------------*/
-
-void unsp_device::code_flush_cache()
-{
- /* empty the transient cache contents */
- m_drcuml->reset();
-
- try
- {
- /* generate the entry point and out-of-cycles handlers */
- static_generate_entry_point();
- static_generate_nocode_handler();
- static_generate_out_of_cycles();
-
- static_generate_memory_accessor(false, "read", m_mem_read);
- static_generate_memory_accessor(true, "write", m_mem_write);
- static_generate_trigger_fiq();
- static_generate_trigger_irq();
- static_generate_check_interrupts();
- }
-
- catch (drcuml_block::abort_compilation &)
- {
- fatalerror("Unable to generate static u'nSP code\n"); fflush(stdout);
- }
-}
-
-/*-------------------------------------------------
- code_compile_block - compile a block of the
- given mode at the specified pc
--------------------------------------------------*/
-
-void unsp_device::code_compile_block(offs_t pc)
-{
- compiler_state compiler = { 0 };
- const opcode_desc *seqhead, *seqlast;
- bool override = false;
-
- g_profiler.start(PROFILER_DRC_COMPILE);
-
- /* get a description of this sequence */
- const opcode_desc *desclist = m_drcfe->describe_code(pc);
-
- bool succeeded = false;
- while (!succeeded)
- {
- try
- {
- /* start the block */
- 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())
- {
- const opcode_desc *curdesc;
- uint32_t nextpc;
-
- /* add a code log entry */
- if (m_drcuml->logging())
- block.append_comment("-------------------------");
-
- /* determine the last instruction in this sequence */
- for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next())
- if (seqlast->flags & OPFLAG_END_SEQUENCE)
- break;
- assert(seqlast != nullptr);
-
- /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
- if (override || !m_drcuml->hash_exists(0, seqhead->pc))
- UML_HASH(block, 0, seqhead->pc);
-
- /* if we already have a hash, and this is the first sequence, assume that we */
- /* are recompiling due to being out of sync and allow future overrides */
- else if (seqhead == desclist)
- {
- override = true;
- UML_HASH(block, 0, seqhead->pc);
- }
-
- /* otherwise, redispatch to that fixed PC and skip the rest of the processing */
- else
- {
- UML_LABEL(block, seqhead->pc | 0x80000000);
- UML_HASHJMP(block, 0, seqhead->pc, *m_nocode);
- continue;
- }
-
- /* validate this code block if we're not pointing into ROM */
- if (m_program->get_write_ptr(seqhead->physpc) != nullptr)
- generate_checksum_block(block, compiler, seqhead, seqlast);
-
- /* label this instruction, if it may be jumped to locally */
- if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET)
- UML_LABEL(block, seqhead->pc | 0x80000000);
-
- /* 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);
- }
-
- 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)
- {
- UML_HASHJMP(block, 0, nextpc, *m_nocode); // hashjmp <mode>,nextpc,nocode
- }
- }
-
- /* end the sequence */
- block.end();
- g_profiler.stop();
- succeeded = true;
- }
- catch (drcuml_block::abort_compilation &)
- {
- code_flush_cache();
- }
- }
-}
-
-/***************************************************************************
- STATIC CODEGEN
-***************************************************************************/
-
-/*-------------------------------------------------
- alloc_handle - allocate a handle if not
- already allocated
--------------------------------------------------*/
-
-static inline void alloc_handle(drcuml_state &drcuml, uml::code_handle *&handleptr, const char *name)
-{
- if (!handleptr)
- handleptr = drcuml.handle_alloc(name);
-}
-
-/*-------------------------------------------------
- generate_entry_point - generate a
- static entry point
--------------------------------------------------*/
-
-void unsp_device::static_generate_entry_point()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(32));
-
- /* forward references */
- alloc_handle(*m_drcuml, m_nocode, "nocode");
-
- alloc_handle(*m_drcuml, m_entry, "entry");
- UML_HANDLE(block, *m_entry);
-
- /* load fast integer registers */
- //load_fast_iregs(block);
-
- /* generate a hash jump via the current mode and PC */
- UML_ROLAND(block, I1, mem(&m_core->m_r[REG_SR]), 16, 0x003f0000);
- UML_OR(block, I1, I1, mem(&m_core->m_r[REG_PC]));
- UML_HASHJMP(block, 0, I1, *m_nocode);
- block.end();
-}
-
-
-/*-------------------------------------------------
- static_generate_nocode_handler - generate an
- exception handler for "out of code"
--------------------------------------------------*/
-
-void unsp_device::static_generate_nocode_handler()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(10));
-
- /* generate a hash jump via the current mode and PC */
- alloc_handle(*m_drcuml, m_nocode, "nocode");
- UML_HANDLE(block, *m_nocode);
- UML_GETEXP(block, I0);
-
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I0, 16, 0x3f);
- UML_AND(block, mem(&m_core->m_r[REG_PC]), I0, 0x0000ffff);
- //save_fast_iregs(block);
- UML_EXIT(block, EXECUTE_MISSING_CODE);
-
- block.end();
-}
-
-
-/*-------------------------------------------------
- static_generate_out_of_cycles - generate an
- out of cycles exception handler
--------------------------------------------------*/
-
-void unsp_device::static_generate_out_of_cycles()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(10));
-
- /* generate a hash jump via the current mode and PC */
- alloc_handle(*m_drcuml, m_out_of_cycles, "out_of_cycles");
- UML_HANDLE(block, *m_out_of_cycles);
- //save_fast_iregs(block);
- UML_EXIT(block, EXECUTE_OUT_OF_CYCLES);
-
- block.end();
-}
-
-/*------------------------------------------------------------------
- static_generate_memory_accessor
-------------------------------------------------------------------*/
-
-void unsp_device::static_generate_memory_accessor(bool iswrite, const char *name, uml::code_handle *&handleptr)
-{
- /* on entry, address is in I0; data for writes is in I1 */
- /* on exit, read result is in I1 */
-
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(32));
-
- /* add a global entry for this */
- alloc_handle(*m_drcuml, handleptr, 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);
-
- block.end();
-}
-
-
-
-/***************************************************************************
- CODE GENERATION
-***************************************************************************/
-
-void unsp_device::static_generate_check_interrupts()
-{
- uml::code_label test_loop = 1;
- uml::code_label found = 2;
- uml::code_label do_irq = 3;
-
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(256));
-
- /* generate a hash jump via the current mode and PC */
- alloc_handle(*m_drcuml, m_check_interrupts, "check_interrupts");
- UML_HANDLE(block, *m_check_interrupts);
-
- UML_CMP(block, mem(&m_core->m_sirq), 0);
- UML_RETc(block, uml::COND_Z);
-
- UML_MOV(block, I2, 0);
- UML_MOV(block, I0, 1);
- UML_MOV(block, I1, mem(&m_core->m_sirq));
-
- UML_LABEL(block, test_loop);
- UML_TEST(block, I1, I0);
- UML_JMPc(block, uml::COND_NZ, found);
- UML_SHL(block, I0, I0, 1);
- UML_ADD(block, I2, I2, 1);
- UML_CMP(block, I0, 1 << 9);
- UML_JMPc(block, uml::COND_NE, test_loop);
- UML_RET(block);
-
- UML_LABEL(block, found);
- UML_CMP(block, I0, 1);
- UML_JMPc(block, uml::COND_NE, do_irq);
- UML_CALLH(block, *m_trigger_fiq);
- UML_RET(block);
-
- UML_LABEL(block, do_irq);
- UML_CALLH(block, *m_trigger_irq);
- UML_RET(block);
-
- block.end();
-}
-
-void unsp_device::static_generate_trigger_fiq()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(256));
-
- /* generate a hash jump via the current mode and PC */
- 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_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, I0, mem(&m_core->m_r[REG_SP]));
-
- UML_MOV(block, I1, mem(&m_core->m_r[REG_PC]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_MOV(block, I1, mem(&m_core->m_r[REG_SR]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_AND(block, mem(&m_core->m_r[REG_SP]), I0, 0x0000ffff);
-
- UML_MOV(block, I0, 0x0000fff6);
- UML_CALLH(block, *m_mem_read);
- UML_MOV(block, mem(&m_core->m_r[REG_PC]), I1);
- UML_MOV(block, mem(&m_core->m_r[REG_SR]), 0);
- UML_HASHJMP(block, 0, I1, *m_nocode);
- UML_RET(block);
-
- block.end();
-}
-
-void unsp_device::static_generate_trigger_irq()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(256));
-
- /* 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);
- UML_RETc(block, uml::COND_NZ);
-
- UML_TEST(block, mem(&m_core->m_enable_irq), 1);
- UML_RETc(block, uml::COND_Z);
-
- 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_MOV(block, I0, mem(&m_core->m_r[REG_SP]));
- UML_MOV(block, I1, mem(&m_core->m_r[REG_PC]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_MOV(block, I1, mem(&m_core->m_r[REG_SR]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_AND(block, mem(&m_core->m_r[REG_SP]), I0, 0x0000ffff);
-
- UML_ADD(block, I0, I2, 0x0000fff7);
-
- UML_CALLH(block, *m_mem_read);
-
- UML_MOV(block, mem(&m_core->m_r[REG_PC]), I1);
- UML_MOV(block, mem(&m_core->m_r[REG_SR]), 0);
- UML_HASHJMP(block, 0, I1, *m_nocode);
- UML_RET(block);
-
- block.end();
-}
-
-/*-------------------------------------------------
- generate_check_cycles - generate code to
- generate an exception if cycles are out
--------------------------------------------------*/
-
-void unsp_device::generate_check_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param)
-{
- UML_CMP(block, mem(&m_core->m_icount), 0);
- UML_EXHc(block, uml::COND_L, *m_out_of_cycles, param);
-}
-
-/*-------------------------------------------------
- generate_checksum_block - generate code to
- validate a sequence of opcodes
--------------------------------------------------*/
-
-void unsp_device::generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast)
-{
- const opcode_desc *curdesc;
- if (m_drcuml->logging())
- {
- block.append_comment("[Validation for %08X]", seqhead->pc);
- }
-
- /* 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++)
- {
- UML_LOAD(block, I1, memptr, i, SIZE_WORD, SCALE_x2);
- UML_ADD(block, I0, I0, I1);
- sum += ((uint16_t*)memptr)[i];
- }
- for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
- {
- 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_LOAD(block, I1, memptr, i, SIZE_WORD, SCALE_x2);
- UML_ADD(block, I0, I0, I1);
- sum += ((uint16_t*)memptr)[i];
- }
- }
- }
- UML_CMP(block, I0, sum);
- UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc);
-}
-
-
-/*-------------------------------------------------
- log_add_disasm_comment - add a comment
- including disassembly of a MIPS instruction
--------------------------------------------------*/
-
-void unsp_device::log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op)
-{
- if (m_drcuml->logging())
- {
- block.append_comment("%08X: %08x", pc, op);
- }
-}
-
-
-/*------------------------------------------------------------------
- generate_branch
-------------------------------------------------------------------*/
-
-void unsp_device::generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
-{
- if (desc->targetpc == BRANCH_TARGET_DYNAMIC)
- {
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 16, 0x3f0000);
- UML_OR(block, mem(&m_core->m_jmpdest), I0, mem(&m_core->m_r[REG_PC]));
- }
-
- /* update the cycles and jump through the hash table to the target */
- if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
- {
- UML_CALLH(block, *m_check_interrupts);
- UML_HASHJMP(block, 0, desc->targetpc, *m_nocode);
- }
- else
- {
- UML_CALLH(block, *m_check_interrupts);
- UML_HASHJMP(block, 0, mem(&m_core->m_jmpdest), *m_nocode);
- }
-}
-
-
-/*-------------------------------------------------
- generate_sequence_instruction - generate code
- for a single instruction in a sequence
--------------------------------------------------*/
-
-void unsp_device::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
-{
- /* add an entry for the log */
- if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
- log_add_disasm_comment(block, desc->pc, desc->opptr.w[0]);
-
- /* set the PC map variable */
- UML_MAPVAR(block, MAPVAR_PC, desc->pc);
-
- /* if we are debugging, call the debugger */
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
- {
- //save_fast_iregs(block);
- UML_DEBUG(block, desc->pc);
- }
-
-#if UNSP_LOG_REGS
- UML_CALLC(block, cfunc_log_regs, this);
-#endif
-
- if (!(desc->flags & OPFLAG_VIRTUAL_NOOP))
- {
- /* compile the instruction */
- if (!generate_opcode(block, compiler, desc))
- {
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), desc->pc, 16, 0x3f);
- UML_AND(block, mem(&m_core->m_r[REG_PC]), desc->pc, 0x0000ffff);
- UML_MOV(block, mem(&m_core->m_arg0), desc->opptr.w[0]);
- UML_CALLC(block, cfunc_unimplemented, this);
- }
- }
-}
-
-
-/*------------------------------------------------------------------
- generate_add_lpc - adds an offset to the long program counter
- comprised of PC and the low 6 bits of SR
-------------------------------------------------------------------*/
-
-void unsp_device::generate_add_lpc(drcuml_block &block, int32_t offset)
-{
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 16, 0x3f0000);
- UML_OR(block, I0, I0, mem(&m_core->m_r[REG_PC]));
- UML_ADD(block, I0, I0, offset);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I0, 16, 0x3f);
- UML_AND(block, mem(&m_core->m_r[REG_PC]), I0, 0x0000ffff);
-}
-
-
-/*------------------------------------------------------------------
- generate_update_nzsc - perform a full flag update
-------------------------------------------------------------------*/
-
-void unsp_device::generate_update_nzsc(drcuml_block &block)
-{
- UML_XOR(block, I1, I1, 0x0000ffff);
- UML_SEXT(block, I1, I1, SIZE_WORD);
- UML_SEXT(block, I2, I2, SIZE_WORD);
- UML_CMP(block, I2, I1);
- UML_SETc(block, uml::COND_L, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_S_SHIFT, UNSP_S);
-
- UML_TEST(block, I3, 0x8000);
- UML_SETc(block, uml::COND_NZ, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_N_SHIFT, UNSP_N);
-
- UML_TEST(block, I3, 0x10000);
- UML_SETc(block, uml::COND_NZ, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_C_SHIFT, UNSP_C);
-
- UML_TEST(block, I3, 0x0000ffff);
- UML_SETc(block, uml::COND_Z, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_Z_SHIFT, UNSP_Z);
-}
-
-
-/*------------------------------------------------------------------
- generate_update_nz - perform a partial flag update
-------------------------------------------------------------------*/
-
-void unsp_device::generate_update_nz(drcuml_block &block)
-{
- UML_TEST(block, I3, 0x8000);
- UML_SETc(block, uml::COND_NZ, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_N_SHIFT, UNSP_N);
-
- UML_AND(block, I2, I3, 0x0000ffff);
- UML_CMP(block, I2, 0);
- UML_SETc(block, uml::COND_E, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_Z_SHIFT, UNSP_Z);
-}
-
-
-/*------------------------------------------------------------------
- generate_opcode - main handler which generates the UML for a
- single opcode
-------------------------------------------------------------------*/
-
-bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
-{
- uint32_t op = (uint32_t)desc->opptr.w[0];
-
- generate_add_lpc(block, 1);
-
- const uint16_t op0 = (op >> 12) & 15;
- const uint16_t opa = (op >> 9) & 7;
- const uint16_t op1 = (op >> 6) & 7;
- const uint16_t opn = (op >> 3) & 7;
- const uint16_t opb = op & 7;
-
- 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++;
- uml::code_label shift_no_sign = compiler.m_labelnum++;
- uml::code_label no_carry = compiler.m_labelnum++;
-
- if(op0 < 0xf && opa == 0x7 && op1 < 2)
- {
- const uint32_t opimm = op & 0x3f;
- switch(op0)
- {
- case 0: // JB
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_C);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- break;
-
- case 1: // JAE
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_C);
- UML_JMPc(block, uml::COND_Z, skip_branch);
- break;
-
- case 2: // JGE
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_S);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- break;
-
- case 3: // JL
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_S);
- UML_JMPc(block, uml::COND_Z, skip_branch);
- break;
-
- case 4: // JNE
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_Z);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- break;
-
- case 5: // JE
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_Z);
- UML_JMPc(block, uml::COND_Z, skip_branch);
- break;
-
- case 6: // JPL
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_N);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- break;
-
- case 7: // JMI
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_N);
- UML_JMPc(block, uml::COND_Z, skip_branch);
- break;
-
- case 8: // JBE
- UML_AND(block, I0, mem(&m_core->m_r[REG_SR]), UNSP_Z | UNSP_C);
- UML_CMP(block, I0, UNSP_C);
- UML_JMPc(block, uml::COND_E, skip_branch);
- break;
-
- case 9: // JA
- UML_AND(block, I0, mem(&m_core->m_r[REG_SR]), UNSP_Z | UNSP_C);
- UML_CMP(block, I0, UNSP_C);
- UML_JMPc(block, uml::COND_NE, skip_branch);
- break;
-
- case 10: // JLE
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_Z | UNSP_S);
- UML_JMPc(block, uml::COND_Z, skip_branch);
- break;
-
- case 11: // JG
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_Z);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_S);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- break;
-
- case 14: // JMP
- 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);
- return true;
-
- default:
- return false;
- }
- 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;
- }
-
- 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;
- UML_MOV(block, I0, mem(&m_core->m_r[opb]));
- while (r0)
- {
- 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--;
- }
- return true;
- }
- else if (lower_op == 0x29)
- {
- if (op == 0x9a98) // reti
- {
- UML_ADD(block, I0, mem(&m_core->m_r[REG_SP]), 1);
- UML_CALLH(block, *m_mem_read);
- UML_MOV(block, mem(&m_core->m_r[REG_SR]), I1);
-
- UML_ADD(block, I0, I0, 1);
- UML_CALLH(block, *m_mem_read);
- UML_MOV(block, mem(&m_core->m_r[REG_PC]), I1);
-
- 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_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_LABEL(block, reti_done);
- UML_MOV(block, mem(&m_core->m_curirq), 0);
- generate_branch(block, compiler, desc);
- }
- else // pop
- {
- uint32_t r0 = opn;
- uint32_t r1 = opa;
- bool do_branch = false;
-
- UML_MOV(block, I0, mem(&m_core->m_r[opb]));
- while (r0)
- {
- 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--;
- }
- if (do_branch)
- generate_branch(block, compiler, desc);
- }
- return true;
- }
- else if (op0 == 0xf)
- {
- switch (op1)
- {
- case 0x00: // Multiply, Unsigned * Signed
- if(opn == 1 && opa != 7)
- {
- UML_MOV(block, I0, mem(&m_core->m_r[opa]));
- UML_MOV(block, I1, mem(&m_core->m_r[opb]));
- UML_MULU(block, I2, I2, I0, I1);
-
- UML_TEST(block, I1, 0x00008000);
- UML_JMPc(block, uml::COND_Z, mul_opb_nohi);
- UML_SHL(block, I0, I0, 16);
- UML_SUB(block, I2, I2, I0);
-
- UML_LABEL(block, mul_opb_nohi);
- UML_SHR(block, mem(&m_core->m_r[REG_R4]), I2, 16);
- UML_AND(block, mem(&m_core->m_r[REG_R3]), I2, 0x0000ffff);
- return true;
- }
- return false;
-
- case 0x01: // Call
- if(!(opa & 1))
- {
- generate_add_lpc(block, 1);
-
- UML_MOV(block, I0, mem(&m_core->m_r[REG_SP]));
-
- UML_MOV(block, I1, mem(&m_core->m_r[REG_PC]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_MOV(block, I1, mem(&m_core->m_r[REG_SR]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_AND(block, mem(&m_core->m_r[REG_SP]), I0, 0x0000ffff);
-
- UML_MOV(block, I0, desc->targetpc);
- UML_AND(block, mem(&m_core->m_r[REG_PC]), I0, 0x0000ffff);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I0, 16, 0x3f);
- generate_branch(block, compiler, desc);
- return true;
- }
- return false;
-
- case 0x02: // Far Jump
- if (opa == 7)
- {
- UML_MOV(block, I0, desc->targetpc);
- UML_AND(block, mem(&m_core->m_r[REG_PC]), I0, 0x0000ffff);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I0, 16, 0x3f);
- generate_branch(block, compiler, desc);
- return true;
- }
- return false;
-
- case 0x04: // Multiply, Signed * Signed
- if(opn == 1 && opa != 7)
- {
- UML_MOV(block, I0, mem(&m_core->m_r[opa]));
- UML_MOV(block, I1, mem(&m_core->m_r[opb]));
- UML_MULU(block, I2, I2, I0, I1);
-
- UML_TEST(block, I1, 0x00008000);
- UML_JMPc(block, uml::COND_Z, mul_opb_nohi);
- UML_SHL(block, I0, I0, 16);
- UML_SUB(block, I2, I2, I0);
-
- UML_LABEL(block, mul_opb_nohi);
- UML_TEST(block, I0, 0x00008000);
- UML_JMPc(block, uml::COND_Z, mul_opa_nohi);
- UML_SHL(block, I1, I1, 16);
- UML_SUB(block, I2, I2, I1);
-
- UML_LABEL(block, mul_opa_nohi);
- UML_SHR(block, mem(&m_core->m_r[REG_R4]), I2, 16);
- UML_AND(block, mem(&m_core->m_r[REG_R3]), I2, 0x0000ffff);
- return true;
- }
- return false;
-
- case 0x05: // Interrupt flags
- switch(op & 0x3f)
- {
- case 0:
- UML_MOV(block, mem(&m_core->m_enable_irq), 0);
- UML_MOV(block, mem(&m_core->m_enable_fiq), 0);
- break;
-
- case 1:
- UML_MOV(block, mem(&m_core->m_enable_irq), 1);
- UML_MOV(block, mem(&m_core->m_enable_fiq), 0);
- break;
-
- case 2:
- UML_MOV(block, mem(&m_core->m_enable_irq), 0);
- UML_MOV(block, mem(&m_core->m_enable_fiq), 1);
- break;
-
- case 3:
- UML_MOV(block, mem(&m_core->m_enable_irq), 1);
- UML_MOV(block, mem(&m_core->m_enable_fiq), 1);
- break;
-
- case 8:
- UML_MOV(block, mem(&m_core->m_enable_irq), 0);
- break;
-
- case 9:
- UML_MOV(block, mem(&m_core->m_enable_irq), 1);
- break;
-
- case 12:
- UML_MOV(block, mem(&m_core->m_enable_fiq), 0);
- break;
-
- case 14:
- UML_MOV(block, mem(&m_core->m_enable_fiq), 1);
- break;
-
- case 37:
- // nop
- break;
-
- default:
- return false;
- }
- return true;
-
- default:
- return false;
- }
- }
-
- // At this point, we should be dealing solely with ALU ops.
- UML_MOV(block, I2, mem(&m_core->m_r[opa]));
-
- switch (op1)
- {
- case 0x00: // r, [bp+imm6]
- UML_ADD(block, I0, mem(&m_core->m_r[REG_BP]), op & 0x3f);
- UML_AND(block, I0, I0, 0x0000ffff);
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
-
- case 0x01: // r, imm6
- UML_MOV(block, I1, op & 0x3f);
- break;
-
- case 0x03: // Indirect
- {
- const uint8_t lsbits = opn & 3;
- if (opn & 4)
- {
- switch (lsbits)
- {
- case 0: // r, [<ds:>r]
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 6, 0x3f0000);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
-
- case 1: // r, [<ds:>r--]
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 6, 0x3f0000);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- UML_SUB(block, I3, I0, 1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I3, 32-6, 0x0000fc00);
- UML_AND(block, mem(&m_core->m_r[opb]), I3, 0x0000ffff);
- break;
-
- case 2: // r, [<ds:>r++]
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 6, 0x3f0000);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- UML_ADD(block, I3, I0, 1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I3, 32-6, 0x0000fc00);
- UML_AND(block, mem(&m_core->m_r[opb]), I3, 0x0000ffff);
- break;
-
- case 3: // r, [<ds:>++r]
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 6, 0x3f0000);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- UML_ADD(block, I0, I0, 1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I0, 32-6, 0x0000fc00);
- UML_AND(block, mem(&m_core->m_r[opb]), I0, 0x0000ffff);
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
-
- default:
- // can't happen
- break;
- }
- }
- else
- {
- switch (lsbits)
- {
- case 0: // r, [r]
- UML_MOV(block, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
-
- case 1: // r, [r--]
- UML_MOV(block, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- UML_SUB(block, I3, I0, 1);
- UML_AND(block, mem(&m_core->m_r[opb]), I3, 0x0000ffff);
- break;
-
- case 2: // r, [r++]
- UML_MOV(block, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- UML_ADD(block, I3, I0, 1);
- UML_AND(block, mem(&m_core->m_r[opb]), I3, 0x0000ffff);
- break;
-
- case 3: // r, [++r]
- UML_ADD(block, I0, mem(&m_core->m_r[opb]), 1);
- UML_AND(block, I0, I0, 0x0000ffff);
- UML_MOV(block, mem(&m_core->m_r[opb]), I0);
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
- default:
- // can't happen
- break;
- }
- }
- break;
- }
-
- case 0x04: // 16-bit ops
- switch (opn)
- {
- case 0x00: // r
- UML_MOV(block, I1, mem(&m_core->m_r[opb]));
- break;
-
- case 0x01: // imm16
- {
- UML_MOV(block, I2, mem(&m_core->m_r[opb]));
- const uint16_t r1 = m_pr16(desc->pc + 1);
- generate_add_lpc(block, 1);
- UML_MOV(block, I1, r1);
- break;
- }
-
- case 0x02: // [imm16]
- {
- UML_MOV(block, I2, mem(&m_core->m_r[opb]));
- const uint16_t r1 = m_pr16(desc->pc + 1);
- generate_add_lpc(block, 1);
- UML_MOV(block, I0, r1);
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
- }
-
- case 0x03: // store [imm16], r
- {
- UML_MOV(block, I1, I2);
- UML_MOV(block, I2, mem(&m_core->m_r[opb]));
- const uint16_t r2 = m_pr16(desc->pc + 1);
- generate_add_lpc(block, 1);
- UML_MOV(block, I0, r2);
- break;
- }
-
- default: // Shifted ops
- {
- UML_SHL(block, I0, mem(&m_core->m_r[opb]), 4);
- UML_OR(block, I0, I0, mem(&m_core->m_sb));
- UML_TEST(block, I0, 0x80000);
- UML_JMPc(block, uml::COND_Z, shift_no_sign);
- UML_OR(block, I0, I0, 0xf00000);
-
- UML_LABEL(block, shift_no_sign);
- UML_SHR(block, I0, I0, opn - 3);
- UML_AND(block, mem(&m_core->m_sb), I0, 0xf);
- UML_SHR(block, I1, I0, 4);
- UML_AND(block, I1, I1, 0x0000ffff);
- break;
- }
- }
- break;
-
- case 0x05: // More shifted ops
- if (opn & 4) // Shift right
- {
- UML_SHL(block, I0, mem(&m_core->m_r[opb]), 4);
- UML_OR(block, I0, I0, mem(&m_core->m_sb));
- UML_SHR(block, I0, I0, opn - 3);
- UML_AND(block, mem(&m_core->m_sb), I0, 0xf);
- UML_SHR(block, I1, I0, 4);
- UML_AND(block, I1, I1, 0x0000ffff);
- }
- else // Shift left
- {
- UML_SHL(block, I0, mem(&m_core->m_sb), 16);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- UML_SHL(block, I0, I0, opn + 1);
- UML_SHR(block, I1, I0, 16);
- UML_AND(block, mem(&m_core->m_sb), I1, 0xf);
- UML_AND(block, I1, I0, 0x0000ffff);
- }
- break;
-
- case 0x06: // Rotated ops
- {
- UML_SHL(block, I0, mem(&m_core->m_sb), 16);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- UML_SHL(block, I0, I0, 4);
- UML_OR(block, I0, I0, mem(&m_core->m_sb));
- if (opn & 4) // Rotate right
- {
- UML_SHR(block, I0, I0, opn - 3);
- UML_AND(block, mem(&m_core->m_sb), I0, 0xf);
- }
- else // Rotate left
- {
- UML_SHL(block, I0, I0, opn + 1);
- UML_SHR(block, I1, I0, 20);
- UML_AND(block, mem(&m_core->m_sb), I1, 0xf);
- }
- UML_SHR(block, I1, I0, 4);
- UML_AND(block, I1, I1, 0x0000ffff);
- break;
- }
-
- case 0x07: // Direct 8
- UML_MOV(block, I0, op & 0x3f);
- UML_CALLH(block, *m_mem_read);
- break;
-
- default:
- break;
- }
-
- switch (op0)
- {
- case 0x00: // Add
- UML_ADD(block, I3, I2, I1);
- if (opa != 7)
- generate_update_nzsc(block);
- break;
-
- case 0x01: // Add w/ carry
- UML_ROLAND(block, I3, mem(&m_core->m_r[REG_SR]), 32-UNSP_C_SHIFT, 1);
- UML_ADD(block, I3, I3, I2);
- UML_ADD(block, I3, I3, I1);
- if (opa != 7)
- generate_update_nzsc(block);
- break;
-
- case 0x02: // Subtract
- UML_XOR(block, I1, I1, 0x0000ffff);
- UML_ADD(block, I3, I1, I2);
- UML_ADD(block, I3, I3, 1);
- if (opa != 7)
- generate_update_nzsc(block);
- break;
-
- case 0x03: // Subtract w/ carry
- UML_XOR(block, I1, I1, 0x0000ffff);
- UML_ADD(block, I3, I1, I2);
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_C);
- UML_JMPc(block, uml::COND_Z, no_carry);
- UML_ADD(block, I3, I3, 1);
-
- UML_LABEL(block, no_carry);
- if (opa != 7)
- generate_update_nzsc(block);
- break;
-
- case 0x04: // Compare
- UML_XOR(block, I1, I1, 0x0000ffff);
- UML_ADD(block, I3, I1, I2);
- UML_ADD(block, I3, I3, 1);
- if (opa != 7)
- generate_update_nzsc(block);
- return true;
-
- case 0x06: // Negate
- UML_SUB(block, I3, 0, I1);
- if (opa != 7)
- generate_update_nz(block);
- break;
-
- case 0x08: // XOR
- UML_XOR(block, I3, I2, I1);
- if (opa != 7)
- generate_update_nz(block);
- break;
-
- case 0x09: // Load
- UML_MOV(block, I3, I1);
- if (opa != 7)
- generate_update_nz(block);
- break;
-
- case 0x0a: // OR
- UML_OR(block, I3, I2, I1);
- if (opa != 7)
- generate_update_nz(block);
- break;
-
- case 0x0b: // AND
- UML_AND(block, I3, I2, I1);
- if (opa != 7)
- generate_update_nz(block);
- break;
-
- case 0x0c: // Test
- UML_AND(block, I3, I2, I1);
- if (opa != 7)
- generate_update_nz(block);
- return true;
-
- case 0x0d: // Store
- UML_MOV(block, I1, I2);
- UML_CALLH(block, *m_mem_write);
- return true;
-
- default:
- return false;
- }
-
- if (op1 == 0x04 && opn == 0x03)
- {
- UML_MOV(block, I1, I3);
- UML_CALLH(block, *m_mem_write);
- return true;
- }
-
- UML_AND(block, mem(&m_core->m_r[opa]), I3, 0x0000ffff);
- if (opa == REG_PC)
- generate_branch(block, compiler, desc);
- return true;
-}