cpu: Got rid of the rest of the static member function trampolines.

cpu/drcbearm64.cpp, cpu/drcbex64.cpp: Removed static trampoline
fallbacks for get map variable value and debugger instrcution hook
functions.

cpu/drcbex86.cpp: Removed static trampolines for get map variable value
and debugger instrcution hook functions.

cpu/drcbex64.cpp: Corrected stack diagram in comment.
This commit is contained in:
Vas Crabb 2025-02-04 07:51:33 +11:00
parent c6b97a6e23
commit 88a26bb838
6 changed files with 83 additions and 66 deletions

View File

@ -973,10 +973,7 @@ drcbe_arm64::drcbe_arm64(drcuml_state &drcuml, device_t &device, drc_cache &cach
// 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));
}
throw emu_fatalerror("Error resolving map variable get value function!\n");
m_resolved_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space)
{
@ -1096,12 +1093,7 @@ void drcbe_arm64::generate(drcuml_block &block, const instruction *instlist, uin
{
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)));
}
throw emu_fatalerror("Error resolving debugger instruction hook member function!\n");
}
// tell all of our utility objects that a block is beginning
@ -1200,7 +1192,7 @@ void drcbe_arm64::op_handle(a64::Assembler &a, const uml::instruction &inst)
// register the current pointer for the handle
inst.param(0).handle().set_codeptr(drccodeptr(a.code()->baseAddress() + a.offset()));
// the handle points to prolog code that creates a minimal non-leaf frame
// the handle points to prologue code that creates a minimal non-leaf frame
a.stp(a64::x29, a64::x30, arm::Mem(a64::sp, -16).pre());
a.bind(skip);
}

View File

@ -407,11 +407,6 @@ uint32_t drc_map_variables::get_value(drccodeptr codebase, uint32_t mapvar) cons
return result;
}
uint32_t drc_map_variables::static_get_value(drc_map_variables &map, drccodeptr codebase, uint32_t mapvar)
{
return map.get_value(codebase, mapvar);
}
//-------------------------------------------------

View File

@ -98,9 +98,6 @@ public:
uint32_t get_value(drccodeptr codebase, uint32_t mapvar) const;
uint32_t get_last_value(uint32_t mapvar);
// static accessors to be called directly by generated code
static uint32_t static_get_value(drc_map_variables &map, drccodeptr codebase, uint32_t mapvar);
private:
// internal state
drc_cache & m_cache; // pointer to the cache

View File

@ -146,23 +146,44 @@
Exit point:
Assumes exit value is in RAX.
Entry stack:
[rsp] - return
Top-level generated code frame:
[rsp+0x00] - rcx home/scratch
[rsp+0x08] - rdx home/scratch
[rsp+0x10] - r8 home/scratch
[rsp+0x18] - r9 home/scratch
[rsp+0x20] - scratch
[rsp+0x28] - saved r15
[rsp+0x30] - saved r14
[rsp+0x38] - saved r13
[rsp+0x40] - saved r12
[rsp+0x48] - saved rbp
[rsp+0x50] - saved rdi
[rsp+0x58] - saved rsi
[rsp+0x60] - saved rbx
[rsp+0x68] - ret
Runtime stack:
[rsp] - r9 home
[rsp+8] - r8 home
[rsp+16] - rdx home
[rsp+24] - rcx home
[rsp+40] - saved r15
[rsp+48] - saved r14
[rsp+56] - saved r13
[rsp+64] - saved r12
[rsp+72] - saved rbp
[rsp+80] - saved rdi
[rsp+88] - saved rsi
[rsp+96] - saved rbx
[rsp+104] - ret
Generated code subroutine call frame:
[rsp+0x00] - rcx home/scratch
[rsp+0x08] - rdx home/scratch
[rsp+0x10] - r8 home/scratch
[rsp+0x18] - r9 home/scratch
[rsp+0x20] - scratch
[rsp+0x28] - ret
...
- rcx home/scratch
- rdx home/scratch
- r8 home/scratch
- r9 home/scratch
- scratch
- saved r15
- saved r14
- saved r13
- saved r12
- saved rdi
- saved rsi
- saved rbp
- saved rbx
- ret
***************************************************************************/
@ -689,10 +710,7 @@ drcbe_x64::drcbe_x64(drcuml_state &drcuml, device_t &device, drc_cache &cache, u
// 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));
}
throw emu_fatalerror("Error resolving map variable get value function!\n");
m_resolved_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space)
{
@ -872,12 +890,7 @@ void drcbe_x64::generate(drcuml_block &block, const instruction *instlist, uint3
{
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)));
}
throw emu_fatalerror("Error resolving debugger instruction hook member function!\n");
}
// tell all of our utility objects that a block is beginning
@ -1420,14 +1433,14 @@ void drcbe_x64::op_handle(Assembler &a, const instruction &inst)
// emit a jump around the stack adjust in case code falls through here
Label skip = a.newLabel();
a.short_().jmp(skip); // jmp skip
a.short_().jmp(skip);
// register the current pointer for the handle
inst.param(0).handle().set_codeptr(drccodeptr(a.code()->baseAddress() + a.offset()));
// by default, the handle points to prolog code that moves the stack pointer
a.lea(rsp, ptr(rsp, -40)); // lea rsp,[rsp-40]
a.bind(skip); // skip:
// by default, the handle points to prologue code that moves the stack pointer
a.lea(rsp, ptr(rsp, -40));
a.bind(skip);
}

View File

@ -602,6 +602,9 @@ drcbe_x86::drcbe_x86(drcuml_state &drcuml, device_t &device, drc_cache &cache, u
}
// 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)
throw emu_fatalerror("Error resolving map variable get value function!\n");
m_memory_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space)
{
@ -856,6 +859,14 @@ int drcbe_x86::execute(code_handle &entry)
void drcbe_x86::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)
throw emu_fatalerror("Error resolving debugger instruction hook member function!\n");
}
// tell all of our utility objects that a block is beginning
m_hash.block_begin(block, instlist, numinst);
m_map.block_begin(block);
@ -2535,25 +2546,27 @@ void drcbe_x86::op_debug(Assembler &a, const instruction &inst)
assert_no_condition(inst);
assert_no_flags(inst);
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
if ((m_device.machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
{
// normalize parameters
be_parameter const pcp(*this, inst.param(0), PTYPE_MRI);
// test and branch
a.test(MABS(&m_device.machine().debug_flags, 4), DEBUG_FLAG_CALL_HOOK); // test [debug_flags],DEBUG_FLAG_CALL_HOOK
a.test(MABS(&m_device.machine().debug_flags, 4), DEBUG_FLAG_CALL_HOOK);
Label skip = a.newLabel();
a.short_().jz(skip); // jz skip
a.short_().jz(skip);
// push the parameter
emit_mov_m32_p32(a, dword_ptr(esp, 4), pcp); // mov [esp+4],pcp
a.mov(dword_ptr(esp, 0), imm(m_device.debug())); // mov [esp],device.debug
a.call(imm(debugger_inst_hook)); // call debugger_inst_hook
emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 0 : 4), pcp);
if (USE_THISCALL)
a.mov(ecx, imm(m_debug_cpu_instruction_hook.obj));
else
a.mov(dword_ptr(esp, 0), imm(m_debug_cpu_instruction_hook.obj));
a.call(imm(m_debug_cpu_instruction_hook.func));
if (USE_THISCALL)
a.sub(esp, 4);
a.bind(skip); // skip:
a.bind(skip);
reset_last_upper_lower_reg();
}
}
@ -2856,14 +2869,19 @@ void drcbe_x86::op_recover(Assembler &a, const instruction &inst)
be_parameter dstp(*this, inst.param(0), PTYPE_MR);
// call the recovery code
a.mov(eax, MABS(&m_stacksave)); // mov eax,stacksave
a.mov(eax, ptr(eax, -4)); // mov eax,[eax-4]
a.sub(eax, 1); // sub eax,1
a.mov(dword_ptr(esp, 8), inst.param(1).mapvar()); // mov [esp+8],param1
a.mov(ptr(esp, 4), eax); // mov [esp+4],eax
a.mov(dword_ptr(esp, 0), imm(&m_map)); // mov [esp],m_map
a.call(imm(&drc_map_variables::static_get_value)); // call drcmap_get_value
emit_mov_p32_r32(a, dstp, eax); // mov dstp,eax
a.mov(eax, MABS(&m_stacksave));
a.mov(eax, ptr(eax, -4));
a.sub(eax, 1);
a.mov(dword_ptr(esp, USE_THISCALL ? 4 : 8), inst.param(1).mapvar());
a.mov(ptr(esp, USE_THISCALL ? 0 : 4), eax);
if (USE_THISCALL)
a.mov(ecx, imm(m_drcmap_get_value.obj));
else
a.mov(dword_ptr(esp, 0), imm(m_drcmap_get_value.obj));
a.call(imm(m_drcmap_get_value.func));
if (USE_THISCALL)
a.sub(esp, 8);
emit_mov_p32_r32(a, dstp, eax);
}

View File

@ -292,6 +292,8 @@ private:
uint64_t m_reshi; // extended high result
// resolved memory handler functions
resolved_member_function m_debug_cpu_instruction_hook;
resolved_member_function m_drcmap_get_value;
resolved_memory_accessors_vector m_memory_accessors;
// globals