mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
cpu/mips: Fixed memory access handling in the IDT MIPS R4650 core. (#11065) [Ryan Holtz]
Correctly support the R4650's lack of TLB.
This commit is contained in:
parent
8aabc8f527
commit
fe00ebe1cb
@ -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<util::disasm_interface> mips3_device::create_disassembler()
|
||||
{
|
||||
return std::make_unique<mips3_disassembler>();
|
||||
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
|
Loading…
Reference in New Issue
Block a user