Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
step 2
Browse files Browse the repository at this point in the history
cuavas committed Jan 15, 2025
1 parent ec790b4 commit 6ca960f
Showing 4 changed files with 53 additions and 28 deletions.
37 changes: 24 additions & 13 deletions src/devices/cpu/drcbearm64.cpp
Original file line number Diff line number Diff line change
@@ -920,11 +920,6 @@ drcbe_arm64::drcbe_arm64(drcuml_state &drcuml, device_t &device, drc_cache &cach
, m_baseptr(cache.near() + 0x80)
, m_near(*(near_state *)cache.alloc_near(sizeof(m_near)))
{
// get pointers to C functions we need to call
using debugger_hook_func = void (*)(device_debug *, offs_t);
static const debugger_hook_func debugger_inst_hook = [] (device_debug *dbg, offs_t pc) { dbg->instruction_hook(pc); };
m_near.debug_cpu_instruction_hook = (uint8_t *)debugger_inst_hook;
m_near.drcmap_get_value = (uint8_t *)&drc_map_variables::static_get_value;
m_near.emulated_flags = 0;

// build the opcode table (static but it doesn't hurt to regenerate it)
@@ -937,7 +932,13 @@ drcbe_arm64::drcbe_arm64(drcuml_state &drcuml, device_t &device, drc_cache &cach
m_log_asmjit = fopen(std::string("drcbearm64_asmjit_").append(device.shortname()).append(".asm").c_str(), "w");
}

// resolve the actual addresses of the address space handlers
// resolve the actual addresses of member functions we need to call
m_drcmap_get_value.set(m_map, &drc_map_variables::get_value);
if (!m_drcmap_get_value)
{
m_drcmap_get_value.obj = uintptr_t(&m_map);
m_drcmap_get_value.func = reinterpret_cast<uint8_t *>(uintptr_t(&drc_map_variables::static_get_value));
}
m_resolved_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space)
{
@@ -1052,6 +1053,19 @@ int drcbe_arm64::execute(code_handle &entry)

void drcbe_arm64::generate(drcuml_block &block, const instruction *instlist, uint32_t numinst)
{
// do this here because device.debug() isn't initialised at construction time
if (!m_debug_cpu_instruction_hook && (m_device.machine().debug_flags & DEBUG_FLAG_ENABLED))
{
m_debug_cpu_instruction_hook.set(*m_device.debug(), &device_debug::instruction_hook);
if (!m_debug_cpu_instruction_hook)
{
m_debug_cpu_instruction_hook.obj = uintptr_t(m_device.debug());
using debugger_hook_func = void (*)(device_debug *, offs_t);
static const auto debugger_inst_hook = [] (device_debug *dbg, offs_t pc) { dbg->instruction_hook(pc); };
m_debug_cpu_instruction_hook.func = reinterpret_cast<uint8_t *>(uintptr_t(debugger_hook_func(debugger_inst_hook)));
}
}

// tell all of our utility objects that a block is beginning
m_hash.block_begin(block, instlist, numinst);
m_map.block_begin(block);
@@ -1237,11 +1251,10 @@ void drcbe_arm64::op_debug(a64::Assembler &a, const uml::instruction &inst)
emit_ldr_mem(a, temp, &m_device.machine().debug_flags);
a.tbz(temp, 1, skip); // DEBUG_FLAG_CALL_HOOK

get_imm_relative(a, REG_PARAM1, (uintptr_t)m_device.debug());
get_imm_relative(a, REG_PARAM1, m_debug_cpu_instruction_hook.obj);
mov_reg_param(a, 4, REG_PARAM2, pcp);

emit_ldr_mem(a, TEMP_REG2, &m_near.debug_cpu_instruction_hook);
a.blr(TEMP_REG2);
call_arm_addr(a, m_debug_cpu_instruction_hook.func);

a.bind(skip);
}
@@ -1560,13 +1573,11 @@ void drcbe_arm64::op_recover(a64::Assembler &a, const uml::instruction &inst)

be_parameter dstp(*this, inst.param(0), PTYPE_MR);

get_imm_relative(a, REG_PARAM1, (uintptr_t)&m_map);
get_imm_relative(a, REG_PARAM1, m_drcmap_get_value.obj);
a.ldr(REG_PARAM2, arm::Mem(a64::x29, -8)); // saved LR (x30) from first level CALLH/EXH or failed hash jump
a.mov(REG_PARAM3, inst.param(1).mapvar());

emit_ldr_mem(a, TEMP_REG1, &m_near.drcmap_get_value);

a.blr(TEMP_REG1);
call_arm_addr(a, m_drcmap_get_value.func);

mov_param_reg(a, inst.size(), dstp, REG_PARAM1);
}
7 changes: 3 additions & 4 deletions src/devices/cpu/drcbearm64.h
Original file line number Diff line number Diff line change
@@ -225,9 +225,6 @@ class drcbe_arm64 : public drcbe_interface

struct near_state
{
void *debug_cpu_instruction_hook;
void *drcmap_get_value;

uint32_t emulated_flags;
};
near_state &m_near;
@@ -241,10 +238,12 @@ 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];

resolved_member_function m_debug_cpu_instruction_hook;
resolved_member_function m_drcmap_get_value;
resolved_memory_accessors_vector m_resolved_accessors;
};

}
} // namespace drc

using drc::drcbe_arm64;

33 changes: 24 additions & 9 deletions src/devices/cpu/drcbex64.cpp
Original file line number Diff line number Diff line change
@@ -658,15 +658,11 @@ drcbe_x64::drcbe_x64(drcuml_state &drcuml, device_t &device, drc_cache &cache, u
m_absmask64[0] = m_absmask64[1] = 0x7fffffffffffffffU;

// get pointers to C functions we need to call
using debugger_hook_func = void (*)(device_debug *, offs_t);
static const debugger_hook_func debugger_inst_hook = [] (device_debug *dbg, offs_t pc) { dbg->instruction_hook(pc); }; // TODO: kill trampoline if possible
m_near.debug_cpu_instruction_hook = (x86code *)debugger_inst_hook;
if (LOG_HASHJMPS)
{
m_near.debug_log_hashjmp = (x86code *)debug_log_hashjmp;
m_near.debug_log_hashjmp_fail = (x86code *)debug_log_hashjmp_fail;
}
m_near.drcmap_get_value = (x86code *)&drc_map_variables::static_get_value;

// build the flags map
for (int entry = 0; entry < std::size(m_near.flagsmap); entry++)
@@ -690,7 +686,13 @@ drcbe_x64::drcbe_x64(drcuml_state &drcuml, device_t &device, drc_cache &cache, u
m_near.flagsunmap[entry] = flags;
}

// resolve the actual addresses of the address space handlers
// resolve the actual addresses of member functions we need to call
m_drcmap_get_value.set(m_map, &drc_map_variables::get_value);
if (!m_drcmap_get_value)
{
m_drcmap_get_value.obj = uintptr_t(&m_map);
m_drcmap_get_value.func = reinterpret_cast<uint8_t *>(uintptr_t(&drc_map_variables::static_get_value));
}
m_resolved_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space)
{
@@ -865,6 +867,19 @@ int drcbe_x64::execute(code_handle &entry)

void drcbe_x64::generate(drcuml_block &block, const instruction *instlist, uint32_t numinst)
{
// do this here because device.debug() isn't initialised at construction time
if (!m_debug_cpu_instruction_hook && (m_device.machine().debug_flags & DEBUG_FLAG_ENABLED))
{
m_debug_cpu_instruction_hook.set(*m_device.debug(), &device_debug::instruction_hook);
if (!m_debug_cpu_instruction_hook)
{
m_debug_cpu_instruction_hook.obj = uintptr_t(m_device.debug());
using debugger_hook_func = void (*)(device_debug *, offs_t);
static const auto debugger_inst_hook = [] (device_debug *dbg, offs_t pc) { dbg->instruction_hook(pc); };
m_debug_cpu_instruction_hook.func = reinterpret_cast<uint8_t *>(uintptr_t(debugger_hook_func(debugger_inst_hook)));
}
}

// tell all of our utility objects that a block is beginning
m_hash.block_begin(block, instlist, numinst);
m_map.block_begin(block);
@@ -1529,9 +1544,9 @@ void drcbe_x64::op_debug(Assembler &a, const instruction &inst)
a.short_().jz(skip);

// push the parameter
mov_r64_imm(a, Gpq(REG_PARAM1), (uintptr_t)m_device.debug()); // mov param1,device.debug
mov_r64_imm(a, Gpq(REG_PARAM1), m_debug_cpu_instruction_hook.obj); // mov param1,device.debug
mov_reg_param(a, Gpd(REG_PARAM2), pcp); // mov param2,pcp
smart_call_m64(a, &m_near.debug_cpu_instruction_hook); // call debug_cpu_instruction_hook
smart_call_r64(a, m_debug_cpu_instruction_hook.func, rax); // call debug_cpu_instruction_hook

a.bind(skip);
}
@@ -1834,10 +1849,10 @@ void drcbe_x64::op_recover(Assembler &a, const instruction &inst)
// call the recovery code
a.mov(rax, MABS(&m_near.stacksave)); // mov rax,stacksave
a.mov(rax, ptr(rax, -8)); // mov rax,[rax-8]
mov_r64_imm(a, Gpq(REG_PARAM1), (uintptr_t)&m_map); // mov param1,m_map
mov_r64_imm(a, Gpq(REG_PARAM1), m_drcmap_get_value.obj); // mov param1,m_map
a.lea(Gpq(REG_PARAM2), ptr(rax, -1)); // lea param2,[rax-1]
mov_r64_imm(a, Gpq(REG_PARAM3), inst.param(1).mapvar()); // mov param3,param[1].value
smart_call_m64(a, &m_near.drcmap_get_value); // call drcmap_get_value
smart_call_r64(a, m_drcmap_get_value.func, rax); // call drcmap_get_value
mov_param_reg(a, dstp, eax); // mov dstp,eax
}

4 changes: 2 additions & 2 deletions src/devices/cpu/drcbex64.h
Original file line number Diff line number Diff line change
@@ -251,10 +251,8 @@ class drcbe_x64 : public drcbe_interface
// state to live in the near cache
struct near_state
{
x86code * debug_cpu_instruction_hook;// debugger callback
x86code * debug_log_hashjmp; // hashjmp debugging
x86code * debug_log_hashjmp_fail; // hashjmp debugging
x86code * drcmap_get_value; // map lookup helper

uint32_t ssemode; // saved SSE mode
uint32_t ssemodesave; // temporary location for saving
@@ -270,6 +268,8 @@ class drcbe_x64 : public drcbe_interface
near_state & m_near;

// resolved memory handler functions
resolved_member_function m_debug_cpu_instruction_hook;
resolved_member_function m_drcmap_get_value;
resolved_memory_accessors_vector m_resolved_accessors;

// globals

0 comments on commit 6ca960f

Please sign in to comment.