cpu/drcbex86.cpp: Don't use static address space accessors.  This gives
a big performance improvement.

cpu/drcbeut.cpp: Made failure to resolve address space accessors fatal.

cpu/drcbearm64.cpp: Removed fallback to static address space accessors.

cpu/mips3/mibs3.cpp: Removed static address space accessors.  All they
were doing was hurting performance.

cpu/drcbex64.cpp: Don't use goofy X64_WINDOWS_ABI macro, just check
_WIN32.  The only other environment that uses the Windows calling
convention is (U)EFI, and we can move feature detection to util/abi.h if
we ever need to care about it.
This commit is contained in:
Vas Crabb 2025-02-03 08:02:40 +11:00
parent bf7061a27e
commit 32736e4c43
10 changed files with 395 additions and 434 deletions

View File

@ -1680,7 +1680,6 @@ CPPCHECK_PARAMS += -I3rdparty/bx/include
CPPCHECK_PARAMS += -I$(BUILDDIR)/generated/emu
CPPCHECK_PARAMS += -I$(BUILDDIR)/generated/emu/layout
CPPCHECK_PARAMS += -I$(BUILDDIR)/generated/mame/layout
CPPCHECK_PARAMS += -DX64_WINDOWS_ABI
CPPCHECK_PARAMS += -DPTR64=1
CPPCHECK_PARAMS += -DMAME_DEBUG
CPPCHECK_PARAMS += -DMAME_PROFILER

View File

@ -2054,66 +2054,29 @@ void drcbe_arm64::op_read(a64::Assembler &a, const uml::instruction &inst)
const parameter &spacesizep = inst.param(2);
assert(spacesizep.is_size_space());
const auto &trampolines = m_accessors[spacesizep.space()];
const auto &resolved = m_resolved_accessors[spacesizep.space()];
mov_reg_param(a, 4, REG_PARAM2, addrp);
if (spacesizep.size() == SIZE_BYTE)
{
if (resolved.read_byte)
{
get_imm_relative(a, REG_PARAM1, resolved.read_byte.obj);
call_arm_addr(a, resolved.read_byte.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.read_byte);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.read_byte.obj);
call_arm_addr(a, resolved.read_byte.func);
}
else if (spacesizep.size() == SIZE_WORD)
{
if (resolved.read_word)
{
get_imm_relative(a, REG_PARAM1, resolved.read_word.obj);
call_arm_addr(a, resolved.read_word.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.read_word);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.read_word.obj);
call_arm_addr(a, resolved.read_word.func);
}
else if (spacesizep.size() == SIZE_DWORD)
{
if (resolved.read_dword)
{
get_imm_relative(a, REG_PARAM1, resolved.read_dword.obj);
call_arm_addr(a, resolved.read_dword.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.read_dword);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.read_dword.obj);
call_arm_addr(a, resolved.read_dword.func);
}
else if (spacesizep.size() == SIZE_QWORD)
{
if (resolved.read_qword)
{
get_imm_relative(a, REG_PARAM1, resolved.read_qword.obj);
call_arm_addr(a, resolved.read_qword.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.read_qword);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.read_qword.obj);
call_arm_addr(a, resolved.read_qword.func);
}
mov_param_reg(a, inst.size(), dstp, REG_PARAM1);
@ -2131,7 +2094,6 @@ void drcbe_arm64::op_readm(a64::Assembler &a, const uml::instruction &inst)
const parameter &spacesizep = inst.param(3);
assert(spacesizep.is_size_space());
const auto &trampolines = m_accessors[spacesizep.space()];
const auto &resolved = m_resolved_accessors[spacesizep.space()];
mov_reg_param(a, 4, REG_PARAM2, addrp);
@ -2139,59 +2101,23 @@ void drcbe_arm64::op_readm(a64::Assembler &a, const uml::instruction &inst)
if (spacesizep.size() == SIZE_BYTE)
{
if (resolved.read_byte_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.read_byte_masked.obj);
call_arm_addr(a, resolved.read_byte_masked.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.read_byte_masked);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.read_byte_masked.obj);
call_arm_addr(a, resolved.read_byte_masked.func);
}
else if (spacesizep.size() == SIZE_WORD)
{
if (resolved.read_word_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.read_word_masked.obj);
call_arm_addr(a, resolved.read_word_masked.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.read_word_masked);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.read_word_masked.obj);
call_arm_addr(a, resolved.read_word_masked.func);
}
else if (spacesizep.size() == SIZE_DWORD)
{
if (resolved.read_dword_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.read_dword_masked.obj);
call_arm_addr(a, resolved.read_dword_masked.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.read_dword_masked);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.read_dword_masked.obj);
call_arm_addr(a, resolved.read_dword_masked.func);
}
else if (spacesizep.size() == SIZE_QWORD)
{
if (resolved.read_qword_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.read_qword_masked.obj);
call_arm_addr(a, resolved.read_qword_masked.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.read_qword_masked);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.read_qword_masked.obj);
call_arm_addr(a, resolved.read_qword_masked.func);
}
mov_param_reg(a, inst.size(), dstp, REG_PARAM1);
@ -2208,7 +2134,6 @@ void drcbe_arm64::op_write(a64::Assembler &a, const uml::instruction &inst)
const parameter &spacesizep = inst.param(2);
assert(spacesizep.is_size_space());
const auto &trampolines = m_accessors[spacesizep.space()];
const auto &resolved = m_resolved_accessors[spacesizep.space()];
mov_reg_param(a, 4, REG_PARAM2, addrp);
@ -2216,59 +2141,23 @@ void drcbe_arm64::op_write(a64::Assembler &a, const uml::instruction &inst)
if (spacesizep.size() == SIZE_BYTE)
{
if (resolved.write_byte)
{
get_imm_relative(a, REG_PARAM1, resolved.write_byte.obj);
call_arm_addr(a, resolved.write_byte.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.write_byte);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.write_byte.obj);
call_arm_addr(a, resolved.write_byte.func);
}
else if (spacesizep.size() == SIZE_WORD)
{
if (resolved.write_word)
{
get_imm_relative(a, REG_PARAM1, resolved.write_word.obj);
call_arm_addr(a, resolved.write_word.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.write_word);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.write_word.obj);
call_arm_addr(a, resolved.write_word.func);
}
else if (spacesizep.size() == SIZE_DWORD)
{
if (resolved.write_dword)
{
get_imm_relative(a, REG_PARAM1, resolved.write_dword.obj);
call_arm_addr(a, resolved.write_dword.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.write_dword);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.write_dword.obj);
call_arm_addr(a, resolved.write_dword.func);
}
else if (spacesizep.size() == SIZE_QWORD)
{
if (resolved.write_qword)
{
get_imm_relative(a, REG_PARAM1, resolved.write_qword.obj);
call_arm_addr(a, resolved.write_qword.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.write_qword);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.write_qword.obj);
call_arm_addr(a, resolved.write_qword.func);
}
}
@ -2285,7 +2174,6 @@ void drcbe_arm64::op_writem(a64::Assembler &a, const uml::instruction &inst)
assert(spacesizep.is_size_space());
// set up a call to the write handler
const auto &trampolines = m_accessors[spacesizep.space()];
const auto &resolved = m_resolved_accessors[spacesizep.space()];
mov_reg_param(a, 4, REG_PARAM2, addrp);
@ -2294,59 +2182,23 @@ void drcbe_arm64::op_writem(a64::Assembler &a, const uml::instruction &inst)
if (spacesizep.size() == SIZE_BYTE)
{
if (resolved.write_byte_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.write_byte_masked.obj);
call_arm_addr(a, resolved.write_byte_masked.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.write_byte_masked);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.write_byte_masked.obj);
call_arm_addr(a, resolved.write_byte_masked.func);
}
else if (spacesizep.size() == SIZE_WORD)
{
if (resolved.write_word_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.write_word_masked.obj);
call_arm_addr(a, resolved.write_word_masked.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.write_word_masked);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.write_word_masked.obj);
call_arm_addr(a, resolved.write_word_masked.func);
}
else if (spacesizep.size() == SIZE_DWORD)
{
if (resolved.write_dword_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.write_dword_masked.obj);
call_arm_addr(a, resolved.write_dword_masked.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.write_dword_masked);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.write_dword_masked.obj);
call_arm_addr(a, resolved.write_dword_masked.func);
}
else if (spacesizep.size() == SIZE_QWORD)
{
if (resolved.write_qword_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.write_qword_masked.obj);
call_arm_addr(a, resolved.write_qword_masked.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.write_qword_masked);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.write_qword_masked.obj);
call_arm_addr(a, resolved.write_qword_masked.func);
}
}
@ -3924,40 +3776,21 @@ void drcbe_arm64::op_fread(a64::Assembler &a, const uml::instruction &inst)
assert(spacesizep.is_size_space());
assert((1 << spacesizep.size()) == inst.size());
const auto &trampolines = m_accessors[spacesizep.space()];
const auto &resolved = m_resolved_accessors[spacesizep.space()];
mov_reg_param(a, 4, REG_PARAM2, addrp);
if (inst.size() == 4)
{
if (resolved.read_dword)
{
get_imm_relative(a, REG_PARAM1, resolved.read_dword.obj);
call_arm_addr(a, resolved.read_dword.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.read_dword);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.read_dword.obj);
call_arm_addr(a, resolved.read_dword.func);
mov_float_param_int_reg(a, inst.size(), dstp, REG_PARAM1.w());
}
else if (inst.size() == 8)
{
if (resolved.read_qword)
{
get_imm_relative(a, REG_PARAM1, resolved.read_qword.obj);
call_arm_addr(a, resolved.read_qword.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.read_qword);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.read_qword.obj);
call_arm_addr(a, resolved.read_qword.func);
mov_float_param_int_reg(a, inst.size(), dstp, REG_PARAM1);
}
@ -3975,7 +3808,6 @@ void drcbe_arm64::op_fwrite(a64::Assembler &a, const uml::instruction &inst)
assert(spacesizep.is_size_space());
assert((1 << spacesizep.size()) == inst.size());
const auto &trampolines = m_accessors[spacesizep.space()];
const auto &resolved = m_resolved_accessors[spacesizep.space()];
mov_reg_param(a, 4, REG_PARAM2, addrp);
@ -3985,31 +3817,13 @@ void drcbe_arm64::op_fwrite(a64::Assembler &a, const uml::instruction &inst)
if (inst.size() == 4)
{
if (resolved.write_dword)
{
get_imm_relative(a, REG_PARAM1, resolved.write_dword.obj);
call_arm_addr(a, resolved.write_dword.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.write_dword);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.write_dword.obj);
call_arm_addr(a, resolved.write_dword.func);
}
else if (inst.size() == 8)
{
if (resolved.write_qword)
{
get_imm_relative(a, REG_PARAM1, resolved.write_qword.obj);
call_arm_addr(a, resolved.write_qword.func);
}
else
{
get_imm_relative(a, REG_PARAM1, (uintptr_t)m_space[spacesizep.space()]);
emit_ldr_mem(a, TEMP_REG1, &trampolines.write_qword);
a.blr(TEMP_REG1);
}
get_imm_relative(a, REG_PARAM1, resolved.write_qword.obj);
call_arm_addr(a, resolved.write_qword.func);
}
}

View File

@ -590,7 +590,7 @@ void drc_label_list::oob_callback(drccodeptr *codeptr, void *param1, void *param
// set - bind to address space
//-------------------------------------------------
void resolved_memory_accessors::set(address_space &space) noexcept
void resolved_memory_accessors::set(address_space &space)
{
read_byte .set(space, static_cast<u8 (address_space::*)(offs_t) >(&address_space::read_byte));
read_byte_masked .set(space, static_cast<u8 (address_space::*)(offs_t, u8) >(&address_space::read_byte));
@ -609,6 +609,15 @@ void resolved_memory_accessors::set(address_space &space) noexcept
write_dword_masked .set(space, static_cast<void (address_space::*)(offs_t, u32, u32)>(&address_space::write_dword));
write_qword .set(space, static_cast<void (address_space::*)(offs_t, u64) >(&address_space::write_qword));
write_qword_masked .set(space, static_cast<void (address_space::*)(offs_t, u64, u64)>(&address_space::write_qword));
if (
!read_byte || !read_byte_masked || !write_byte || !write_byte_masked ||
!read_word || !read_word_masked || !write_word || !write_word_masked ||
!read_dword || !read_dword_masked || !write_dword || !write_dword_masked ||
!read_qword || !read_qword_masked || !write_qword || !write_qword_masked)
{
throw emu_fatalerror("Error resolving address space accessor member functions!\n");
}
}
} // namespace drc

View File

@ -214,7 +214,7 @@ struct resolved_memory_accessors
resolved_member_function write_qword;
resolved_member_function write_qword_masked;
void set(address_space &space) noexcept;
void set(address_space &space);
};
using resolved_memory_accessors_vector = std::vector<resolved_memory_accessors>;

View File

@ -214,7 +214,7 @@ const uint32_t PTYPE_MR = PTYPE_M | PTYPE_R;
const uint32_t PTYPE_MRI = PTYPE_M | PTYPE_R | PTYPE_I;
const uint32_t PTYPE_MF = PTYPE_M | PTYPE_F;
#ifdef X64_WINDOWS_ABI
#ifdef _WIN32
const Gp::Id REG_PARAM1 = Gp::kIdCx;
const Gp::Id REG_PARAM2 = Gp::kIdDx;
@ -233,7 +233,7 @@ const Gp::Id REG_PARAM4 = Gp::kIdCx;
// register mapping tables
const Gp::Id int_register_map[REG_I_COUNT] =
{
#ifdef X64_WINDOWS_ABI
#ifdef _WIN32
Gp::kIdBx, Gp::kIdSi, Gp::kIdDi, Gp::kIdR12, Gp::kIdR13, Gp::kIdR14, Gp::kIdR15,
#else
Gp::kIdBx, Gp::kIdR12, Gp::kIdR13, Gp::kIdR14, Gp::kIdR15
@ -242,10 +242,10 @@ const Gp::Id int_register_map[REG_I_COUNT] =
uint32_t float_register_map[REG_F_COUNT] =
{
#ifdef X64_WINDOWS_ABI
#ifdef _WIN32
6, 7, 8, 9, 10, 11, 12, 13, 14, 15
#else
// on AMD x64 ABI, XMM0-7 are FP function args. since this code has no args, and we
// on SysV x64 ABI, XMM0-7 are FP function args. since this code has no args, and we
// save/restore them around CALLC, they should be safe for our use.
0, 1, 2, 3, 4, 5, 6, 7
#endif

View File

@ -257,7 +257,7 @@ private:
uint32_t ssemode; // saved SSE mode
uint32_t ssemodesave; // temporary location for saving
uint32_t ssecontrol[4]; // copy of the sse_control array
float single1; // 1.0 is single-precision
float single1; // 1.0 in single-precision
double double1; // 1.0 in double-precision
void * stacksave; // saved stack pointer

View File

@ -114,6 +114,12 @@ namespace {
// CONSTANTS
//**************************************************************************
#ifdef _WIN32
constexpr bool USE_THISCALL = true;
#else
constexpr bool USE_THISCALL = false;
#endif
const uint32_t PTYPE_M = 1 << parameter::PTYPE_MEMORY;
const uint32_t PTYPE_I = 1 << parameter::PTYPE_IMMEDIATE;
const uint32_t PTYPE_R = 1 << parameter::PTYPE_INT_REGISTER;
@ -538,32 +544,32 @@ inline bool drcbe_x86::can_skip_upper_load(Assembler &a, uint32_t *memref, Gp co
// drcbe_x86 - constructor
//-------------------------------------------------
drcbe_x86::drcbe_x86(drcuml_state &drcuml, device_t &device, drc_cache &cache, uint32_t flags, int modes, int addrbits, int ignorebits)
: drcbe_interface(drcuml, cache, device),
m_hash(cache, modes, addrbits, ignorebits),
m_map(cache, 0),
m_log(nullptr),
m_log_asmjit(nullptr),
m_logged_common(false),
m_sse3(CpuInfo::host().features().x86().hasSSE3()),
m_entry(nullptr),
m_exit(nullptr),
m_nocode(nullptr),
m_save(nullptr),
m_restore(nullptr),
m_last_lower_reg(Gp()),
m_last_lower_pc(nullptr),
m_last_lower_addr(nullptr),
m_last_upper_reg(Gp()),
m_last_upper_pc(nullptr),
m_last_upper_addr(nullptr),
m_fptemp(0),
m_fpumode(0),
m_fmodesave(0),
m_stacksave(nullptr),
m_hashstacksave(nullptr),
m_reslo(0),
m_reshi(0)
drcbe_x86::drcbe_x86(drcuml_state &drcuml, device_t &device, drc_cache &cache, uint32_t flags, int modes, int addrbits, int ignorebits) :
drcbe_interface(drcuml, cache, device)
, m_hash(cache, modes, addrbits, ignorebits)
, m_map(cache, 0)
, m_log(nullptr)
, m_log_asmjit(nullptr)
, m_logged_common(false)
, m_sse3(CpuInfo::host().features().x86().hasSSE3())
, m_entry(nullptr)
, m_exit(nullptr)
, m_nocode(nullptr)
, m_save(nullptr)
, m_restore(nullptr)
, m_last_lower_reg(Gp())
, m_last_lower_pc(nullptr)
, m_last_lower_addr(nullptr)
, m_last_upper_reg(Gp())
, m_last_upper_pc(nullptr)
, m_last_upper_addr(nullptr)
, m_fptemp(0)
, m_fpumode(0)
, m_fmodesave(0)
, m_stacksave(nullptr)
, m_hashstacksave(nullptr)
, m_reslo(0)
, m_reshi(0)
{
// compute hi pointers for each register
for (int regnum = 0; regnum < std::size(int_register_map); regnum++)
@ -595,6 +601,14 @@ drcbe_x86::drcbe_x86(drcuml_state &drcuml, device_t &device, drc_cache &cache, u
flags_unmap[entry] = flags;
}
// resolve the actual addresses of member functions we need to call
m_memory_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space)
{
if (m_space[space])
m_memory_accessors[space].set(*m_space[space]);
}
// build the opcode table (static but it doesn't hurt to regenerate it)
for (auto & elem : s_opcode_table_source)
s_opcode_table[elem.opcode] = elem.func;
@ -3448,52 +3462,75 @@ void drcbe_x86::op_read(Assembler &a, const instruction &inst)
// pick a target register for the general case
Gp const dstreg = dstp.select_register(eax);
// set up a call to the read byte handler
emit_mov_m32_p32(a, dword_ptr(esp, 4), addrp); // mov [esp+4],addrp
a.mov(dword_ptr(esp, 0), imm(m_space[spacesizep.space()])); // mov [esp],space
// set up a call to the read handler
auto const &accessors = m_memory_accessors[spacesizep.space()];
emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 0 : 4), addrp);
if (spacesizep.size() == SIZE_BYTE)
{
a.call(imm(m_accessors[spacesizep.space()].read_byte)); // call read_byte
a.movzx(dstreg, al); // movzx dstreg,al
if (USE_THISCALL)
a.mov(ecx, imm(accessors.read_byte.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.read_byte.obj));
a.call(imm(accessors.read_byte.func));
if (USE_THISCALL)
a.sub(esp, 4);
a.movzx(dstreg, al);
}
else if (spacesizep.size() == SIZE_WORD)
{
a.call(imm(m_accessors[spacesizep.space()].read_word)); // call read_word
a.movzx(dstreg, ax); // movzx dstreg,ax
if (USE_THISCALL)
a.mov(ecx, imm(accessors.read_word.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.read_word.obj));
a.call(imm(accessors.read_word.func));
if (USE_THISCALL)
a.sub(esp, 4);
a.movzx(dstreg, ax);
}
else if (spacesizep.size() == SIZE_DWORD)
{
a.call(imm(m_accessors[spacesizep.space()].read_dword)); // call read_dword
a.mov(dstreg, eax); // mov dstreg,eax
if (USE_THISCALL)
a.mov(ecx, imm(accessors.read_dword.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.read_dword.obj));
a.call(imm(accessors.read_dword.func));
if (USE_THISCALL)
a.sub(esp, 4);
a.mov(dstreg, eax);
}
else if (spacesizep.size() == SIZE_QWORD)
{
a.call(imm(m_accessors[spacesizep.space()].read_qword)); // call read_qword
a.mov(dstreg, eax); // mov dstreg,eax
if (USE_THISCALL)
a.mov(ecx, imm(accessors.read_qword.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.read_qword.obj));
a.call(imm(accessors.read_qword.func));
if (USE_THISCALL)
a.sub(esp, 4);
a.mov(dstreg, eax);
}
// store low 32 bits
emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg
emit_mov_p32_r32(a, dstp, dstreg);
// 64-bit form stores upper 32 bits
if (inst.size() == 8)
{
// 1, 2, or 4-byte case
if (spacesizep.size() != SIZE_QWORD)
{
// 1, 2, or 4-byte case
if (dstp.is_memory())
a.mov(MABS(dstp.memory(4), 4), 0); // mov [dstp+4],0
a.mov(MABS(dstp.memory(4), 4), 0);
else if (dstp.is_int_register())
a.mov(MABS(m_reghi[dstp.ireg()], 4), 0); // mov [reghi],0
a.mov(MABS(m_reghi[dstp.ireg()], 4), 0);
}
// 8-byte case
else
{
// 8-byte case
if (dstp.is_memory())
a.mov(MABS(dstp.memory(4)), edx); // mov [dstp+4],edx
a.mov(MABS(dstp.memory(4)), edx);
else if (dstp.is_int_register())
a.mov(MABS(m_reghi[dstp.ireg()]), edx); // mov [reghi],edx
a.mov(MABS(m_reghi[dstp.ireg()]), edx);
}
}
}
@ -3521,55 +3558,78 @@ void drcbe_x86::op_readm(Assembler &a, const instruction &inst)
Gp const dstreg = dstp.select_register(eax);
// set up a call to the read byte handler
auto const &accessors = m_memory_accessors[spacesizep.space()];
if (spacesizep.size() != SIZE_QWORD)
emit_mov_m32_p32(a, dword_ptr(esp, 8), maskp); // mov [esp+8],maskp
emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 4 : 8), maskp);
else
emit_mov_m64_p64(a, qword_ptr(esp, 8), maskp); // mov [esp+8],maskp
emit_mov_m32_p32(a, dword_ptr(esp, 4), addrp); // mov [esp+4],addrp
a.mov(dword_ptr(esp, 0), imm(m_space[spacesizep.space()])); // mov [esp],space
emit_mov_m64_p64(a, qword_ptr(esp, USE_THISCALL ? 4 : 8), maskp);
emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 0 : 4), addrp);
if (spacesizep.size() == SIZE_BYTE)
{
a.call(imm(m_accessors[spacesizep.space()].read_byte_masked)); // call read_byte_masked
a.movzx(dstreg, al); // movzx dstreg,al
if (USE_THISCALL)
a.mov(ecx, imm(accessors.read_byte_masked.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.read_byte_masked.obj));
a.call(imm(accessors.read_byte_masked.func));
if (USE_THISCALL)
a.sub(esp, 8);
a.movzx(dstreg, al);
}
else if (spacesizep.size() == SIZE_WORD)
{
a.call(imm(m_accessors[spacesizep.space()].read_word_masked)); // call read_word_masked
a.movzx(dstreg, ax); // movzx dstreg,ax
if (USE_THISCALL)
a.mov(ecx, imm(accessors.read_word_masked.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.read_word_masked.obj));
a.call(imm(accessors.read_word_masked.func));
if (USE_THISCALL)
a.sub(esp, 8);
a.movzx(dstreg, ax);
}
else if (spacesizep.size() == SIZE_DWORD)
{
a.call(imm(m_accessors[spacesizep.space()].read_dword_masked)); // call read_dword_masked
a.mov(dstreg, eax); // mov dstreg,eax
if (USE_THISCALL)
a.mov(ecx, imm(accessors.read_dword_masked.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.read_dword_masked.obj));
a.call(imm(accessors.read_dword_masked.func));
if (USE_THISCALL)
a.sub(esp, 8);
a.mov(dstreg, eax);
}
else if (spacesizep.size() == SIZE_QWORD)
{
a.call(imm(m_accessors[spacesizep.space()].read_qword_masked)); // call read_qword_masked
a.mov(dstreg, eax); // mov dstreg,eax
if (USE_THISCALL)
a.mov(ecx, imm(accessors.read_qword_masked.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.read_qword_masked.obj));
a.call(imm(accessors.read_qword_masked.func));
if (USE_THISCALL)
a.sub(esp, 12);
a.mov(dstreg, eax);
}
// store low 32 bits
emit_mov_p32_r32(a, dstp, dstreg); // mov dstp,dstreg
emit_mov_p32_r32(a, dstp, dstreg);
// 64-bit form stores upper 32 bits
if (inst.size() == 8)
{
// 1, 2, or 4-byte case
if (spacesizep.size() != SIZE_QWORD)
{
// 1, 2, or 4-byte case
if (dstp.is_memory())
a.mov(MABS(dstp.memory(4), 4), 0); // mov [dstp+4],0
a.mov(MABS(dstp.memory(4), 4), 0);
else if (dstp.is_int_register())
a.mov(MABS(m_reghi[dstp.ireg()], 4), 0); // mov [reghi],0
a.mov(MABS(m_reghi[dstp.ireg()], 4), 0);
}
// 8-byte case
else
{
// 8-byte case
if (dstp.is_memory())
a.mov(MABS(dstp.memory(4)), edx); // mov [dstp+4],edx
a.mov(MABS(dstp.memory(4)), edx);
else if (dstp.is_int_register())
a.mov(MABS(m_reghi[dstp.ireg()]), edx); // mov [reghi],edx
a.mov(MABS(m_reghi[dstp.ireg()]), edx);
}
}
}
@ -3593,20 +3653,52 @@ void drcbe_x86::op_write(Assembler &a, const instruction &inst)
assert(spacesizep.is_size_space());
// set up a call to the write byte handler
auto const &accessors = m_memory_accessors[spacesizep.space()];
if (spacesizep.size() != SIZE_QWORD)
emit_mov_m32_p32(a, dword_ptr(esp, 8), srcp); // mov [esp+8],srcp
emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 4 : 8), srcp);
else
emit_mov_m64_p64(a, qword_ptr(esp, 8), srcp); // mov [esp+8],srcp
emit_mov_m32_p32(a, dword_ptr(esp, 4), addrp); // mov [esp+4],addrp
a.mov(dword_ptr(esp, 0), imm(m_space[spacesizep.space()])); // mov [esp],space
emit_mov_m64_p64(a, qword_ptr(esp, USE_THISCALL ? 4 : 8), srcp);
emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 0 : 4), addrp);
if (spacesizep.size() == SIZE_BYTE)
a.call(imm(m_accessors[spacesizep.space()].write_byte)); // call write_byte
{
if (USE_THISCALL)
a.mov(ecx, imm(accessors.write_byte.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.write_byte.obj));
a.call(imm(accessors.write_byte.func));
if (USE_THISCALL)
a.sub(esp, 8);
}
else if (spacesizep.size() == SIZE_WORD)
a.call(imm(m_accessors[spacesizep.space()].write_word)); // call write_word
{
if (USE_THISCALL)
a.mov(ecx, imm(accessors.write_word.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.write_word.obj));
a.call(imm(accessors.write_word.func));
if (USE_THISCALL)
a.sub(esp, 8);
}
else if (spacesizep.size() == SIZE_DWORD)
a.call(imm(m_accessors[spacesizep.space()].write_dword)); // call write_dword
{
if (USE_THISCALL)
a.mov(ecx, imm(accessors.write_dword.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.write_dword.obj));
a.call(imm(accessors.write_dword.func));
if (USE_THISCALL)
a.sub(esp, 8);
}
else if (spacesizep.size() == SIZE_QWORD)
a.call(imm(m_accessors[spacesizep.space()].write_qword)); // call write_qword
{
if (USE_THISCALL)
a.mov(ecx, imm(accessors.write_qword.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.write_qword.obj));
a.call(imm(accessors.write_qword.func));
if (USE_THISCALL)
a.sub(esp, 12);
}
}
@ -3629,26 +3721,58 @@ void drcbe_x86::op_writem(Assembler &a, const instruction &inst)
assert(spacesizep.is_size_space());
// set up a call to the write byte handler
auto const &accessors = m_memory_accessors[spacesizep.space()];
if (spacesizep.size() != SIZE_QWORD)
{
emit_mov_m32_p32(a, dword_ptr(esp, 12), maskp); // mov [esp+12],maskp
emit_mov_m32_p32(a, dword_ptr(esp, 8), srcp); // mov [esp+8],srcp
emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 8 : 12), maskp);
emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 4 : 8), srcp);
}
else
{
emit_mov_m64_p64(a, qword_ptr(esp, 16), maskp); // mov [esp+16],maskp
emit_mov_m64_p64(a, qword_ptr(esp, 8), srcp); // mov [esp+8],srcp
emit_mov_m64_p64(a, qword_ptr(esp, USE_THISCALL ? 12 : 16), maskp);
emit_mov_m64_p64(a, qword_ptr(esp, USE_THISCALL ? 4 : 8), srcp);
}
emit_mov_m32_p32(a, dword_ptr(esp, 4), addrp); // mov [esp+4],addrp
a.mov(dword_ptr(esp, 0), imm(m_space[spacesizep.space()])); // mov [esp],space
emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 0 : 4), addrp);
if (spacesizep.size() == SIZE_BYTE)
a.call(imm(m_accessors[spacesizep.space()].write_byte_masked)); // call write_byte_masked
{
if (USE_THISCALL)
a.mov(ecx, imm(accessors.write_byte_masked.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.write_byte_masked.obj));
a.call(imm(accessors.write_byte_masked.func));
if (USE_THISCALL)
a.sub(esp, 12);
}
else if (spacesizep.size() == SIZE_WORD)
a.call(imm(m_accessors[spacesizep.space()].write_word_masked)); // call write_word_masked
{
if (USE_THISCALL)
a.mov(ecx, imm(accessors.write_word_masked.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.write_word_masked.obj));
a.call(imm(accessors.write_word_masked.func));
if (USE_THISCALL)
a.sub(esp, 12);
}
else if (spacesizep.size() == SIZE_DWORD)
a.call(imm(m_accessors[spacesizep.space()].write_dword_masked)); // call write_dword_masked
{
if (USE_THISCALL)
a.mov(ecx, imm(accessors.write_dword_masked.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.write_dword_masked.obj));
a.call(imm(accessors.write_dword_masked.func));
if (USE_THISCALL)
a.sub(esp, 12);
}
else if (spacesizep.size() == SIZE_QWORD)
a.call(imm(m_accessors[spacesizep.space()].write_qword_masked)); // call write_qword_masked
{
if (USE_THISCALL)
a.mov(ecx, imm(accessors.write_qword_masked.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessors.write_qword_masked.obj));
a.call(imm(accessors.write_qword_masked.func));
if (USE_THISCALL)
a.sub(esp, 20);
}
}
@ -6066,18 +6190,22 @@ void drcbe_x86::op_fread(Assembler &a, const instruction &inst)
assert((1 << spacep.size()) == inst.size());
// set up a call to the read dword/qword handler
emit_mov_m32_p32(a, dword_ptr(esp, 4), addrp); // mov [esp+4],addrp
a.mov(dword_ptr(esp, 0), imm(m_space[spacep.space()])); // mov [esp],space
if (inst.size() == 4)
a.call(imm(m_accessors[spacep.space()].read_dword)); // call read_dword
else if (inst.size() == 8)
a.call(imm(m_accessors[spacep.space()].read_qword)); // call read_qword
auto const &accessors = m_memory_accessors[spacep.space()];
auto const &accessor = (inst.size() == 4) ? accessors.read_dword : accessors.read_qword;
emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 0 : 4), addrp);
if (USE_THISCALL)
a.mov(ecx, imm(accessor.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessor.obj));
a.call(imm(accessor.func));
if (USE_THISCALL)
a.sub(esp, 4);
// store result
if (inst.size() == 4)
emit_mov_p32_r32(a, dstp, eax); // mov dstp,eax
emit_mov_p32_r32(a, dstp, eax);
else if (inst.size() == 8)
emit_mov_p64_r64(a, dstp, eax, edx); // mov dstp,edx:eax
emit_mov_p64_r64(a, dstp, eax, edx);
}
@ -6100,16 +6228,19 @@ void drcbe_x86::op_fwrite(Assembler &a, const instruction &inst)
assert((1 << spacep.size()) == inst.size());
// set up a call to the write dword/qword handler
auto const &accessors = m_memory_accessors[spacep.space()];
auto const &accessor = (inst.size() == 4) ? accessors.write_dword : accessors.write_qword;
if (inst.size() == 4)
emit_mov_m32_p32(a, dword_ptr(esp, 8), srcp); // mov [esp+8],srcp
emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 4 : 8), srcp);
else if (inst.size() == 8)
emit_mov_m64_p64(a, qword_ptr(esp, 8), srcp); // mov [esp+8],srcp
emit_mov_m32_p32(a, dword_ptr(esp, 4), addrp); // mov [esp+4],addrp
a.mov(dword_ptr(esp, 0), imm(m_space[spacep.space()])); // mov [esp],space
if (inst.size() == 4)
a.call(imm(m_accessors[spacep.space()].write_dword)); // call write_dword
else if (inst.size() == 8)
a.call(imm(m_accessors[spacep.space()].write_qword)); // call write_qword
emit_mov_m64_p64(a, qword_ptr(esp, USE_THISCALL ? 4 : 8), srcp);
if (USE_THISCALL)
a.mov(ecx, imm(accessor.obj));
else
a.mov(dword_ptr(esp, 0), imm(accessor.obj));
a.call(imm(accessor.func));
if (USE_THISCALL)
a.sub(esp, (inst.size() == 4) ? 8 : 12);
}

View File

@ -291,6 +291,9 @@ private:
uint64_t m_reslo; // extended low result
uint64_t m_reshi; // extended high result
// resolved memory handler functions
resolved_memory_accessors_vector m_memory_accessors;
// globals
typedef void (drcbe_x86::*opcode_generate_func)(asmjit::x86::Assembler &a, const uml::instruction &inst);
struct opcode_table_entry

View File

@ -429,9 +429,6 @@ void mips3_device::device_start()
}
}
/* set up the endianness */
m_program->accessors(m_memory);
/* allocate a timer for the compare interrupt */
m_compare_int_timer = timer_alloc(FUNC(mips3_device::compare_int_callback), this);
@ -1204,11 +1201,11 @@ inline bool mips3_device::RBYTE(offs_t address, uint32_t *result)
*result = m_fastram[ramnum].offset_base8[tlbaddress ^ m_byte_xor];
return true;
}
*result = (*m_memory.read_byte)(*m_program, tlbaddress);
*result = m_program->read_byte(tlbaddress);
}
else
{
if(tlbval & FLAG_FIXED)
if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBLOAD, address);
}
@ -1237,11 +1234,11 @@ inline bool mips3_device::RHALF(offs_t address, uint32_t *result)
*result = m_fastram[ramnum].offset_base16[(tlbaddress ^ m_word_xor) >> 1];
return true;
}
*result = (*m_memory.read_word)(*m_program, tlbaddress);
*result = m_program->read_word(tlbaddress);
}
else
{
if(tlbval & FLAG_FIXED)
if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBLOAD, address);
}
@ -1270,11 +1267,11 @@ inline bool mips3_device::RWORD(offs_t address, uint32_t *result, bool insn)
*result = m_fastram[ramnum].offset_base32[(tlbaddress ^ m_dword_xor) >> 2];
return true;
}
*result = (*m_memory.read_dword)(*m_program, tlbaddress);
*result = m_program->read_dword(tlbaddress);
}
else
{
if(tlbval & FLAG_FIXED)
if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBLOAD, address);
}
@ -1293,11 +1290,11 @@ inline bool mips3_device::RWORD_MASKED(offs_t address, uint32_t *result, uint32_
const uint32_t tlbval = vtlb_table()[address >> 12];
if (tlbval & READ_ALLOWED)
{
*result = (*m_memory.read_dword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), mem_mask);
*result = m_program->read_dword((tlbval & ~0xfff) | (address & 0xfff), mem_mask);
}
else
{
if(tlbval & FLAG_FIXED)
if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBLOAD, address);
}
@ -1316,11 +1313,11 @@ inline bool mips3_device::RDOUBLE(offs_t address, uint64_t *result)
const uint32_t tlbval = vtlb_table()[address >> 12];
if (tlbval & READ_ALLOWED)
{
*result = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff));
*result = m_program->read_qword((tlbval & ~0xfff) | (address & 0xfff));
}
else
{
if(tlbval & FLAG_FIXED)
if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBLOAD, address);
}
@ -1339,11 +1336,11 @@ inline bool mips3_device::RDOUBLE_MASKED(offs_t address, uint64_t *result, uint6
const uint32_t tlbval = vtlb_table()[address >> 12];
if (tlbval & READ_ALLOWED)
{
*result = (*m_memory.read_qword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), mem_mask);
*result = m_program->read_qword((tlbval & ~0xfff) | (address & 0xfff), mem_mask);
}
else
{
if(tlbval & FLAG_FIXED)
if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBLOAD, address);
}
@ -1372,15 +1369,15 @@ inline void mips3_device::WBYTE(offs_t address, uint8_t data)
m_fastram[ramnum].offset_base8[tlbaddress ^ m_byte_xor] = data;
return;
}
(*m_memory.write_byte)(*m_program, tlbaddress, data);
m_program->write_byte(tlbaddress, data);
}
else
{
if(tlbval & READ_ALLOWED)
if (tlbval & READ_ALLOWED)
{
generate_tlb_exception(EXCEPTION_TLBMOD, address);
}
else if(tlbval & FLAG_FIXED)
else if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBSTORE, address);
}
@ -1406,15 +1403,15 @@ inline void mips3_device::WHALF(offs_t address, uint16_t data)
m_fastram[ramnum].offset_base16[(tlbaddress ^ m_word_xor) >> 1] = data;
return;
}
(*m_memory.write_word)(*m_program, tlbaddress, data);
m_program->write_word(tlbaddress, data);
}
else
{
if(tlbval & READ_ALLOWED)
if (tlbval & READ_ALLOWED)
{
generate_tlb_exception(EXCEPTION_TLBMOD, address);
}
else if(tlbval & FLAG_FIXED)
else if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBSTORE, address);
}
@ -1440,15 +1437,15 @@ inline void mips3_device::WWORD(offs_t address, uint32_t data)
m_fastram[ramnum].offset_base32[(tlbaddress ^ m_dword_xor) >> 2] = data;
return;
}
(*m_memory.write_dword)(*m_program, tlbaddress, data);
m_program->write_dword(tlbaddress, data);
}
else
{
if(tlbval & READ_ALLOWED)
if (tlbval & READ_ALLOWED)
{
generate_tlb_exception(EXCEPTION_TLBMOD, address);
}
else if(tlbval & FLAG_FIXED)
else if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBSTORE, address);
}
@ -1464,15 +1461,15 @@ inline void mips3_device::WWORD_MASKED(offs_t address, uint32_t data, uint32_t m
const uint32_t tlbval = vtlb_table()[address >> 12];
if (tlbval & WRITE_ALLOWED)
{
(*m_memory.write_dword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data, mem_mask);
m_program->write_dword((tlbval & ~0xfff) | (address & 0xfff), data, mem_mask);
}
else
{
if(tlbval & READ_ALLOWED)
if (tlbval & READ_ALLOWED)
{
generate_tlb_exception(EXCEPTION_TLBMOD, address);
}
else if(tlbval & FLAG_FIXED)
else if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBSTORE, address);
}
@ -1488,15 +1485,15 @@ inline void mips3_device::WDOUBLE(offs_t address, uint64_t data)
const uint32_t tlbval = vtlb_table()[address >> 12];
if (tlbval & WRITE_ALLOWED)
{
(*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data);
m_program->write_qword((tlbval & ~0xfff) | (address & 0xfff), data);
}
else
{
if(tlbval & READ_ALLOWED)
if (tlbval & READ_ALLOWED)
{
generate_tlb_exception(EXCEPTION_TLBMOD, address);
}
else if(tlbval & FLAG_FIXED)
else if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBSTORE, address);
}
@ -1512,15 +1509,15 @@ inline void mips3_device::WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t
const uint32_t tlbval = vtlb_table()[address >> 12];
if (tlbval & WRITE_ALLOWED)
{
(*m_memory.write_qword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data, mem_mask);
m_program->write_qword((tlbval & ~0xfff) | (address & 0xfff), data, mem_mask);
}
else
{
if(tlbval & READ_ALLOWED)
if (tlbval & READ_ALLOWED)
{
generate_tlb_exception(EXCEPTION_TLBMOD, address);
}
else if(tlbval & FLAG_FIXED)
else if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBSTORE, address);
}
@ -1535,7 +1532,7 @@ 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);
*result = m_program->read_byte(address);
return true;
}
@ -1545,7 +1542,7 @@ inline bool r4650_device::RBYTE(offs_t address, uint32_t *result)
*result = 0;
return false;
}
*result = (*m_memory.read_byte)(*m_program, address + m_core->cpr[0][COP0_R4650_DBase]);
*result = m_program->read_byte(address + m_core->cpr[0][COP0_R4650_DBase]);
return true;
}
@ -1553,7 +1550,7 @@ 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);
*result = m_program->read_word(address);
return true;
}
@ -1563,7 +1560,7 @@ inline bool r4650_device::RHALF(offs_t address, uint32_t *result)
*result = 0;
return false;
}
*result = (*m_memory.read_word)(*m_program, address + m_core->cpr[0][COP0_R4650_DBase]);
*result = m_program->read_word(address + m_core->cpr[0][COP0_R4650_DBase]);
return true;
}
@ -1571,7 +1568,7 @@ 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);
*result = m_program->read_dword(address);
return true;
}
@ -1585,7 +1582,7 @@ inline bool r4650_device::RWORD(offs_t address, uint32_t *result, bool insn)
*result = 0;
return false;
}
*result = (*m_memory.read_dword)(*m_program, address + base);
*result = m_program->read_dword(address + base);
return true;
}
@ -1593,7 +1590,7 @@ inline bool r4650_device::RWORD_MASKED(offs_t address, uint32_t *result, uint32_
{
if ((SR & SR_KSU_USER) == SR_KSU_KERNEL)
{
*result = (*m_memory.read_dword_masked)(*m_program, address, mem_mask);
*result = m_program->read_dword(address, mem_mask);
return true;
}
@ -1603,7 +1600,7 @@ inline bool r4650_device::RWORD_MASKED(offs_t address, uint32_t *result, uint32_
*result = 0;
return false;
}
*result = (*m_memory.read_dword_masked)(*m_program, address + m_core->cpr[0][COP0_R4650_DBase], mem_mask);
*result = m_program->read_dword(address + m_core->cpr[0][COP0_R4650_DBase], mem_mask);
return true;
}
@ -1611,7 +1608,7 @@ 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);
*result = m_program->read_qword(address);
return true;
}
@ -1621,7 +1618,7 @@ inline bool r4650_device::RDOUBLE(offs_t address, uint64_t *result)
*result = 0;
return false;
}
*result = (*m_memory.read_qword)(*m_program, address + m_core->cpr[0][COP0_R4650_DBase]);
*result = m_program->read_qword(address + m_core->cpr[0][COP0_R4650_DBase]);
return true;
}
@ -1629,7 +1626,7 @@ inline bool r4650_device::RDOUBLE_MASKED(offs_t address, uint64_t *result, uint6
{
if ((SR & SR_KSU_USER) == SR_KSU_KERNEL)
{
*result = (*m_memory.read_qword_masked)(*m_program, address, mem_mask);
*result = m_program->read_qword(address, mem_mask);
return true;
}
@ -1639,102 +1636,103 @@ inline bool r4650_device::RDOUBLE_MASKED(offs_t address, uint64_t *result, uint6
*result = 0;
return false;
}
*result = (*m_memory.read_qword_masked)(*m_program, address + m_core->cpr[0][COP0_R4650_DBase], mem_mask);
*result = m_program->read_qword(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);
m_program->write_byte(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);
m_program->write_byte(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);
m_program->write_word(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);
m_program->write_word(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);
m_program->write_dword(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);
m_program->write_dword(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);
m_program->write_dword(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);
m_program->write_dword(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);
m_program->write_qword(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);
m_program->write_qword(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);
m_program->write_qword(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);
m_program->write_qword(address + m_core->cpr[0][COP0_R4650_DBound], data, mem_mask);
}
inline void r5900_device::WBYTE(offs_t address, uint8_t data)
{
if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_byte)(*m_program, address, data);
if (address >= 0x70000000 && address < 0x70004000) m_program->write_byte(address, data);
else mips3_device::WBYTE(address, data);
}
inline void r5900_device::WHALF(offs_t address, uint16_t data)
{
if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_word)(*m_program, address, data);
if (address >= 0x70000000 && address < 0x70004000) m_program->write_word(address, data);
else mips3_device::WHALF(address, data);
}
inline void r5900_device::WWORD(offs_t address, uint32_t data)
{
if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_dword)(*m_program, address, data);
if (address >= 0x70000000 && address < 0x70004000) m_program->write_dword(address, data);
else mips3_device::WWORD(address, data);
}
inline void r5900_device::WWORD_MASKED(offs_t address, uint32_t data, uint32_t mem_mask)
{
if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_dword_masked)(*m_program, address, data, mem_mask);
if (address >= 0x70000000 && address < 0x70004000) m_program->write_dword(address, data, mem_mask);
else mips3_device::WWORD_MASKED(address, data, mem_mask);
}
inline void r5900_device::WDOUBLE(offs_t address, uint64_t data) {
if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_qword)(*m_program, address, data);
inline void r5900_device::WDOUBLE(offs_t address, uint64_t data)
{
if (address >= 0x70000000 && address < 0x70004000) m_program->write_qword(address, data);
else mips3_device::WDOUBLE(address, data);
}
inline void r5900_device::WDOUBLE_MASKED(offs_t address, uint64_t data, uint64_t mem_mask)
{
if (address >= 0x70000000 && address < 0x70004000) (*m_memory.write_qword_masked)(*m_program, address, data, mem_mask);
if (address >= 0x70000000 && address < 0x70004000) m_program->write_qword(address, data, mem_mask);
else mips3_device::WDOUBLE_MASKED(address, data, mem_mask);
}
@ -1742,24 +1740,24 @@ inline void r5900le_device::WQUAD(offs_t address, uint64_t data_hi, uint64_t dat
{
if (address >= 0x70000000 && address < 0x70004000)
{
(*m_memory.write_qword)(*m_program, address, data_lo);
(*m_memory.write_qword)(*m_program, address + 8, data_hi);
m_program->write_qword(address, data_lo);
m_program->write_qword(address + 8, data_hi);
return;
}
const uint32_t tlbval = vtlb_table()[address >> 12];
if (tlbval & WRITE_ALLOWED)
{
(*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data_lo);
(*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff), data_hi);
m_program->write_qword((tlbval & ~0xfff) | (address & 0xfff), data_lo);
m_program->write_qword((tlbval & ~0xfff) | ((address + 8) & 0xfff), data_hi);
}
else
{
if(tlbval & READ_ALLOWED)
if (tlbval & READ_ALLOWED)
{
generate_tlb_exception(EXCEPTION_TLBMOD, address);
}
else if(tlbval & FLAG_FIXED)
else if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBSTORE, address);
}
@ -1774,24 +1772,24 @@ inline void r5900be_device::WQUAD(offs_t address, uint64_t data_hi, uint64_t dat
{
if (address >= 0x70000000 && address < 0x70004000)
{
(*m_memory.write_qword)(*m_program, address, data_hi);
(*m_memory.write_qword)(*m_program, address + 8, data_lo);
m_program->write_qword(address, data_hi);
m_program->write_qword(address + 8, data_lo);
return;
}
const uint32_t tlbval = vtlb_table()[address >> 12];
if (tlbval & WRITE_ALLOWED)
{
(*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data_hi);
(*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff), data_lo);
m_program->write_qword((tlbval & ~0xfff) | (address & 0xfff), data_hi);
m_program->write_qword((tlbval & ~0xfff) | ((address + 8) & 0xfff), data_lo);
}
else
{
if(tlbval & READ_ALLOWED)
if (tlbval & READ_ALLOWED)
{
generate_tlb_exception(EXCEPTION_TLBMOD, address);
}
else if(tlbval & FLAG_FIXED)
else if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBSTORE, address);
}
@ -1802,9 +1800,11 @@ inline void r5900be_device::WQUAD(offs_t address, uint64_t data_hi, uint64_t dat
}
}
inline bool r5900_device::RBYTE(offs_t address, uint32_t *result) {
if (address >= 0x70000000 && address < 0x70004000) {
*result = (*m_memory.read_byte)(*m_program, address);
inline bool r5900_device::RBYTE(offs_t address, uint32_t *result)
{
if (address >= 0x70000000 && address < 0x70004000)
{
*result = m_program->read_byte(address);
return true;
}
return mips3_device::RBYTE(address, result);
@ -1814,7 +1814,7 @@ inline bool r5900_device::RHALF(offs_t address, uint32_t *result)
{
if (address >= 0x70000000 && address < 0x70004000)
{
*result = (*m_memory.read_word)(*m_program, address);
*result = m_program->read_word(address);
return true;
}
return mips3_device::RHALF(address, result);
@ -1824,7 +1824,7 @@ inline bool r5900_device::RWORD(offs_t address, uint32_t *result, bool insn)
{
if (address >= 0x70000000 && address < 0x70004000)
{
*result = (*m_memory.read_dword)(*m_program, address);
*result = m_program->read_dword(address);
return true;
}
return mips3_device::RWORD(address, result, insn);
@ -1834,7 +1834,7 @@ inline bool r5900_device::RWORD_MASKED(offs_t address, uint32_t *result, uint32_
{
if (address >= 0x70000000 && address < 0x70004000)
{
*result = (*m_memory.read_dword_masked)(*m_program, address, mem_mask);
*result = m_program->read_dword(address, mem_mask);
return true;
}
return mips3_device::RWORD_MASKED(address, result, mem_mask);
@ -1844,7 +1844,7 @@ inline bool r5900_device::RDOUBLE(offs_t address, uint64_t *result)
{
if (address >= 0x70000000 && address < 0x70004000)
{
*result = (*m_memory.read_qword)(*m_program, address);
*result = m_program->read_qword(address);
return true;
}
return mips3_device::RDOUBLE(address, result);
@ -1854,7 +1854,7 @@ inline bool r5900_device::RDOUBLE_MASKED(offs_t address, uint64_t *result, uint6
{
if (address >= 0x70000000 && address < 0x70004000)
{
*result = (*m_memory.read_qword_masked)(*m_program, address, mem_mask);
*result = m_program->read_qword(address, mem_mask);
return true;
}
return mips3_device::RDOUBLE_MASKED(address, result, mem_mask);
@ -1864,20 +1864,20 @@ inline bool r5900le_device::RQUAD(offs_t address, uint64_t *result_hi, uint64_t
{
if (address >= 0x70000000 && address < 0x70004000)
{
*result_lo = (*m_memory.read_qword)(*m_program, address);
*result_hi = (*m_memory.read_qword)(*m_program, address + 8);
*result_lo = m_program->read_qword(address);
*result_hi = m_program->read_qword(address + 8);
return true;
}
const uint32_t tlbval = vtlb_table()[address >> 12];
if (tlbval & READ_ALLOWED)
{
*result_lo = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff));
*result_hi = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff));
*result_lo = m_program->read_qword((tlbval & ~0xfff) | (address & 0xfff));
*result_hi = m_program->read_qword((tlbval & ~0xfff) | ((address + 8) & 0xfff));
}
else
{
if(tlbval & FLAG_FIXED)
if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBLOAD, address);
}
@ -1896,20 +1896,20 @@ inline bool r5900be_device::RQUAD(offs_t address, uint64_t *result_hi, uint64_t
{
if (address >= 0x70000000 && address < 0x70004000)
{
*result_hi = (*m_memory.read_qword)(*m_program, address);
*result_lo = (*m_memory.read_qword)(*m_program, address + 8);
*result_hi = m_program->read_qword(address);
*result_lo = m_program->read_qword(address + 8);
return true;
}
const uint32_t tlbval = vtlb_table()[address >> 12];
if (tlbval & READ_ALLOWED)
{
*result_hi = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff));
*result_lo = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | ((address + 8) & 0xfff));
*result_hi = m_program->read_qword((tlbval & ~0xfff) | (address & 0xfff));
*result_lo = m_program->read_qword((tlbval & ~0xfff) | ((address + 8) & 0xfff));
}
else
{
if(tlbval & FLAG_FIXED)
if (tlbval & FLAG_FIXED)
{
generate_tlb_exception(EXCEPTION_TLBLOAD, address);
}
@ -2255,25 +2255,31 @@ void mips3_device::handle_cop1_fr0(uint32_t op)
break;
case 0x03:
if (IS_SINGLE(op)) { /* DIV.S */
if (FTVALW_FR0 == 0 && (COP1_FCR31 & (1 << (FCR31_ENABLE + FPE_DIV0)))) {
if (IS_SINGLE(op)) /* DIV.S */
{
if (FTVALW_FR0 == 0 && (COP1_FCR31 & (1 << (FCR31_ENABLE + FPE_DIV0))))
{
COP1_FCR31 |= (1 << (FCR31_FLAGS + FPE_DIV0)); // Set flag
COP1_FCR31 |= (1 << (FCR31_CAUSE + FPE_DIV0)); // Set cause
generate_exception(EXCEPTION_FPE, 1);
//machine().debug_break();
}
else {
else
{
FDVALS_FR0 = FSVALS_FR0 / FTVALS_FR0;
}
}
else { /* DIV.D */
if (FTVALL_FR0 == 0ull && (COP1_FCR31 & (1 << (FCR31_ENABLE + FPE_DIV0)))) {
else /* DIV.D */
{
if (FTVALL_FR0 == 0ull && (COP1_FCR31 & (1 << (FCR31_ENABLE + FPE_DIV0))))
{
COP1_FCR31 |= (1 << (FCR31_FLAGS + FPE_DIV0)); // Set flag
COP1_FCR31 |= (1 << (FCR31_CAUSE + FPE_DIV0)); // Set cause
generate_exception(EXCEPTION_FPE, 1);
//machine().debug_break();
}
else {
else
{
FDVALD_FR0 = FSVALD_FR0 / FTVALD_FR0;
}
}

View File

@ -448,7 +448,6 @@ protected:
uint32_t m_byte_xor;
uint32_t m_word_xor;
uint32_t m_dword_xor;
data_accessors m_memory;
/* cache memory */
size_t c_icache_size;