diff --git a/src/devices/cpu/drcbearm64.cpp b/src/devices/cpu/drcbearm64.cpp index 0d9f05dd46224..521dc8f5204b3 100644 --- a/src/devices/cpu/drcbearm64.cpp +++ b/src/devices/cpu/drcbearm64.cpp @@ -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(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(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); } diff --git a/src/devices/cpu/drcbearm64.h b/src/devices/cpu/drcbearm64.h index 9623050765407..258d2947d3e68 100644 --- a/src/devices/cpu/drcbearm64.h +++ b/src/devices/cpu/drcbearm64.h @@ -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; diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp index 662802a80f997..b57c48828d189 100644 --- a/src/devices/cpu/drcbex64.cpp +++ b/src/devices/cpu/drcbex64.cpp @@ -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(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(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 } diff --git a/src/devices/cpu/drcbex64.h b/src/devices/cpu/drcbex64.h index ffb19e965d477..18c5f1d59b8aa 100644 --- a/src/devices/cpu/drcbex64.h +++ b/src/devices/cpu/drcbex64.h @@ -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