// license:BSD-3-Clause // copyright-holders:Ville Linde /****************************************************************************** SHARC UML recompiler core ******************************************************************************/ #include "emu.h" #include "debugger.h" #include "sharc.h" #include "sharcfe.h" #include "cpu/drcfe.h" #include "cpu/drcuml.h" #include "cpu/drcumlsh.h" using namespace uml; #define USE_SWAPDQ 0 #define WRITE_SNOOP 0 // map variables #define MAPVAR_PC M0 #define MAPVAR_CYCLES M1 // exit codes #define EXECUTE_OUT_OF_CYCLES 0 #define EXECUTE_MISSING_CODE 1 #define EXECUTE_UNMAPPED_CODE 2 #define EXECUTE_RESET_CACHE 3 #define REG(reg) m_regmap[reg] #define DM_I(reg) mem(&m_core->dag1.i[reg]) #define DM_M(reg) mem(&m_core->dag1.m[reg]) #define DM_L(reg) mem(&m_core->dag1.l[reg]) #define DM_B(reg) mem(&m_core->dag1.b[reg]) #define PM_I(reg) mem(&m_core->dag2.i[reg]) #define PM_M(reg) mem(&m_core->dag2.m[reg]) #define PM_L(reg) mem(&m_core->dag2.l[reg]) #define PM_B(reg) mem(&m_core->dag2.b[reg]) #define ASTAT_AZ mem(&m_core->astat_drc.az) #define ASTAT_AV mem(&m_core->astat_drc.av) #define ASTAT_AN mem(&m_core->astat_drc.an) #define ASTAT_AC mem(&m_core->astat_drc.ac) #define ASTAT_AS mem(&m_core->astat_drc.as) #define ASTAT_AI mem(&m_core->astat_drc.ai) #define ASTAT_AF mem(&m_core->astat_drc.af) #define ASTAT_MN mem(&m_core->astat_drc.mn) #define ASTAT_MV mem(&m_core->astat_drc.mv) #define ASTAT_MU mem(&m_core->astat_drc.mu) #define ASTAT_MI mem(&m_core->astat_drc.mi) #define ASTAT_SV mem(&m_core->astat_drc.sv) #define ASTAT_SZ mem(&m_core->astat_drc.sz) #define ASTAT_SS mem(&m_core->astat_drc.ss) #define ASTAT_BTF mem(&m_core->astat_drc.btf) #define FLAG0 mem(&m_core->flag[0]) #define FLAG1 mem(&m_core->flag[1]) #define FLAG2 mem(&m_core->flag[2]) #define FLAG3 mem(&m_core->flag[3]) #define CURLCNTR mem(&m_core->curlcntr) #define LCNTR mem(&m_core->lcntr) #define PCSTK mem(&m_core->pcstk) #define PCSTKP mem(&m_core->pcstkp) #define STKY mem(&m_core->stky) #define LSTKP mem(&m_core->lstkp) #define USTAT1 mem(&m_core->ustat1) #define USTAT2 mem(&m_core->ustat2) #define IRPTL mem(&m_core->irptl) #define MODE1 mem(&m_core->mode1) #define MODE2 mem(&m_core->mode2) #define IMASK mem(&m_core->imask) #define IMASKP mem(&m_core->imaskp) #define MRF mem(&m_core->mrf) #define MRB mem(&m_core->mrb) #define AZ_CALC_REQUIRED ((desc->regreq[0] & 0x00010000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define AV_CALC_REQUIRED ((desc->regreq[0] & 0x00020000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define AN_CALC_REQUIRED ((desc->regreq[0] & 0x00040000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define AC_CALC_REQUIRED ((desc->regreq[0] & 0x00080000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define AS_CALC_REQUIRED ((desc->regreq[0] & 0x00100000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define AI_CALC_REQUIRED ((desc->regreq[0] & 0x00200000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define MN_CALC_REQUIRED ((desc->regreq[0] & 0x00400000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define MV_CALC_REQUIRED ((desc->regreq[0] & 0x00800000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define MU_CALC_REQUIRED ((desc->regreq[0] & 0x01000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define MI_CALC_REQUIRED ((desc->regreq[0] & 0x02000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define SV_CALC_REQUIRED ((desc->regreq[0] & 0x04000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define SZ_CALC_REQUIRED ((desc->regreq[0] & 0x08000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define SS_CALC_REQUIRED ((desc->regreq[0] & 0x10000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define BTF_CALC_REQUIRED ((desc->regreq[0] & 0x20000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define AF_CALC_REQUIRED ((desc->regreq[0] & 0x40000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) #define IRAM_BLOCK0_START 0x20000 #define IRAM_BLOCK0_END 0x27fff #define IRAM_BLOCK1_START 0x28000 #define IRAM_BLOCK1_END 0x3ffff #define IRAM_SHORT_BLOCK0_START 0x40000 #define IRAM_SHORT_BLOCK0_END 0x4ffff #define IRAM_SHORT_BLOCK1_START 0x50000 #define IRAM_SHORT_BLOCK1_END 0x7ffff #define IOP_REGISTER_START 0x00000 #define IOP_REGISTER_END 0x000ff #define IRAM_END 0x7ffff inline void adsp21062_device::alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name) { if (*handleptr == nullptr) *handleptr = drcuml->handle_alloc(name); } static void cfunc_unimplemented(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_unimplemented(); } static void cfunc_read_iop(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_read_iop(); } static void cfunc_write_iop(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_write_iop(); } static void cfunc_pcstack_overflow(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_pcstack_overflow(); } static void cfunc_pcstack_underflow(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_pcstack_underflow(); } static void cfunc_loopstack_overflow(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_loopstack_overflow(); } static void cfunc_loopstack_underflow(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_loopstack_underflow(); } static void cfunc_statusstack_overflow(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_statusstack_overflow(); } static void cfunc_statusstack_underflow(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_statusstack_underflow(); } static void cfunc_unimplemented_compute(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_unimplemented_compute(); } static void cfunc_unimplemented_shiftimm(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_unimplemented_shiftimm(); } #if WRITE_SNOOP void adsp21062_device::sharc_cfunc_write_snoop() { printf("Write %08X to %08X at %08X\n", m_core->arg0, m_core->arg1, m_core->arg2); } static void cfunc_write_snoop(void *param) { adsp21062_device *sharc = (adsp21062_device *)param; sharc->sharc_cfunc_write_snoop(); } #endif void adsp21062_device::sharc_cfunc_unimplemented() { UINT64 op = m_core->arg64; fatalerror("PC=%08X: Unimplemented op %04X%08X\n", m_core->pc, (UINT32)(op >> 32), (UINT32)(op)); } void adsp21062_device::sharc_cfunc_unimplemented_compute() { UINT64 op = m_core->arg64; fatalerror("PC=%08X: Unimplemented compute %04X%08X\n", m_core->pc, (UINT32)(op >> 32), (UINT32)(op)); } void adsp21062_device::sharc_cfunc_unimplemented_shiftimm() { UINT64 op = m_core->arg64; fatalerror("PC=%08X: Unimplemented shiftimm %04X%08X\n", m_core->pc, (UINT32)(op >> 32), (UINT32)(op)); } void adsp21062_device::sharc_cfunc_read_iop() { m_core->arg1 = sharc_iop_r(m_core->arg0); } void adsp21062_device::sharc_cfunc_write_iop() { sharc_iop_w(m_core->arg0, m_core->arg1); } void adsp21062_device::sharc_cfunc_pcstack_overflow() { fatalerror("SHARC: PCStack overflow"); } void adsp21062_device::sharc_cfunc_pcstack_underflow() { fatalerror("SHARC: PCStack underflow"); } void adsp21062_device::sharc_cfunc_loopstack_overflow() { fatalerror("SHARC: Loop Stack overflow"); } void adsp21062_device::sharc_cfunc_loopstack_underflow() { fatalerror("SHARC: Loop Stack underflow"); } void adsp21062_device::sharc_cfunc_statusstack_overflow() { fatalerror("SHARC: Status Stack overflow"); } void adsp21062_device::sharc_cfunc_statusstack_underflow() { fatalerror("SHARC: Status Stack underflow"); } bool adsp21062_device::if_condition_always_true(int condition) { if (condition == 0x1f || condition == 0x1e) return true; else return false; } UINT32 adsp21062_device::do_condition_astat_bits(int condition) { UINT32 r = 0; switch (condition) { case 0x00: r = AZ; break; // EQ case 0x01: r = AZ | AN; break; // LT case 0x02: r = AZ | AN; break; // LE case 0x03: r = AC; break; // AC case 0x04: r = AV; break; // AV case 0x05: r = MV; break; // MV case 0x06: r = MN; break; // MS case 0x07: r = SV; break; // SV case 0x08: r = SZ; break; // SZ case 0x0d: r = BTF; break; // TF case 0x10: r = AZ; break; // NOT EQUAL case 0x11: r = AZ | AN; break; // GE case 0x12: r = AZ | AN; break; // GT case 0x13: r = AC; break; // NOT AC case 0x14: r = AV; break; // NOT AV case 0x15: r = MV; break; // NOT MV case 0x16: r = MN; break; // NOT MS case 0x17: r = SV; break; // NOT SV case 0x18: r = SZ; break; // NOT SZ case 0x1d: r = BTF; break; // NOT TF } return r; } /*------------------------------------------------- load_fast_iregs - load any fast integer registers -------------------------------------------------*/ inline void adsp21062_device::load_fast_iregs(drcuml_block *block) { int regnum; for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) { if (m_regmap[regnum].is_int_register()) { UML_MOV(block, ireg(m_regmap[regnum].ireg() - REG_I0), mem(&m_core->r[regnum])); } } } /*------------------------------------------------- save_fast_iregs - save any fast integer registers -------------------------------------------------*/ void adsp21062_device::save_fast_iregs(drcuml_block *block) { int regnum; for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) { if (m_regmap[regnum].is_int_register()) { UML_MOV(block, mem(&m_core->r[regnum]), ireg(m_regmap[regnum].ireg() - REG_I0)); } } } void adsp21062_device::static_generate_memory_accessor(MEM_ACCESSOR_TYPE type, const char *name, code_handle *&handleptr) { // I0 = read/write data // I1 = address // I2 is trashed void* block0 = &m_internal_ram_block0[0]; void* block0_1 = &m_internal_ram_block0[1]; void* block0_2 = &m_internal_ram_block0[2]; void* block1 = &m_internal_ram_block1[0]; void* block1_1 = &m_internal_ram_block1[1]; void* block1_2 = &m_internal_ram_block1[2]; code_label label = 1; drcuml_block *block = m_drcuml->begin_block(1024); // add a global entry for this alloc_handle(m_drcuml.get(), &handleptr, name); UML_HANDLE(block, *handleptr); // handle *handleptr switch (type) { case MEM_ACCESSOR_PM_READ48: UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START UML_JMPc(block, COND_B, label); // jb label1 UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END UML_JMPc(block, COND_A, label); // ja label1 // 0x20000 ... 0x27fff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff UML_MULS(block, I1, I1, I1, 3); // muls i1,3 UML_DLOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x2); // dload i0,[block0],i1,word,scale_x2 UML_DSHL(block, I0, I0, 32); // dshl i0,i0,32 UML_DLOAD(block, I2, block0_1, I1, SIZE_WORD, SCALE_x2); // dload i2,[block0_1],i1,word,scale_x2 UML_DSHL(block, I2, I2, 16); // dshl i2,i2,16 UML_DOR(block, I0, I0, I2); // dor i0,i0,i2 UML_DLOAD(block, I2, block0_2, I1, SIZE_WORD, SCALE_x2); // dload i2,[block0_2],i1,word,scale_x2 UML_DOR(block, I0, I0, I2); // dor i0,i0,i2 UML_RET(block); // ret UML_LABEL(block, label++); // label1: UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START UML_JMPc(block, COND_B, label); // jb label2 UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END UML_JMPc(block, COND_A, label); // ja label2 // 0x28000 ... 0x3ffff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff) UML_MULS(block, I1, I1, I1, 3); // muls i1,3 UML_DLOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x2); // dload i0,[block1],i1,word,scale_x2 UML_DSHL(block, I0, I0, 32); // dshl i0,i0,32 UML_DLOAD(block, I2, block1_1, I1, SIZE_WORD, SCALE_x2); // dload i2,[block1_1],i1,word,scale_x2 UML_DSHL(block, I2, I2, 16); // dshl i2,i2,16 UML_DOR(block, I0, I0, I2); // dor i0,i0,i2 UML_DLOAD(block, I2, block1_2, I1, SIZE_WORD, SCALE_x2); // dload i2,[block1_2],i1,word,scale_x2 UML_DOR(block, I0, I0, I2); // dor i0,i0,i2 UML_RET(block); // ret UML_LABEL(block, label++); // label2: break; case MEM_ACCESSOR_PM_WRITE48: UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START UML_JMPc(block, COND_B, label); // jb label1 UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END UML_JMPc(block, COND_A, label); // ja label1 // 0x20000 ... 0x27fff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff UML_MULS(block, I1, I1, I1, 3); // muls i1,3 UML_DSTORE(block, block0_2, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block0_2],i1,i0,word,scale_x2 UML_DSHR(block, I0, I0, 16); // dshr i0,i0,16 UML_DSTORE(block, block0_1, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block0_1],i1,i0,word,scale_x2 UML_DSHR(block, I0, I0, 16); // dshr i0,i0,16 UML_DSTORE(block, block0, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block0],i1,i0,word,scale_x2 UML_MOV(block, mem(&m_core->force_recompile), 1); UML_RET(block); // ret UML_LABEL(block, label++); // label1: UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START UML_JMPc(block, COND_B, label); // jb label2 UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END UML_JMPc(block, COND_A, label); // ja label2 // 0x28000 ... 0x3ffff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff) UML_MULS(block, I1, I1, I1, 3); // muls i1,3 UML_DSTORE(block, block1_2, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block1_2],i1,i0,word,scale_x2 UML_DSHR(block, I0, I0, 16); // dshr i0,i0,16 UML_DSTORE(block, block1_1, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block1_1],i1,i0,word,scale_x2 UML_DSHR(block, I0, I0, 16); // dshr i0,i0,16 UML_DSTORE(block, block1, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block1],i1,i0,word,scale_x2 UML_RET(block); // ret UML_LABEL(block, label++); // label2: break; case MEM_ACCESSOR_PM_READ32: UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START UML_JMPc(block, COND_B, label); // jb label1 UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END UML_JMPc(block, COND_A, label); // ja label1 // 0x20000 ... 0x27fff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff UML_MULS(block, I1, I1, I1, 3); // muls i1,3 UML_LOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x2); // load i0,[block0],i1,word,scale_x2 UML_SHL(block, I0, I0, 16); // shl i0,i0,16 UML_LOAD(block, I2, block0_1, I1, SIZE_WORD, SCALE_x2); // load i2,[block0_1],i1,word,scale_x2 UML_OR(block, I0, I0, I2); // or i0,i0,i2 UML_RET(block); // ret UML_LABEL(block, label++); // label1: UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START UML_JMPc(block, COND_B, label); // jb label2 UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END UML_JMPc(block, COND_A, label); // ja label2 // 0x28000 ... 0x3ffff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff) UML_MULS(block, I1, I1, I1, 3); // muls i1,3 UML_LOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x2); // load i0,[block1],i1,word,scale_x2 UML_SHL(block, I0, I0, 16); // shl i0,i0,16 UML_LOAD(block, I2, block1_1, I1, SIZE_WORD, SCALE_x2); // load i2,[block1_1],i1,word,scale_x2 UML_OR(block, I0, I0, I2); // or i0,i0,i2 UML_RET(block); // ret UML_LABEL(block, label++); // label2: break; case MEM_ACCESSOR_PM_WRITE32: UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START UML_JMPc(block, COND_B, label); // jb label1 UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END UML_JMPc(block, COND_A, label); // ja label1 // 0x20000 ... 0x27fff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff UML_MULS(block, I1, I1, I1, 3); // muls i1,3 UML_STORE(block, block0_1, I1, I0, SIZE_WORD, SCALE_x2); // store [block0_1],i1,i0,word,scale_x2 UML_SHR(block, I0, I0, 16); // shr i0,i0,16 UML_STORE(block, block0, I1, I0, SIZE_WORD, SCALE_x2); // store [block0],i1,i0,word,scale_x2 UML_RET(block); // ret UML_LABEL(block, label++); // label1: UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START UML_JMPc(block, COND_B, label); // jb label2 UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END UML_JMPc(block, COND_A, label); // ja label2 // 0x28000 ... 0x3ffff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff) UML_MULS(block, I1, I1, I1, 3); // muls i1,3 UML_STORE(block, block1_1, I1, I0, SIZE_WORD, SCALE_x2); // store [block1_1],i1,i0,word,scale_x2 UML_SHR(block, I0, I0, 16); // shr i0,i0,16 UML_STORE(block, block1, I1, I0, SIZE_WORD, SCALE_x2); // store [block1],i1,i0,word,scale_x2 UML_RET(block); // ret UML_LABEL(block, label++); // label2: break; case MEM_ACCESSOR_DM_READ32: UML_CMP(block, I1, IRAM_END); // cmp i1,IRAM_END UML_JMPc(block, COND_BE, label); // jbe label1 // 0x80000 ... UML_SHL(block, I1, I1, 2); // shl i1,i1,2 UML_READ(block, I0, I1, SIZE_DWORD, SPACE_DATA); // read i0,i1,dword,SPACE_DATA UML_RET(block); UML_LABEL(block, label++); // label1: UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START UML_JMPc(block, COND_B, label); // jb label2 UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END UML_JMPc(block, COND_A, label); // ja label2 // 0x20000 ... 0x27fff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff UML_LOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x4); // load i0,[block0],i1,word,scale_x4 UML_SHL(block, I0, I0, 16); // shl i0,i0,16 UML_LOAD(block, I2, block0_1, I1, SIZE_WORD, SCALE_x4); // load i2,[block0_1],i1,word,scale_x4 UML_OR(block, I0, I0, I2); // or i0,i0,i2 UML_RET(block); UML_LABEL(block, label++); // label2: UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START UML_JMPc(block, COND_B, label); // jb label3 UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END UML_JMPc(block, COND_A, label); // ja label3 // 0x28000 ... 0x3ffff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff UML_LOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x4); // load i0,[block1],i1,word,scale_x4 UML_SHL(block, I0, I0, 16); // shl i0,i0,16 UML_LOAD(block, I2, block1_1, I1, SIZE_WORD, SCALE_x4); // load i2,[block1_1],i1,word,scale_x4 UML_OR(block, I0, I0, I2); // or i0,i0,i2 UML_RET(block); UML_LABEL(block, label++); // Label3: UML_CMP(block, I1, IOP_REGISTER_END); // cmp i1,IOP_REGISTER_END UML_JMPc(block, COND_A, label); // ja label4 // IOP registers UML_MOV(block, mem(&m_core->arg0), I1); // mov [m_core->arg0],i1 UML_CALLC(block, cfunc_read_iop, this); // callc cfunc_read_iop UML_MOV(block, I0, mem(&m_core->arg1)); // mov i0,[m_core->arg1] UML_RET(block); UML_LABEL(block, label++); // label4: UML_CMP(block, I1, IRAM_SHORT_BLOCK0_START); // cmp i1,IRAM_SHORT_BLOCK0_START UML_JMPc(block, COND_B, label+1); // jb label6 UML_CMP(block, I1, IRAM_SHORT_BLOCK0_END); // cmp i1,IRAM_SHORT_BLOCK0_END UML_JMPc(block, COND_A, label+1); // ja label6 // 0x40000 ... 0x4ffff UML_AND(block, I1, I1, 0xffff); // and i1,i1,0xffff UML_XOR(block, I1, I1, 1); // xor i1,i1,1 UML_TEST(block, mem(&m_core->mode1), 0x4000); // test [m_core->mode1],0x4000 UML_JMPc(block, COND_Z, label); // jz label5 UML_LOADS(block, I0, block0, I1, SIZE_WORD, SCALE_x2); // loads i0,[block0],i1,word,scale_x2 UML_RET(block); UML_LABEL(block, label++); // label5: UML_LOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x2); // load i0,[block0],i1,word,scale_x2 UML_RET(block); UML_LABEL(block, label++); // label6: UML_CMP(block, I1, IRAM_SHORT_BLOCK1_START); // cmp i1,IRAM_SHORT_BLOCK1_START UML_JMPc(block, COND_B, label+1); // jb label8 UML_CMP(block, I1, IRAM_SHORT_BLOCK1_END); // cmp i1,IRAM_SHORT_BLOCK1_END UML_JMPc(block, COND_A, label+1); // ja label8 // 0x50000 ... 0x7ffff UML_AND(block, I1, I1, 0xffff); // and i1,i1,0xffff UML_XOR(block, I1, I1, 1); // xor i1,i1,1 UML_TEST(block, mem(&m_core->mode1), 0x4000); // test [m_core->mode1],0x4000 UML_JMPc(block, COND_Z, label); // jz label7 UML_LOADS(block, I0, block1, I1, SIZE_WORD, SCALE_x2); // loads i0,[block1],i1,word,scale_x2 UML_RET(block); UML_LABEL(block, label++); // label7: UML_LOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x2); // load i0,[block1],i1,word,scale_x2 UML_RET(block); UML_LABEL(block, label++); // label8: break; case MEM_ACCESSOR_DM_WRITE32: #if WRITE_SNOOP //UML_CMP(block, I1, 0x283eb); UML_CMP(block, I1, 0x2400047); UML_JMPc(block, COND_NE, label); UML_MOV(block, mem(&m_core->arg0), I0); UML_MOV(block, mem(&m_core->arg1), I1); UML_MOV(block, mem(&m_core->arg2), mem(&m_core->pc)); UML_CALLC(block, cfunc_write_snoop, this); UML_LABEL(block, label++); #endif UML_CMP(block, I1, IRAM_END); // cmp i1,IRAM_END UML_JMPc(block, COND_BE, label); // jbe label1 // 0x80000 ... UML_SHL(block, I1, I1, 2); // shl i1,i1,2 UML_WRITE(block, I1, I0, SIZE_DWORD, SPACE_DATA); // write i1,i0,dword,SPACE_DATA UML_RET(block); UML_LABEL(block, label++); // label1: UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START UML_JMPc(block, COND_B, label); // jb label2 UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END UML_JMPc(block, COND_A, label); // ja label2 // 0x20000 ... 0x27fff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff UML_STORE(block, block0_1, I1, I0, SIZE_WORD, SCALE_x4); // store [block0_1],i1,i0,word,scale_x4 UML_SHR(block, I0, I0, 16); // shr i0,i0,16 UML_STORE(block, block0, I1, I0, SIZE_WORD, SCALE_x4); // store [block0],i1,i0,word,scale_x4 UML_RET(block); UML_LABEL(block, label++); // label2: UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START UML_JMPc(block, COND_B, label); // jb label3 UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END UML_JMPc(block, COND_A, label); // ja label3 // 0x28000 ... 0x3ffff UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff UML_STORE(block, block1_1, I1, I0, SIZE_WORD, SCALE_x4); // store [block1_1],i1,i0,word,scale_x4 UML_SHR(block, I0, I0, 16); // shr i0,i0,16 UML_STORE(block, block1, I1, I0, SIZE_WORD, SCALE_x4); // store [block1],i1,i0,word,scale_x4 UML_RET(block); UML_LABEL(block, label++); // Label3: UML_CMP(block, I1, IOP_REGISTER_END); // cmp i1,IOP_REGISTER_END UML_JMPc(block, COND_A, label); // ja label4 // IOP registers UML_MOV(block, mem(&m_core->arg0), I1); // mov [m_core->arg0],i1 UML_MOV(block, mem(&m_core->arg1), I0); // mov [m_core->arg1],i0 UML_CALLC(block, cfunc_write_iop, this); // callc cfunc_write_iop UML_RET(block); UML_LABEL(block, label++); // label4: UML_CMP(block, I1, IRAM_SHORT_BLOCK0_START); // cmp i1,IRAM_SHORT_BLOCK0_START UML_JMPc(block, COND_B, label); // jb label5 UML_CMP(block, I1, IRAM_SHORT_BLOCK0_END); // cmp i1,IRAM_SHORT_BLOCK0_END UML_JMPc(block, COND_A, label); // ja label5 // 0x40000 ... 0x4ffff UML_AND(block, I1, I1, 0xffff); // and i1,i1,0xffff UML_XOR(block, I1, I1, 1); // xor i1,i1,1 UML_STORE(block, block0, I1, I0, SIZE_WORD, SCALE_x2); // store [block0],i1,i0,word,scale_x2 UML_RET(block); UML_LABEL(block, label++); // label5: UML_CMP(block, I1, IRAM_SHORT_BLOCK1_START); // cmp i1,IRAM_SHORT_BLOCK1_START UML_JMPc(block, COND_B, label); // jb label6 UML_CMP(block, I1, IRAM_SHORT_BLOCK1_END); // cmp i1,IRAM_SHORT_BLOCK1_END UML_JMPc(block, COND_A, label); // ja label6 // 0x50000 ... 0x7ffff UML_AND(block, I1, I1, 0xffff); // and i1,i1,0xffff UML_XOR(block, I1, I1, 1); // xor i1,i1,1 UML_STORE(block, block1, I1, I0, SIZE_WORD, SCALE_x2); // store [block1],i1,i0,word,scale_x2 UML_RET(block); UML_LABEL(block, label++); // label6: break; } UML_RET(block); block->end(); } void adsp21062_device::static_generate_push_pc() { // Push contents of I0 to PC stack // Trashes I1 code_label label = 1; drcuml_block *block = m_drcuml->begin_block(32); // add a global entry for this alloc_handle(m_drcuml.get(), &m_push_pc, "push_pc"); UML_HANDLE(block, *m_push_pc); // handle *m_push_pc UML_MOV(block, I1, PCSTKP); // mov i1,PCSTKP UML_ADD(block, I1, I1, 1); // add i1,i1,1 UML_CMP(block, I1, 32); // cmp i1,32 UML_JMPc(block, COND_L,label); // jl label1 UML_CALLC(block, cfunc_pcstack_overflow, this); // callc cfunc_pcstack_overflow UML_LABEL(block, label++); // label1: UML_CMP(block, I1, 0); // cmp i1,0 UML_JMPc(block, COND_E, label); // je label2 UML_AND(block, STKY, STKY, ~0x400000); // and STKY,~0x400000 UML_JMP(block, label + 1); // jmp label3 UML_LABEL(block, label++); // label2: UML_OR(block, STKY, STKY, 0x400000); // or STKY,0x400000 UML_LABEL(block, label++); // label3: UML_MOV(block, PCSTK, I0); // mov PCSTK,pc UML_STORE(block, &m_core->pcstack, I1, I0, SIZE_DWORD, SCALE_x4); // store [m_core->pcstack],i1,i0,dword,scale_x4 UML_MOV(block, PCSTKP, I1); // mov PCSTKP,i1 UML_RET(block); block->end(); } void adsp21062_device::static_generate_pop_pc() { // Pop PC stack into I0 // Trashes I1 code_label label = 1; drcuml_block *block = m_drcuml->begin_block(32); // add a global entry for this alloc_handle(m_drcuml.get(), &m_pop_pc, "pop_pc"); UML_HANDLE(block, *m_pop_pc); // handle *m_pop_pc UML_MOV(block, I1, PCSTKP); // mov i0,PCSTKP UML_LOAD(block, I0, &m_core->pcstack, I1, SIZE_DWORD, SCALE_x4); // load i1,[m_core->pcstack],i0,dword,scale_x4 UML_CMP(block, I1, 0); // cmp i1,0 UML_JMPc(block, COND_NE, label); // jne label1 UML_CALLC(block, cfunc_pcstack_underflow, this); // callc cfunc_pcstack_underflow UML_LABEL(block, label++); // label1: UML_SUB(block, I1, I1, 1); // sub i1,i1,1 UML_CMP(block, I1, 0); // cmp i1,0 UML_JMPc(block, COND_E, label); // je label2 UML_AND(block, STKY, STKY, ~0x400000); // and STKY,~0x400000 UML_JMP(block, label + 1); // jmp label3 UML_LABEL(block, label++); // label2: UML_OR(block, STKY, STKY, 0x400000); // or STKY,0x400000 UML_LABEL(block, label++); // label3: UML_MOV(block, PCSTKP, I1); // mov PCSTKP,i1 UML_MOV(block, PCSTK, I0); // mov PCSTK,i0 UML_RET(block); block->end(); } void adsp21062_device::static_generate_push_loop() { // I0 = counter // I1 = type/condition/addr // Trashes I2 code_label label = 1; drcuml_block *block = m_drcuml->begin_block(32); // add a global entry for this alloc_handle(m_drcuml.get(), &m_push_loop, "push_loop"); UML_HANDLE(block, *m_push_loop); // handle *m_push_loop UML_MOV(block, I2, LSTKP); // mov i2,LSTKP UML_ADD(block, I2, I2, 1); // add i2,1 UML_CMP(block, I2, 6); // cmp i2,6 UML_JMPc(block, COND_L, label); // jl label1 UML_CALLC(block, cfunc_loopstack_overflow, this); // callc cfunc_loopstack_overflow UML_LABEL(block, label++); // label1: UML_CMP(block, I2, 0); // cmp i2,0 UML_JMPc(block, COND_E, label); // je label2 UML_AND(block, STKY, STKY, ~0x4000000); // and STKY,~0x4000000 UML_JMP(block, label + 1); // jmp label3 UML_LABEL(block, label++); // label2: UML_OR(block, STKY, STKY, 0x4000000); // or STKY,0x4000000 UML_LABEL(block, label++); // label3: UML_STORE(block, m_core->lcstack, I2, I0, SIZE_DWORD, SCALE_x4); // store m_core->lcstack,i2,i0,dword,scale_x4 UML_STORE(block, m_core->lastack, I2, I1, SIZE_DWORD, SCALE_x4); // store m_core->lastack,i2,i1,dword,scale_x4 UML_MOV(block, CURLCNTR, I0); // mov CURLCNTR,i0 UML_MOV(block, LSTKP, I2); // mov LSTKP,i2 UML_RET(block); block->end(); } void adsp21062_device::static_generate_pop_loop() { // Trashes I0,I2 code_label label = 1; drcuml_block *block = m_drcuml->begin_block(32); // add a global entry for this alloc_handle(m_drcuml.get(), &m_pop_loop, "pop_loop"); UML_HANDLE(block, *m_pop_loop); // handle *m_pop_loop UML_MOV(block, I2, LSTKP); // mov i2,LSTKP UML_CMP(block, I2, 0); // cmp i2,0 UML_JMPc(block, COND_NE, label); // jne label1 UML_CALLC(block, cfunc_loopstack_underflow, this); // callc cfunc_loopstack_underflow UML_LABEL(block, label++); // label1: UML_SUB(block, I2, I2, 1); // sub i2,i2,1 UML_CMP(block, I2, 0); // cmp i2,0 UML_JMPc(block, COND_E, label); // je label2 UML_AND(block, STKY, STKY, ~0x4000000); // and STKY,~0x4000000 UML_JMP(block, label + 1); // jmp label3 UML_LABEL(block, label++); // label2: UML_OR(block, STKY, STKY, 0x4000000); // or STKY,0x4000000 UML_LABEL(block, label++); // label3: UML_LOAD(block, I0, m_core->lcstack, I2, SIZE_DWORD, SCALE_x4); // load i0,m_core->lcstack,i2,dword,scale_x4 UML_MOV(block, CURLCNTR, I0); // mov CURLCNTR,i0 UML_MOV(block, LSTKP, I2); // mov LSTKP,i2 UML_RET(block); block->end(); } void adsp21062_device::static_generate_push_status() { // Trashes I2 code_label label = 1; drcuml_block *block = m_drcuml->begin_block(32); // add a global entry for this alloc_handle(m_drcuml.get(), &m_push_status, "push_status"); UML_HANDLE(block, *m_push_status); // handle *m_push_status UML_MOV(block, I2, mem(&m_core->status_stkp)); // mov i2,[status_stkp] UML_ADD(block, I2, I2, 1); // add i2,1 UML_CMP(block, I2, 5); // cmp i2,5 UML_JMPc(block, COND_L, label); // jl label1 UML_CALLC(block, cfunc_statusstack_overflow, this); // callc cfunc_statusstack_overflow UML_LABEL(block, label++); // label1: UML_CMP(block, I2, 0); // cmp i2,0 UML_JMPc(block, COND_E, label); // je label2 UML_AND(block, STKY, STKY, ~0x1000000); // and STKY,~0x1000000 UML_JMP(block, label + 1); // jmp label3 UML_LABEL(block, label++); // label2: UML_OR(block, STKY, STKY, 0x1000000); // or STKY,0x1000000 UML_LABEL(block, label++); // label3: UML_MOV(block, mem(&m_core->status_stkp), I2); // mov [status_stkp],i2 //TODO: load MODE1 //TODO: load ASTAT UML_RET(block); block->end(); } void adsp21062_device::static_generate_pop_status() { // Trashes I2 code_label label = 1; drcuml_block *block = m_drcuml->begin_block(32); // add a global entry for this alloc_handle(m_drcuml.get(), &m_pop_status, "pop_status"); UML_HANDLE(block, *m_pop_status); // handle *m_pop_status //TODO: store MODE1 //TODO: store ASTAT UML_MOV(block, I2, mem(&m_core->status_stkp)); // mov i2,[status_stkp] UML_CMP(block, I2, 0); // cmp i2,0 UML_JMPc(block, COND_NE, label); // jl label1 UML_CALLC(block, cfunc_statusstack_underflow, this); // callc cfunc_statusstack_underflow UML_LABEL(block, label++); // label1: UML_SUB(block, I2, I2, 1); // sub i2,1 UML_CMP(block, I2, 0); // cmp i2,0 UML_JMPc(block, COND_E, label); // je label2 UML_AND(block, STKY, STKY, ~0x1000000); // and STKY,~0x1000000 UML_JMP(block, label + 1); // jmp label3 UML_LABEL(block, label++); // label2: UML_OR(block, STKY, STKY, 0x1000000); // or STKY,0x1000000 UML_LABEL(block, label++); // label3: UML_MOV(block, mem(&m_core->status_stkp), I2); // mov [status_stkp],i2 UML_RET(block); block->end(); } void adsp21062_device::static_generate_exception(UINT8 exception, const char *name) { code_handle *&exception_handle = m_exception[exception]; code_label label = 1; code_label label_nopush = label++; /* begin generating */ drcuml_block *block = m_drcuml->begin_block(1024); /* add a global entry for this */ alloc_handle(m_drcuml.get(), &exception_handle, name); UML_HANDLE(block, *exception_handle); // handle name UML_AND(block, I3, mem(&m_core->irq_pending), IMASK); // and i3,[irq_pending],IMASK UML_TZCNT(block, I3, I3); // tzcnt i3,i3 UML_MOV(block, I2, 1); // mov i2,1 UML_SHL(block, I2, I2, I3); // shl i2,i2,i3 UML_OR(block, IRPTL, IRPTL, I2); // or IRPTL,i2 UML_XOR(block, mem(&m_core->irq_pending), mem(&m_core->irq_pending), I2); // xor [irq_pending],i2 UML_MOV(block, mem(&m_core->active_irq_num), I3); // mov [active_irq_num],i3 UML_MOV(block, mem(&m_core->interrupt_active), 1); // mov [interrupt_active],1 UML_CALLH(block, *m_push_pc); // callh m_push_pc UML_CMP(block, I3, 6); // cmp i3,6 UML_JMPc(block, COND_L, label_nopush); // jl label_nopush UML_CMP(block, I3, 8); // cmp i3,8 UML_JMPc(block, COND_G, label_nopush); // jg label_nopush UML_CALLH(block, *m_push_status); // callh m_push_status UML_LABEL(block, label_nopush); // label_nopush: UML_SHL(block, I0, I3, 2); // shl i0,i3,2 UML_ADD(block, I0, I0, 0x20000); // add i0,0x20000 UML_HASHJMP(block, 0, I0, *m_nocode); // hashjmp i0,m_nocode block->end(); } void adsp21062_device::static_generate_mode1_ops() { drcuml_block *block; // TODO: these could be further optimized with 64-bit or 128-bit swaps // e.g SWAP128 instruction (swap 128 bits between 2 memory locations) block = m_drcuml->begin_block(128); alloc_handle(m_drcuml.get(), &m_swap_dag1_0_3, "swap_dag1_0_3"); UML_HANDLE(block, *m_swap_dag1_0_3); // handle name #if !USE_SWAPDQ for (int i = 0; i < 4; i++) { UML_MOV(block, I0, mem(&m_core->dag1.i[i])); UML_MOV(block, I1, mem(&m_core->dag1_alt.i[i])); UML_MOV(block, mem(&m_core->dag1.i[i]), I1); UML_MOV(block, mem(&m_core->dag1_alt.i[i]), I0); UML_MOV(block, I0, mem(&m_core->dag1.m[i])); UML_MOV(block, I1, mem(&m_core->dag1_alt.m[i])); UML_MOV(block, mem(&m_core->dag1.m[i]), I1); UML_MOV(block, mem(&m_core->dag1_alt.m[i]), I0); UML_MOV(block, I0, mem(&m_core->dag1.l[i])); UML_MOV(block, I1, mem(&m_core->dag1_alt.l[i])); UML_MOV(block, mem(&m_core->dag1.l[i]), I1); UML_MOV(block, mem(&m_core->dag1_alt.l[i]), I0); UML_MOV(block, I0, mem(&m_core->dag1.b[i])); UML_MOV(block, I1, mem(&m_core->dag1_alt.b[i])); UML_MOV(block, mem(&m_core->dag1.b[i]), I1); UML_MOV(block, mem(&m_core->dag1_alt.b[i]), I0); } #else UML_SWAPDQ(block, mem(&m_core->dag1.i[0]), mem(&m_core->dag1_alt.i[0])); UML_SWAPDQ(block, mem(&m_core->dag1.m[0]), mem(&m_core->dag1_alt.m[0])); UML_SWAPDQ(block, mem(&m_core->dag1.l[0]), mem(&m_core->dag1_alt.l[0])); UML_SWAPDQ(block, mem(&m_core->dag1.b[0]), mem(&m_core->dag1_alt.b[0])); #endif UML_RET(block); block->end(); block = m_drcuml->begin_block(128); alloc_handle(m_drcuml.get(), &m_swap_dag1_4_7, "swap_dag1_4_7"); UML_HANDLE(block, *m_swap_dag1_4_7); // handle name #if !USE_SWAPDQ for (int i = 4; i < 8; i++) { UML_MOV(block, I0, mem(&m_core->dag1.i[i])); UML_MOV(block, I1, mem(&m_core->dag1_alt.i[i])); UML_MOV(block, mem(&m_core->dag1.i[i]), I1); UML_MOV(block, mem(&m_core->dag1_alt.i[i]), I0); UML_MOV(block, I0, mem(&m_core->dag1.m[i])); UML_MOV(block, I1, mem(&m_core->dag1_alt.m[i])); UML_MOV(block, mem(&m_core->dag1.m[i]), I1); UML_MOV(block, mem(&m_core->dag1_alt.m[i]), I0); UML_MOV(block, I0, mem(&m_core->dag1.l[i])); UML_MOV(block, I1, mem(&m_core->dag1_alt.l[i])); UML_MOV(block, mem(&m_core->dag1.l[i]), I1); UML_MOV(block, mem(&m_core->dag1_alt.l[i]), I0); UML_MOV(block, I0, mem(&m_core->dag1.b[i])); UML_MOV(block, I1, mem(&m_core->dag1_alt.b[i])); UML_MOV(block, mem(&m_core->dag1.b[i]), I1); UML_MOV(block, mem(&m_core->dag1_alt.b[i]), I0); } #else UML_SWAPDQ(block, mem(&m_core->dag1.i[4]), mem(&m_core->dag1_alt.i[4])); UML_SWAPDQ(block, mem(&m_core->dag1.m[4]), mem(&m_core->dag1_alt.m[4])); UML_SWAPDQ(block, mem(&m_core->dag1.l[4]), mem(&m_core->dag1_alt.l[4])); UML_SWAPDQ(block, mem(&m_core->dag1.b[4]), mem(&m_core->dag1_alt.b[4])); #endif UML_RET(block); block->end(); block = m_drcuml->begin_block(128); alloc_handle(m_drcuml.get(), &m_swap_dag2_0_3, "swap_dag2_0_3"); UML_HANDLE(block, *m_swap_dag2_0_3); // handle name #if !USE_SWAPDQ for (int i = 0; i < 4; i++) { UML_MOV(block, I0, mem(&m_core->dag2.i[i])); UML_MOV(block, I1, mem(&m_core->dag2_alt.i[i])); UML_MOV(block, mem(&m_core->dag2.i[i]), I1); UML_MOV(block, mem(&m_core->dag2_alt.i[i]), I0); UML_MOV(block, I0, mem(&m_core->dag2.m[i])); UML_MOV(block, I1, mem(&m_core->dag2_alt.m[i])); UML_MOV(block, mem(&m_core->dag2.m[i]), I1); UML_MOV(block, mem(&m_core->dag2_alt.m[i]), I0); UML_MOV(block, I0, mem(&m_core->dag2.l[i])); UML_MOV(block, I1, mem(&m_core->dag2_alt.l[i])); UML_MOV(block, mem(&m_core->dag2.l[i]), I1); UML_MOV(block, mem(&m_core->dag2_alt.l[i]), I0); UML_MOV(block, I0, mem(&m_core->dag2.b[i])); UML_MOV(block, I1, mem(&m_core->dag2_alt.b[i])); UML_MOV(block, mem(&m_core->dag2.b[i]), I1); UML_MOV(block, mem(&m_core->dag2_alt.b[i]), I0); } #else UML_SWAPDQ(block, mem(&m_core->dag2.i[0]), mem(&m_core->dag2_alt.i[0])); UML_SWAPDQ(block, mem(&m_core->dag2.m[0]), mem(&m_core->dag2_alt.m[0])); UML_SWAPDQ(block, mem(&m_core->dag2.l[0]), mem(&m_core->dag2_alt.l[0])); UML_SWAPDQ(block, mem(&m_core->dag2.b[0]), mem(&m_core->dag2_alt.b[0])); #endif UML_RET(block); block->end(); block = m_drcuml->begin_block(128); alloc_handle(m_drcuml.get(), &m_swap_dag2_4_7, "swap_dag2_4_7"); UML_HANDLE(block, *m_swap_dag2_4_7); // handle name #if !USE_SWAPDQ for (int i = 4; i < 8; i++) { UML_MOV(block, I0, mem(&m_core->dag2.i[i])); UML_MOV(block, I1, mem(&m_core->dag2_alt.i[i])); UML_MOV(block, mem(&m_core->dag2.i[i]), I1); UML_MOV(block, mem(&m_core->dag2_alt.i[i]), I0); UML_MOV(block, I0, mem(&m_core->dag2.m[i])); UML_MOV(block, I1, mem(&m_core->dag2_alt.m[i])); UML_MOV(block, mem(&m_core->dag2.m[i]), I1); UML_MOV(block, mem(&m_core->dag2_alt.m[i]), I0); UML_MOV(block, I0, mem(&m_core->dag2.l[i])); UML_MOV(block, I1, mem(&m_core->dag2_alt.l[i])); UML_MOV(block, mem(&m_core->dag2.l[i]), I1); UML_MOV(block, mem(&m_core->dag2_alt.l[i]), I0); UML_MOV(block, I0, mem(&m_core->dag2.b[i])); UML_MOV(block, I1, mem(&m_core->dag2_alt.b[i])); UML_MOV(block, mem(&m_core->dag2.b[i]), I1); UML_MOV(block, mem(&m_core->dag2_alt.b[i]), I0); } #else UML_SWAPDQ(block, mem(&m_core->dag2.i[4]), mem(&m_core->dag2_alt.i[4])); UML_SWAPDQ(block, mem(&m_core->dag2.m[4]), mem(&m_core->dag2_alt.m[4])); UML_SWAPDQ(block, mem(&m_core->dag2.l[4]), mem(&m_core->dag2_alt.l[4])); UML_SWAPDQ(block, mem(&m_core->dag2.b[4]), mem(&m_core->dag2_alt.b[4])); #endif UML_RET(block); block->end(); block = m_drcuml->begin_block(64); alloc_handle(m_drcuml.get(), &m_swap_r0_7, "swap_r0_7"); UML_HANDLE(block, *m_swap_r0_7); // handle name #if !USE_SWAPDQ for (int i = 0; i < 8; i++) { UML_MOV(block, I0, mem(&m_core->r[i])); UML_MOV(block, I1, mem(&m_core->reg_alt[i])); UML_MOV(block, mem(&m_core->r[i]), I1); UML_MOV(block, mem(&m_core->reg_alt[i]), I0); } #else UML_SWAPDQ(block, mem(&m_core->r[0]), mem(&m_core->reg_alt[0])); UML_SWAPDQ(block, mem(&m_core->r[4]), mem(&m_core->reg_alt[4])); #endif UML_RET(block); block->end(); block = m_drcuml->begin_block(64); alloc_handle(m_drcuml.get(), &m_swap_r8_15, "swap_r8_15"); UML_HANDLE(block, *m_swap_r8_15); // handle name #if !USE_SWAPDQ for (int i = 8; i < 16; i++) { UML_MOV(block, I0, mem(&m_core->r[i])); UML_MOV(block, I1, mem(&m_core->reg_alt[i])); UML_MOV(block, mem(&m_core->r[i]), I1); UML_MOV(block, mem(&m_core->reg_alt[i]), I0); } #else UML_SWAPDQ(block, mem(&m_core->r[8]), mem(&m_core->reg_alt[8])); UML_SWAPDQ(block, mem(&m_core->r[12]), mem(&m_core->reg_alt[12])); #endif UML_RET(block); block->end(); } void adsp21062_device::execute_run_drc() { drcuml_state *drcuml = m_drcuml.get(); int execute_result; // if (m_cache_dirty) // printf("SHARC cache reset\n"); /* reset the cache if dirty */ if (m_cache_dirty) flush_cache(); m_cache_dirty = false; m_core->force_recompile = 0; /* execute */ do { execute_result = drcuml->execute(*m_entry); /* if we need to recompile, do it */ if (execute_result == EXECUTE_MISSING_CODE) { compile_block(m_core->pc); } else if (execute_result == EXECUTE_UNMAPPED_CODE) { fatalerror("Attempted to execute unmapped code at PC=%08X\n", m_core->pc); } else if (execute_result == EXECUTE_RESET_CACHE) { flush_cache(); } } while (execute_result != EXECUTE_OUT_OF_CYCLES); } void adsp21062_device::compile_block(offs_t pc) { compiler_state compiler = { 0 }; const opcode_desc *seqhead, *seqlast; const opcode_desc *desclist; bool override = false; drcuml_block *block; desclist = m_drcfe->describe_code(pc); bool succeeded = false; while (!succeeded) { try { block = m_drcuml->begin_block(4096); for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next()) { const opcode_desc *curdesc; UINT32 nextpc; /* 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); // hash mode,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); // hash mode,pc } /* otherwise, redispatch to that fixed PC and skip the rest of the processing */ else { UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc UML_HASHJMP(block, 0, seqhead->pc, *m_nocode); // hashjmp <0>,seqhead->pc,nocode continue; } /* label this instruction, if it may be jumped to locally */ if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET) UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc /* iterate over instructions in the sequence and compile them */ for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next()) generate_sequence_instruction(block, &compiler, curdesc, false); /* if we need to return to the start, do it */ if (seqlast->flags & OPFLAG_RETURN_TO_START) nextpc = pc; /* otherwise we just go to the next instruction */ else nextpc = seqlast->pc + (seqlast->skipslots + 1); // force recompilation at end of block, if needed UML_CMP(block, mem(&m_core->force_recompile), 0); UML_JMPc(block, COND_Z, compiler.labelnum); UML_MOV(block, mem(&m_cache_dirty), 1); UML_MOV(block, mem(&m_core->icount), 0); UML_LABEL(block, compiler.labelnum++); /* count off cycles and go there */ generate_update_cycles(block, &compiler, nextpc, TRUE); // if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc) UML_HASHJMP(block, 0, nextpc, *m_nocode); // hashjmp ,nextpc,nocode } block->end(); succeeded = true; } catch (drcuml_block::abort_compilation &) { flush_cache(); } } } void adsp21062_device::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(); // generate utility functions static_generate_push_pc(); static_generate_pop_pc(); static_generate_push_loop(); static_generate_pop_loop(); static_generate_push_status(); static_generate_pop_status(); static_generate_mode1_ops(); // generate exception handlers static_generate_exception(EXCEPTION_INTERRUPT, "exception_interrupt"); // generate memory accessors static_generate_memory_accessor(MEM_ACCESSOR_PM_READ48, "pm_read48", m_pm_read48); static_generate_memory_accessor(MEM_ACCESSOR_PM_WRITE48, "pm_write48", m_pm_write48); static_generate_memory_accessor(MEM_ACCESSOR_PM_READ32, "pm_read32", m_pm_read32); static_generate_memory_accessor(MEM_ACCESSOR_PM_WRITE32, "pm_write32", m_pm_write32); static_generate_memory_accessor(MEM_ACCESSOR_DM_READ32, "dm_read32", m_dm_read32); static_generate_memory_accessor(MEM_ACCESSOR_DM_WRITE32, "dm_write32", m_dm_write32); } catch (drcuml_block::abort_compilation &) { fatalerror("Error generating SHARC static handlers\n"); } } void adsp21062_device::static_generate_entry_point() { code_label skip = 1; drcuml_block *block; /* begin generating */ block = m_drcuml->begin_block(20); /* forward references */ alloc_handle(m_drcuml.get(), &m_nocode, "nocode"); alloc_handle(m_drcuml.get(), &m_exception[EXCEPTION_INTERRUPT], "exception_interrupt"); alloc_handle(m_drcuml.get(), &m_entry, "entry"); UML_HANDLE(block, *m_entry); // handle entry load_fast_iregs(block); // /* check for interrupts */ UML_CMP(block, mem(&m_core->irq_pending), 0); // cmp [irq_pending],0 UML_JMPc(block, COND_E, skip); // je skip UML_CMP(block, mem(&m_core->interrupt_active), 0); // cmp [interrupt_active],0 UML_JMPc(block, COND_NE, skip); // jne skip UML_TEST(block, mem(&m_core->irq_pending), IMASK); // test [irq_pending],IMASK UML_JMPc(block, COND_Z, skip); // jz skip UML_TEST(block, mem(&m_core->mode1), MODE1_IRPTEN); // test MODE1,MODE1_IRPTEN UML_JMPc(block, COND_Z, skip); // jz skip UML_MOV(block, I0, mem(&m_core->pc)); // mov i0,nextpc UML_MOV(block, I1, 0); // mov i1,0 UML_CALLH(block, *m_exception[EXCEPTION_INTERRUPT]); // callh m_exception[EXCEPTION_INTERRUPT] UML_LABEL(block, skip); /* generate a hash jump via the current mode and PC */ UML_HASHJMP(block, 0, mem(&m_core->pc), *m_nocode); // hashjmp ,,nocode block->end(); } void adsp21062_device::static_generate_nocode_handler() { drcuml_block *block; /* begin generating */ block = m_drcuml->begin_block(10); /* generate a hash jump via the current mode and PC */ alloc_handle(m_drcuml.get(), &m_nocode, "nocode"); UML_HANDLE(block, *m_nocode); // handle nocode UML_GETEXP(block, I0); // getexp i0 UML_MOV(block, mem(&m_core->pc), I0); // mov [pc],i0 save_fast_iregs(block); // UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE block->end(); } void adsp21062_device::static_generate_out_of_cycles() { drcuml_block *block; /* begin generating */ block = m_drcuml->begin_block(10); /* generate a hash jump via the current mode and PC */ alloc_handle(m_drcuml.get(), &m_out_of_cycles, "out_of_cycles"); UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles UML_GETEXP(block, I0); // getexp i0 UML_MOV(block, mem(&m_core->pc), I0); // mov ,i0 save_fast_iregs(block); // UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES block->end(); } void adsp21062_device::generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, bool last_delayslot) { /* add an entry for the log */ // if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) // log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]); /* set the PC map variable */ UML_MAPVAR(block, MAPVAR_PC, desc->pc); // mapvar PC,desc->pc /* accumulate total cycles */ compiler->cycles += desc->cycles; /* update the icount map variable */ UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles /* if we are debugging, call the debugger */ if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) { UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc save_fast_iregs(block); // UML_DEBUG(block, desc->pc); // debug desc->pc } /* if we hit an unmapped address, fatal error */ if (desc->flags & OPFLAG_COMPILER_UNMAPPED) { UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc save_fast_iregs(block); // UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE } // handle a special case where call is used as the last operation in a loop if (desc->userflags & OP_USERFLAG_CALL && desc->userflags & (OP_USERFLAG_COND_LOOP | OP_USERFLAG_COUNTER_LOOP)) { if (desc->userflags & OP_USERFLAG_COUNTER_LOOP) { code_label end = compiler->labelnum++; UML_LOAD(block, I0, m_core->lastack, LSTKP, SIZE_DWORD, SCALE_x4); UML_CMP(block, I0, desc->pc); UML_JMPc(block, COND_NE, end); code_label label_expire = compiler->labelnum++; UML_MOV(block, I1, mem(&m_core->lstkp)); // mov i1,[m_core->lstkp] UML_LOAD(block, I0, m_core->lcstack, I1, SIZE_DWORD, SCALE_x4); // load i0,m_core->lcstack,i1,dword,scale_x4 UML_SUB(block, I0, I0, 1); // sub i0,1 UML_STORE(block, m_core->lcstack, I1, I0, SIZE_DWORD, SCALE_x4); // store m_core->lcstack,i1,i0,dword,scale_x4 UML_SUB(block, CURLCNTR, CURLCNTR, 1); // sub CURLCNTR,1 UML_JMPc(block, COND_E, label_expire); // jne label_expire UML_MOV(block, mem(&m_core->temp_return), desc->userdata0); UML_JMP(block, end); UML_LABEL(block, label_expire); // label_expire: UML_CALLH(block, *m_pop_pc); // callh m_pop_pc UML_CALLH(block, *m_pop_loop); // callh m_pop_loop UML_MOV(block, mem(&m_core->temp_return), desc->pc + 1); UML_LABEL(block, end); } if (desc->userflags & OP_USERFLAG_COND_LOOP) { code_label end = compiler->labelnum++; UML_LOAD(block, I0, m_core->lastack, LSTKP, SIZE_DWORD, SCALE_x4); UML_CMP(block, I0, desc->pc); UML_JMPc(block, COND_NE, end); code_label label_expire = compiler->labelnum++; int condition = (desc->userflags & OP_USERFLAG_COND_FIELD) >> OP_USERFLAG_COND_FIELD_SHIFT; generate_do_condition(block, compiler, desc, condition, label_expire, m_core->astat_delay_copy); UML_MOV(block, mem(&m_core->temp_return), desc->userdata0); UML_JMP(block, end); UML_LABEL(block, label_expire); UML_CALLH(block, *m_pop_pc); UML_CALLH(block, *m_pop_loop); UML_MOV(block, mem(&m_core->temp_return), desc->pc + 1); UML_LABEL(block, end); } } /* if this is an invalid opcode, generate the exception now */ // if (desc->flags & OPFLAG_INVALID_OPCODE) // UML_EXH(block, *m_exception[EXCEPTION_PROGRAM], 0x80000); // exh exception_program,0x80000 /* unless this is a virtual no-op, it's a regular instruction */ if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) { /* compile the instruction */ if (!generate_opcode(block, compiler, desc)) { UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); // dmov [arg64],*desc->opptr.q UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented,ppc } } // insert delayed MODE1 operation if needed if (compiler->mode1_delay.counter > 0) { compiler->mode1_delay.counter--; // delayed operation in the last delay slot needs to be done before the branch is taken if (last_delayslot) compiler->mode1_delay.counter = 0; if (compiler->mode1_delay.counter <= 0) { switch (compiler->mode1_delay.mode) { case MODE1_WRITE_IMM: generate_write_mode1_imm(block, compiler, desc, compiler->mode1_delay.data); break; case MODE1_WRITE_REG: fatalerror("MODE1 delay REG"); break; case MODE1_SET: generate_set_mode1_imm(block, compiler, desc, compiler->mode1_delay.data); break; case MODE1_CLEAR: generate_clear_mode1_imm(block, compiler, desc, compiler->mode1_delay.data); break; case MODE1_TOGGLE: fatalerror("MODE1 delay TOGGLE"); break; } } } // insert loop check at this instruction if needed if (desc->userflags & OP_USERFLAG_COUNTER_LOOP) { code_label label_skip_loop = compiler->labelnum++; UML_LOAD(block, I0, m_core->lastack, LSTKP, SIZE_DWORD, SCALE_x4); UML_CMP(block, I0, desc->pc); UML_JMPc(block, COND_NE, label_skip_loop); code_label label_expire = compiler->labelnum++; UML_MOV(block, I1, mem(&m_core->lstkp)); // mov i1,[m_core->lstkp] UML_LOAD(block, I0, m_core->lcstack, I1, SIZE_DWORD, SCALE_x4); // load i0,m_core->lcstack,i1,dword,scale_x4 UML_SUB(block, I0, I0, 1); // sub i0,1 UML_STORE(block, m_core->lcstack, I1, I0, SIZE_DWORD, SCALE_x4); // store m_core->lcstack,i1,i0,dword,scale_x4 UML_SUB(block, CURLCNTR, CURLCNTR, 1); // sub CURLCNTR,1 UML_JMPc(block, COND_E, label_expire); // jne label_expire generate_loop_jump(block, compiler, desc); UML_LABEL(block, label_expire); // label_expire: UML_CALLH(block, *m_pop_pc); // callh m_pop_pc UML_CALLH(block, *m_pop_loop); // callh m_pop_loop UML_LABEL(block, label_skip_loop); } if (desc->userflags & OP_USERFLAG_COND_LOOP) { code_label label_skip_loop = compiler->labelnum++; UML_LOAD(block, I0, m_core->lastack, LSTKP, SIZE_DWORD, SCALE_x4); UML_CMP(block, I0, desc->pc); UML_JMPc(block, COND_NE, label_skip_loop); code_label label_expire = compiler->labelnum++; int condition = (desc->userflags & OP_USERFLAG_COND_FIELD) >> OP_USERFLAG_COND_FIELD_SHIFT; generate_do_condition(block, compiler, desc, condition, label_expire, m_core->astat_delay_copy); generate_loop_jump(block, compiler, desc); UML_LABEL(block, label_expire); UML_CALLH(block, *m_pop_pc); UML_CALLH(block, *m_pop_loop); UML_LABEL(block, label_skip_loop); } // copy ASTAT bits over for conditional loop if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY) { if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AZ) UML_MOV(block, mem(&m_core->astat_delay_copy.az), mem(&m_core->astat_drc.az)); if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AN) UML_MOV(block, mem(&m_core->astat_delay_copy.an), mem(&m_core->astat_drc.an)); if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AV) UML_MOV(block, mem(&m_core->astat_delay_copy.av), mem(&m_core->astat_drc.av)); if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AC) UML_MOV(block, mem(&m_core->astat_delay_copy.ac), mem(&m_core->astat_drc.ac)); if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_MN) UML_MOV(block, mem(&m_core->astat_delay_copy.mn), mem(&m_core->astat_drc.mn)); if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_MV) UML_MOV(block, mem(&m_core->astat_delay_copy.mv), mem(&m_core->astat_drc.mv)); if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_SV) UML_MOV(block, mem(&m_core->astat_delay_copy.sv), mem(&m_core->astat_drc.sv)); if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_SZ) UML_MOV(block, mem(&m_core->astat_delay_copy.sz), mem(&m_core->astat_drc.sz)); if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_BTF) UML_MOV(block, mem(&m_core->astat_delay_copy.btf), mem(&m_core->astat_drc.btf)); } } void adsp21062_device::generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, int allow_exception) { /* check full interrupts if pending */ if (compiler->checkints) { code_label skip = compiler->labelnum++; compiler->checkints = FALSE; UML_CMP(block, mem(&m_core->irq_pending), 0); // cmp [irq_pending],0 UML_JMPc(block, COND_E, skip); // je skip UML_CMP(block, mem(&m_core->interrupt_active), 0); // cmp [interrupt_active],0 UML_JMPc(block, COND_NE, skip); // jne skip UML_TEST(block, mem(&m_core->irq_pending), IMASK); // test [irq_pending],IMASK UML_JMPc(block, COND_Z, skip); // jz skip UML_TEST(block, mem(&m_core->mode1), MODE1_IRPTEN); // test MODE1,MODE1_IRPTEN UML_JMPc(block, COND_Z, skip); // jz skip UML_MOV(block, I0, param); // mov i0,nextpc UML_MOV(block, I1, compiler->cycles); // mov i1,cycles UML_CALLH(block, *m_exception[EXCEPTION_INTERRUPT]); // callh m_exception[EXCEPTION_INTERRUPT] UML_LABEL(block, skip); } /* account for cycles */ if (compiler->cycles > 0) { UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), MAPVAR_CYCLES); // sub icount,icount,cycles UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0 if (allow_exception) UML_EXHc(block, COND_S, *m_out_of_cycles, param); // exh out_of_cycles,nextpc } compiler->cycles = 0; } void adsp21062_device::generate_write_mode1_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 data) { code_label skip; // TODO: swap effects if (data & 0x1) fatalerror("generate_write_mode1_imm: tried to enable I8 bit reversing"); if (data & 0x2) fatalerror("generate_write_mode1_imm: tried to enable I0 bit reversing"); if (data & 0x4) fatalerror("generate_write_mode1_imm: tried to enable MR alternate"); // DAG1 regs 4-7 skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x8); UML_JMPc(block, (data & 0x8) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same UML_CALLH(block, *m_swap_dag1_4_7); UML_LABEL(block, skip); // DAG1 regs 0-3 skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x10); UML_JMPc(block, (data & 0x10) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same UML_CALLH(block, *m_swap_dag1_0_3); UML_LABEL(block, skip); // DAG2 regs 4-7 skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x20); UML_JMPc(block, (data & 0x20) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same UML_CALLH(block, *m_swap_dag2_4_7); UML_LABEL(block, skip); // DAG2 regs 0-3 skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x40); UML_JMPc(block, (data & 0x40) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same UML_CALLH(block, *m_swap_dag2_0_3); UML_LABEL(block, skip); // REG 8-15 skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x80); UML_JMPc(block, (data & 0x80) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same UML_CALLH(block, *m_swap_r8_15); UML_LABEL(block, skip); // REG 0-7 skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x400); UML_JMPc(block, (data & 0x400) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same UML_CALLH(block, *m_swap_r0_7); UML_LABEL(block, skip); UML_MOV(block, MODE1, data); } void adsp21062_device::generate_set_mode1_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 data) { if (data & 0x1) fatalerror("generate_set_mode1_imm: tried to enable I8 bit reversing"); if (data & 0x2) fatalerror("generate_set_mode1_imm: tried to enable I0 bit reversing"); if (data & 0x4) fatalerror("generate_set_mode1_imm: tried to enable MR alternate"); if (data & 0x8) // DAG1 regs 4-7 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x8); UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 UML_CALLH(block, *m_swap_dag1_4_7); UML_LABEL(block, skip); } if (data & 0x10) // DAG1 regs 0-3 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x10); UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 UML_CALLH(block, *m_swap_dag1_0_3); UML_LABEL(block, skip); } if (data & 0x20) // DAG2 regs 4-7 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x20); UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 UML_CALLH(block, *m_swap_dag2_4_7); UML_LABEL(block, skip); } if (data & 0x40) // DAG1 regs 0-3 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x40); UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 UML_CALLH(block, *m_swap_dag2_0_3); UML_LABEL(block, skip); } if (data & 0x80) // REG 8-15 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x80); UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 UML_CALLH(block, *m_swap_r8_15); UML_LABEL(block, skip); } if (data & 0x400) // REG 0-7 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x400); UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 UML_CALLH(block, *m_swap_r0_7); UML_LABEL(block, skip); } UML_OR(block, MODE1, MODE1, data); } void adsp21062_device::generate_clear_mode1_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 data) { if (data & 0x1) fatalerror("generate_clear_mode1_imm: tried to disable I8 bit reversing"); if (data & 0x2) fatalerror("generate_clear_mode1_imm: tried to disable I0 bit reversing"); if (data & 0x4) fatalerror("generate_clear_mode1_imm: tried to disable MR alternate"); if (data & 0x8) // DAG1 regs 4-7 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x8); UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 UML_CALLH(block, *m_swap_dag1_4_7); UML_LABEL(block, skip); } if (data & 0x10) // DAG1 regs 0-3 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x10); UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 UML_CALLH(block, *m_swap_dag1_0_3); UML_LABEL(block, skip); } if (data & 0x20) // DAG2 regs 4-7 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x20); UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 UML_CALLH(block, *m_swap_dag2_4_7); UML_LABEL(block, skip); } if (data & 0x40) // DAG1 regs 0-3 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x40); UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 UML_CALLH(block, *m_swap_dag2_0_3); UML_LABEL(block, skip); } if (data & 0x80) // REG 8-15 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x80); UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 UML_CALLH(block, *m_swap_r8_15); UML_LABEL(block, skip); } if (data & 0x400) // REG 0-7 { code_label skip = compiler->labelnum++; UML_TEST(block, MODE1, 0x400); UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 UML_CALLH(block, *m_swap_r0_7); UML_LABEL(block, skip); } UML_AND(block, MODE1, MODE1, ~data); } void adsp21062_device::generate_update_circular_buffer(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int g, int i) { if (g) { // PM code_label end = compiler->labelnum++; code_label label2 = compiler->labelnum++; UML_CMP(block, PM_L(i), 0); UML_JMPc(block, COND_E, end); UML_ADD(block, I0, PM_B(i), PM_L(i)); UML_CMP(block, PM_I(i), I0); UML_JMPc(block, COND_LE, label2); UML_SUB(block, PM_I(i), PM_I(i), PM_L(i)); UML_JMP(block, end); UML_LABEL(block, label2); UML_CMP(block, PM_I(i), PM_B(i)); UML_JMPc(block, COND_G, end); UML_ADD(block, PM_I(i), PM_I(i), PM_L(i)); UML_LABEL(block, end); } else { // DM code_label end = compiler->labelnum++; code_label label2 = compiler->labelnum++; UML_CMP(block, DM_L(i), 0); UML_JMPc(block, COND_E, end); UML_ADD(block, I0, DM_B(i), DM_L(i)); UML_CMP(block, DM_I(i), I0); UML_JMPc(block, COND_LE, label2); UML_SUB(block, DM_I(i), DM_I(i), DM_L(i)); UML_JMP(block, end); UML_LABEL(block, label2); UML_CMP(block, DM_I(i), DM_B(i)); UML_JMPc(block, COND_G, end); UML_ADD(block, DM_I(i), DM_I(i), DM_L(i)); UML_LABEL(block, end); } } void adsp21062_device::generate_astat_copy(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) { UML_MOV(block, mem(&m_core->astat_drc_copy.az), ASTAT_AZ); UML_MOV(block, mem(&m_core->astat_drc_copy.av), ASTAT_AV); UML_MOV(block, mem(&m_core->astat_drc_copy.an), ASTAT_AN); UML_MOV(block, mem(&m_core->astat_drc_copy.av), ASTAT_AV); UML_MOV(block, mem(&m_core->astat_drc_copy.as), ASTAT_AS); UML_MOV(block, mem(&m_core->astat_drc_copy.ai), ASTAT_AI); UML_MOV(block, mem(&m_core->astat_drc_copy.af), ASTAT_AF); UML_MOV(block, mem(&m_core->astat_drc_copy.mn), ASTAT_MN); UML_MOV(block, mem(&m_core->astat_drc_copy.mv), ASTAT_MV); UML_MOV(block, mem(&m_core->astat_drc_copy.mu), ASTAT_MU); UML_MOV(block, mem(&m_core->astat_drc_copy.mi), ASTAT_MI); UML_MOV(block, mem(&m_core->astat_drc_copy.sv), ASTAT_SV); UML_MOV(block, mem(&m_core->astat_drc_copy.sz), ASTAT_SZ); UML_MOV(block, mem(&m_core->astat_drc_copy.ss), ASTAT_SS); UML_MOV(block, mem(&m_core->astat_drc_copy.btf), ASTAT_BTF); UML_MOV(block, mem(&m_core->astat_drc_copy.cacc), mem(&m_core->astat_drc.cacc)); } void adsp21062_device::generate_call(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, bool delayslot) { // I0 = target pc for dynamic branches compiler_state compiler_temp = *compiler; // save branch target if (desc->targetpc == BRANCH_TARGET_DYNAMIC) { UML_MOV(block, mem(&m_core->jmpdest), I0); // mov [jmpdest],i0 } // compile delay slots if needed if (delayslot) { generate_sequence_instruction(block, &compiler_temp, desc->delay.first(), false); generate_sequence_instruction(block, &compiler_temp, desc->delay.last(), true); } // if this is the last instruction of a loop, we need to use the return PC from the resolved loop if (desc->userflags & OP_USERFLAG_CALL && desc->userflags & (OP_USERFLAG_COND_LOOP | OP_USERFLAG_COUNTER_LOOP)) { UML_MOV(block, I0, mem(&m_core->temp_return)); } else { if (delayslot) UML_MOV(block, I0, desc->pc + 3); else UML_MOV(block, I0, desc->pc + 1); } UML_CALLH(block, *m_push_pc); // update cycles and hash jump if (desc->targetpc != BRANCH_TARGET_DYNAMIC) { generate_update_cycles(block, &compiler_temp, desc->targetpc, TRUE); if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) UML_JMP(block, desc->targetpc | 0x80000000); // jmp targetpc | 0x80000000 else UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp 0,targetpc,nocode } else { generate_update_cycles(block, &compiler_temp, mem(&m_core->jmpdest), TRUE); UML_HASHJMP(block, 0, mem(&m_core->jmpdest), *m_nocode); // hashjmp 0,jmpdest,nocode } // update compiler label compiler->labelnum = compiler_temp.labelnum; /* reset the mapvar to the current cycles and account for skipped slots */ compiler->cycles += desc->skipslots; UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles } void adsp21062_device::generate_jump(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, bool delayslot, bool loopabort, bool clearint) { // I0 = target pc for dynamic branches compiler_state compiler_temp = *compiler; // save branch target if (desc->targetpc == BRANCH_TARGET_DYNAMIC) { UML_MOV(block, mem(&m_core->jmpdest), I0); // mov [jmpdest],i0 } // compile delay slots if needed if (delayslot) { generate_sequence_instruction(block, &compiler_temp, desc->delay.first(), false); generate_sequence_instruction(block, &compiler_temp, desc->delay.last(), true); } // clear interrupt if (clearint) { code_label skip_pop = compiler_temp.labelnum++; UML_MOV(block, mem(&m_core->interrupt_active), 0); // mov [interrupt_active],0 UML_SHL(block, I1, 1, mem(&m_core->active_irq_num)); // shl i1,1,[active_irq_num] UML_XOR(block, IRPTL, IRPTL, I1); // xor IRPTL,i1 UML_CMP(block, mem(&m_core->status_stkp), 0); // cmp [status_stkp],0 UML_JMPc(block, COND_Z, skip_pop); // jz skip_pop UML_CALLH(block, *m_pop_status); // callh m_pop_status UML_LABEL(block, skip_pop); // skip_pop: } // loop abort if (loopabort) { UML_CALLH(block, *m_pop_pc); UML_CALLH(block, *m_pop_loop); } // update cycles and hash jump if (desc->targetpc != BRANCH_TARGET_DYNAMIC) { generate_update_cycles(block, &compiler_temp, desc->targetpc, TRUE); if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) UML_JMP(block, desc->targetpc | 0x80000000); // jmp targetpc | 0x80000000 else UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp 0,targetpc,nocode } else { generate_update_cycles(block, &compiler_temp, mem(&m_core->jmpdest), TRUE); UML_HASHJMP(block, 0, mem(&m_core->jmpdest), *m_nocode); // hashjmp 0,jmpdest,nocode } // update compiler label compiler->labelnum = compiler_temp.labelnum; /* reset the mapvar to the current cycles and account for skipped slots */ compiler->cycles += desc->skipslots; UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles } void adsp21062_device::generate_loop_jump(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) { // update cycles and hash jump generate_update_cycles(block, compiler, desc->userdata0, TRUE); /* if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) UML_JMP(block, desc->targetpc | 0x80000000); // jmp targetpc | 0x80000000 else UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp 0,targetpc,nocode */ UML_HASHJMP(block, 0, desc->userdata0, *m_nocode); /* reset the mapvar to the current cycles and account for skipped slots */ compiler->cycles += desc->skipslots; UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles } /*------------------------------------------------- generate_write_ureg - UREG is read into I0 -------------------------------------------------*/ void adsp21062_device::generate_read_ureg(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int ureg, bool has_compute) { // UREG is read into I0 switch (ureg) { // REG 0-15 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: UML_MOV(block, I0, REG(ureg & 0xf)); break; // I0-7 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: UML_MOV(block, I0, mem(&m_core->dag1.i[ureg & 7])); break; // I8-15 case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: UML_MOV(block, I0, mem(&m_core->dag2.i[ureg & 7])); break; // M0-7 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: UML_MOV(block, I0, mem(&m_core->dag1.m[ureg & 7])); break; // M8-15 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: UML_MOV(block, I0, mem(&m_core->dag2.m[ureg & 7])); break; // L0-7 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: UML_MOV(block, I0, mem(&m_core->dag1.l[ureg & 7])); break; // L8-15 case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: UML_MOV(block, I0, mem(&m_core->dag2.l[ureg & 7])); break; // B0-7 case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: UML_MOV(block, I0, mem(&m_core->dag1.b[ureg & 7])); break; // B8-15 case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: UML_MOV(block, I0, mem(&m_core->dag2.b[ureg & 7])); break; case 0x64: // PCSTK UML_LOAD(block, I0, &m_core->pcstack, PCSTKP, SIZE_DWORD, SCALE_x4); break; case 0x70: // USTAT1 UML_MOV(block, I0, mem(&m_core->ustat1)); break; case 0x71: // USTAT2 UML_MOV(block, I0, mem(&m_core->ustat2)); break; case 0x79: // IRPTL UML_MOV(block, I0, mem(&m_core->irptl)); break; case 0x7a: // MODE2 UML_MOV(block, I0, mem(&m_core->mode2)); break; case 0x7b: // MODE1 UML_MOV(block, I0, mem(&m_core->mode1)); break; case 0x7c: // ASTAT // construct from bits if (!has_compute) { // no compute, just read normally from ASTAT UML_XOR(block, I0, I0, I0); UML_OR(block, I0, I0, ASTAT_AZ); UML_SHL(block, I1, ASTAT_AV, 1); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_AN, 2); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_AC, 3); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_AS, 4); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_AI, 5); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_MN, 6); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_MV, 7); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_MU, 8); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_MI, 9); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_AF, 10); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_SV, 11); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_SZ, 12); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_SS, 13); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, ASTAT_BTF, 18); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, FLAG0, 19); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, FLAG1, 20); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, FLAG2, 21); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, FLAG3, 22); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc.cacc), 24); UML_OR(block, I0, I0, I1); } else { // read from ASTAT copy if this opcode also does compute UML_XOR(block, I0, I0, I0); UML_OR(block, I0, I0, mem(&m_core->astat_drc_copy.az)); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.av), 1); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.an), 2); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.ac), 3); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.as), 4); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.ai), 5); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.mn), 6); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.mv), 7); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.mu), 8); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.mi), 9); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.af), 10); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.sv), 11); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.sz), 12); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.ss), 13); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.btf), 18); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, FLAG0, 19); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, FLAG1, 20); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, FLAG2, 21); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, FLAG3, 22); UML_OR(block, I0, I0, I1); UML_SHL(block, I1, mem(&m_core->astat_drc_copy.cacc), 24); UML_OR(block, I0, I0, I1); } break; case 0x7d: // IMASK UML_MOV(block, I0, mem(&m_core->imask)); break; case 0x7e: // STKY UML_MOV(block, I0, mem(&m_core->stky)); break; case 0xdb: // PX UML_DMOV(block, I0, mem(&m_core->px)); // NOTE: this returns 64 bits break; case 0xdc: // PX1 (bits 0-15 of PX) UML_MOV(block, I0, mem(&m_core->px)); UML_AND(block, I0, I0, 0xffff); break; case 0xdd: // PX2 (bits 16-47 of PX) UML_DMOV(block, I0, mem(&m_core->px)); UML_DSHR(block, I0, I0, 16); UML_DAND(block, I0, I0, 0xffffffff); break; default: fatalerror("generate_read_ureg %02X", ureg); break; } } /*------------------------------------------------- generate_write_ureg - contents of register I0 or 32-bit immediate data are written into UREG -------------------------------------------------*/ void adsp21062_device::generate_write_ureg(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int ureg, bool imm, UINT32 data) { switch (ureg) { // REG 0-15 case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: UML_MOV(block, REG(ureg & 0xf), imm ? data : I0); break; // I0-7 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: UML_MOV(block, DM_I(ureg & 7), imm ? data : I0); break; // I8-15 case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: UML_MOV(block, PM_I(ureg & 7), imm ? data : I0); break; // M0-7 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: UML_MOV(block, DM_M(ureg & 7), imm ? data : I0); break; // M8-15 case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: UML_MOV(block, PM_M(ureg & 7), imm ? data : I0); break; // L0-7 case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: UML_MOV(block, DM_L(ureg & 7), imm ? data : I0); break; // L8-15 case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: UML_MOV(block, PM_L(ureg & 7), imm ? data : I0); break; // B0-7 case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: // Note: loading B also loads the same value in I UML_MOV(block, DM_B(ureg & 7), imm ? data : I0); UML_MOV(block, DM_I(ureg & 7), imm ? data : I0); break; // B8-15 case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: // Note: loading B also loads the same value in I UML_MOV(block, PM_B(ureg & 7), imm ? data : I0); UML_MOV(block, PM_B(ureg & 7), imm ? data : I0); break; case 0x64: // PCSTK fatalerror("generate_write_ureg: PCSTK"); break; case 0x65: // PCSTKP UML_MOV(block, PCSTKP, imm ? data : I0); break; case 0x67: // CURLCNTR UML_MOV(block, CURLCNTR, imm ? data : I0); break; case 0x68: // LCNTR UML_MOV(block, LCNTR, imm ? data : I0); break; case 0x70: // USTAT1 UML_MOV(block, mem(&m_core->ustat1), imm ? data : I0); break; case 0x71: // USTAT2 UML_MOV(block, mem(&m_core->ustat2), imm ? data : I0); break; case 0x79: // IRPTL UML_MOV(block, mem(&m_core->irptl), imm ? data : I0); break; case 0x7a: // MODE2 UML_MOV(block, mem(&m_core->mode2), imm ? data : I0); break; case 0x7b: // MODE1 // MODE1 needs to be written delayed if (imm) { compiler->mode1_delay.counter = 2; compiler->mode1_delay.data = data; compiler->mode1_delay.mode = MODE1_WRITE_IMM; } else { compiler->mode1_delay.counter = 2; compiler->mode1_delay.mode = MODE1_WRITE_REG; UML_MOV(block, mem(&m_core->mode1_delay_data), I0); } break; case 0x7c: // ASTAT // TODO: needs bit break up fatalerror("generate_write_ureg: ASTAT"); break; case 0x7d: // IMASK UML_MOV(block, mem(&m_core->imask), imm ? data : I0); break; case 0x7e: // STKY UML_MOV(block, mem(&m_core->stky), imm ? data : I0); break; case 0xdb: // PX if (imm) { fatalerror("generate_write_ureg %02X with immediate!", ureg); } else { UML_DMOV(block, mem(&m_core->px), I0); } break; case 0xdc: // PX1 (bits 0-15 of PX) if (imm) { UML_DAND(block, mem(&m_core->px), mem(&m_core->px), ~0xffff); UML_DOR(block, mem(&m_core->px), mem(&m_core->px), (UINT64)(data)); } else { UML_DAND(block, mem(&m_core->px), mem(&m_core->px), ~0xffff); UML_DXOR(block, I1, I1, I1); UML_DAND(block, I1, I0, 0xffff); UML_DOR(block, mem(&m_core->px), mem(&m_core->px), I1); } break; case 0xdd: // PX2 (bits 16-47 of PX) if (imm) { UML_DAND(block, mem(&m_core->px), mem(&m_core->px), 0xffff); UML_DOR(block, mem(&m_core->px), mem(&m_core->px), (UINT64)(data) << 16); } else { UML_DAND(block, mem(&m_core->px), mem(&m_core->px), 0xffff); UML_DSHL(block, I0, I0, 16); UML_DOR(block, mem(&m_core->px), mem(&m_core->px), I0); } break; default: fatalerror("generate_write_ureg %02X", ureg); break; } } int adsp21062_device::generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) { UINT64 opcode = desc->opptr.q[0]; switch ((opcode >> 45) & 7) { case 0: // subops { UINT32 subop = (opcode >> 40) & 0x1f; switch (subop) { case 0x00: // NOP / idle |000|00000| if (opcode & U64(0x008000000000)) { // IDLE UML_MOV(block, mem(&m_core->idle), 1); UML_MOV(block, mem(&m_core->icount), 0); return TRUE; } else { // NOP return TRUE; } break; case 0x01: // compute |000|00001| { int cond = (opcode >> 33) & 0x1f; bool has_condition = !if_condition_always_true(cond); int skip_label = 0; if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } generate_compute(block, compiler, desc); if (has_condition) UML_LABEL(block, skip_label); return TRUE; } case 0x02: // immediate shift |000|00010| { int shiftop = (opcode >> 16) & 0x3f; int rn = (opcode >> 4) & 0xf; int rx = (opcode & 0xf); int cond = (opcode >> 33) & 0x1f; int data = ((opcode >> 8) & 0xff) | ((opcode >> 19) & 0xf00); bool has_condition = !if_condition_always_true(cond); int skip_label = 0; if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } generate_shift_imm(block, compiler, desc, data, shiftop, rn, rx); if (has_condition) UML_LABEL(block, skip_label); return TRUE; } case 0x04: // compute / modify |000|00100| { int cond = (opcode >> 33) & 0x1f; int g = (opcode >> 38) & 0x1; int m = (opcode >> 27) & 0x7; int i = (opcode >> 30) & 0x7; bool has_condition = !if_condition_always_true(cond); int skip_label = 0; if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } generate_compute(block, compiler, desc); if (g) { // PM UML_ADD(block, PM_I(i), PM_I(i), PM_M(m)); } else { // DM UML_ADD(block, DM_I(i), DM_I(i), DM_M(m)); } generate_update_circular_buffer(block, compiler, desc, g, i); if (has_condition) UML_LABEL(block, skip_label); return TRUE; } case 0x06: // direct jump|call |000|00110| { int b = (opcode >> 39) & 0x1; int j = (opcode >> 26) & 0x1; int la = (opcode >> 38) & 0x1; int ci = (opcode >> 24) & 0x1; int cond = (opcode >> 33) & 0x1f; bool has_condition = !if_condition_always_true(cond); int skip_label = 0; if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } if (b) // call { generate_call(block, compiler, desc, j != 0); } else // jump { generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); } if (has_condition) UML_LABEL(block, skip_label); return TRUE; } case 0x07: // direct jump|call |000|00111| { int b = (opcode >> 39) & 0x1; int j = (opcode >> 26) & 0x1; int la = (opcode >> 38) & 0x1; int ci = (opcode >> 24) & 0x1; int cond = (opcode >> 33) & 0x1f; bool has_condition = !if_condition_always_true(cond); int skip_label = 0; if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } if (b) // call { generate_call(block, compiler, desc, j != 0); } else // jump { generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); } if (has_condition) UML_LABEL(block, skip_label); return TRUE; } case 0x08: // indirect jump|call / compute |000|01000| { int la = (opcode >> 38) & 0x1; int ci = (opcode >> 24) & 0x1; int b = (opcode >> 39) & 0x1; int j = (opcode >> 26) & 0x1; int e = (opcode >> 25) & 0x1; int pmi = (opcode >> 30) & 0x7; int pmm = (opcode >> 27) & 0x7; int cond = (opcode >> 33) & 0x1f; if (e) { // IF ... ELSE int label_else = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, label_else); UML_ADD(block, I0, PM_I(pmi), PM_M(pmm)); if (b) // call { generate_call(block, compiler, desc, j != 0); } else // jump { generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); } UML_LABEL(block, label_else); generate_compute(block, compiler, desc); } else { // IF bool has_condition = !if_condition_always_true(cond); int skip_label = 0; if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } generate_compute(block, compiler, desc); UML_ADD(block, I0, PM_I(pmi), PM_M(pmm)); if (b) // call { generate_call(block, compiler, desc, j != 0); } else // jump { generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); } if (has_condition) UML_LABEL(block, skip_label); } return TRUE; } case 0x09: // indirect jump|call / compute |000|01001| { int la = (opcode >> 38) & 0x1; int ci = (opcode >> 24) & 0x1; int b = (opcode >> 39) & 0x1; int j = (opcode >> 26) & 0x1; int e = (opcode >> 25) & 0x1; int cond = (opcode >> 33) & 0x1f; if (e) { // IF ... ELSE int label_else = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, label_else); if (b) // call { generate_call(block, compiler, desc, j != 0); } else // jump { generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); } UML_LABEL(block, label_else); generate_compute(block, compiler, desc); } else { // IF bool has_condition = !if_condition_always_true(cond); int skip_label = 0; if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } generate_compute(block, compiler, desc); if (b) // call { generate_call(block, compiler, desc, j != 0); } else // jump { generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); } if (has_condition) UML_LABEL(block, skip_label); } return TRUE; } case 0x0a: // return from subroutine / compute |000|01010| { int cond = (opcode >> 33) & 0x1f; int j = (opcode >> 26) & 0x1; int e = (opcode >> 25) & 0x1; //int lr = (opcode >> 24) & 0x1; // TODO: loop re-entry if (e) { // IF ... ELSE int label_else = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, label_else); UML_CALLH(block, *m_pop_pc); generate_jump(block, compiler, desc, j != 0, false, false); UML_LABEL(block, label_else); generate_compute(block, compiler, desc); } else { // IF bool has_condition = !if_condition_always_true(cond); int skip_label = 0; if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } generate_compute(block, compiler, desc); UML_CALLH(block, *m_pop_pc); generate_jump(block, compiler, desc, j != 0, false, false); if (has_condition) UML_LABEL(block, skip_label); } return TRUE; } case 0x0b: // return from interrupt / compute |000|01011| { int cond = (opcode >> 33) & 0x1f; int j = (opcode >> 26) & 0x1; int e = (opcode >> 25) & 0x1; code_label skip_pop = compiler->labelnum++; UML_MOV(block, mem(&m_core->interrupt_active), 0); // mov [interrupt_active],0 UML_MOV(block, I0, 1); // mov i0,1 UML_SHL(block, I0, I0, mem(&m_core->active_irq_num)); // shl i0,[active_irq_num] UML_XOR(block, IRPTL, IRPTL, I0); // xor IRPTL,i0 UML_CMP(block, mem(&m_core->status_stkp), 0); // cmp [status_stkp],0 UML_JMPc(block, COND_Z, skip_pop); // jz skip_pop UML_CALLH(block, *m_pop_status); // callh m_pop_status UML_LABEL(block, skip_pop); // skip_pop: // TODO: check interrupts if (e) { // IF ... ELSE code_label label_else = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, label_else); UML_CALLH(block, *m_pop_pc); generate_jump(block, compiler, desc, j != 0, false, false); UML_LABEL(block, label_else); generate_compute(block, compiler, desc); } else { // IF bool has_condition = !if_condition_always_true(cond); code_label skip_label = 0; if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } generate_compute(block, compiler, desc); UML_CALLH(block, *m_pop_pc); generate_jump(block, compiler, desc, j != 0, false, false); if (has_condition) UML_LABEL(block, skip_label); } return TRUE; } case 0x0c: // do until counter expired |000|01100| { UINT16 data = (UINT16)(opcode >> 24); int offset = SIGN_EXTEND24(opcode & 0xffffff); UINT32 address = desc->pc + offset; UML_MOV(block, LCNTR, data); if (data > 0) { // push pc UML_MOV(block, I0, desc->pc + 1); UML_CALLH(block, *m_push_pc); // push loop UML_MOV(block, I0, data); UML_MOV(block, I1, address); UML_CALLH(block, *m_push_loop); } return TRUE; } case 0x0d: // do until counter expired |000|01101| { int ureg = (opcode >> 32) & 0xff; int offset = SIGN_EXTEND24(opcode & 0xffffff); UINT32 address = desc->pc + offset; generate_read_ureg(block, compiler, desc, ureg, false); UML_MOV(block, I3, I0); UML_MOV(block, LCNTR, I3); // push pc UML_MOV(block, I0, desc->pc + 1); UML_CALLH(block, *m_push_pc); // push loop UML_MOV(block, I0, I3); UML_MOV(block, I1, address); UML_CALLH(block, *m_push_loop); return TRUE; } case 0x0e: // do until |000|01110| { int offset = SIGN_EXTEND24(opcode & 0xffffff); UINT32 address = desc->pc + offset; // push pc UML_MOV(block, I0, desc->pc + 1); UML_CALLH(block, *m_push_pc); // push loop UML_MOV(block, I0, 0); UML_MOV(block, I1, address); UML_CALLH(block, *m_push_loop); return TRUE; } case 0x0f: // immediate data -> ureg |000|01111| { int ureg = (opcode >> 32) & 0xff; UINT32 data = (UINT32)opcode; generate_write_ureg(block, compiler, desc, ureg, true, data); return TRUE; } case 0x10: // ureg <-> DM|PM (direct) |000|100|G|D| case 0x11: case 0x12: case 0x13: { int ureg = (opcode >> 32) & 0xff; UINT32 address = (UINT32)(opcode); int d = (opcode >> 40) & 1; int g = (opcode >> 41) & 1; UML_MOV(block, I1, address); if (d) { generate_read_ureg(block, compiler, desc, ureg, false); // write if (g) { // PM if (ureg == 0xdb) // PX is 48-bit UML_CALLH(block, *m_pm_write48); else UML_CALLH(block, *m_pm_write32); } else { // DM UML_CALLH(block, *m_dm_write32); } } else { // read if (g) { // PM if (ureg == 0xdb) // PX is 48-bit UML_CALLH(block, *m_pm_read48); else UML_CALLH(block, *m_pm_read32); } else { // DM UML_CALLH(block, *m_dm_read32); } generate_write_ureg(block, compiler, desc, ureg, false, 0); } return TRUE; } case 0x14: // system register bit manipulation |000|10100| { int bop = (opcode >> 37) & 0x7; int sreg = (opcode >> 32) & 0xf; UINT32 data = (UINT32)opcode; switch (bop) { case 0: // SET { switch (sreg) { case 0x0: // USTAT1 UML_OR(block, USTAT1, USTAT1, data); break; case 0x1: // USTAT2 UML_OR(block, USTAT2, USTAT2, data); break; case 0x9: // IRPTL UML_OR(block, IRPTL, IRPTL, data); break; case 0xa: // MODE2 UML_OR(block, MODE2, MODE2, data); break; case 0xb: // MODE1 compiler->mode1_delay.counter = 2; compiler->mode1_delay.data = data; compiler->mode1_delay.mode = MODE1_SET; break; case 0xc: // ASTAT // TODO: does this need delay? if (data & ASTAT_FLAGS::AZ) UML_MOV(block, ASTAT_AZ, 1); if (data & ASTAT_FLAGS::AV) UML_MOV(block, ASTAT_AV, 1); if (data & ASTAT_FLAGS::AN) UML_MOV(block, ASTAT_AN, 1); if (data & ASTAT_FLAGS::AC) UML_MOV(block, ASTAT_AC, 1); if (data & ASTAT_FLAGS::AS) UML_MOV(block, ASTAT_AS, 1); if (data & ASTAT_FLAGS::AI) UML_MOV(block, ASTAT_AI, 1); if (data & ASTAT_FLAGS::MN) UML_MOV(block, ASTAT_MN, 1); if (data & ASTAT_FLAGS::MV) UML_MOV(block, ASTAT_MV, 1); if (data & ASTAT_FLAGS::MU) UML_MOV(block, ASTAT_MU, 1); if (data & ASTAT_FLAGS::MI) UML_MOV(block, ASTAT_MI, 1); if (data & ASTAT_FLAGS::AF) UML_MOV(block, ASTAT_AF, 1); if (data & ASTAT_FLAGS::SV) UML_MOV(block, ASTAT_SV, 1); if (data & ASTAT_FLAGS::SZ) UML_MOV(block, ASTAT_SZ, 1); if (data & ASTAT_FLAGS::SS) UML_MOV(block, ASTAT_SS, 1); if (data & ASTAT_FLAGS::BTF) UML_MOV(block, ASTAT_BTF, 1); if (data & ASTAT_FLAGS::FLG0) UML_MOV(block, FLAG0, 1); if (data & ASTAT_FLAGS::FLG1) UML_MOV(block, FLAG1, 1); if (data & ASTAT_FLAGS::FLG2) UML_MOV(block, FLAG2, 1); if (data & ASTAT_FLAGS::FLG3) UML_MOV(block, FLAG3, 1); if (data & 0xff000000) { UML_OR(block, mem(&m_core->astat_drc.cacc), mem(&m_core->astat_drc.cacc), (data >> 24)); } break; case 0xd: // IMASK UML_OR(block, IMASK, IMASK, data); break; case 0xe: // STKY UML_OR(block, STKY, STKY, data); break; case 0xf: // IMASKP UML_OR(block, IMASKP, IMASKP, data); break; default: return FALSE; } return TRUE; } case 1: // CLEAR { switch (sreg) { case 0x0: // USTAT1 UML_AND(block, USTAT1, USTAT1, ~data); break; case 0x1: // USTAT2 UML_AND(block, USTAT2, USTAT2, ~data); break; case 0x9: // IRPTL UML_AND(block, IRPTL, IRPTL, ~data); break; case 0xa: // MODE2 UML_AND(block, MODE2, MODE2, ~data); break; case 0xb: // MODE1 compiler->mode1_delay.counter = 2; compiler->mode1_delay.data = data; compiler->mode1_delay.mode = MODE1_CLEAR; break; case 0xc: // ASTAT // TODO: does this need delay? if (data & ASTAT_FLAGS::AZ) UML_MOV(block, ASTAT_AZ, 0); if (data & ASTAT_FLAGS::AV) UML_MOV(block, ASTAT_AV, 0); if (data & ASTAT_FLAGS::AN) UML_MOV(block, ASTAT_AN, 0); if (data & ASTAT_FLAGS::AC) UML_MOV(block, ASTAT_AC, 0); if (data & ASTAT_FLAGS::AS) UML_MOV(block, ASTAT_AS, 0); if (data & ASTAT_FLAGS::AI) UML_MOV(block, ASTAT_AI, 0); if (data & ASTAT_FLAGS::MN) UML_MOV(block, ASTAT_MN, 0); if (data & ASTAT_FLAGS::MV) UML_MOV(block, ASTAT_MV, 0); if (data & ASTAT_FLAGS::MU) UML_MOV(block, ASTAT_MU, 0); if (data & ASTAT_FLAGS::MI) UML_MOV(block, ASTAT_MI, 0); if (data & ASTAT_FLAGS::AF) UML_MOV(block, ASTAT_AF, 0); if (data & ASTAT_FLAGS::SV) UML_MOV(block, ASTAT_SV, 0); if (data & ASTAT_FLAGS::SZ) UML_MOV(block, ASTAT_SZ, 0); if (data & ASTAT_FLAGS::SS) UML_MOV(block, ASTAT_SS, 0); if (data & ASTAT_FLAGS::BTF) UML_MOV(block, ASTAT_BTF, 0); if (data & ASTAT_FLAGS::FLG0) UML_MOV(block, FLAG0, 0); if (data & ASTAT_FLAGS::FLG1) UML_MOV(block, FLAG1, 0); if (data & ASTAT_FLAGS::FLG2) UML_MOV(block, FLAG2, 0); if (data & ASTAT_FLAGS::FLG3) UML_MOV(block, FLAG3, 0); if (data & 0xff000000) { UML_AND(block, mem(&m_core->astat_drc.cacc), mem(&m_core->astat_drc.cacc), ~(data >> 24)); } break; case 0xd: // IMASK UML_AND(block, IMASK, IMASK, ~data); break; case 0xe: // STKY UML_AND(block, STKY, STKY, ~data); break; case 0xf: // IMASKP UML_AND(block, IMASKP, IMASKP, ~data); break; default: return FALSE; } return TRUE; } case 2: // TOGGLE { switch (sreg) { case 0x0: // USTAT1 UML_XOR(block, USTAT1, USTAT1, data); break; case 0x1: // USTAT2 UML_XOR(block, USTAT2, USTAT2, data); break; case 0x9: // IRPTL UML_XOR(block, IRPTL, IRPTL, data); break; case 0xa: // MODE2 UML_XOR(block, MODE2, MODE2, data); break; case 0xb: // MODE1 compiler->mode1_delay.counter = 2; compiler->mode1_delay.data = data; compiler->mode1_delay.mode = MODE1_TOGGLE; break; case 0xc: // ASTAT return FALSE; case 0xd: // IMASK UML_XOR(block, IMASK, IMASK, data); break; case 0xe: // STKY UML_XOR(block, STKY, STKY, data); break; case 0xf: // IMASKP UML_XOR(block, IMASKP, IMASKP, data); break; default: return FALSE; } return TRUE; } case 4: // TEST { switch (sreg) { case 0x0: // USTAT1 UML_AND(block, I0, USTAT1, data); UML_CMP(block, I0, data); UML_SETc(block, COND_E, ASTAT_BTF); break; case 0x1: // USTAT2 UML_AND(block, I0, USTAT2, data); UML_CMP(block, I0, data); UML_SETc(block, COND_E, ASTAT_BTF); break; case 0x9: // IRPTL UML_AND(block, I0, IRPTL, data); UML_CMP(block, I0, data); UML_SETc(block, COND_E, ASTAT_BTF); break; case 0xa: // MODE2 UML_AND(block, I0, MODE2, data); UML_CMP(block, I0, data); UML_SETc(block, COND_E, ASTAT_BTF); break; case 0xb: // MODE1 UML_AND(block, I0, MODE1, data); UML_CMP(block, I0, data); UML_SETc(block, COND_E, ASTAT_BTF); break; case 0xc: // ASTAT return FALSE; case 0xd: // IMASK UML_AND(block, I0, IMASK, data); UML_CMP(block, I0, data); UML_SETc(block, COND_E, ASTAT_BTF); break; case 0xe: // STKY UML_AND(block, I0, STKY, data); UML_CMP(block, I0, data); UML_SETc(block, COND_E, ASTAT_BTF); break; case 0xf: // IMASKP UML_AND(block, I0, IMASKP, data); UML_CMP(block, I0, data); UML_SETc(block, COND_E, ASTAT_BTF); break; default: return FALSE; } return TRUE; } case 5: // XOR { return FALSE; } default: return FALSE; } return TRUE; } case 0x16: // I register modify / bit-reverse |000|10110| { if (opcode & U64(0x008000000000)) // bit reverse { return FALSE; } else // modify { int g = (opcode >> 38) & 0x1; int i = (opcode >> 32) & 0x7; INT32 data = (INT32)(opcode); if (g) { // PM UML_ADD(block, PM_I(i), PM_I(i), data); } else { // DM UML_ADD(block, DM_I(i), DM_I(i), data); } generate_update_circular_buffer(block, compiler, desc, g, i); return TRUE; } } case 0x17: // push|pop stacks / flush cache |000|10111| { if (opcode & U64(0x008000000000)) { fatalerror("sharcdrc: push/pop stacks: push loop not implemented\n"); } if (opcode & U64(0x004000000000)) { fatalerror("sharcdrc: push/pop stacks: pop loop not implemented\n"); } if (opcode & U64(0x002000000000)) { UML_CALLH(block, *m_push_status); } if (opcode & U64(0x001000000000)) { UML_CALLH(block, *m_pop_status); } if (opcode & U64(0x000800000000)) { UML_MOV(block, I0, PCSTK); UML_CALLH(block, *m_push_pc); } if (opcode & U64(0x000400000000)) { UML_CALLH(block, *m_pop_pc); } return TRUE; } case 0x18: // cjump |000|11000| return FALSE; case 0x19: // rframe |000|11001| return FALSE; default: return FALSE; } break; } case 1: // compute / dreg <-> DM / dreg <-> PM |001| { int pm_dreg = (opcode >> 23) & 0xf; int pmm = (opcode >> 27) & 0x7; int pmi = (opcode >> 30) & 0x7; int dm_dreg = (opcode >> 33) & 0xf; int dmm = (opcode >> 38) & 0x7; int dmi = (opcode >> 41) & 0x7; int pmd = (opcode >> 37) & 0x1; int dmd = (opcode >> 44) & 0x1; int compute = opcode & 0x7fffff; bool temp_pm_dreg = false; if (compute != 0 && pmd && desc->regout[0] & (1 << pm_dreg)) { UML_MOV(block, mem(&m_core->dreg_temp), REG(pm_dreg)); temp_pm_dreg = true; } bool temp_dm_dreg = false; if (compute != 0 && dmd && desc->regout[0] & (1 << dm_dreg)) { UML_MOV(block, mem(&m_core->dreg_temp2), REG(dm_dreg)); temp_dm_dreg = true; } generate_compute(block, compiler, desc); // PM transfer if (pmd) { // dreg -> PM if (temp_pm_dreg) UML_MOV(block, I0, mem(&m_core->dreg_temp)); else UML_MOV(block, I0, REG(pm_dreg)); UML_MOV(block, I1, PM_I(pmi)); UML_CALLH(block, *m_pm_write32); UML_ADD(block, PM_I(pmi), PM_I(pmi), PM_M(pmm)); generate_update_circular_buffer(block, compiler, desc, 1, pmi); } else { // PM -> dreg UML_MOV(block, I1, PM_I(pmi)); UML_CALLH(block, *m_pm_read32); UML_MOV(block, REG(pm_dreg), I0); UML_ADD(block, PM_I(pmi), PM_I(pmi), PM_M(pmm)); generate_update_circular_buffer(block, compiler, desc, 1, pmi); } // DM transfer if (dmd) { // dreg -> DM if (temp_dm_dreg) UML_MOV(block, I0, mem(&m_core->dreg_temp2)); else UML_MOV(block, I0, REG(dm_dreg)); UML_MOV(block, I1, DM_I(dmi)); UML_CALLH(block, *m_dm_write32); UML_ADD(block, DM_I(dmi), DM_I(dmi), DM_M(dmm)); generate_update_circular_buffer(block, compiler, desc, 0, dmi); } else { // DM -> dreg UML_MOV(block, I1, DM_I(dmi)); UML_CALLH(block, *m_dm_read32); UML_MOV(block, REG(dm_dreg), I0); UML_ADD(block, DM_I(dmi), DM_I(dmi), DM_M(dmm)); generate_update_circular_buffer(block, compiler, desc, 0, dmi); } return TRUE; } case 2: // compute / ureg <-> DM|PM, register modify |010| { int u = (opcode >> 44) & 0x1; int i = (opcode >> 41) & 0x7; int m = (opcode >> 38) & 0x7; int cond = (opcode >> 33) & 0x1f; int g = (opcode >> 32) & 0x1; int d = (opcode >> 31) & 0x1; int ureg = (opcode >> 23) & 0xff; int compute = opcode & 0x7fffff; bool ureg_is_dreg = (ureg >= 0 && ureg < 16); bool has_condition = !if_condition_always_true(cond); int skip_label = 0; bool ureg_is_astat = (ureg == 0x7c); if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } if (d) { // UREG -> DM|PM bool temp_ureg = false; // save UREG if compute writes to it if (compute != 0 && ureg_is_dreg && desc->regout[0] & (1 << (ureg & 0xf))) { UML_MOV(block, mem(&m_core->dreg_temp), REG(ureg & 0xf)); temp_ureg = true; } // save a copy of ASTAT if we need to read it if (ureg_is_astat) generate_astat_copy(block, compiler, desc); // compute generate_compute(block, compiler, desc); // transfer UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] if (u == 0) // pre-modify without update UML_ADD(block, I1, I1, (g) ? PM_M(m) : DM_M(m)); // add i1,i1,dm|pm[m] if (temp_ureg) UML_MOV(block, I0, mem(&m_core->dreg_temp)); // mov i0,[m_core->dreg_temp] else generate_read_ureg(block, compiler, desc, ureg, ureg_is_astat); if (ureg == 0xdb && (g)) // PX is 48-bit when writing to PM UML_CALLH(block, *m_pm_write48); // callh pm_write48 else UML_CALLH(block, (g) ? *m_pm_write32 : *m_dm_write32); // callh dm|pm_write32 } else { // DM|PM -> UREG // compute generate_compute(block, compiler, desc); // transfer UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] if (u == 0) // pre-modify without update UML_ADD(block, I1, I1, (g) ? PM_M(m) : DM_M(m)); // add i1,i1,dm|pm[m] if (ureg == 0xdb && (g)) // PX is 48-bit when reading from PM UML_CALLH(block, *m_pm_read48); // callh pm_read48 else UML_CALLH(block, (g) ? *m_pm_read32 : *m_dm_read32); // callh dm|pm_read32 generate_write_ureg(block, compiler, desc, ureg, false, 0); } if (u != 0) // post-modify with update { if (g) UML_ADD(block, PM_I(i), PM_I(i), PM_M(m)); // add pm[i],pm[m] else UML_ADD(block, DM_I(i), DM_I(i), DM_M(m)); // add dm[i],dm[m] generate_update_circular_buffer(block, compiler, desc, g, i); } if (has_condition) UML_LABEL(block, skip_label); return TRUE; } case 3: { if (opcode & U64(0x100000000000)) // compute / ureg <-> ureg |011|1| { int src_ureg = (opcode >> 36) & 0xff; int dst_ureg = (opcode >> 23) & 0xff; int cond = (opcode >> 31) & 0x1f; int compute = opcode & 0x7fffff; bool has_condition = !if_condition_always_true(cond); bool src_is_dreg = (src_ureg >= 0 && src_ureg < 16); int skip_label = 0; bool src_ureg_is_astat = (src_ureg == 0x7c); if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } bool temp_ureg = false; // save UREG if compute writes to it if (compute != 0 && src_is_dreg && desc->regout[0] & (1 << (src_ureg & 0xf))) { UML_MOV(block, mem(&m_core->dreg_temp), REG(src_ureg & 0xf)); temp_ureg = true; } // save a copy of ASTAT if we need to read it if (src_ureg_is_astat) generate_astat_copy(block, compiler, desc); generate_compute(block, compiler, desc); if (temp_ureg) { UML_MOV(block, I0, mem(&m_core->dreg_temp)); } else { generate_read_ureg(block, compiler, desc, src_ureg, src_ureg_is_astat); } generate_write_ureg(block, compiler, desc, dst_ureg, false, 0); if (has_condition) UML_LABEL(block, skip_label); return TRUE; } else // compute / dreg <-> DM|PM, immediate modify |011|0| { int cond = (opcode >> 33) & 0x1f; int u = (opcode >> 38) & 0x1; int d = (opcode >> 39) & 0x1; int g = (opcode >> 40) & 0x1; int dreg = (opcode >> 23) & 0xf; int i = (opcode >> 41) & 0x7; int mod = SIGN_EXTEND6((opcode >> 27) & 0x3f); int compute = opcode & 0x7fffff; bool has_condition = !if_condition_always_true(cond); int skip_label = 0; if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } if (d) { // DREG -> DM|PM bool temp_dreg = false; // save dreg if compute writes to it if (compute != 0 && desc->regout[0] & (1 << dreg)) { UML_MOV(block, mem(&m_core->dreg_temp), REG(dreg)); temp_dreg = true; } // compute generate_compute(block, compiler, desc); // transfer UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] if (u == 0) // pre-modify without update UML_ADD(block, I1, I1, mod); // add i1,i1,mod if (temp_dreg) UML_MOV(block, I0, mem(&m_core->dreg_temp)); // mov i0,[m_core->dreg_temp] else UML_MOV(block, I0, REG(dreg)); // mov i0,reg[dreg] UML_CALLH(block, (g) ? *m_pm_write32 : *m_dm_write32); // callh dm|pm_write32 } else { // DM|PM -> DREG // compute generate_compute(block, compiler, desc); // transfer UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] if (u == 0) // pre-modify without update UML_ADD(block, I1, I1, mod); // add i1,i1,mod UML_CALLH(block, (g) ? *m_pm_read32 : *m_dm_read32); // callh dm|pm_read32 UML_MOV(block, REG(dreg), I0); // mov reg[dreg],i0 } if (u != 0) // post-modify with update { if (g) UML_ADD(block, PM_I(i), PM_I(i), mod); // add pm[i],mod else UML_ADD(block, DM_I(i), DM_I(i), mod); // add dm[i],mod generate_update_circular_buffer(block, compiler, desc, g, i); } if (has_condition) UML_LABEL(block, skip_label); return TRUE; } break; } case 4: { if (opcode & U64(0x100000000000)) // immediate data -> DM|PM |100|1| { int i = (opcode >> 41) & 0x7; int m = (opcode >> 38) & 0x7; int g = (opcode >> 37) & 0x1; UINT32 data = (UINT32)opcode; if (g) { // PM UML_MOV(block, I0, data); UML_MOV(block, I1, PM_I(i)); UML_CALLH(block, *m_pm_write32); UML_ADD(block, PM_I(i), PM_I(i), PM_M(m)); } else { // DM UML_MOV(block, I0, data); UML_MOV(block, I1, DM_I(i)); UML_CALLH(block, *m_dm_write32); UML_ADD(block, DM_I(i), DM_I(i), DM_M(m)); } generate_update_circular_buffer(block, compiler, desc, g, i); return TRUE; } else // immediate shift / dreg <-> DM|PM |100|0| { int i = (opcode >> 41) & 0x7; int m = (opcode >> 38) & 0x7; int g = (opcode >> 32) & 0x1; int d = (opcode >> 31) & 0x1; int dreg = (opcode >> 23) & 0xf; int cond = (opcode >> 33) & 0x1f; int data = ((opcode >> 8) & 0xff) | ((opcode >> 19) & 0xf00); int shiftop = (opcode >> 16) & 0x3f; int rn = (opcode >> 4) & 0xf; int rx = (opcode & 0xf); bool has_condition = !if_condition_always_true(cond); int skip_label = 0; if (has_condition) { skip_label = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, skip_label); } if (d) { // DREG -> DM|PM bool temp_dreg = false; // save dreg if shiftop writes to it if (desc->regout[0] & (1 << dreg)) { UML_MOV(block, mem(&m_core->dreg_temp), REG(dreg)); temp_dreg = true; } // shiftop generate_shift_imm(block, compiler, desc, data, shiftop, rn, rx); // transfer UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] if (temp_dreg) UML_MOV(block, I0, mem(&m_core->dreg_temp)); // mov i0,[m_core->dreg_temp] else UML_MOV(block, I0, REG(dreg)); // mov i0,reg[dreg] UML_CALLH(block, (g) ? *m_pm_write32 : *m_dm_write32); // callh dm|pm_write32 } else { // DM|PM -> DREG // shiftop generate_shift_imm(block, compiler, desc, data, shiftop, rn, rx); // transfer UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] UML_CALLH(block, (g) ? *m_pm_read32 : *m_dm_read32); // callh dm|pm_read32 UML_MOV(block, REG(dreg), I0); // mov reg[dreg],i0 } // update I if (g) UML_ADD(block, PM_I(i), PM_I(i), PM_M(m)); else UML_ADD(block, DM_I(i), DM_I(i), DM_M(m)); generate_update_circular_buffer(block, compiler, desc, g, i); if (has_condition) UML_LABEL(block, skip_label); return TRUE; } break; } case 5: // ureg <-> DM|PM (indirect) |101| { int g = (opcode >> 44) & 1; int d = (opcode >> 40) & 1; int i = (opcode >> 41) & 0x7; int ureg = (opcode >> 32) & 0xff; UINT32 offset = (UINT32)opcode; if (d) { // UREG -> DM|PM UML_ADD(block, I1, (g) ? PM_I(i) : DM_I(i), offset); // add i1,dm|pm[i],offset generate_read_ureg(block, compiler, desc, ureg, false); if (ureg == 0xdb && (g)) // PX is 48-bit when writing to PM UML_CALLH(block, *m_pm_write48); // callh pm_write48 else UML_CALLH(block, (g) ? *m_pm_write32 : *m_dm_write32); // callh dm|pm_write32 } else { // DM|PM -> UREG UML_ADD(block, I1, (g) ? PM_I(i) : DM_I(i), offset); // add i1,dm|pm[i],offset if (ureg == 0xdb && (g)) // PX is 48-bit when reading from PM UML_CALLH(block, *m_pm_read48); // callh pm_read48 else UML_CALLH(block, (g) ? *m_pm_read32 : *m_dm_read32); // callh dm|pm_read32 generate_write_ureg(block, compiler, desc, ureg, false, 0); } return TRUE; } case 6: // indirect jump / compute / dreg <-> DM |110| { int d = (opcode >> 44) & 0x1; int dmi = (opcode >> 41) & 0x7; int dmm = (opcode >> 38) & 0x7; int pmi = (opcode >> 30) & 0x7; int pmm = (opcode >> 27) & 0x7; int cond = (opcode >> 33) & 0x1f; int dreg = (opcode >> 23) & 0xf; code_label label_else = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, label_else); UML_ADD(block, I0, PM_I(pmi), PM_M(pmm)); generate_jump(block, compiler, desc, false, false, false); UML_LABEL(block, label_else); if (d) { // DREG -> DM bool temp_dreg = false; // save dreg if compute writes to it if (desc->regout[0] & (1 << dreg)) { UML_MOV(block, mem(&m_core->dreg_temp), REG(dreg)); temp_dreg = true; } // compute generate_compute(block, compiler, desc); // transfer UML_MOV(block, I1, DM_I(dmi)); if (temp_dreg) UML_MOV(block, I0, mem(&m_core->dreg_temp)); else UML_MOV(block, I0, REG(dreg)); UML_CALLH(block, *m_dm_write32); } else { // DM -> DREG // compute generate_compute(block, compiler, desc); // transfer UML_MOV(block, I1, DM_I(dmi)); UML_CALLH(block, *m_dm_read32); UML_MOV(block, REG(dreg), I0); } // update I UML_ADD(block, DM_I(dmi), DM_I(dmi), DM_M(dmm)); generate_update_circular_buffer(block, compiler, desc, 0, dmi); return TRUE; } case 7: // indirect jump / compute / dreg <-> DM |111| { int d = (opcode >> 44) & 0x1; int dmi = (opcode >> 41) & 0x7; int dmm = (opcode >> 38) & 0x7; int cond = (opcode >> 33) & 0x1f; int dreg = (opcode >> 23) & 0xf; code_label label_else = compiler->labelnum++; generate_if_condition(block, compiler, desc, cond, label_else); generate_jump(block, compiler, desc, false, false, false); UML_LABEL(block, label_else); if (d) { // DREG -> DM bool temp_dreg = false; // save dreg if compute writes to it if (desc->regout[0] & (1 << dreg)) { UML_MOV(block, mem(&m_core->dreg_temp), REG(dreg)); temp_dreg = true; } // compute generate_compute(block, compiler, desc); // transfer UML_MOV(block, I1, DM_I(dmi)); if (temp_dreg) UML_MOV(block, I0, mem(&m_core->dreg_temp)); else UML_MOV(block, I0, REG(dreg)); UML_CALLH(block, *m_dm_write32); } else { // DM -> DREG // compute generate_compute(block, compiler, desc); // transfer UML_MOV(block, I1, DM_I(dmi)); UML_CALLH(block, *m_dm_read32); UML_MOV(block, REG(dreg), I0); } // update I UML_ADD(block, DM_I(dmi), DM_I(dmi), DM_M(dmm)); generate_update_circular_buffer(block, compiler, desc, 0, dmi); return TRUE; } } return FALSE; } void adsp21062_device::generate_unimplemented_compute(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) { UML_MOV(block, mem(&m_core->pc), desc->pc); UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); UML_CALLC(block, cfunc_unimplemented_compute, this); } void adsp21062_device::generate_compute(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) { UINT64 opcode = desc->opptr.q[0]; if ((opcode & 0x7fffff) == 0) return; int rs = (opcode >> 12) & 0xf; int rn = (opcode >> 8) & 0xf; int ra = rn; int rx = (opcode >> 4) & 0xf; int ry = (opcode >> 0) & 0xf; int ps = (opcode >> 16) & 0xf; if (opcode & 0x400000) // multi-function operation { UINT32 multiop = (opcode >> 16) & 0x3f; int fm = rs; int fa = rn; int fxm = (opcode >> 6) & 0x3; // registers 0 - 3 int fym = ((opcode >> 4) & 0x3) + 4; // registers 4 - 7 int fxa = ((opcode >> 2) & 0x3) + 8; // registers 8 - 11 int fya = (opcode & 0x3) + 12; // registers 12 - 15 switch (multiop) { case 0x00: // Rn = MRxx { generate_unimplemented_compute(block, compiler, desc); return; } case 0x01: // MRxx = Rn { int ai = rs; switch (ai) { case 0x00: // MR0F UML_DAND(block, MRF, MRF, U64(0xffffffff00000000)); UML_AND(block, I0, REG(rn), 0xffffffff); UML_DOR(block, MRF, MRF, I0); break; case 0x01: // MR1F UML_DAND(block, MRF, MRF, U64(0x00000000ffffffff)); UML_DSHL(block, I0, REG(rn), 32); UML_DOR(block, MRF, MRF, I0); break; case 0x04: // MR0B UML_DAND(block, MRB, MRB, U64(0xffffffff00000000)); UML_AND(block, I0, REG(rn), 0xffffffff); UML_DOR(block, MRB, MRB, I0); break; case 0x05: // MR1B UML_DAND(block, MRB, MRB, U64(0x00000000ffffffff)); UML_DSHL(block, I0, REG(rn), 32); UML_DOR(block, MRB, MRB, I0); break; case 0x02: // MR2F case 0x06: // MR2B generate_unimplemented_compute(block, compiler, desc); return; } return; } case 0x07: // Ra = Rx + Ry, Rs = Rx - Ry case 0x0f: // Fa = Fx + Fy, Fs = Fx - Fy case 0x06: // Rm = R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 case 0x08: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = R11-8 + R15-12 case 0x09: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = R11-8 - R15-12 case 0x0a: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = (R11-8 + R15-12) / 2 case 0x0c: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 case 0x0d: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 case 0x0e: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 case 0x10: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = R11-8 + R15-12 case 0x11: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = R11-8 - R15-12 case 0x12: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = (R11-8 + R15-12) / 2 case 0x14: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 case 0x15: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 case 0x16: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 generate_unimplemented_compute(block, compiler, desc); return; case 0x1c: // Fm = F3-0 * F7-4, Fa = (F11-8 + F15-12) / 2 generate_unimplemented_compute(block, compiler, desc); return; case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12, Rs = R11-8 - R15-12 generate_unimplemented_compute(block, compiler, desc); return; case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: // Fm = F3-0 * F7-4, Fa = F11-8 + F15-12, Fs = F11-8 - F15-12 // TODO: denormals UML_FSCOPYI(block, F0, REG(fxm)); UML_FSCOPYI(block, F1, REG(fym)); UML_FSCOPYI(block, F2, REG(fxa)); UML_FSCOPYI(block, F3, REG(fya)); UML_FSMUL(block, F0, F0, F1); UML_FSADD(block, F4, F2, F3); UML_FSSUB(block, F5, F2, F3); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F4, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F5, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, I0); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, I1); if (AZ_CALC_REQUIRED) UML_OR(block, ASTAT_AZ, ASTAT_AZ, I0); if (AN_CALC_REQUIRED) UML_OR(block, ASTAT_AN, ASTAT_AN, I1); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO if (MN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); // TODO: MV, MU, MI flags UML_ICOPYFS(block, REG(fm), F0); UML_ICOPYFS(block, REG(fa), F4); UML_ICOPYFS(block, REG(ps), F5); return; case 0x04: // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 UML_DSEXT(block, I0, REG(fxm), SIZE_DWORD); UML_DSEXT(block, I1, REG(fym), SIZE_DWORD); UML_DMULS(block, I0, I0, I0, I1); UML_DSHR(block, I0, I0, 31); UML_ADD(block, I2, REG(fxa), REG(fya)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO: multiplier flags UML_MOV(block, REG(fm), I0); UML_MOV(block, REG(fa), I2); return; case 0x05: // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 UML_DSEXT(block, I0, REG(fxm), SIZE_DWORD); UML_DSEXT(block, I1, REG(fym), SIZE_DWORD); UML_DMULS(block, I0, I0, I0, I1); UML_DSHR(block, I0, I0, 31); UML_SUB(block, I2, REG(fxa), REG(fya)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO: multiplier flags UML_MOV(block, REG(fm), I0); UML_MOV(block, REG(fa), I2); return; case 0x18: // Fm = F3-0 * F7-4, Fa = F11-8 + F15-12 // TODO: denormals UML_FSCOPYI(block, F0, REG(fxm)); UML_FSCOPYI(block, F1, REG(fym)); UML_FSCOPYI(block, F2, REG(fxa)); UML_FSCOPYI(block, F3, REG(fya)); UML_FSMUL(block, F0, F0, F1); UML_FSADD(block, F2, F2, F3); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F2, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO if (MN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); // TODO: MV, MU, MI flags UML_ICOPYFS(block, REG(fm), F0); UML_ICOPYFS(block, REG(fa), F2); return; case 0x19: // Fm = F3-0 * F7-4, Fa = F11-8 - F15-12 // TODO: denormals UML_FSCOPYI(block, F0, REG(fxm)); UML_FSCOPYI(block, F1, REG(fym)); UML_FSCOPYI(block, F2, REG(fxa)); UML_FSCOPYI(block, F3, REG(fya)); UML_FSMUL(block, F0, F0, F1); UML_FSSUB(block, F2, F2, F3); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F2, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO if (MN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); // TODO: MV, MU, MI flags UML_ICOPYFS(block, REG(fm), F0); UML_ICOPYFS(block, REG(fa), F2); return; case 0x1a: // Fm = F3-0 * F7-4, Fa = FLOAT F11-8 BY R15-12 { code_label denormal = compiler->labelnum++; code_label end = compiler->labelnum++; // TODO: denormals UML_FSCOPYI(block, F0, REG(fxm)); UML_FSCOPYI(block, F1, REG(fym)); UML_FSMUL(block, F0, F0, F1); UML_FSFRINT(block, F2, REG(fxa), SIZE_DWORD); UML_ICOPYFS(block, I1, F2); UML_AND(block, I0, I1, 0x7f800000); UML_AND(block, I1, I1, 0x807fffff); UML_SHR(block, I0, I0, 23); UML_SUB(block, I0, I0, 127); UML_ADD(block, I0, I0, REG(fya)); UML_CMP(block, I0, -126); UML_JMPc(block, COND_L, denormal); UML_ADD(block, I0, I0, 127); UML_AND(block, I0, I0, 0xff); UML_SHL(block, I0, I0, 23); UML_OR(block, I0, I0, I1); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); UML_JMP(block, end); UML_LABEL(block, denormal); UML_AND(block, I0, I1, 0x80000000); if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 1); if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); UML_LABEL(block, end); if (MN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); // TODO: MV, MU, MI flags UML_ICOPYFS(block, REG(fm), F0); UML_MOV(block, REG(fa), I0); return; } case 0x1b: // Fm = F3-0 * F7-4, Fa = FIX F11-8 BY R15-12 { code_label denormal = compiler->labelnum++; code_label end = compiler->labelnum++; // TODO: denormals UML_FSCOPYI(block, F0, REG(fxm)); UML_FSCOPYI(block, F1, REG(fym)); UML_FSMUL(block, F0, F0, F1); UML_MOV(block, I1, REG(fxa)); UML_AND(block, I0, I1, 0x7f800000); UML_AND(block, I1, I1, 0x807fffff); UML_SHR(block, I0, I0, 23); UML_SUB(block, I0, I0, 127); UML_ADD(block, I0, I0, REG(fya)); UML_CMP(block, I0, -126); UML_JMPc(block, COND_L, denormal); UML_ADD(block, I0, I0, 127); UML_AND(block, I0, I0, 0xff); UML_SHL(block, I0, I0, 23); UML_OR(block, I0, I0, I1); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); UML_JMP(block, end); UML_LABEL(block, denormal); UML_AND(block, I0, I1, 0x80000000); if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 1); if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); UML_LABEL(block, end); UML_FSCOPYI(block, F2, I0); UML_TEST(block, MODE1, MODE1_TRUNCATE); UML_JMPc(block, COND_Z, compiler->labelnum); UML_FSTOINT(block, I0, F2, SIZE_DWORD, ROUND_TRUNC); UML_JMP(block, compiler->labelnum + 1); UML_LABEL(block, compiler->labelnum++); UML_FSTOINT(block, I0, F2, SIZE_DWORD, ROUND_ROUND); UML_LABEL(block, compiler->labelnum++); if (MN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); // TODO: MV, MU, MI flags UML_ICOPYFS(block, REG(fm), F0); UML_MOV(block, REG(fa), I0); return; } case 0x1d: // Fm = F3-0 * F7-4, Fa = ABS F11-8 UML_FSCOPYI(block, F0, REG(fxm)); UML_FSCOPYI(block, F1, REG(fym)); UML_AND(block, I0, REG(fxa), 0x7fffffff); UML_FSMUL(block, F0, F0, F1); if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 0); // TODO if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); // TODO if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO if (MN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); // TODO: MV, MU, MI flags UML_ICOPYFS(block, REG(fm), F0); UML_MOV(block, REG(fa), I0); return; case 0x1e: // Fm = F3-0 * F7-4, Fa = MAX(F11-8, F15-12) // TODO: denormals UML_FSCOPYI(block, F0, REG(fxm)); UML_FSCOPYI(block, F1, REG(fym)); UML_FSCOPYI(block, F2, REG(fxa)); UML_FSCOPYI(block, F3, REG(fya)); UML_FSMUL(block, F0, F0, F1); UML_FSMOV(block, F4, F2); UML_FSCMP(block, F2, F3); UML_FSMOVc(block, COND_C, F4, F3); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F4, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO if (MN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); // TODO: MV, MU, MI flags UML_ICOPYFS(block, REG(fm), F0); UML_ICOPYFS(block, REG(fa), F4); return; case 0x1f: // Fm = F3-0 * F7-4, Fa = MIN(F11-8, F15-12) // TODO: denormals UML_FSCOPYI(block, F0, REG(fxm)); UML_FSCOPYI(block, F1, REG(fym)); UML_FSCOPYI(block, F2, REG(fxa)); UML_FSCOPYI(block, F3, REG(fya)); UML_FSMUL(block, F0, F0, F1); UML_FSMOV(block, F4, F2); UML_FSCMP(block, F3, F2); UML_FSMOVc(block, COND_C, F4, F3); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F4, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO if (MN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); // TODO: MV, MU, MI flags UML_ICOPYFS(block, REG(fm), F0); UML_ICOPYFS(block, REG(fa), F4); return; default: generate_unimplemented_compute(block, compiler, desc); return; } } else // single-function operation { UINT32 operation = (opcode >> 12) & 0xff; switch ((opcode >> 20) & 3) { case 0: // ALU operations { switch (operation) { case 0x09: // Rn = (Rx + Ry) / 2 case 0x63: // Rn = CLIP Rx BY Ry case 0x92: // Fn = ABS(Fx - Fy) case 0x89: // Fn = (Fx + Fy) / 2 case 0xdd: // Rn = TRUNC Fx BY Ry case 0xe0: // Fn = Fx COPYSIGN Fy case 0x05: // Rn = Rx + Ry + CI case 0x06: // Rn = Rx - Ry + CI - 1 case 0x25: // Rn = Rx + CI case 0x26: // Rn = Rx + CI - 1 case 0x30: // Rn = ABS Rx case 0x43: // Rn = NOT Rx case 0xa5: // Fn = RND Fx case 0xad: // Rn = MANT Fx case 0xcd: // Rn = TRUNC Fx generate_unimplemented_compute(block, compiler, desc); return; case 0x01: // Rn = Rx + Ry UML_ADD(block, REG(rn), REG(rx), REG(ry)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x02: // Rn = Rx - Ry UML_SUB(block, REG(rn), REG(rx), REG(ry)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x0a: // COMP(Rx, Ry) UML_CMP(block, REG(rx), REG(ry)); UML_SETc(block, COND_Z, I0); UML_SETc(block, COND_L, I1); UML_MOV(block, ASTAT_AZ, I0); UML_MOV(block, ASTAT_AN, I1); UML_XOR(block, I0, I0, 1); UML_XOR(block, I1, I1, 1); UML_AND(block, I0, I0, I1); UML_SHL(block, I0, I0, 7); UML_MOV(block, I2, mem(&m_core->astat_drc.cacc)); UML_SHR(block, I2, I2, 1); UML_OR(block, I2, I2, I0); UML_MOV(block, mem(&m_core->astat_drc.cacc), I2); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x21: // Rn = PASS Rx UML_MOV(block, REG(rn), REG(rx)); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_CMP(block, REG(rn), 0); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x22: // Rn = -Rx UML_SUB(block, REG(rn), 0, REG(rx)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x29: // Rn = Rx + 1 UML_ADD(block, REG(rn), REG(rx), 1); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x2a: // Rn = Rx - 1 UML_SUB(block, REG(rn), REG(rx), 1); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x40: // Rn = Rx AND Ry UML_AND(block, REG(rn), REG(rx), REG(ry)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x41: // Rn = Rx OR Ry UML_OR(block, REG(rn), REG(rx), REG(ry)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x42: // Rn = Rx XOR Ry UML_XOR(block, REG(rn), REG(rx), REG(ry)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x61: // Rn = MIN(Rx, Ry) UML_MOV(block, REG(rn), REG(rx)); UML_CMP(block, REG(rx), REG(ry)); UML_MOVc(block, COND_G, REG(rn), REG(ry)); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_CMP(block, REG(rn), 0); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x62: // Rn = MAX(Rx, Ry) UML_MOV(block, REG(rn), REG(rx)); UML_CMP(block, REG(rx), REG(ry)); UML_MOVc(block, COND_L, REG(rn), REG(ry)); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_CMP(block, REG(rn), 0); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: { /* Fixed-point Dual Add/Subtract */ UML_ADD(block, I0, REG(rx), REG(ry)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); UML_SUB(block, I1, REG(rx), REG(ry)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, mem(&m_core->arg0)); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, mem(&m_core->arg1)); if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, mem(&m_core->arg2)); if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, mem(&m_core->arg3)); if (AZ_CALC_REQUIRED) UML_OR(block, ASTAT_AZ, ASTAT_AZ, mem(&m_core->arg0)); if (AN_CALC_REQUIRED) UML_OR(block, ASTAT_AN, ASTAT_AN, mem(&m_core->arg1)); if (AV_CALC_REQUIRED) UML_OR(block, ASTAT_AV, ASTAT_AV, mem(&m_core->arg2)); if (AC_CALC_REQUIRED) UML_OR(block, ASTAT_AC, ASTAT_AC, mem(&m_core->arg3)); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); UML_MOV(block, REG(ra), I0); UML_MOV(block, REG(rs), I1); return; } case 0x81: // Fn = Fx + Fy // TODO: denormals UML_FSCOPYI(block, F0, REG(rx)); UML_FSCOPYI(block, F1, REG(ry)); UML_FSADD(block, F0, F0, F1); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO UML_ICOPYFS(block, REG(rn), F0); return; case 0x82: // Fn = Fx - Fy // TODO: denormals UML_FSCOPYI(block, F0, REG(rx)); UML_FSCOPYI(block, F1, REG(ry)); UML_FSSUB(block, F0, F0, F1); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO UML_ICOPYFS(block, REG(rn), F0); return; case 0x8a: // COMP(Fx, Fy) UML_FSCOPYI(block, F0, REG(rx)); UML_FSCOPYI(block, F1, REG(ry)); UML_FSCMP(block, F0, F1); UML_SETc(block, COND_Z, I0); UML_SETc(block, COND_C, I1); UML_MOV(block, ASTAT_AZ, I0); UML_MOV(block, ASTAT_AN, I1); UML_XOR(block, I0, I0, 1); UML_XOR(block, I1, I1, 1); UML_AND(block, I0, I0, I1); UML_SHL(block, I0, I0, 7); UML_MOV(block, I2, mem(&m_core->astat_drc.cacc)); UML_SHR(block, I2, I2, 1); UML_OR(block, I2, I2, I0); UML_MOV(block, mem(&m_core->astat_drc.cacc), I2); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO return; case 0x91: // Fn = ABS(Fx + Fy) // TODO: denormals UML_FSCOPYI(block, F0, REG(rx)); UML_FSCOPYI(block, F1, REG(ry)); UML_FSADD(block, F0, F0, F1); UML_FSABS(block, F0, F0); UML_ICOPYFS(block, REG(rn), F0); if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 0); // TODO if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO return; case 0xa1: // Fn = PASS Fx UML_MOV(block, REG(rn), REG(rx)); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) { UML_FSCOPYI(block, F0, REG(rn)); UML_FSCMP(block, F0, mem(&m_core->fp0)); } if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO return; case 0xa2: // Fn = -Fx UML_FSCOPYI(block, F0, REG(rx)); UML_FSNEG(block, F0, F0); UML_ICOPYFS(block, REG(rn), F0); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO return; case 0xb0: // Fn = ABS(Fx) UML_FSCOPYI(block, F0, REG(rx)); UML_FSABS(block, F0, F0); UML_ICOPYFS(block, REG(rn), F0); if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 0); // TODO if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); // TODO if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO return; case 0xbd: // Fn = SCALB Fx BY Ry // TODO: source = nan, result = denormal UML_MOV(block, I1, REG(rx)); UML_AND(block, I0, I1, 0x7f800000); UML_AND(block, I1, I1, 0x807fffff); UML_SHR(block, I0, I0, 23); UML_SUB(block, I0, I0, 127); UML_ADD(block, I0, I0, REG(ry)); UML_ADD(block, I0, I0, 127); UML_AND(block, I0, I0, 0xff); UML_SHL(block, I0, I0, 23); UML_OR(block, REG(rn), I0, I1); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO return; case 0xc1: // Rn = LOGB Fx // TODO: source = zero, infinity, nan UML_SHR(block, I0, REG(rx), 23); UML_AND(block, I0, I0, 0xff); UML_SUB(block, REG(rn), I0, 127); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0xc4: // Fn = RECIPS Fx // TODO: denormals // TODO: use the bit accurate method from interpreter? UML_FSCOPYI(block, F0, REG(rx)); if (AN_CALC_REQUIRED || AV_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AV); UML_FSCMP(block, F0, mem(&m_core->fp0)); UML_JMPc(block, COND_Z, compiler->labelnum); UML_FSRECIP(block, F0, F0); UML_LABEL(block, compiler->labelnum++); if (AZ_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO UML_ICOPYFS(block, REG(rn), F0); return; case 0xc5: // Fn = RSQRTS Fx // TODO: denormals // TODO: use the bit accurate method from interpreter? UML_FSCOPYI(block, F0, REG(rx)); UML_FSCMP(block, F0, mem(&m_core->fp0)); UML_JMPc(block, COND_Z, compiler->labelnum); UML_FSRSQRT(block, F0, F0); UML_LABEL(block, compiler->labelnum++); UML_ICOPYFS(block, REG(rn), F0); // TODO: flags! if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); return; case 0xca: // Fn = FLOAT Rx UML_FSFRINT(block, F0, REG(rx), SIZE_DWORD); UML_ICOPYFS(block, REG(rn), F0); if (AZ_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); return; case 0xc9: // Rn = FIX Fx UML_FSCOPYI(block, F0, REG(rx)); UML_TEST(block, MODE1, MODE1_TRUNCATE); UML_JMPc(block, COND_Z, compiler->labelnum); UML_FSTOINT(block, I0, F0, SIZE_DWORD, ROUND_TRUNC); UML_JMP(block, compiler->labelnum + 1); UML_LABEL(block, compiler->labelnum++); UML_FSTOINT(block, I0, F0, SIZE_DWORD, ROUND_ROUND); UML_LABEL(block, compiler->labelnum++); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_CMP(block, I0, 0); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO UML_MOV(block, REG(rn), I0); return; case 0xd9: // Rn = FIX Fx BY Ry { code_label denormal = compiler->labelnum++; code_label end = compiler->labelnum++; UML_MOV(block, I1, REG(rx)); UML_AND(block, I0, I1, 0x7f800000); UML_AND(block, I1, I1, 0x807fffff); UML_SHR(block, I0, I0, 23); UML_SUB(block, I0, I0, 127); UML_ADD(block, I0, I0, REG(ry)); UML_CMP(block, I0, -126); UML_JMPc(block, COND_L, denormal); UML_ADD(block, I0, I0, 127); UML_AND(block, I0, I0, 0xff); UML_SHL(block, I0, I0, 23); UML_OR(block, I0, I0, I1); UML_FSCOPYI(block, F2, I0); UML_TEST(block, MODE1, MODE1_TRUNCATE); UML_JMPc(block, COND_Z, compiler->labelnum); UML_FSTOINT(block, I0, F2, SIZE_DWORD, ROUND_TRUNC); UML_JMP(block, compiler->labelnum + 1); UML_LABEL(block, compiler->labelnum++); UML_FSTOINT(block, I0, F2, SIZE_DWORD, ROUND_ROUND); UML_LABEL(block, compiler->labelnum++); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_CMP(block, I0, 0); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO UML_MOV(block, REG(rn), I0); UML_JMP(block, end); UML_LABEL(block, denormal); UML_AND(block, I0, I1, 0x80000000); if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 1); if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); UML_MOV(block, REG(rn), I0); UML_LABEL(block, end); return; } case 0xda: // Fn = FLOAT Rx BY Ry { code_label denormal = compiler->labelnum++; code_label end = compiler->labelnum++; UML_FSFRINT(block, F0, REG(rx), SIZE_DWORD); UML_ICOPYFS(block, I1, F0); UML_AND(block, I0, I1, 0x7f800000); UML_AND(block, I1, I1, 0x807fffff); UML_SHR(block, I0, I0, 23); UML_SUB(block, I0, I0, 127); UML_ADD(block, I0, I0, REG(ry)); UML_CMP(block, I0, -126); UML_JMPc(block, COND_L, denormal); UML_ADD(block, I0, I0, 127); UML_AND(block, I0, I0, 0xff); UML_SHL(block, I0, I0, 23); UML_OR(block, REG(rn), I0, I1); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); UML_JMP(block, end); UML_LABEL(block, denormal); UML_AND(block, I0, I1, 0x80000000); if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 1); if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); UML_MOV(block, REG(rn), I0); UML_LABEL(block, end); return; } case 0xe1: // Fn = MIN(Fx, Fy) UML_FSCOPYI(block, F2, REG(rx)); UML_FSCOPYI(block, F3, REG(ry)); UML_FSMOV(block, F4, F2); UML_FSCMP(block, F3, F2); UML_FSMOVc(block, COND_C, F4, F3); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F4, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO UML_ICOPYFS(block, REG(rn), F4); return; case 0xe2: // Fn = MAX(Fx, Fy) UML_FSCOPYI(block, F2, REG(rx)); UML_FSCOPYI(block, F3, REG(ry)); UML_FSMOV(block, F4, F2); UML_FSCMP(block, F2, F3); UML_FSMOVc(block, COND_C, F4, F3); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F4, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO UML_ICOPYFS(block, REG(rn), F4); return; case 0xe3: // Fn = CLIP Fx BY Fy { code_label label_1 = compiler->labelnum++; code_label label_2 = compiler->labelnum++; UML_FSCOPYI(block, F0, REG(rx)); UML_FSCOPYI(block, F1, REG(ry)); UML_FSABS(block, F1, F1); UML_FSCMP(block, F0, F1); UML_JMPc(block, COND_C, label_1); UML_FSCMP(block, F0, mem(&m_core->fp0)); UML_JMPc(block, COND_C, label_2); UML_FSMOV(block, F0, F1); UML_JMP(block, label_1); UML_LABEL(block, label_2); UML_FSNEG(block, F0, F1); UML_LABEL(block, label_1); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO UML_ICOPYFS(block, REG(rn), F0); return; } case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: { /* Floating-point Dual Add/Subtract */ UML_FSCOPYI(block, F0, REG(rx)); UML_FSCOPYI(block, F1, REG(ry)); UML_FSADD(block, F2, F0, F1); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F2, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); UML_FSSUB(block, F3, F0, F1); if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) UML_FSCMP(block, F2, mem(&m_core->fp0)); if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, I0); if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, I1); if (AZ_CALC_REQUIRED) UML_OR(block, ASTAT_AZ, ASTAT_AZ, I0); if (AN_CALC_REQUIRED) UML_OR(block, ASTAT_AN, ASTAT_AN, I1); if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO UML_ICOPYFS(block, REG(ra), F2); UML_ICOPYFS(block, REG(rs), F3); return; } default: generate_unimplemented_compute(block, compiler, desc); return; } break; } case 1: // multiplier operations { switch (operation) { case 0x48: // Rn = Rx * Ry (UUF) case 0x49: // Rn = Rx * Ry (UUFR) case 0x50: // Rn = Rx * Ry (SUI) case 0x58: // Rn = Rx * Ry (SUF) case 0x59: // Rn = Rx * Ry (SUFR) case 0x60: // Rn = Rx * Ry (USI) case 0x68: // Rn = Rx * Ry (USF) case 0x69: // Rn = Rx * Ry (USFR) case 0x78: // Rn = Rx * Ry (SSF) case 0x79: // Rn = Rx * Ry (SSFR) case 0x44: // MRF = Rx * Ry (UUI) case 0x4c: // MRF = Rx * Ry (UUF) case 0x4d: // MRF = Rx * Ry (UUFR) case 0x54: // MRF = Rx * Ry (SUI) case 0x5c: // MRF = Rx * Ry (SUF) case 0x5d: // MRF = Rx * Ry (SUFR) case 0x64: // MRF = Rx * Ry (USI) case 0x6c: // MRF = Rx * Ry (USF) case 0x6d: // MRF = Rx * Ry (USFR) case 0x74: // MRF = Rx * Ry (SSI) case 0x7c: // MRF = Rx * Ry (SSF) case 0x7d: // MRF = Rx * Ry (SSFR) case 0x46: // MRB = Rx * Ry (UUI) case 0x4e: // MRB = Rx * Ry (UUF) case 0x4f: // MRB = Rx * Ry (UUFR) case 0x56: // MRB = Rx * Ry (SUI) case 0x5e: // MRB = Rx * Ry (SUF) case 0x5f: // MRB = Rx * Ry (SUFR) case 0x66: // MRB = Rx * Ry (USI) case 0x6e: // MRB = Rx * Ry (USF) case 0x6f: // MRB = Rx * Ry (USFR) case 0x76: // MRB = Rx * Ry (SSI) case 0x7e: // MRB = Rx * Ry (SSF) case 0x7f: // MRB = Rx * Ry (SSFR) case 0x80: // Rn = MRF + Rx * Ry (UUI) case 0x88: // Rn = MRF + Rx * Ry (UUF) case 0x89: // Rn = MRF + Rx * Ry (UUFR) case 0x90: // Rn = MRF + Rx * Ry (SUI) case 0x98: // Rn = MRF + Rx * Ry (SUF) case 0x99: // Rn = MRF + Rx * Ry (SUFR) case 0xa0: // Rn = MRF + Rx * Ry (USI) case 0xa8: // Rn = MRF + Rx * Ry (USF) case 0xa9: // Rn = MRF + Rx * Ry (USFR) case 0xb8: // Rn = MRF + Rx * Ry (SSF) case 0xb9: // Rn = MRF + Rx * Ry (SSFR) case 0x82: // Rn = MRB + Rx * Ry (UUI) case 0x8a: // Rn = MRB + Rx * Ry (UUF) case 0x8b: // Rn = MRB + Rx * Ry (UUFR) case 0x92: // Rn = MRB + Rx * Ry (SUI) case 0x9a: // Rn = MRB + Rx * Ry (SUF) case 0x9b: // Rn = MRB + Rx * Ry (SUFR) case 0xa2: // Rn = MRB + Rx * Ry (USI) case 0xaa: // Rn = MRB + Rx * Ry (USF) case 0xab: // Rn = MRB + Rx * Ry (USFR) case 0xba: // Rn = MRB + Rx * Ry (SSF) case 0xbb: // Rn = MRB + Rx * Ry (SSFR) case 0x84: // MRF = MRF + Rx * Ry (UUI) case 0x8c: // MRF = MRF + Rx * Ry (UUF) case 0x8d: // MRF = MRF + Rx * Ry (UUFR) case 0x94: // MRF = MRF + Rx * Ry (SUI) case 0x9c: // MRF = MRF + Rx * Ry (SUF) case 0x9d: // MRF = MRF + Rx * Ry (SUFR) case 0xa4: // MRF = MRF + Rx * Ry (USI) case 0xac: // MRF = MRF + Rx * Ry (USF) case 0xad: // MRF = MRF + Rx * Ry (USFR) case 0xb4: // MRF = MRF + Rx * Ry (SSI) case 0xbc: // MRF = MRF + Rx * Ry (SSF) case 0xbd: // MRF = MRF + Rx * Ry (SSFR) case 0x86: // MRB = MRB + Rx * Ry (UUI) case 0x8e: // MRB = MRB + Rx * Ry (UUF) case 0x8f: // MRB = MRB + Rx * Ry (UUFR) case 0x96: // MRB = MRB + Rx * Ry (SUI) case 0x9e: // MRB = MRB + Rx * Ry (SUF) case 0x9f: // MRB = MRB + Rx * Ry (SUFR) case 0xa6: // MRB = MRB + Rx * Ry (USI) case 0xae: // MRB = MRB + Rx * Ry (USF) case 0xaf: // MRB = MRB + Rx * Ry (USFR) case 0xb6: // MRB = MRB + Rx * Ry (SSI) case 0xbe: // MRB = MRB + Rx * Ry (SSF) case 0xbf: // MRB = MRB + Rx * Ry (SSFR) case 0xc0: // Rn = MRF - Rx * Ry (UUI) case 0xc8: // Rn = MRF - Rx * Ry (UUF) case 0xc9: // Rn = MRF - Rx * Ry (UUFR) case 0xd0: // Rn = MRF - Rx * Ry (SUI) case 0xd8: // Rn = MRF - Rx * Ry (SUF) case 0xd9: // Rn = MRF - Rx * Ry (SUFR) case 0xe0: // Rn = MRF - Rx * Ry (USI) case 0xe8: // Rn = MRF - Rx * Ry (USF) case 0xe9: // Rn = MRF - Rx * Ry (USFR) case 0xf0: // Rn = MRF - Rx * Ry (SSI) case 0xf8: // Rn = MRF - Rx * Ry (SSF) case 0xf9: // Rn = MRF - Rx * Ry (SSFR) case 0xc2: // Rn = MRB - Rx * Ry (UUI) case 0xca: // Rn = MRB - Rx * Ry (UUF) case 0xcb: // Rn = MRB - Rx * Ry (UUFR) case 0xd2: // Rn = MRB - Rx * Ry (SUI) case 0xda: // Rn = MRB - Rx * Ry (SUF) case 0xdb: // Rn = MRB - Rx * Ry (SUFR) case 0xe2: // Rn = MRB - Rx * Ry (USI) case 0xea: // Rn = MRB - Rx * Ry (USF) case 0xeb: // Rn = MRB - Rx * Ry (USFR) case 0xf2: // Rn = MRB - Rx * Ry (SSI) case 0xfa: // Rn = MRB - Rx * Ry (SSF) case 0xfb: // Rn = MRB - Rx * Ry (SSFR) case 0xc4: // MRF = MRF - Rx * Ry (UUI) case 0xcc: // MRF = MRF - Rx * Ry (UUF) case 0xcd: // MRF = MRF - Rx * Ry (UUFR) case 0xd4: // MRF = MRF - Rx * Ry (SUI) case 0xdc: // MRF = MRF - Rx * Ry (SUF) case 0xdd: // MRF = MRF - Rx * Ry (SUFR) case 0xe4: // MRF = MRF - Rx * Ry (USI) case 0xec: // MRF = MRF - Rx * Ry (USF) case 0xed: // MRF = MRF - Rx * Ry (USFR) case 0xf4: // MRF = MRF - Rx * Ry (SSI) case 0xfc: // MRF = MRF - Rx * Ry (SSF) case 0xfd: // MRF = MRF - Rx * Ry (SSFR) case 0xc6: // MRB = MRB - Rx * Ry (UUI) case 0xce: // MRB = MRB - Rx * Ry (UUF) case 0xcf: // MRB = MRB - Rx * Ry (UUFR) case 0xd6: // MRB = MRB - Rx * Ry (SUI) case 0xde: // MRB = MRB - Rx * Ry (SUF) case 0xdf: // MRB = MRB - Rx * Ry (SUFR) case 0xe6: // MRB = MRB - Rx * Ry (USI) case 0xee: // MRB = MRB - Rx * Ry (USF) case 0xef: // MRB = MRB - Rx * Ry (USFR) case 0xf6: // MRB = MRB - Rx * Ry (SSI) case 0xfe: // MRB = MRB - Rx * Ry (SSF) case 0xff: // MRB = MRB - Rx * Ry (SSFR) case 0x00: // Rn = SAT MRF (UI) case 0x01: // Rn = SAT MRF (SI) case 0x08: // Rn = SAT MRF (UF) case 0x09: // Rn = SAT MRF (SF) case 0x02: // Rn = SAT MRB (UI) case 0x03: // Rn = SAT MRB (SI) case 0x0a: // Rn = SAT MRB (UF) case 0x0b: // Rn = SAT MRB (SF) case 0x04: // MRF = SAT MRF (UI) case 0x05: // MRF = SAT MRF (SI) case 0x0c: // MRF = SAT MRF (UF) case 0x0d: // MRF = SAT MRF (SF) case 0x06: // MRB = SAT MRB (UI) case 0x07: // MRB = SAT MRB (SI) case 0x0e: // MRB = SAT MRB (UF) case 0x0f: // MRB = SAT MRB (SF) case 0x18: // Rn = RND MRF (U) case 0x19: // Rn = RND MRF (S) case 0x1a: // Rn = RND MRB (U) case 0x1b: // Rn = RND MRB (S) case 0x1c: // MRF = RND MRF (U) case 0x1d: // MRF = RND MRF (S) case 0x1e: // MRB = RND MRB (U) case 0x1f: // MRB = RND MRB (S) generate_unimplemented_compute(block, compiler, desc); return; case 0x14: // MRF = 0 UML_DMOV(block, mem(&m_core->mrf), 0); if (MN_CALC_REQUIRED) UML_MOV(block, ASTAT_MN, 0); if (MV_CALC_REQUIRED) UML_MOV(block, ASTAT_MV, 0); if (MU_CALC_REQUIRED) UML_MOV(block, ASTAT_MU, 0); if (MI_CALC_REQUIRED) UML_MOV(block, ASTAT_MI, 0); return; case 0x16: // MRB = 0 UML_DMOV(block, mem(&m_core->mrb), 0); if (MN_CALC_REQUIRED) UML_MOV(block, ASTAT_MN, 0); if (MV_CALC_REQUIRED) UML_MOV(block, ASTAT_MV, 0); if (MU_CALC_REQUIRED) UML_MOV(block, ASTAT_MU, 0); if (MI_CALC_REQUIRED) UML_MOV(block, ASTAT_MI, 0); return; case 0x30: // Fn = Fx * Fy UML_FSCOPYI(block, F0, REG(rx)); UML_FSCOPYI(block, F1, REG(ry)); UML_FSMUL(block, F0, F0, F1); UML_ICOPYFS(block, REG(rn), F0); if (MN_CALC_REQUIRED) UML_FSCMP(block, F0, mem(&m_core->fp0)); if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); // TODO: MV, MU, MI flags return; case 0x40: // Rn = Rx * Ry (UUI) UML_MULU(block, I0, I0, REG(rx), REG(ry)); UML_MOV(block, REG(rn), I0); // TODO: flags return; case 0x70: // Rn = Rx * Ry (SSI) UML_MULS(block, I0, I0, REG(rx), REG(ry)); UML_MOV(block, REG(rn), I0); // TODO: flags return; case 0xb0: // Rn = MRF + Rx * Ry (SSI) UML_DSEXT(block, I0, REG(rx), SIZE_DWORD); UML_DSEXT(block, I1, REG(ry), SIZE_DWORD); UML_DMULS(block, I0, I0, I0, I1); UML_DADD(block, I0, I0, mem(&m_core->mrf)); UML_MOV(block, REG(rn), I0); // TODO: flags! return; case 0xb2: // Rn = MRB + Rx * Ry (SSI) UML_DSEXT(block, I0, REG(rx), SIZE_DWORD); UML_DSEXT(block, I1, REG(ry), SIZE_DWORD); UML_DMULS(block, I0, I0, I0, I1); UML_DADD(block, I0, I0, mem(&m_core->mrb)); UML_MOV(block, REG(rn), I0); // TODO: flags! return; default: generate_unimplemented_compute(block, compiler, desc); return; } break; } case 2: // shifter operations { switch (operation) { case 0x04: // Rn = ASHIFT Rx BY Ry | case 0x44: // Rn = FDEP Rx BY Ry | : case 0x4c: // Rn = FDEP Rx BY Ry | : (SE) case 0x24: // Rn = Rn OR ASHIFT Rx BY Ry | case 0x6c: // Rn = Rn OR FDEP Rx BY Ry | : (SE) case 0x80: // Rn = EXP Rx case 0x84: // Rn = EXP Rx (EX) case 0x88: // Rn = LEFTZ Rx case 0x8c: // Rn = LEFTO Rx case 0x90: // Rn = FPACK Fx case 0x94: // Fn = FUNPACK Rx generate_unimplemented_compute(block, compiler, desc); return; case 0x00: // Rn = LSHIFT Rx BY Ry | { code_label shift_neg = compiler->labelnum++; code_label shift_end = compiler->labelnum++; UML_MOV(block, I0, REG(ry)); UML_CMP(block, I0, 0); UML_JMPc(block, COND_L, shift_neg); UML_SHR(block, I1, REG(rx), I0); UML_JMP(block, shift_end); UML_LABEL(block, shift_neg); UML_SUB(block, I2, 0, I0); UML_SHR(block, I1, REG(rx), I2); UML_LABEL(block, shift_end); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED) { UML_CMP(block, I0, 0); UML_SETc(block, COND_NE, ASTAT_AV); } if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); UML_MOV(block, REG(rn), I1); return; } case 0x08: // Rn = ROT Rx BY Ry | { code_label shift_neg = compiler->labelnum++; code_label shift_end = compiler->labelnum++; UML_MOV(block, I0, REG(ry)); UML_CMP(block, I0, 0); UML_JMPc(block, COND_L, shift_neg); UML_ROL(block, I1, REG(rx), I0); UML_JMP(block, shift_end); UML_LABEL(block, shift_neg); UML_SUB(block, I2, 0, I0); UML_ROR(block, I1, REG(rx), I2); UML_LABEL(block, shift_end); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); UML_MOV(block, REG(rn), I1); return; } case 0x20: // Rn = Rn OR LSHIFT Rx BY Ry | { code_label shift_neg = compiler->labelnum++; code_label shift_end = compiler->labelnum++; UML_MOV(block, I0, REG(ry)); UML_CMP(block, I0, 0); UML_JMPc(block, COND_L, shift_neg); UML_SHL(block, I1, REG(rx), I0); UML_JMP(block, shift_end); UML_LABEL(block, shift_neg); UML_SUB(block, I2, 0, I0); UML_SHR(block, I1, REG(rx), I2); UML_LABEL(block, shift_end); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED) { UML_CMP(block, I0, 0); UML_SETc(block, COND_NZ, ASTAT_SV); } if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); UML_OR(block, REG(rn), REG(rn), I1); return; } case 0x40: // Rn = FEXT Rx BY Ry | : // extraction mask UML_MOV(block, I0, REG(ry)); UML_SHR(block, I1, I0, 6); UML_AND(block, I1, I1, 0x3f); // i1 = len6 UML_AND(block, I0, I0, 0x3f); // i0 = bit6 UML_MOV(block, I3, 0xffffffff); UML_SUB(block, I2, 32, I1); UML_SHR(block, I3, I3, I2); UML_SHL(block, I3, I3, I0); UML_AND(block, I2, REG(rx), I3); UML_SHR(block, REG(rn), I2, I0); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED) { UML_ADD(block, I0, I0, I1); UML_CMP(block, I0, 32); UML_SETc(block, COND_G, ASTAT_SV); } if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; case 0x48: // Rn = FEXT Rx BY Ry | : (SE) // extraction mask UML_MOV(block, I0, REG(ry)); UML_SHR(block, I1, I0, 6); UML_AND(block, I1, I1, 0x3f); // i1 = len6 UML_AND(block, I0, I0, 0x3f); // i0 = bit6 UML_MOV(block, I3, 0xffffffff); UML_SUB(block, I2, 32, I1); UML_SHR(block, I3, I3, I2); UML_SHL(block, I3, I3, I0); UML_AND(block, I3, REG(rx), I3); UML_ADD(block, I2, I0, I1); UML_SUB(block, I2, 32, I2); UML_SHL(block, I3, I3, I2); UML_ADD(block, I2, I2, I0); UML_SAR(block, REG(rn), I3, I2); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED) { UML_ADD(block, I0, I0, I1); UML_CMP(block, I0, 32); UML_SETc(block, COND_G, ASTAT_SV); } if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; case 0x64: // Rn = Rn OR FDEP Rx BY Ry | : // extraction mask UML_MOV(block, I0, REG(ry)); UML_SHR(block, I1, I0, 6); UML_AND(block, I1, I1, 0x3f); // i1 = len6 UML_AND(block, I0, I0, 0x3f); // i0 = bit6 UML_MOV(block, I3, 0xffffffff); UML_SUB(block, I2, 32, I1); UML_SHR(block, I3, I3, I2); UML_AND(block, I3, REG(rx), I3); UML_SHL(block, I3, I3, I0); UML_OR(block, REG(rn), REG(rn), I3); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED) { UML_ADD(block, I0, I0, I1); UML_CMP(block, I0, 32); UML_SETc(block, COND_G, ASTAT_SV); } if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; case 0xc0: // Rn = BSET Rx BY Ry | { UML_MOV(block, I0, REG(ry)); UML_SHL(block, I1, 1, I0); UML_OR(block, REG(rn), REG(rn), I1); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED) { UML_CMP(block, I0, 31); UML_SETc(block, COND_G, ASTAT_SV); } if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; } case 0xc4: // Rn = BCLR Rx BY Ry | { UML_MOV(block, I0, REG(ry)); UML_SHL(block, I1, 1, I0); UML_XOR(block, I1, I1, 0xffffffff); UML_AND(block, REG(rn), REG(rn), I1); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED) { UML_CMP(block, I0, 31); UML_SETc(block, COND_G, ASTAT_SV); } if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; } case 0xcc: // BTST Rx BY Ry | { UML_MOV(block, I0, REG(ry)); UML_SHL(block, I1, 1, I0); UML_TEST(block, REG(rx), I1); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED) UML_CMP(block, I0, 31); if (SV_CALC_REQUIRED) UML_SETc(block, COND_G, ASTAT_SV); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; } default: generate_unimplemented_compute(block, compiler, desc); return; } break; } default: generate_unimplemented_compute(block, compiler, desc); return; } } } void adsp21062_device::generate_if_condition(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int condition, int skip_label) { // Jump to skip_label if condition is not true code_label not_skip; switch (condition) { case 0x00: /* EQ */ UML_TEST(block, ASTAT_AZ, 1); UML_JMPc(block, COND_E, skip_label); break; case 0x01: /* LT */ UML_TEST(block, ASTAT_AZ, 1); UML_JMPc(block, COND_NE, skip_label); UML_TEST(block, ASTAT_AN, 1); UML_JMPc(block, COND_E, skip_label); break; case 0x02: /* LE */ not_skip = compiler->labelnum++; UML_TEST(block, ASTAT_AZ, 1); UML_JMPc(block, COND_NZ, not_skip); UML_TEST(block, ASTAT_AN, 1); UML_JMPc(block, COND_NZ, not_skip); UML_JMP(block, skip_label); UML_LABEL(block, not_skip); break; case 0x03: /* AC */ UML_TEST(block, ASTAT_AC, 1); UML_JMPc(block, COND_E, skip_label); break; case 0x04: /* AV */ UML_TEST(block, ASTAT_AV, 1); UML_JMPc(block, COND_E, skip_label); break; case 0x05: /* MV */ UML_TEST(block, ASTAT_MV, 1); UML_JMPc(block, COND_E, skip_label); break; case 0x06: /* MS */ UML_TEST(block, ASTAT_MN, 1); UML_JMPc(block, COND_E, skip_label); break; case 0x07: /* SV */ UML_TEST(block, ASTAT_SV, 1); UML_JMPc(block, COND_E, skip_label); break; case 0x08: /* SZ */ UML_TEST(block, ASTAT_SZ, 1); UML_JMPc(block, COND_E, skip_label); break; case 0x09: /* FLAG0 */ UML_CMP(block, FLAG0, 0); UML_JMPc(block, COND_E, skip_label); break; case 0x0a: /* FLAG1 */ UML_CMP(block, FLAG1, 0); UML_JMPc(block, COND_E, skip_label); break; case 0x0b: /* FLAG2 */ UML_CMP(block, FLAG2, 0); UML_JMPc(block, COND_E, skip_label); break; case 0x0c: /* FLAG3 */ UML_CMP(block, FLAG3, 0); UML_JMPc(block, COND_E, skip_label); break; case 0x0d: /* TF */ UML_TEST(block, ASTAT_BTF, 1); UML_JMPc(block, COND_E, skip_label); break; case 0x0e: /* BM */ UML_JMP(block, skip_label); break; case 0x0f: /* NOT LCE */ UML_CMP(block, CURLCNTR, 1); UML_JMPc(block, COND_E, skip_label); break; case 0x10: /* NOT EQUAL */ UML_TEST(block, ASTAT_AZ, 1); UML_JMPc(block, COND_NE, skip_label); break; case 0x11: /* GE */ not_skip = compiler->labelnum++; UML_TEST(block, ASTAT_AZ, 1); UML_JMPc(block, COND_NZ, not_skip); UML_TEST(block, ASTAT_AN, 1); UML_JMPc(block, COND_Z, not_skip); UML_JMP(block, skip_label); UML_LABEL(block, not_skip); break; case 0x12: /* GT */ UML_TEST(block, ASTAT_AZ, 1); UML_JMPc(block, COND_NZ, skip_label); UML_TEST(block, ASTAT_AN, 1); UML_JMPc(block, COND_NZ, skip_label); break; case 0x13: /* NOT AC */ UML_TEST(block, ASTAT_AC, 1); UML_JMPc(block, COND_NE, skip_label); break; case 0x14: /* NOT AV */ UML_TEST(block, ASTAT_AV, 1); UML_JMPc(block, COND_NE, skip_label); break; case 0x15: /* NOT MV */ UML_TEST(block, ASTAT_MV, 1); UML_JMPc(block, COND_NE, skip_label); break; case 0x16: /* NOT MS */ UML_TEST(block, ASTAT_MN, 1); UML_JMPc(block, COND_NE, skip_label); break; case 0x17: /* NOT SV */ UML_TEST(block, ASTAT_SV, 1); UML_JMPc(block, COND_NE, skip_label); break; case 0x18: /* NOT SZ */ UML_TEST(block, ASTAT_SZ, 1); UML_JMPc(block, COND_NE, skip_label); break; case 0x19: /* NOT FLAG0 */ UML_CMP(block, FLAG0, 0); UML_JMPc(block, COND_NE, skip_label); break; case 0x1a: /* NOT FLAG1 */ UML_CMP(block, FLAG1, 0); UML_JMPc(block, COND_NE, skip_label); break; case 0x1b: /* NOT FLAG2 */ UML_CMP(block, FLAG2, 0); UML_JMPc(block, COND_NE, skip_label); break; case 0x1c: /* NOT FLAG3 */ UML_CMP(block, FLAG3, 0); UML_JMPc(block, COND_NE, skip_label); break; case 0x1d: /* NOT TF */ UML_TEST(block, ASTAT_BTF, 1); UML_JMPc(block, COND_NE, skip_label); break; case 0x1e: /* NOT BM */ fatalerror("generate_if_condition 0x1e"); // should not happen break; case 0x1f: /* TRUE */ fatalerror("generate_if_condition 0x1f"); // should not happen break; } } void adsp21062_device::generate_do_condition(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int condition, int skip_label, ASTAT_DRC &astat) { // Jump to skip_label if condition is true code_label not_skip; switch (condition) { case 0x00: /* EQ */ UML_TEST(block, mem(&m_core->astat_delay_copy.az), 1); UML_JMPc(block, COND_NZ, skip_label); break; case 0x01: /* LT */ not_skip = compiler->labelnum++; UML_TEST(block, mem(&m_core->astat_delay_copy.az), 1); UML_JMPc(block, COND_NZ, not_skip); UML_TEST(block, mem(&m_core->astat_delay_copy.an), 1); UML_JMPc(block, COND_Z, not_skip); UML_JMP(block, skip_label); UML_LABEL(block, not_skip); break; case 0x02: /* LE */ UML_TEST(block, mem(&m_core->astat_delay_copy.az), 1); UML_JMPc(block, COND_NZ, skip_label); UML_TEST(block, mem(&m_core->astat_delay_copy.an), 1); UML_JMPc(block, COND_NZ, skip_label); break; case 0x03: /* AC */ UML_TEST(block, mem(&m_core->astat_delay_copy.ac), 1); UML_JMPc(block, COND_NZ, skip_label); break; case 0x04: /* AV */ UML_TEST(block, mem(&m_core->astat_delay_copy.av), 1); UML_JMPc(block, COND_NZ, skip_label); break; case 0x05: /* MV */ UML_TEST(block, mem(&m_core->astat_delay_copy.mv), 1); UML_JMPc(block, COND_NZ, skip_label); break; case 0x06: /* MS */ UML_TEST(block, mem(&m_core->astat_delay_copy.mn), 1); UML_JMPc(block, COND_NZ, skip_label); break; case 0x07: /* SV */ UML_TEST(block, mem(&m_core->astat_delay_copy.sv), 1); UML_JMPc(block, COND_NZ, skip_label); break; case 0x08: /* SZ */ UML_TEST(block, mem(&m_core->astat_delay_copy.sz), 1); UML_JMPc(block, COND_NZ, skip_label); break; case 0x09: /* FLAG0 */ UML_CMP(block, FLAG0, 0); UML_JMPc(block, COND_NE, skip_label); break; case 0x0a: /* FLAG1 */ UML_CMP(block, FLAG1, 0); UML_JMPc(block, COND_NE, skip_label); break; case 0x0b: /* FLAG2 */ UML_CMP(block, FLAG2, 0); UML_JMPc(block, COND_NE, skip_label); break; case 0x0c: /* FLAG3 */ UML_CMP(block, FLAG3, 0); UML_JMPc(block, COND_NE, skip_label); break; case 0x0d: /* TF */ UML_TEST(block, mem(&m_core->astat_delay_copy.btf), 1); UML_JMPc(block, COND_NZ, skip_label); break; case 0x0e: /* BM */ // infinite loop break; case 0x0f: /* LCE */ fatalerror("generate_do_condition 0x0f"); // this should only be used with counter loops break; case 0x10: /* NOT EQUAL */ UML_TEST(block, mem(&m_core->astat_delay_copy.az), 1); UML_JMPc(block, COND_Z, skip_label); break; case 0x11: /* GE */ UML_TEST(block, mem(&m_core->astat_delay_copy.az), 1); UML_JMPc(block, COND_NZ, skip_label); UML_TEST(block, mem(&m_core->astat_delay_copy.an), 1); UML_JMPc(block, COND_Z, skip_label); break; case 0x12: /* GT */ not_skip = compiler->labelnum++; UML_TEST(block, mem(&m_core->astat_delay_copy.az), 1); UML_JMPc(block, COND_NZ, not_skip); UML_TEST(block, mem(&m_core->astat_delay_copy.an), 1); UML_JMPc(block, COND_NZ, not_skip); UML_JMP(block, skip_label); UML_LABEL(block, not_skip); break; case 0x13: /* NOT AC */ UML_TEST(block, mem(&m_core->astat_delay_copy.ac), 1); UML_JMPc(block, COND_Z, skip_label); break; case 0x14: /* NOT AV */ UML_TEST(block, mem(&m_core->astat_delay_copy.av), 1); UML_JMPc(block, COND_Z, skip_label); break; case 0x15: /* NOT MV */ UML_TEST(block, mem(&m_core->astat_delay_copy.mv), 1); UML_JMPc(block, COND_Z, skip_label); break; case 0x16: /* NOT MS */ UML_TEST(block, mem(&m_core->astat_delay_copy.mn), 1); UML_JMPc(block, COND_Z, skip_label); break; case 0x17: /* NOT SV */ UML_TEST(block, mem(&m_core->astat_delay_copy.sv), 1); UML_JMPc(block, COND_Z, skip_label); break; case 0x18: /* NOT SZ */ UML_TEST(block, mem(&m_core->astat_delay_copy.sz), 1); UML_JMPc(block, COND_Z, skip_label); break; case 0x19: /* NOT FLAG0 */ UML_CMP(block, FLAG0, 0); UML_JMPc(block, COND_E, skip_label); break; case 0x1a: /* NOT FLAG1 */ UML_CMP(block, FLAG1, 0); UML_JMPc(block, COND_E, skip_label); break; case 0x1b: /* NOT FLAG2 */ UML_CMP(block, FLAG2, 0); UML_JMPc(block, COND_E, skip_label); break; case 0x1c: /* NOT FLAG3 */ UML_CMP(block, FLAG3, 0); UML_JMPc(block, COND_E, skip_label); break; case 0x1d: /* NOT TF */ UML_TEST(block, mem(&m_core->astat_delay_copy.btf), 1); UML_JMPc(block, COND_Z, skip_label); break; case 0x1e: /* NOT BM */ // always true UML_JMP(block, skip_label); break; case 0x1f: /* FALSE (FOREVER) */ // infinite loop break; } } void adsp21062_device::generate_shift_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int data, int shiftop, int rn, int rx) { INT8 shift = data & 0xff; int bit = data & 0x3f; int len = (data >> 6) & 0x3f; switch (shiftop) { case 0x11: // FDEP Rx BY : case 0x13: // FDEP Rx BY : (SE) case 0x1b: // Rn = Rn OR FDEP Rx BY : (SE) UML_MOV(block, mem(&m_core->pc), desc->pc); UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); UML_CALLC(block, cfunc_unimplemented_shiftimm, this); break; case 0x00: // LSHIFT Rx BY if (abs(shift) >= 32) { UML_MOV(block, REG(rn), 0); if (SZ_CALC_REQUIRED) UML_MOV(block, ASTAT_SZ, 1); if (SV_CALC_REQUIRED) UML_MOV(block, ASTAT_SV, 1); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); } else { if (shift < 0) UML_SHR(block, REG(rn), REG(rx), -shift); else UML_SHL(block, REG(rn), REG(rx), shift); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED && shift != 0) UML_MOV(block, ASTAT_SV, 1); if (SV_CALC_REQUIRED && shift == 0) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); } return; case 0x01: // ASHIFT Rx BY if (abs(shift) >= 32) { UML_MOV(block, REG(rn), 0); UML_TEST(block, REG(rn), 0x80000000); UML_MOVc(block, COND_NZ, REG(rn), 0xffffffff); if (SZ_CALC_REQUIRED) UML_MOV(block, ASTAT_SZ, 1); if (SV_CALC_REQUIRED) UML_MOV(block, ASTAT_SV, 1); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); } else { if (shift < 0) UML_SAR(block, REG(rn), REG(rx), -shift); else UML_SHL(block, REG(rn), REG(rx), shift); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED && shift != 0) UML_MOV(block, ASTAT_SV, 1); if (SV_CALC_REQUIRED && shift == 0) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); } return; case 0x02: // ROT Rx BY if (shift < 0) UML_ROR(block, REG(rn), REG(rx), (-shift) & 0x1f); else UML_ROL(block, REG(rn), REG(rx), shift & 0x1f); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; case 0x08: // Rn = Rn OR LSHIFT Rx BY if (abs(shift) >= 32) { UML_MOV(block, I0, 0); if (SZ_CALC_REQUIRED) UML_MOV(block, ASTAT_SZ, 1); if (SV_CALC_REQUIRED) UML_MOV(block, ASTAT_SV, 1); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); UML_OR(block, REG(rn), REG(rn), I0); } else { if (shift < 0) UML_SHR(block, I0, REG(rx), -shift); else UML_SHL(block, I0, REG(rx), shift); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED && shift != 0) UML_MOV(block, ASTAT_SV, 1); if (SV_CALC_REQUIRED && shift == 0) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); UML_OR(block, REG(rn), REG(rn), I0); } return; case 0x10: // FEXT Rx BY : if (bit == 0) { UML_AND(block, REG(rn), REG(rx), MAKE_EXTRACT_MASK(bit, len)); } else { UML_AND(block, I0, REG(rx), MAKE_EXTRACT_MASK(bit, len)); UML_SHR(block, REG(rn), I0, bit); } if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED && (bit + len) > 32) UML_MOV(block, ASTAT_SV, 1); if (SV_CALC_REQUIRED && (bit + len) <= 32) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; case 0x12: // FEXT Rx BY : (SE) UML_AND(block, I0, REG(rx), MAKE_EXTRACT_MASK(bit, len)); UML_SHL(block, I0, I0, 32 - (bit + len)); UML_SAR(block, REG(rn), I0, 32 - (bit + len) + bit); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED && (bit + len) > 32) UML_MOV(block, ASTAT_SV, 1); if (SV_CALC_REQUIRED && (bit + len) <= 32) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; case 0x19: // Rn = Rn OR FDEP Rx BY : UML_AND(block, I0, REG(rx), MAKE_EXTRACT_MASK(0, len)); if (bit > 0) UML_SHL(block, I0, I0, bit); UML_OR(block, REG(rn), REG(rn), I0); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED && (bit + len) > 32) UML_MOV(block, ASTAT_SV, 1); if (SV_CALC_REQUIRED && (bit + len) <= 32) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; case 0x30: // BSET Rx BY UML_OR(block, REG(rn), REG(rx), 1 << data); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED && data > 31) UML_MOV(block, ASTAT_SV, 1); if (SV_CALC_REQUIRED && data <= 31) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; case 0x31: // BCLR Rx By UML_AND(block, REG(rn), REG(rx), ~(1 << data)); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED && data > 31) UML_MOV(block, ASTAT_SV, 1); if (SV_CALC_REQUIRED && data <= 31) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; case 0x32: // BTGL Rx BY UML_XOR(block, REG(rn), REG(rx), 1 << data); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED && data > 31) UML_MOV(block, ASTAT_SV, 1); if (SV_CALC_REQUIRED && data <= 31) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; case 0x33: // BTST Rx BY UML_TEST(block, REG(rx), 1 << data); if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); if (SV_CALC_REQUIRED && data > 31) UML_MOV(block, ASTAT_SV, 1); if (SV_CALC_REQUIRED && data <= 31) UML_MOV(block, ASTAT_SV, 0); if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); return; default: UML_MOV(block, mem(&m_core->pc), desc->pc); UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); UML_CALLC(block, cfunc_unimplemented_compute, this); return; } }