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 // resolve the actual addresses of member functions we need to call
m_drcmap_get_value.set(m_map, &drc_map_variables::get_value); m_drcmap_get_value.set(m_map, &drc_map_variables::get_value);
if (!m_drcmap_get_value) if (!m_drcmap_get_value)
{ throw emu_fatalerror("Error resolving map variable get value function!\n");
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()); m_resolved_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space) 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); m_debug_cpu_instruction_hook.set(*m_device.debug(), &device_debug::instruction_hook);
if (!m_debug_cpu_instruction_hook) if (!m_debug_cpu_instruction_hook)
{ throw emu_fatalerror("Error resolving debugger instruction hook member function!\n");
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 // 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 // register the current pointer for the handle
inst.param(0).handle().set_codeptr(drccodeptr(a.code()->baseAddress() + a.offset())); 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.stp(a64::x29, a64::x30, arm::Mem(a64::sp, -16).pre());
a.bind(skip); a.bind(skip);
} }

View File

@ -407,11 +407,6 @@ uint32_t drc_map_variables::get_value(drccodeptr codebase, uint32_t mapvar) cons
return result; 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_value(drccodeptr codebase, uint32_t mapvar) const;
uint32_t get_last_value(uint32_t mapvar); 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: private:
// internal state // internal state
drc_cache & m_cache; // pointer to the cache drc_cache & m_cache; // pointer to the cache

View File

@ -146,23 +146,44 @@
Exit point: Exit point:
Assumes exit value is in RAX. Assumes exit value is in RAX.
Entry stack: Top-level generated code frame:
[rsp] - return [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: Generated code subroutine call frame:
[rsp] - r9 home [rsp+0x00] - rcx home/scratch
[rsp+8] - r8 home [rsp+0x08] - rdx home/scratch
[rsp+16] - rdx home [rsp+0x10] - r8 home/scratch
[rsp+24] - rcx home [rsp+0x18] - r9 home/scratch
[rsp+40] - saved r15 [rsp+0x20] - scratch
[rsp+48] - saved r14 [rsp+0x28] - ret
[rsp+56] - saved r13 ...
[rsp+64] - saved r12 - rcx home/scratch
[rsp+72] - saved rbp - rdx home/scratch
[rsp+80] - saved rdi - r8 home/scratch
[rsp+88] - saved rsi - r9 home/scratch
[rsp+96] - saved rbx - scratch
[rsp+104] - ret - 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 // resolve the actual addresses of member functions we need to call
m_drcmap_get_value.set(m_map, &drc_map_variables::get_value); m_drcmap_get_value.set(m_map, &drc_map_variables::get_value);
if (!m_drcmap_get_value) if (!m_drcmap_get_value)
{ throw emu_fatalerror("Error resolving map variable get value function!\n");
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()); m_resolved_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space) 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); m_debug_cpu_instruction_hook.set(*m_device.debug(), &device_debug::instruction_hook);
if (!m_debug_cpu_instruction_hook) if (!m_debug_cpu_instruction_hook)
{ throw emu_fatalerror("Error resolving debugger instruction hook member function!\n");
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 // 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 // emit a jump around the stack adjust in case code falls through here
Label skip = a.newLabel(); Label skip = a.newLabel();
a.short_().jmp(skip); // jmp skip a.short_().jmp(skip);
// register the current pointer for the handle // register the current pointer for the handle
inst.param(0).handle().set_codeptr(drccodeptr(a.code()->baseAddress() + a.offset())); 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 // by default, the handle points to prologue code that moves the stack pointer
a.lea(rsp, ptr(rsp, -40)); // lea rsp,[rsp-40] a.lea(rsp, ptr(rsp, -40));
a.bind(skip); // skip: 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 // 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()); m_memory_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space) 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) 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 // tell all of our utility objects that a block is beginning
m_hash.block_begin(block, instlist, numinst); m_hash.block_begin(block, instlist, numinst);
m_map.block_begin(block); 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_condition(inst);
assert_no_flags(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) if ((m_device.machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
{ {
// normalize parameters // normalize parameters
be_parameter const pcp(*this, inst.param(0), PTYPE_MRI); be_parameter const pcp(*this, inst.param(0), PTYPE_MRI);
// test and branch // 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(); Label skip = a.newLabel();
a.short_().jz(skip); // jz skip a.short_().jz(skip);
// push the parameter // push the parameter
emit_mov_m32_p32(a, dword_ptr(esp, 4), pcp); // mov [esp+4],pcp emit_mov_m32_p32(a, dword_ptr(esp, USE_THISCALL ? 0 : 4), pcp);
a.mov(dword_ptr(esp, 0), imm(m_device.debug())); // mov [esp],device.debug if (USE_THISCALL)
a.call(imm(debugger_inst_hook)); // call debugger_inst_hook 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(); 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); be_parameter dstp(*this, inst.param(0), PTYPE_MR);
// call the recovery code // call the recovery code
a.mov(eax, MABS(&m_stacksave)); // mov eax,stacksave a.mov(eax, MABS(&m_stacksave));
a.mov(eax, ptr(eax, -4)); // mov eax,[eax-4] a.mov(eax, ptr(eax, -4));
a.sub(eax, 1); // sub eax,1 a.sub(eax, 1);
a.mov(dword_ptr(esp, 8), inst.param(1).mapvar()); // mov [esp+8],param1 a.mov(dword_ptr(esp, USE_THISCALL ? 4 : 8), inst.param(1).mapvar());
a.mov(ptr(esp, 4), eax); // mov [esp+4],eax a.mov(ptr(esp, USE_THISCALL ? 0 : 4), eax);
a.mov(dword_ptr(esp, 0), imm(&m_map)); // mov [esp],m_map if (USE_THISCALL)
a.call(imm(&drc_map_variables::static_get_value)); // call drcmap_get_value a.mov(ecx, imm(m_drcmap_get_value.obj));
emit_mov_p32_r32(a, dstp, eax); // mov dstp,eax 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 uint64_t m_reshi; // extended high result
// resolved memory handler functions // 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; resolved_memory_accessors_vector m_memory_accessors;
// globals // globals