diff --git a/src/devices/cpu/drcbearm64.cpp b/src/devices/cpu/drcbearm64.cpp index 8493e4b7106..24c7f54bc28 100644 --- a/src/devices/cpu/drcbearm64.cpp +++ b/src/devices/cpu/drcbearm64.cpp @@ -81,10 +81,14 @@ the location FP points to. #include "debug/debugcpu.h" #include "emuopts.h" +#include "mfpresolve.h" + #include "asmjit/src/asmjit/asmjit.h" #include "asmjit/src/asmjit/a64.h" #include +#include +#include #include @@ -619,6 +623,8 @@ private: void call_arm_addr(asmjit::a64::Assembler &a, const void *offs) const; + [[noreturn]] void end_of_block() const; + drc_hash_table m_hash; drc_map_variables m_map; FILE *m_log_asmjit; @@ -627,6 +633,7 @@ private: arm64_entry_point_func m_entry; drccodeptr m_exit; drccodeptr m_nocode; + drccodeptr m_endofblock; uint8_t *m_baseptr; @@ -1429,6 +1436,7 @@ drcbe_arm64::drcbe_arm64(drcuml_state &drcuml, device_t &device, drc_cache &cach , m_entry(nullptr) , m_exit(nullptr) , m_nocode(nullptr) + , m_endofblock(nullptr) , m_baseptr(cache.near() + 0x100) , m_near(*(near_state *)cache.alloc_near(sizeof(m_near))) { @@ -1556,6 +1564,13 @@ void drcbe_arm64::reset() a.bind(a.newNamedLabel("nocode_point")); a.br(REG_PARAM1); + // generate an end-of-block handler point + m_endofblock = dst + a.offset(); + a.bind(a.newNamedLabel("end_of_block_point")); + auto const [entrypoint, adjusted] = util::resolve_member_function(&drcbe_arm64::end_of_block, *this); + get_imm_relative(a, REG_PARAM1, adjusted); + call_arm_addr(a, (const void *)entrypoint); + // emit the generated code emit(ch); @@ -1640,7 +1655,10 @@ void drcbe_arm64::generate(drcuml_block &block, const instruction *instlist, uin (this->*s_opcode_table[inst.opcode()])(a, inst); } - emit_str_mem(a, FLAGS_REG.w(), &m_near.emulated_flags); + // catch falling off the end of a block + if (logger.file()) + a.setInlineComment("end of block"); + a.b(m_endofblock); // emit the generated code if (!emit(ch)) @@ -1671,6 +1689,16 @@ void drcbe_arm64::get_info(drcbe_info &info) const noexcept } } + +[[noreturn]] void drcbe_arm64::end_of_block() const +{ + osd_printf_error("drcbe_arm64(%s): fell off the end of a generated code block!\n", m_device.tag()); + std::fflush(stdout); + std::fflush(stderr); + std::abort(); +} + + void drcbe_arm64::op_handle(a64::Assembler &a, const uml::instruction &inst) { assert_no_condition(inst); @@ -1753,7 +1781,8 @@ void drcbe_arm64::op_mapvar(a64::Assembler &a, const uml::instruction &inst) void drcbe_arm64::op_nop(a64::Assembler &a, const uml::instruction &inst) { - a.nop(); + // nothing + //a.nop(); } void drcbe_arm64::op_break(a64::Assembler &a, const uml::instruction &inst) diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp index d246b2b6dc5..25541400028 100644 --- a/src/devices/cpu/drcbex64.cpp +++ b/src/devices/cpu/drcbex64.cpp @@ -122,7 +122,7 @@ R14 - maps to I5 R15 - maps to I6 - Registers (Linux/MacOS): + Registers (SysV) RAX - scratch register RBX - maps to I0 RCX - scratch register @@ -146,7 +146,7 @@ Exit point: Assumes exit value is in RAX. - Top-level generated code frame: + Top-level generated code frame (Windows): [rsp+0x00] - rcx home/scratch [rsp+0x08] - rdx home/scratch [rsp+0x10] - r8 home/scratch @@ -162,6 +162,20 @@ [rsp+0x60] - saved rbx [rsp+0x68] - ret + Top-level generated code frame (SysV): + [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 rbx + [rsp+0x58] - ret + Generated code subroutine call frame: [rsp+0x00] - rcx home/scratch [rsp+0x08] - rdx home/scratch @@ -179,11 +193,7 @@ - saved r14 - saved r13 - saved r12 - - saved rdi - - saved rsi - - saved rbp - - saved rbx - - ret + ... ***************************************************************************/ @@ -196,9 +206,13 @@ #include "debug/debugcpu.h" #include "emuopts.h" +#include "mfpresolve.h" + #include "asmjit/src/asmjit/asmjit.h" #include +#include +#include #include @@ -451,6 +465,7 @@ private: void smart_call_r64(asmjit::x86::Assembler &a, x86code *target, asmjit::x86::Gp const ®); void smart_call_m64(asmjit::x86::Assembler &a, x86code **target); + [[noreturn]] void end_of_block() const; static void debug_log_hashjmp(offs_t pc, int mode); static void debug_log_hashjmp_fail(); @@ -575,6 +590,7 @@ private: x86_entry_point_func m_entry; // entry point x86code * m_exit; // exit point x86code * m_nocode; // nocode handler + x86code * m_endofblock; // end of block handler // state to live in the near cache struct near_state @@ -944,6 +960,7 @@ drcbe_x64::drcbe_x64(drcuml_state &drcuml, device_t &device, drc_cache &cache, u , m_entry(nullptr) , m_exit(nullptr) , m_nocode(nullptr) + , m_endofblock(nullptr) , m_near(*(near_state *)cache.alloc_near(sizeof(m_near))) { // build up necessary arrays @@ -1146,14 +1163,22 @@ void drcbe_x64::reset() a.bind(a.newNamedLabel("nocode_point")); a.jmp(Gpq(REG_PARAM1)); - // emit the generated code - size_t bytes = emit(ch); + // generate an end-of-block handler point + m_endofblock = dst + a.offset(); + a.bind(a.newNamedLabel("end_of_block_point")); + auto const [entrypoint, adjusted] = util::resolve_member_function(&drcbe_x64::end_of_block, *this); + mov_r64_imm(a, Gpq(REG_PARAM1), adjusted); + smart_call_r64(a, (x86code *)entrypoint, rax); - if (m_log != nullptr) + // emit the generated code + const size_t bytes = emit(ch); + + if (m_log) { x86log_disasm_code_range(m_log, "entry_point", dst, m_exit); x86log_disasm_code_range(m_log, "exit_point", m_exit, m_nocode); - x86log_disasm_code_range(m_log, "nocode_point", m_nocode, dst + bytes); + x86log_disasm_code_range(m_log, "nocode_point", m_nocode, m_endofblock); + x86log_disasm_code_range(m_log, "end_of_block", m_endofblock, dst + bytes); } // reset our hash tables @@ -1238,7 +1263,7 @@ void drcbe_x64::generate(drcuml_block &block, const instruction *instlist, uint3 std::string dasm; // add a comment - if (m_log != nullptr) + if (m_log) { dasm = inst.disasm(&m_drcuml); @@ -1259,13 +1284,21 @@ void drcbe_x64::generate(drcuml_block &block, const instruction *instlist, uint3 (this->*s_opcode_table[inst.opcode()])(a, inst); } + // catch falling off the end of a block + if (m_log) + { + x86log_add_comment(m_log, dst + a.offset(), "%s", "end of block"); + a.setInlineComment("end of block"); + } + a.jmp(imm(m_endofblock)); + // emit the generated code size_t const bytes = emit(ch); if (!bytes) block.abort(); // log it - if (m_log != nullptr) + if (m_log) x86log_disasm_code_range(m_log, (blockname.empty()) ? "Unknown block" : blockname.c_str(), dst, dst + bytes); // tell all of our utility objects that the block is finished @@ -1674,11 +1707,11 @@ void drcbe_x64::movsd_p64_r128(Assembler &a, be_parameter const ¶m, Xmm cons { assert(!param.is_immediate()); if (param.is_memory()) - a.movsd(MABS(param.memory(), 8), reg); // movsd [param],reg + a.movsd(MABS(param.memory(), 8), reg); else if (param.is_float_register()) { if (reg.id() != param.freg()) - a.movsd(Xmm(param.freg()), reg); // movsd param,reg + a.movsd(Xmm(param.freg()), reg); } } @@ -1687,6 +1720,20 @@ void drcbe_x64::movsd_p64_r128(Assembler &a, be_parameter const ¶m, Xmm cons // DEBUG HELPERS //************************************************************************** +//------------------------------------------------- +// end_of_block - function to catch falling off +// the end of a generated code block +//------------------------------------------------- + +[[noreturn]] void drcbe_x64::end_of_block() const +{ + osd_printf_error("drcbe_x64(%s): fell off the end of a generated code block!\n", m_device.tag()); + std::fflush(stdout); + std::fflush(stderr); + std::abort(); +} + + //------------------------------------------------- // debug_log_hashjmp - callback to handle // logging of hashjmps @@ -1694,7 +1741,7 @@ void drcbe_x64::movsd_p64_r128(Assembler &a, be_parameter const ¶m, Xmm cons void drcbe_x64::debug_log_hashjmp(offs_t pc, int mode) { - printf("mode=%d PC=%08X\n", mode, pc); + std::printf("mode=%d PC=%08X\n", mode, pc); } @@ -1705,7 +1752,7 @@ void drcbe_x64::debug_log_hashjmp(offs_t pc, int mode) void drcbe_x64::debug_log_hashjmp_fail() { - printf(" (FAIL)\n"); + std::printf(" (FAIL)\n"); } diff --git a/src/devices/cpu/drcbex86.cpp b/src/devices/cpu/drcbex86.cpp index 97813ba65e0..b3acf261860 100644 --- a/src/devices/cpu/drcbex86.cpp +++ b/src/devices/cpu/drcbex86.cpp @@ -91,9 +91,13 @@ #include "debug/debugcpu.h" #include "emuopts.h" +#include "mfpresolve.h" + #include "asmjit/src/asmjit/asmjit.h" #include +#include +#include namespace drc { @@ -498,6 +502,7 @@ private: bool can_skip_lower_load(asmjit::x86::Assembler &a, uint32_t *memref, asmjit::x86::Gp const ®lo); bool can_skip_upper_load(asmjit::x86::Assembler &a, uint32_t *memref, asmjit::x86::Gp const ®hi); + [[noreturn]] void end_of_block() const; static void debug_log_hashjmp(int mode, offs_t pc); // code generators @@ -636,6 +641,7 @@ private: x86_entry_point_func m_entry; // entry point x86code * m_exit; // exit point x86code * m_nocode; // nocode handler + x86code * m_endofblock; // end of block handler x86code * m_save; // save handler x86code * m_restore; // restore handler @@ -1027,6 +1033,7 @@ drcbe_x86::drcbe_x86(drcuml_state &drcuml, device_t &device, drc_cache &cache, u , m_entry(nullptr) , m_exit(nullptr) , m_nocode(nullptr) + , m_endofblock(nullptr) , m_save(nullptr) , m_restore(nullptr) , m_last_lower_reg(Gp()) @@ -1217,6 +1224,18 @@ void drcbe_x86::reset() a.bind(a.newNamedLabel("nocode_point")); a.ret(); // ret + // generate an end-of-block handler point + m_endofblock = dst + a.offset(); + a.bind(a.newNamedLabel("end_of_block_point")); + auto const [entrypoint, adjusted] = util::resolve_member_function(&drcbe_x86::end_of_block, *this); + if (USE_THISCALL) + a.mov(ecx, imm(adjusted)); + else + a.mov(dword_ptr(esp, 0), imm(adjusted)); + a.call(imm(entrypoint)); + if (USE_THISCALL) + a.sub(esp, 4); + // generate a save subroutine m_save = dst + a.offset(); a.bind(a.newNamedLabel("save")); @@ -1299,7 +1318,8 @@ void drcbe_x86::reset() { x86log_disasm_code_range(m_log, "entry_point", dst, m_exit); x86log_disasm_code_range(m_log, "exit_point", m_exit, m_nocode); - x86log_disasm_code_range(m_log, "nocode_point", m_nocode, m_save); + x86log_disasm_code_range(m_log, "nocode_point", m_nocode, m_endofblock); + x86log_disasm_code_range(m_log, "end_of_block", m_endofblock, m_save); x86log_disasm_code_range(m_log, "save", m_save, m_restore); x86log_disasm_code_range(m_log, "restore", m_restore, dst + bytes); @@ -1387,7 +1407,7 @@ void drcbe_x86::generate(drcuml_block &block, const instruction *instlist, uint3 std::string dasm; // add a comment - if (m_log != nullptr) + if (m_log) { dasm = inst.disasm(&m_drcuml); x86log_add_comment(m_log, dst + a.offset(), "%s", dasm.c_str()); @@ -1407,13 +1427,21 @@ void drcbe_x86::generate(drcuml_block &block, const instruction *instlist, uint3 (this->*s_opcode_table[inst.opcode()])(a, inst); } + // catch falling off the end of a block + if (m_log) + { + x86log_add_comment(m_log, dst + a.offset(), "%s", "end of block"); + a.setInlineComment("end of block"); + } + a.jmp(imm(m_endofblock)); + // emit the generated code size_t const bytes = emit(ch); if (!bytes) block.abort(); // log it - if (m_log != nullptr) + if (m_log) x86log_disasm_code_range(m_log, (blockname.empty()) ? "Unknown block" : blockname.c_str(), dst, dst + bytes); // tell all of our utility objects that the block is finished @@ -2816,6 +2844,20 @@ void drcbe_x86::emit_fstp_p(Assembler &a, int size, be_parameter const ¶m) // DEBUG HELPERS //************************************************************************** +//------------------------------------------------- +// end_of_block - function to catch falling off +// the end of a generated code block +//------------------------------------------------- + +[[noreturn]] void drcbe_x86::end_of_block() const +{ + osd_printf_error("drcbe_x86(%s): fell off the end of a generated code block!\n", m_device.tag()); + std::fflush(stdout); + std::fflush(stderr); + std::abort(); +} + + //------------------------------------------------- // debug_log_hashjmp - callback to handle // logging of hashjmps @@ -2823,7 +2865,7 @@ void drcbe_x86::emit_fstp_p(Assembler &a, int size, be_parameter const ¶m) void drcbe_x86::debug_log_hashjmp(int mode, offs_t pc) { - printf("mode=%d PC=%08X\n", mode, pc); + std::printf("mode=%d PC=%08X\n", mode, pc); } diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index d7d9a8fdf08..da9900ff680 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -1539,7 +1539,7 @@ void cli_frontend::verifysoftlist(const std::vector &args) void cli_frontend::version(const std::vector &args) { - osd_printf_info("%s", emulator_info::get_build_version()); + osd_printf_info("%s\n", emulator_info::get_build_version()); }