Skip to content

Commit

Permalink
cpu/drcbearm64.cpp: Added scaffolding for directly dispatching memory…
Browse files Browse the repository at this point in the history
… accesses.
  • Loading branch information
cuavas committed Feb 5, 2025
1 parent b7a80b1 commit be02455
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 62 deletions.
99 changes: 51 additions & 48 deletions src/devices/cpu/drcbearm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -974,11 +974,14 @@ drcbe_arm64::drcbe_arm64(drcuml_state &drcuml, device_t &device, drc_cache &cach
m_drcmap_get_value.set(m_map, &drc_map_variables::get_value);
if (!m_drcmap_get_value)
throw emu_fatalerror("Error resolving map variable get value function!\n");
m_resolved_accessors.resize(m_space.size());
m_memory_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space)
{
if (m_space[space])
m_resolved_accessors[space].set(*m_space[space]);
{
m_memory_accessors[space].resolved.set(*m_space[space]);
m_memory_accessors[space].specific = m_space[space]->specific_accessors();
}
}
}

Expand Down Expand Up @@ -2046,29 +2049,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 &resolved = m_resolved_accessors[spacesizep.space()];
auto const &accessors = m_memory_accessors[spacesizep.space()];

mov_reg_param(a, 4, REG_PARAM2, addrp);

if (spacesizep.size() == SIZE_BYTE)
{
get_imm_relative(a, REG_PARAM1, resolved.read_byte.obj);
call_arm_addr(a, resolved.read_byte.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.read_byte.obj);
call_arm_addr(a, accessors.resolved.read_byte.func);
}
else if (spacesizep.size() == SIZE_WORD)
{
get_imm_relative(a, REG_PARAM1, resolved.read_word.obj);
call_arm_addr(a, resolved.read_word.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.read_word.obj);
call_arm_addr(a, accessors.resolved.read_word.func);
}
else if (spacesizep.size() == SIZE_DWORD)
{
get_imm_relative(a, REG_PARAM1, resolved.read_dword.obj);
call_arm_addr(a, resolved.read_dword.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.read_dword.obj);
call_arm_addr(a, accessors.resolved.read_dword.func);
}
else if (spacesizep.size() == SIZE_QWORD)
{
get_imm_relative(a, REG_PARAM1, resolved.read_qword.obj);
call_arm_addr(a, resolved.read_qword.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.read_qword.obj);
call_arm_addr(a, accessors.resolved.read_qword.func);
}

mov_param_reg(a, inst.size(), dstp, REG_PARAM1);
Expand All @@ -2086,30 +2089,30 @@ 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 &resolved = m_resolved_accessors[spacesizep.space()];
auto const &accessors = m_memory_accessors[spacesizep.space()];

mov_reg_param(a, 4, REG_PARAM2, addrp);
mov_reg_param(a, inst.size(), REG_PARAM3, maskp);

if (spacesizep.size() == SIZE_BYTE)
{
get_imm_relative(a, REG_PARAM1, resolved.read_byte_masked.obj);
call_arm_addr(a, resolved.read_byte_masked.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.read_byte_masked.obj);
call_arm_addr(a, accessors.resolved.read_byte_masked.func);
}
else if (spacesizep.size() == SIZE_WORD)
{
get_imm_relative(a, REG_PARAM1, resolved.read_word_masked.obj);
call_arm_addr(a, resolved.read_word_masked.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.read_word_masked.obj);
call_arm_addr(a, accessors.resolved.read_word_masked.func);
}
else if (spacesizep.size() == SIZE_DWORD)
{
get_imm_relative(a, REG_PARAM1, resolved.read_dword_masked.obj);
call_arm_addr(a, resolved.read_dword_masked.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.read_dword_masked.obj);
call_arm_addr(a, accessors.resolved.read_dword_masked.func);
}
else if (spacesizep.size() == SIZE_QWORD)
{
get_imm_relative(a, REG_PARAM1, resolved.read_qword_masked.obj);
call_arm_addr(a, resolved.read_qword_masked.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.read_qword_masked.obj);
call_arm_addr(a, accessors.resolved.read_qword_masked.func);
}

mov_param_reg(a, inst.size(), dstp, REG_PARAM1);
Expand All @@ -2126,30 +2129,30 @@ 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 &resolved = m_resolved_accessors[spacesizep.space()];
auto const &accessors = m_memory_accessors[spacesizep.space()];

mov_reg_param(a, 4, REG_PARAM2, addrp);
mov_reg_param(a, inst.size(), REG_PARAM3, srcp);

if (spacesizep.size() == SIZE_BYTE)
{
get_imm_relative(a, REG_PARAM1, resolved.write_byte.obj);
call_arm_addr(a, resolved.write_byte.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.write_byte.obj);
call_arm_addr(a, accessors.resolved.write_byte.func);
}
else if (spacesizep.size() == SIZE_WORD)
{
get_imm_relative(a, REG_PARAM1, resolved.write_word.obj);
call_arm_addr(a, resolved.write_word.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.write_word.obj);
call_arm_addr(a, accessors.resolved.write_word.func);
}
else if (spacesizep.size() == SIZE_DWORD)
{
get_imm_relative(a, REG_PARAM1, resolved.write_dword.obj);
call_arm_addr(a, resolved.write_dword.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.write_dword.obj);
call_arm_addr(a, accessors.resolved.write_dword.func);
}
else if (spacesizep.size() == SIZE_QWORD)
{
get_imm_relative(a, REG_PARAM1, resolved.write_qword.obj);
call_arm_addr(a, resolved.write_qword.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.write_qword.obj);
call_arm_addr(a, accessors.resolved.write_qword.func);
}
}

Expand All @@ -2166,31 +2169,31 @@ 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 &resolved = m_resolved_accessors[spacesizep.space()];
auto const &accessors = m_memory_accessors[spacesizep.space()];

mov_reg_param(a, 4, REG_PARAM2, addrp);
mov_reg_param(a, inst.size(), REG_PARAM3, srcp);
mov_reg_param(a, inst.size(), REG_PARAM4, maskp);

if (spacesizep.size() == SIZE_BYTE)
{
get_imm_relative(a, REG_PARAM1, resolved.write_byte_masked.obj);
call_arm_addr(a, resolved.write_byte_masked.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.write_byte_masked.obj);
call_arm_addr(a, accessors.resolved.write_byte_masked.func);
}
else if (spacesizep.size() == SIZE_WORD)
{
get_imm_relative(a, REG_PARAM1, resolved.write_word_masked.obj);
call_arm_addr(a, resolved.write_word_masked.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.write_word_masked.obj);
call_arm_addr(a, accessors.resolved.write_word_masked.func);
}
else if (spacesizep.size() == SIZE_DWORD)
{
get_imm_relative(a, REG_PARAM1, resolved.write_dword_masked.obj);
call_arm_addr(a, resolved.write_dword_masked.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.write_dword_masked.obj);
call_arm_addr(a, accessors.resolved.write_dword_masked.func);
}
else if (spacesizep.size() == SIZE_QWORD)
{
get_imm_relative(a, REG_PARAM1, resolved.write_qword_masked.obj);
call_arm_addr(a, resolved.write_qword_masked.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.write_qword_masked.obj);
call_arm_addr(a, accessors.resolved.write_qword_masked.func);
}
}

Expand Down Expand Up @@ -3768,21 +3771,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 &resolved = m_resolved_accessors[spacesizep.space()];
auto const &accessors = m_memory_accessors[spacesizep.space()];

mov_reg_param(a, 4, REG_PARAM2, addrp);

if (inst.size() == 4)
{
get_imm_relative(a, REG_PARAM1, resolved.read_dword.obj);
call_arm_addr(a, resolved.read_dword.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.read_dword.obj);
call_arm_addr(a, accessors.resolved.read_dword.func);

mov_float_param_int_reg(a, inst.size(), dstp, REG_PARAM1.w());
}
else if (inst.size() == 8)
{
get_imm_relative(a, REG_PARAM1, resolved.read_qword.obj);
call_arm_addr(a, resolved.read_qword.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.read_qword.obj);
call_arm_addr(a, accessors.resolved.read_qword.func);

mov_float_param_int_reg(a, inst.size(), dstp, REG_PARAM1);
}
Expand All @@ -3800,7 +3803,7 @@ 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 &resolved = m_resolved_accessors[spacesizep.space()];
auto const &accessors = m_memory_accessors[spacesizep.space()];

mov_reg_param(a, 4, REG_PARAM2, addrp);
mov_float_reg_param(a, inst.size(), TEMPF_REG1, srcp);
Expand All @@ -3809,13 +3812,13 @@ void drcbe_arm64::op_fwrite(a64::Assembler &a, const uml::instruction &inst)

if (inst.size() == 4)
{
get_imm_relative(a, REG_PARAM1, resolved.write_dword.obj);
call_arm_addr(a, resolved.write_dword.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.write_dword.obj);
call_arm_addr(a, accessors.resolved.write_dword.func);
}
else if (inst.size() == 8)
{
get_imm_relative(a, REG_PARAM1, resolved.write_qword.obj);
call_arm_addr(a, resolved.write_qword.func);
get_imm_relative(a, REG_PARAM1, accessors.resolved.write_qword.obj);
call_arm_addr(a, accessors.resolved.write_qword.func);
}
}

Expand Down
7 changes: 6 additions & 1 deletion src/devices/cpu/drcbearm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,14 @@ class drcbe_arm64 : public drcbe_interface
static const opcode_table_entry s_opcode_table_source[];
static opcode_generate_func s_opcode_table[uml::OP_MAX];

struct memory_accessors
{
resolved_memory_accessors resolved;
address_space::specific_access_info specific;
};
resolved_member_function m_debug_cpu_instruction_hook;
resolved_member_function m_drcmap_get_value;
resolved_memory_accessors_vector m_resolved_accessors;
std::vector<memory_accessors> m_memory_accessors;
};

} // namespace drc
Expand Down
28 changes: 15 additions & 13 deletions src/devices/cpu/drcbex64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2587,14 +2587,18 @@ void drcbe_x64::op_read(Assembler &a, const instruction &inst)
a.mov(r10d, Gpd(REG_PARAM2)); // copy masked address
a.shr(Gpd(REG_PARAM2), accessors.specific.low_bits); // shift off low bits
}
a.and_(ecx, imm((accessors.specific.native_bytes - (1 << spacesizep.size())) << 3)); // mask bit address
a.mov(rax, ptr(rax, Gpq(REG_PARAM2), 3)); // load dispatch table entry
a.and_(ecx, imm((accessors.specific.native_bytes - (1 << spacesizep.size())) << 3)); // mask bit address
if (accessors.specific.low_bits)
a.mov(Gpd(REG_PARAM2), r10d); // restore masked address
if (need_save)
a.mov(Gpd(int_register_map[0]), ecx); // save masked bit address
else
a.mov(dstreg.r32(), ecx); // save masked bit address
if (accessors.specific.read.is_virtual)
a.mov(r10, ptr(rax, accessors.specific.read.displacement)); // load vtable pointer
if (accessors.specific.read.displacement)
a.add(rax, accessors.specific.read.displacement); // apply this pointer offset
if (accessors.specific.native_bytes <= 4)
a.shl(Gpd(REG_PARAM3), cl); // shift mem_mask by masked bit address
else
Expand All @@ -2603,11 +2607,7 @@ void drcbe_x64::op_read(Assembler &a, const instruction &inst)
// need to do this after finished with CL as REG_PARAM1 is C on Windows
a.mov(Gpq(REG_PARAM1), rax);
if (accessors.specific.read.is_virtual)
a.mov(rax, ptr(rax, accessors.specific.read.displacement)); // load vtable pointer
if (accessors.specific.read.displacement)
a.add(Gpq(REG_PARAM1), accessors.specific.read.displacement); // apply this pointer offset
if (accessors.specific.read.is_virtual)
a.call(ptr(rax, accessors.specific.read.function)); // call virtual member function
a.call(ptr(r10, accessors.specific.read.function)); // call virtual member function
else
smart_call_r64(a, (x86code *)accessors.specific.read.function, rax); // call non-virtual member function

Expand Down Expand Up @@ -3041,31 +3041,33 @@ void drcbe_x64::op_writem(Assembler &a, const instruction &inst)
a.mov(r10d, Gpd(REG_PARAM2)); // copy masked address
a.shr(Gpd(REG_PARAM2), accessors.specific.low_bits); // shift off low bits
}
a.and_(ecx, imm((accessors.specific.native_bytes - (1 << spacesizep.size())) << 3)); // mask bit address
a.mov(rax, ptr(rax, Gpq(REG_PARAM2), 3)); // load dispatch table entry
a.and_(ecx, imm((accessors.specific.native_bytes - (1 << spacesizep.size())) << 3)); // mask bit address
if (accessors.specific.low_bits)
a.mov(Gpd(REG_PARAM2), r10d); // restore masked address
if (accessors.specific.native_bytes <= 4)
{
a.shl(r11d, cl); // shift mem_mask by masked bit address
a.shl(Gpd(REG_PARAM3), cl); // shift data by masked bit address
a.mov(Gpd(REG_PARAM4), r11d); // copy mem_mask to parameter 4 (ECX on SysV)
}
else
{
a.shl(r11, cl); // shift mem_mask by masked bit address
a.shl(Gpq(REG_PARAM3), cl); // shift data by masked bit address
a.mov(Gpq(REG_PARAM4), r11); // copy mem_mask to parameter 4 (RCX on SysV)
}
if (accessors.specific.write.is_virtual)
a.mov(r10, ptr(rax, accessors.specific.write.displacement)); // load vtable pointer

// need to do this after finished with CL as REG_PARAM1 is C on Windows
// need to do this after finished with CL as REG_PARAM1 is C on Windows and REG_PARAM4 is C on SysV
a.mov(Gpq(REG_PARAM1), rax);
if (accessors.specific.write.is_virtual)
a.mov(rax, ptr(rax, accessors.specific.write.displacement)); // load vtable pointer
if (accessors.specific.native_bytes <= 4)
a.mov(Gpd(REG_PARAM4), r11d); // copy mem_mask to parameter 4 (ECX on SysV)
else
a.mov(Gpq(REG_PARAM4), r11); // copy mem_mask to parameter 4 (RCX on SysV)
if (accessors.specific.write.displacement)
a.add(Gpq(REG_PARAM1), accessors.specific.write.displacement); // apply this pointer offset
if (accessors.specific.write.is_virtual)
a.call(ptr(rax, accessors.specific.write.function)); // call virtual member function
a.call(ptr(r10, accessors.specific.write.function)); // call virtual member function
else
smart_call_r64(a, (x86code *)accessors.specific.write.function, rax); // call non-virtual member function
}
Expand Down

0 comments on commit be02455

Please sign in to comment.