diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index becb973bc08..2775353b1a0 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -243,7 +243,7 @@ void mips3_device::generate_exception(int exception, int backup) if (exception != 0) { - fprintf(stderr, "Exception: PC=%08X, PPC=%08X\n", m_core->pc, m_ppc); + fprintf(stderr, "Exception type %d: PC=%08X, PPC=%08X\n", exception, m_core->pc, m_ppc); machine().debug_break(); } */ @@ -1159,6 +1159,12 @@ bool mips3_device::memory_translate(int spacenum, int intention, offs_t &address return true; } +bool r4650_device::memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) +{ + target_space = &space(spacenum); + return true; +} + std::unique_ptr mips3_device::create_disassembler() { return std::make_unique(); @@ -1517,6 +1523,178 @@ inline void mips3_device::WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t } } +inline bool r4650_device::RBYTE(offs_t address, uint32_t *result) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = (*m_memory.read_byte)(*m_program, address); + return true; + } + + if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = (*m_memory.read_byte)(*m_program, address + m_core->cpr[0][COP0_R4650_DBase]); + return true; +} + +inline bool r4650_device::RHALF(offs_t address, uint32_t *result) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = (*m_memory.read_word)(*m_program, address); + return true; + } + + if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = (*m_memory.read_word)(*m_program, address + m_core->cpr[0][COP0_R4650_DBase]); + return true; +} + +inline bool r4650_device::RWORD(offs_t address, uint32_t *result, bool insn) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = (*m_memory.read_dword)(*m_program, address); + return true; + } + + static const uint32_t BASE_INDICES[2] = { COP0_R4650_DBase, COP0_R4650_IBase }; + static const uint32_t BOUND_INDICES[2] = { COP0_R4650_DBound, COP0_R4650_IBound }; + const uint32_t base = m_core->cpr[0][BASE_INDICES[insn]]; + const uint32_t bound = m_core->cpr[0][BOUND_INDICES[insn]]; + if ((address & 0xfffff000) > bound) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = (*m_memory.read_dword)(*m_program, address + base); + return true; +} + +inline bool r4650_device::RWORD_MASKED(offs_t address, uint32_t *result, uint32_t mem_mask) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = (*m_memory.read_dword_masked)(*m_program, address, mem_mask); + return true; + } + + if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = (*m_memory.read_dword_masked)(*m_program, address + m_core->cpr[0][COP0_R4650_DBase], mem_mask); + return true; +} + +inline bool r4650_device::RDOUBLE(offs_t address, uint64_t *result) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = (*m_memory.read_qword)(*m_program, address); + return true; + } + + if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = (*m_memory.read_qword)(*m_program, address + m_core->cpr[0][COP0_R4650_DBase]); + return true; +} + +inline bool r4650_device::RDOUBLE_MASKED(offs_t address, uint64_t *result, uint64_t mem_mask) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + { + *result = (*m_memory.read_qword_masked)(*m_program, address, mem_mask); + return true; + } + + if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + { + generate_tlb_exception(EXCEPTION_ADDRLOAD, address); + *result = 0; + return false; + } + *result = (*m_memory.read_qword_masked)(*m_program, address + m_core->cpr[0][COP0_R4650_DBase], mem_mask); + return true; +} + +inline void r4650_device::WBYTE(offs_t address, uint8_t data) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + (*m_memory.write_byte)(*m_program, address, data); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + (*m_memory.write_byte)(*m_program, address + m_core->cpr[0][COP0_R4650_DBound], data); +} + +inline void r4650_device::WHALF(offs_t address, uint16_t data) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + (*m_memory.write_word)(*m_program, address, data); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + (*m_memory.write_word)(*m_program, address + m_core->cpr[0][COP0_R4650_DBound], data); +} + +inline void r4650_device::WWORD(offs_t address, uint32_t data) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + (*m_memory.write_dword)(*m_program, address, data); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + (*m_memory.write_dword)(*m_program, address + m_core->cpr[0][COP0_R4650_DBound], data); +} + +inline void r4650_device::WWORD_MASKED(offs_t address, uint32_t data, uint32_t mem_mask) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + (*m_memory.write_dword_masked)(*m_program, address, data, mem_mask); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + (*m_memory.write_dword_masked)(*m_program, address + m_core->cpr[0][COP0_R4650_DBound], data, mem_mask); +} + +inline void r4650_device::WDOUBLE(offs_t address, uint64_t data) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + (*m_memory.write_qword)(*m_program, address, data); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + (*m_memory.write_qword)(*m_program, address + m_core->cpr[0][COP0_R4650_DBound], data); +} + +inline void r4650_device::WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask) +{ + if ((SR & SR_KSU_USER) == SR_KSU_KERNEL) + (*m_memory.write_qword_masked)(*m_program, address, data, mem_mask); + else if ((address & 0xfffff000) > m_core->cpr[0][COP0_R4650_DBound]) + generate_tlb_exception(EXCEPTION_ADDRSTORE, address); + else + (*m_memory.write_qword_masked)(*m_program, address + m_core->cpr[0][COP0_R4650_DBound], data, mem_mask); +} + inline void r5900le_device::WBYTE(offs_t address, uint8_t data) { if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_byte)(*m_program, address, data); @@ -1713,6 +1891,22 @@ uint64_t mips3_device::get_cop0_reg(int idx) return m_core->cpr[0][idx]; } +void r4650_device::set_cop0_reg(int idx, uint64_t val) +{ + switch (idx) + { + case COP0_R4650_IBase: + case COP0_R4650_IBound: + case COP0_R4650_DBase: + case COP0_R4650_DBound: + m_core->cpr[0][idx] = val; + break; + default: + mips3_device::set_cop0_reg(idx, val); + break; + } +} + void mips3_device::set_cop0_reg(int idx, uint64_t val) { switch (idx) diff --git a/src/devices/cpu/mips/mips3.h b/src/devices/cpu/mips/mips3.h index bfee20c7f7c..cb78b56e8f3 100644 --- a/src/devices/cpu/mips/mips3.h +++ b/src/devices/cpu/mips/mips3.h @@ -352,6 +352,8 @@ protected: virtual void WDOUBLE(offs_t address, uint64_t data); virtual void WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask); + virtual void set_cop0_reg(int idx, uint64_t val); + struct internal_mips3_state { /* core registers */ uint32_t pc; @@ -519,6 +521,12 @@ protected: void generate_exception(int exception, int backup); void generate_tlb_exception(int exception, offs_t address); + + void static_generate_memory_mode_checks(drcuml_block &block, uml::code_handle &exception_addrerr, int &label, int mode); + void static_generate_fastram_accessor(drcuml_block &block, int &label, int size, bool iswrite, bool ismasked); + void static_generate_memory_rw(drcuml_block &block, int size, bool iswrite, bool ismasked); + virtual void static_generate_memory_accessor(int mode, int size, bool iswrite, bool ismasked, const char *name, uml::code_handle *&handleptr); + virtual void check_irqs(); virtual void handle_mult(uint32_t op); virtual void handle_multu(uint32_t op); @@ -539,7 +547,6 @@ private: void tlb_write_common(int tlbindex); uint64_t get_cop0_reg(int idx); - void set_cop0_reg(int idx, uint64_t val); uint64_t get_cop0_creg(int idx); void set_cop0_creg(int idx, uint64_t val); void handle_cop0(uint32_t op); @@ -620,7 +627,6 @@ private: void static_generate_out_of_cycles(); void static_generate_tlb_mismatch(); void static_generate_exception(uint8_t exception, int recover, const char *name); - void static_generate_memory_accessor(int mode, int size, int iswrite, int ismasked, const char *name, uml::code_handle *&handleptr); void generate_update_mode(drcuml_block &block); void generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception); @@ -745,20 +751,49 @@ public: } }; -class r4650be_device : public mips3_device { +class r4650_device : public mips3_device { +public: + // construction/destruction + r4650_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness) + : mips3_device(mconfig, type, tag, owner, clock, MIPS3_TYPE_R4650, endianness, 32) // Should be 64 bits + { + } + +protected: + virtual bool memory_translate(int spacenum, int intention, offs_t &address, address_space *&target_space) override; + + virtual void static_generate_memory_accessor(int mode, int size, bool iswrite, bool ismasked, const char *name, uml::code_handle *&handleptr) override; + + virtual bool RBYTE(offs_t address, uint32_t *result) override; + virtual bool RHALF(offs_t address, uint32_t *result) override; + virtual bool RWORD(offs_t address, uint32_t *result, bool insn = false) override; + virtual bool RWORD_MASKED(offs_t address, uint32_t *result, uint32_t mem_mask) override; + virtual bool RDOUBLE(offs_t address, uint64_t *result) override; + virtual bool RDOUBLE_MASKED(offs_t address, uint64_t *result, uint64_t mem_mask) override; + virtual void WBYTE(offs_t address, uint8_t data) override; + virtual void WHALF(offs_t address, uint16_t data) override; + virtual void WWORD(offs_t address, uint32_t data) override; + virtual void WWORD_MASKED(offs_t address, uint32_t data, uint32_t mem_mask) override; + virtual void WDOUBLE(offs_t address, uint64_t data) override; + virtual void WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask) override; + + virtual void set_cop0_reg(int idx, uint64_t val) override; +}; + +class r4650be_device : public r4650_device { public: // construction/destruction r4650be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : mips3_device(mconfig, R4650BE, tag, owner, clock, MIPS3_TYPE_R4650, ENDIANNESS_BIG, 32) // Should be 64 bits + : r4650_device(mconfig, R4650BE, tag, owner, clock, ENDIANNESS_BIG) { } }; -class r4650le_device : public mips3_device { +class r4650le_device : public r4650_device { public: // construction/destruction r4650le_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : mips3_device(mconfig, R4650LE, tag, owner, clock, MIPS3_TYPE_R4650, ENDIANNESS_LITTLE, 32) // Should be 64 bits + : r4650_device(mconfig, R4650LE, tag, owner, clock, ENDIANNESS_LITTLE) { } }; diff --git a/src/devices/cpu/mips/mips3com.h b/src/devices/cpu/mips/mips3com.h index 343e161ee68..8976f42575f 100644 --- a/src/devices/cpu/mips/mips3com.h +++ b/src/devices/cpu/mips/mips3com.h @@ -107,6 +107,10 @@ #define COP0_TagLo 28 #define COP0_TagHi 29 #define COP0_ErrorPC 30 +#define COP0_R4650_IBase 0 +#define COP0_R4650_IBound 1 +#define COP0_R4650_DBase 2 +#define COP0_R4650_DBound 3 /* Status register bits */ #define SR_IE 0x00000001 diff --git a/src/devices/cpu/mips/mips3drc.cpp b/src/devices/cpu/mips/mips3drc.cpp index 399df424ae6..1b1683b8d65 100644 --- a/src/devices/cpu/mips/mips3drc.cpp +++ b/src/devices/cpu/mips/mips3drc.cpp @@ -828,120 +828,106 @@ void mips3_device::static_generate_exception(uint8_t exception, int recover, con /*------------------------------------------------------------------ - static_generate_memory_accessor + static_generate_memory_mode_checks ------------------------------------------------------------------*/ -void mips3_device::static_generate_memory_accessor(int mode, int size, int iswrite, int ismasked, const char *name, uml::code_handle *&handleptr) +void mips3_device::static_generate_memory_mode_checks(drcuml_block &block, uml::code_handle &exception_addrerr, int &label, int mode) { - /* on entry, address is in I0; data for writes is in I1; mask for accesses is in I2 */ - /* on exit, read result is in I0 */ - /* routine trashes I0-I3 */ - uml::code_handle &exception_tlb = *m_exception[iswrite ? EXCEPTION_TLBSTORE : EXCEPTION_TLBLOAD]; - uml::code_handle &exception_tlbfill = *m_exception[iswrite ? EXCEPTION_TLBSTORE_FILL : EXCEPTION_TLBLOAD_FILL]; - uml::code_handle &exception_addrerr = *m_exception[iswrite ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD]; - int tlbmiss = 0; - int label = 1; - int ramnum; - - /* begin generating */ - drcuml_block &block(m_drcuml->begin_block(1024)); - - /* add a global entry for this */ - alloc_handle(*m_drcuml, handleptr, name); - UML_HANDLE(block, *handleptr); // handle handleptr - /* user mode? generate address exception if top bit is set */ if (mode == MODE_USER) { - UML_TEST(block, I0, 0x80000000); // test i0,0x80000000 - UML_EXHc(block, COND_NZ, exception_addrerr, I0); // exh addrerr,i0,nz + UML_TEST(block, I0, 0x80000000); // test i0,0x80000000 + UML_EXHc(block, COND_NZ, exception_addrerr, I0); // exh addrerr,i0,nz } /* supervisor mode? generate address exception if not in user space or in $C0000000-DFFFFFFF */ if (mode == MODE_SUPER) { int addrok; - UML_TEST(block, I0, 0x80000000); // test i0,0x80000000 + UML_TEST(block, I0, 0x80000000); // test i0,0x80000000 UML_JMPc(block, COND_Z, addrok = label++); // jz addrok - UML_SHR(block, I3, I0, 29); // shr i3,i0,29 - UML_CMP(block, I3, 6); // cmp i3,6 + UML_SHR(block, I3, I0, 29); // shr i3,i0,29 + UML_CMP(block, I3, 6); // cmp i3,6 UML_EXHc(block, COND_NE, exception_addrerr, I0); // exh addrerr,i0,ne - UML_LABEL(block, addrok); // addrok: + UML_LABEL(block, addrok); // addrok: } +} - /* general case: assume paging and perform a translation */ - UML_SHR(block, I3, I0, 12); // shr i3,i0,12 - UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb_table],i3,dword - UML_TEST(block, I3, iswrite ? WRITE_ALLOWED : READ_ALLOWED);// test i3,iswrite ? WRITE_ALLOWED : READ_ALLOWED - UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z - UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000 +/*------------------------------------------------------------------ + static_generate_fastram_accessor +------------------------------------------------------------------*/ + +void mips3_device::static_generate_fastram_accessor(drcuml_block &block, int &label, int size, bool iswrite, bool ismasked) +{ if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0) - for (ramnum = 0; ramnum < m_fastram_select; ramnum++) + { + for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) + { if (!(iswrite && m_fastram[ramnum].readonly)) { void *fastbase = (uint8_t *)m_fastram[ramnum].base - m_fastram[ramnum].start; uint32_t skip = label++; if (m_fastram[ramnum].end != 0xffffffff) { - UML_CMP(block, I0, m_fastram[ramnum].end); // cmp i0,end - UML_JMPc(block, COND_A, skip); // ja skip + UML_CMP(block, I0, m_fastram[ramnum].end); // cmp i0,end + UML_JMPc(block, COND_A, skip); // ja skip } if (m_fastram[ramnum].start != 0x00000000) { - UML_CMP(block, I0, m_fastram[ramnum].start);// cmp i0,fastram_start - UML_JMPc(block, COND_B, skip); // jb skip + UML_CMP(block, I0, m_fastram[ramnum].start); // cmp i0,fastram_start + UML_JMPc(block, COND_B, skip); // jb skip } if (!iswrite) { if (size == 1) { UML_XOR(block, I0, I0, m_bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0)); - // xor i0,i0,bytexor - UML_LOAD(block, I0, fastbase, I0, SIZE_BYTE, SCALE_x1); // load i0,fastbase,i0,byte + // xor i0,i0,bytexor + UML_LOAD(block, I0, fastbase, I0, SIZE_BYTE, SCALE_x1); // load i0,fastbase,i0,byte } else if (size == 2) { UML_XOR(block, I0, I0, m_bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0)); - // xor i0,i0,wordxor - UML_LOAD(block, I0, fastbase, I0, SIZE_WORD, SCALE_x1); // load i0,fastbase,i0,word_x1 + // xor i0,i0,wordxor + UML_LOAD(block, I0, fastbase, I0, SIZE_WORD, SCALE_x1); // load i0,fastbase,i0,word_x1 } else if (size == 4) { - UML_LOAD(block, I0, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i0,fastbase,i0,dword_x1 + UML_LOAD(block, I0, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i0,fastbase,i0,dword_x1 } else if (size == 8) { - UML_DLOAD(block, I0, fastbase, I0, SIZE_QWORD, SCALE_x1); // dload i0,fastbase,i0,qword_x1 + UML_DLOAD(block, I0, fastbase, I0, SIZE_QWORD, SCALE_x1); // dload i0,fastbase,i0,qword_x1 UML_DROR(block, I0, I0, 32 * (m_bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0))); - // dror i0,i0,32*bytexor + // dror i0,i0,32*bytexor } - UML_RET(block); // ret + UML_RET(block); // ret } else { if (size == 1) { UML_XOR(block, I0, I0, m_bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0)); - // xor i0,i0,bytexor - UML_STORE(block, fastbase, I0, I1, SIZE_BYTE, SCALE_x1);// store fastbase,i0,i1,byte + // xor i0,i0,bytexor + UML_STORE(block, fastbase, I0, I1, SIZE_BYTE, SCALE_x1); // store fastbase,i0,i1,byte } else if (size == 2) { UML_XOR(block, I0, I0, m_bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0)); - // xor i0,i0,wordxor - UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1);// store fastbase,i0,i1,word_x1 + // xor i0,i0,wordxor + UML_STORE(block, fastbase, I0, I1, SIZE_WORD, SCALE_x1); // store fastbase,i0,i1,word_x1 } else if (size == 4) { if (ismasked) { - UML_LOAD(block, I3, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i3,fastbase,i0,dword_x1 - UML_ROLINS(block, I3, I1, 0, I2); // rolins i3,i1,0,i2 - UML_STORE(block, fastbase, I0, I3, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i3,dword_x1 + UML_LOAD(block, I3, fastbase, I0, SIZE_DWORD, SCALE_x1); // load i3,fastbase,i0,dword_x1 + UML_ROLINS(block, I3, I1, 0, I2); // rolins i3,i1,0,i2 + UML_STORE(block, fastbase, I0, I3, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i3,dword_x1 } else - UML_STORE(block, fastbase, I0, I1, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i1,dword_x1 + UML_STORE(block, fastbase, I0, I1, SIZE_DWORD, SCALE_x1); // store fastbase,i0,i1,dword_x1 } else if (size == 8) { @@ -951,8 +937,8 @@ void mips3_device::static_generate_memory_accessor(int mode, int size, int iswri { UML_DROR(block, I2, I2, 32 * (m_bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0))); // dror i2,i2,32*bytexor - UML_DLOAD(block, I3, fastbase, I0, SIZE_QWORD, SCALE_x1); // dload i3,fastbase,i0,qword_x1 - UML_DROLINS(block, I3, I1, 0, I2); // drolins i3,i1,0,i2 + UML_DLOAD(block, I3, fastbase, I0, SIZE_QWORD, SCALE_x1); // dload i3,fastbase,i0,qword_x1 + UML_DROLINS(block, I3, I1, 0, I2); // drolins i3,i1,0,i2 UML_DSTORE(block, fastbase, I0, I3, SIZE_QWORD, SCALE_x1); // dstore fastbase,i0,i3,qword_x1 } else @@ -961,9 +947,19 @@ void mips3_device::static_generate_memory_accessor(int mode, int size, int iswri UML_RET(block); // ret } - UML_LABEL(block, skip); // skip: + UML_LABEL(block, skip); // skip: } + } + } +} + +/*------------------------------------------------------------------ + static_generate_memory_rw +------------------------------------------------------------------*/ + +void mips3_device::static_generate_memory_rw(drcuml_block &block, int size, bool iswrite, bool ismasked) +{ switch (size) { case 1: @@ -984,9 +980,9 @@ void mips3_device::static_generate_memory_accessor(int mode, int size, int iswri if (iswrite) { if (!ismasked) - UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM); // write i0,i1,program_dword + UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_PROGRAM); // write i0,i1,program_dword else - UML_WRITEM(block, I0, I1, I2, SIZE_DWORD, SPACE_PROGRAM); // writem i0,i1,i2,program_dword + UML_WRITEM(block, I0, I1, I2, SIZE_DWORD, SPACE_PROGRAM); // writem i0,i1,i2,program_dword } else { @@ -1001,38 +997,104 @@ void mips3_device::static_generate_memory_accessor(int mode, int size, int iswri if (iswrite) { if (!ismasked) - UML_DWRITE(block, I0, I1, SIZE_QWORD, SPACE_PROGRAM); // dwrite i0,i1,program_qword + UML_DWRITE(block, I0, I1, SIZE_QWORD, SPACE_PROGRAM); // dwrite i0,i1,program_qword else - UML_DWRITEM(block, I0, I1, I2, SIZE_QWORD, SPACE_PROGRAM); // dwritem i0,i1,i2,program_qword + UML_DWRITEM(block, I0, I1, I2, SIZE_QWORD, SPACE_PROGRAM); // dwritem i0,i1,i2,program_qword } else { if (!ismasked) - UML_DREAD(block, I0, I0, SIZE_QWORD, SPACE_PROGRAM); // dread i0,i0,program_qword + UML_DREAD(block, I0, I0, SIZE_QWORD, SPACE_PROGRAM); // dread i0,i0,program_qword else - UML_DREADM(block, I0, I0, I2, SIZE_QWORD, SPACE_PROGRAM); // dreadm i0,i0,i2,program_qword + UML_DREADM(block, I0, I0, I2, SIZE_QWORD, SPACE_PROGRAM); // dreadm i0,i0,i2,program_qword } break; } UML_RET(block); // ret +} + + +/*------------------------------------------------------------------ + static_generate_memory_accessor +------------------------------------------------------------------*/ + +void mips3_device::static_generate_memory_accessor(int mode, int size, bool iswrite, bool ismasked, const char *name, uml::code_handle *&handleptr) +{ + /* on entry, address is in I0; data for writes is in I1; mask for accesses is in I2 */ + /* on exit, read result is in I0 */ + /* routine trashes I0-I3 */ + uml::code_handle &exception_tlb = *m_exception[iswrite ? EXCEPTION_TLBSTORE : EXCEPTION_TLBLOAD]; + uml::code_handle &exception_tlbfill = *m_exception[iswrite ? EXCEPTION_TLBSTORE_FILL : EXCEPTION_TLBLOAD_FILL]; + uml::code_handle &exception_addrerr = *m_exception[iswrite ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD]; + int tlbmiss = 0; + int label = 1; + + /* begin generating */ + drcuml_block &block(m_drcuml->begin_block(1024)); + + /* add a global entry for this */ + alloc_handle(*m_drcuml, handleptr, name); + UML_HANDLE(block, *handleptr); // handle handleptr + + static_generate_memory_mode_checks(block, exception_addrerr, label, mode); + + /* general case: assume paging and perform a translation */ + UML_SHR(block, I3, I0, 12); // shr i3,i0,12 + UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4); // load i3,[vtlb_table],i3,dword + UML_TEST(block, I3, iswrite ? WRITE_ALLOWED : READ_ALLOWED); // test i3,iswrite ? WRITE_ALLOWED : READ_ALLOWED + UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z + UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000 + + static_generate_fastram_accessor(block, label, size, iswrite, ismasked); + static_generate_memory_rw(block, size, iswrite, ismasked); if (tlbmiss != 0) { - UML_LABEL(block, tlbmiss); // tlbmiss: + UML_LABEL(block, tlbmiss); // tlbmiss: if (iswrite) { - UML_TEST(block, I3, READ_ALLOWED); // test i3,READ_ALLOWED - UML_EXHc(block, COND_NZ, *m_exception[EXCEPTION_TLBMOD], I0); - // exh tlbmod,i0,nz + UML_TEST(block, I3, READ_ALLOWED); // test i3,READ_ALLOWED + UML_EXHc(block, COND_NZ, *m_exception[EXCEPTION_TLBMOD], I0); // exh tlbmod,i0,nz } - UML_TEST(block, I3, FLAG_FIXED); // test i3,FLAG_FIXED + UML_TEST(block, I3, FLAG_FIXED); // test i3,FLAG_FIXED UML_EXHc(block, COND_NZ, exception_tlb, I0); // exh tlb,i0,nz - UML_EXH(block, exception_tlbfill, I0); // exh tlbfill,i0 + UML_EXH(block, exception_tlbfill, I0); // exh tlbfill,i0 } block.end(); } +void r4650_device::static_generate_memory_accessor(int mode, int size, bool iswrite, bool ismasked, const char *name, uml::code_handle *&handleptr) +{ + /* on entry, address is in I0; data for writes is in I1; mask for accesses is in I2 */ + /* on exit, read result is in I0 */ + /* routine trashes I0-I3 */ + uml::code_handle &exception_addrerr = *m_exception[iswrite ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD]; + int label = 1; + + /* begin generating */ + drcuml_block &block(m_drcuml->begin_block(1024)); + + /* add a global entry for this */ + alloc_handle(*m_drcuml, handleptr, name); + UML_HANDLE(block, *handleptr); // handle handleptr + + static_generate_memory_mode_checks(block, exception_addrerr, label, mode); + + if (mode == MODE_USER) + { + int addrok; + UML_CMP(block, I0, CPR032(COP0_R4650_DBound)); // cmp i0,CPR0[DBound] + UML_JMPc(block, COND_LE, addrok = label++); // jle addrok + UML_EXHc(block, COND_G, exception_addrerr, I0); // exh addrerr,i0,ne + UML_LABEL(block, addrok); // addrok: + UML_ADD(block, I0, I0, CPR032(COP0_R4650_DBase)); // add i0,i0,CPR0[DBase] + } + + static_generate_fastram_accessor(block, label, size, iswrite, ismasked); + static_generate_memory_rw(block, size, iswrite, ismasked); + block.end(); +} /***************************************************************************