diff options
Diffstat (limited to 'src/devices/cpu/unsp/unspdrc.cpp')
-rw-r--r-- | src/devices/cpu/unsp/unspdrc.cpp | 1316 |
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; -} |