mirror of
https://github.com/holub/mame
synced 2025-04-20 15:32:45 +03:00
-cpu/drcbe*.cpp: Print an error message and abort when running off the end of a generated code block.
-cpu/drcbearm64.cpp: Don't emit code for UML NOP - the simplifier litters the code with these for elided operations. -frontend/mame/clifront.cpp: Added newline at end of -version output.
This commit is contained in:
parent
b5fafba307
commit
daedf2ff31
@ -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 <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@ -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)
|
||||
|
@ -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 <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -91,9 +91,13 @@
|
||||
#include "debug/debugcpu.h"
|
||||
#include "emuopts.h"
|
||||
|
||||
#include "mfpresolve.h"
|
||||
|
||||
#include "asmjit/src/asmjit/asmjit.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1539,7 +1539,7 @@ void cli_frontend::verifysoftlist(const std::vector<std::string> &args)
|
||||
|
||||
void cli_frontend::version(const std::vector<std::string> &args)
|
||||
{
|
||||
osd_printf_info("%s", emulator_info::get_build_version());
|
||||
osd_printf_info("%s\n", emulator_info::get_build_version());
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user