summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rwxr-xr-xscripts/src/3rdparty.lua7
-rw-r--r--scripts/src/cpu.lua21
-rw-r--r--src/devices/cpu/drcbearm64.cpp531
-rw-r--r--src/devices/cpu/drcbearm64.h45
-rw-r--r--src/devices/cpu/drcbec.cpp4
-rw-r--r--src/devices/cpu/drcbec.h4
-rw-r--r--src/devices/cpu/drcbeut.cpp61
-rw-r--r--src/devices/cpu/drcbeut.h77
-rw-r--r--src/devices/cpu/drcbex64.cpp94
-rw-r--r--src/devices/cpu/drcbex64.h29
10 files changed, 469 insertions, 404 deletions
diff --git a/scripts/src/3rdparty.lua b/scripts/src/3rdparty.lua
index 785daa4a93b..492f01faabe 100755
--- a/scripts/src/3rdparty.lua
+++ b/scripts/src/3rdparty.lua
@@ -1959,13 +1959,6 @@ project "asmjit"
end
end
- if (_OPTIONS["PLATFORM"]=="arm64") then
- configuration { }
- defines {
- "ASMJIT_NO_X86",
- }
- end
-
files {
MAME_DIR .. "3rdparty/asmjit/src/asmjit/a64.h",
MAME_DIR .. "3rdparty/asmjit/src/asmjit/arm.h",
diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua
index 8d115a91ed0..f65aaf725be 100644
--- a/scripts/src/cpu.lua
+++ b/scripts/src/cpu.lua
@@ -42,19 +42,14 @@ if (CPU_INCLUDE_DRC) then
MAME_DIR .. "src/devices/cpu/drcumlsh.h",
}
if not _OPTIONS["FORCE_DRC_C_BACKEND"] then
- if (_OPTIONS["PLATFORM"]=="arm64") then
- files {
- MAME_DIR .. "src/devices/cpu/drcbearm64.cpp",
- MAME_DIR .. "src/devices/cpu/drcbearm64.h",
- }
- else
- files {
- MAME_DIR .. "src/devices/cpu/drcbex64.cpp",
- MAME_DIR .. "src/devices/cpu/drcbex64.h",
- MAME_DIR .. "src/devices/cpu/drcbex86.cpp",
- MAME_DIR .. "src/devices/cpu/drcbex86.h",
- }
- end
+ files {
+ MAME_DIR .. "src/devices/cpu/drcbearm64.cpp",
+ MAME_DIR .. "src/devices/cpu/drcbearm64.h",
+ MAME_DIR .. "src/devices/cpu/drcbex64.cpp",
+ MAME_DIR .. "src/devices/cpu/drcbex64.h",
+ MAME_DIR .. "src/devices/cpu/drcbex86.cpp",
+ MAME_DIR .. "src/devices/cpu/drcbex86.h",
+ }
end
if _OPTIONS["targetos"]=="macosx" and _OPTIONS["gcc"]~=nil then
diff --git a/src/devices/cpu/drcbearm64.cpp b/src/devices/cpu/drcbearm64.cpp
index b9851e3bf70..71002364461 100644
--- a/src/devices/cpu/drcbearm64.cpp
+++ b/src/devices/cpu/drcbearm64.cpp
@@ -1,5 +1,76 @@
// license:BSD-3-Clause
// copyright-holders:windyfairy
+/***************************************************************************
+
+Register use:
+
+r0 first function parameter/return value
+r1 second function parameter
+r2 third function parameter
+r3 fourth function parameter
+r4
+r5
+r6
+r7
+r8
+r9 temporary for intermediate values
+r10 temporary for intermediate values
+r11 temporary for intermediate values
+r12 scratch register used by helper functions
+r13 scratch register used by helper functions
+r14 scratch register used for address calculation
+r15 temporary used in opcode functions
+r16
+r17
+r18
+r19 UML register I0
+r20 UML register I1
+r21 UML register I2
+r22 UML register I3
+r23 UML register I4
+r24 UML register I5
+r35 UML register I6
+r26 UML register I7
+r27 near cache pointer
+r28 emulated flags
+r29 base generated code frame pointer
+r30 link register
+sp stack pointer
+
+
+Stack layout in top-level generated code frame:
+
+FP -> SP + 0x00 previous FP
+ SP + 0x08 top-level return address
+ SP + 0x10 saved non-volatile registers
+ SP + 0x18 ...
+
+Stack layout in nested generated code subroutine call frame:
+
+SP -> SP + 0x00 previous FP
+ SP + 0x08 return address
+ ...
+ FP - 0x10 previous FP
+ FP - 0x08 return address
+FP -> FP + 0x00 previous FP
+ FP + 0x08 top-level return address
+
+The frame pointer (FP or x29) is only updated by the top-level generated
+code entry point. Generated code subroutines (called using CALLH, EXH or
+on a failed HASHJMP) push FP and LR onto the stack but do not update FP.
+All the saved FP values will be identical.
+
+A native debugger following the FP chain will see any number of nested
+generated code subroutine call frames as a single stack frame. The return
+addresses and duplicate saved FP values for the generated code subroutine
+calls will appear as the local variable area of the frame.
+
+You can calculate the generated code subroutine call depth as
+(FP - SP) / 0x10. You can see the return addresses for the generated code
+subroutine calls at SP + 0x08, SP + 0x18, SP + 0x28, etc. until reaching
+the location FP points to.
+
+***************************************************************************/
#include "emu.h"
#include "drcbearm64.h"
@@ -8,8 +79,6 @@
#include "emuopts.h"
#include "uml.h"
-#include "mfpresolve.h"
-
#include <cstddef>
@@ -44,12 +113,12 @@ const a64::Gp TEMP_REG3 = a64::x11;
const a64::Gp SCRATCH_REG1 = a64::x12;
const a64::Gp SCRATCH_REG2 = a64::x13;
-// Only to be used in an opcode level function. Should not be used in helper functions
-const a64::Gp FUNC_SCRATCH_REG = a64::x15;
-
// Temporary memory calculation register, should not be used outside of functions that calculate memory addresses
const a64::Gp MEM_SCRATCH_REG = a64::x14;
+// Only to be used in an opcode level function. Should not be used in helper functions
+const a64::Gp FUNC_SCRATCH_REG = a64::x15;
+
const a64::Vec TEMPF_REG1 = a64::d16;
const a64::Vec TEMPF_REG2 = a64::d17;
const a64::Vec TEMPF_REG3 = a64::d18;
@@ -124,6 +193,111 @@ public:
}
};
+
+// helper functions
+
+a64::Vec select_register(a64::Vec const &reg, uint32_t regsize)
+{
+ if (regsize == 4)
+ return reg.s();
+ return reg.d();
+}
+
+a64::Gp select_register(a64::Gp const &reg, uint32_t regsize)
+{
+ if (regsize == 4)
+ return reg.w();
+ return reg.x();
+}
+
+bool is_valid_immediate_mask(uint64_t val, size_t bytes)
+{
+ // all zeros and all ones aren't allowed, and disallow any value with bits outside of the max bit range
+ if (val == 0 || val == make_bitmask<uint64_t>(bytes * 8))
+ return false;
+
+ uint32_t head = 64 - count_leading_zeros_64(val);
+ if (head >= (bytes * 8))
+ return false;
+
+ uint32_t tail = 0;
+ while (tail < head)
+ {
+ if (BIT(val, tail))
+ break;
+ tail++;
+ }
+
+ return population_count_64(val) == head - tail;
+}
+
+bool is_valid_immediate(uint64_t val, size_t bits)
+{
+ assert(bits < 64);
+ return val < (uint64_t(1) << bits);
+}
+
+bool is_valid_immediate_signed(int64_t val, size_t bits)
+{
+ return util::sext(val, bits) == val;
+}
+
+bool emit_add_optimized(a64::Assembler &a, const a64::Gp &dst, const a64::Gp &src, int64_t val)
+{
+ // If the bottom 12 bits are 0s then an optimized form can be used if the remaining bits are <= 12
+ if (is_valid_immediate(val, 12) || ((val & 0xfff) == 0 && is_valid_immediate(val >> 12, 12)))
+ {
+ a.add(dst, src, val);
+ return true;
+ }
+
+ return false;
+}
+
+bool emit_sub_optimized(a64::Assembler &a, const a64::Gp &dst, const a64::Gp &src, int64_t val)
+{
+ if (val < 0)
+ val = -val;
+
+ // If the bottom 12 bits are 0s then an optimized form can be used if the remaining bits are <= 12
+ if (is_valid_immediate(val, 12) || ((val & 0xfff) == 0 && is_valid_immediate(val >> 12, 12)))
+ {
+ a.sub(dst, src, val);
+ return true;
+ }
+
+ return false;
+}
+
+arm::Mem get_mem_absolute(a64::Assembler &a, const void *ptr)
+{
+ const uint64_t codeoffs = a.code()->baseAddress() + a.offset();
+ const int64_t reloffs = codeoffs - (int64_t)ptr;
+ if (is_valid_immediate_signed(reloffs, 21))
+ {
+ a.adr(MEM_SCRATCH_REG, ptr);
+ return arm::Mem(MEM_SCRATCH_REG);
+ }
+
+ const uint64_t pagebase = codeoffs & ~make_bitmask<uint64_t>(12);
+ const int64_t pagerel = (int64_t)ptr - pagebase;
+ if (is_valid_immediate_signed(pagerel, 33))
+ {
+ const uint64_t targetpage = (uint64_t)ptr & ~make_bitmask<uint64_t>(12);
+ const uint64_t pageoffs = (uint64_t)ptr & util::make_bitmask<uint64_t>(12);
+
+ a.adrp(MEM_SCRATCH_REG, targetpage);
+
+ if (is_valid_immediate_signed(pageoffs, 9))
+ return arm::Mem(MEM_SCRATCH_REG, pageoffs);
+ else if (emit_add_optimized(a, MEM_SCRATCH_REG, MEM_SCRATCH_REG, pageoffs))
+ return arm::Mem(MEM_SCRATCH_REG);
+ }
+
+ a.mov(MEM_SCRATCH_REG, ptr);
+ return arm::Mem(MEM_SCRATCH_REG);
+}
+
} // anonymous namespace
@@ -161,67 +335,67 @@ const drcbe_arm64::opcode_table_entry drcbe_arm64::s_opcode_table_source[] =
{ uml::OP_RESTORE, &drcbe_arm64::op_restore }, // RESTORE dst
// Integer Operations
- { uml::OP_LOAD, &drcbe_arm64::op_load }, // LOAD dst,base,index,size
- { uml::OP_LOADS, &drcbe_arm64::op_loads }, // LOADS dst,base,index,size
- { uml::OP_STORE, &drcbe_arm64::op_store }, // STORE base,index,src,size
- { uml::OP_READ, &drcbe_arm64::op_read }, // READ dst,src1,spacesize
- { uml::OP_READM, &drcbe_arm64::op_readm }, // READM dst,src1,mask,spacesize
- { uml::OP_WRITE, &drcbe_arm64::op_write }, // WRITE dst,src1,spacesize
- { uml::OP_WRITEM, &drcbe_arm64::op_writem }, // WRITEM dst,src1,spacesize
- { uml::OP_CARRY, &drcbe_arm64::op_carry }, // CARRY src,bitnum
- { uml::OP_SET, &drcbe_arm64::op_set }, // SET dst,c
- { uml::OP_MOV, &drcbe_arm64::op_mov }, // MOV dst,src[,c]
- { uml::OP_SEXT, &drcbe_arm64::op_sext }, // SEXT dst,src
- { uml::OP_ROLAND, &drcbe_arm64::op_roland }, // ROLAND dst,src1,src2,src3
- { uml::OP_ROLINS, &drcbe_arm64::op_rolins }, // ROLINS dst,src1,src2,src3
- { uml::OP_ADD, &drcbe_arm64::op_add<a64::Inst::kIdAdds> }, // ADD dst,src1,src2[,f]
- { uml::OP_ADDC, &drcbe_arm64::op_add<a64::Inst::kIdAdcs> }, // ADDC dst,src1,src2[,f]
- { uml::OP_SUB, &drcbe_arm64::op_sub<a64::Inst::kIdSubs> }, // SUB dst,src1,src2[,f]
- { uml::OP_SUBB, &drcbe_arm64::op_sub<a64::Inst::kIdSbcs> }, // SUBB dst,src1,src2[,f]
- { uml::OP_CMP, &drcbe_arm64::op_cmp }, // CMP src1,src2[,f]
- { uml::OP_MULU, &drcbe_arm64::op_mulu }, // MULU dst,edst,src1,src2[,f]
- { uml::OP_MULULW, &drcbe_arm64::op_mululw }, // MULULW dst,src1,src2[,f]
- { uml::OP_MULS, &drcbe_arm64::op_muls }, // MULS dst,edst,src1,src2[,f]
- { uml::OP_MULSLW, &drcbe_arm64::op_mulslw }, // MULSLW dst,src1,src2[,f]
- { uml::OP_DIVU, &drcbe_arm64::op_div<a64::Inst::kIdUdiv> }, // DIVU dst,edst,src1,src2[,f]
- { uml::OP_DIVS, &drcbe_arm64::op_div<a64::Inst::kIdSdiv> }, // DIVS dst,edst,src1,src2[,f]
- { uml::OP_AND, &drcbe_arm64::op_and }, // AND dst,src1,src2[,f]
- { uml::OP_TEST, &drcbe_arm64::op_test }, // TEST src1,src2[,f]
- { uml::OP_OR, &drcbe_arm64::op_or }, // OR dst,src1,src2[,f]
- { uml::OP_XOR, &drcbe_arm64::op_xor }, // XOR dst,src1,src2[,f]
- { uml::OP_LZCNT, &drcbe_arm64::op_lzcnt }, // LZCNT dst,src[,f]
- { uml::OP_TZCNT, &drcbe_arm64::op_tzcnt }, // TZCNT dst,src[,f]
- { uml::OP_BSWAP, &drcbe_arm64::op_bswap }, // BSWAP dst,src
- { uml::OP_SHL, &drcbe_arm64::op_shift<a64::Inst::kIdLsl> }, // SHL dst,src,count[,f]
- { uml::OP_SHR, &drcbe_arm64::op_shift<a64::Inst::kIdLsr> }, // SHR dst,src,count[,f]
- { uml::OP_SAR, &drcbe_arm64::op_shift<a64::Inst::kIdAsr> }, // SAR dst,src,count[,f]
- { uml::OP_ROL, &drcbe_arm64::op_rol }, // ROL dst,src,count[,f]
- { uml::OP_ROLC, &drcbe_arm64::op_rolc }, // ROLC dst,src,count[,f]
+ { uml::OP_LOAD, &drcbe_arm64::op_load }, // LOAD dst,base,index,size
+ { uml::OP_LOADS, &drcbe_arm64::op_loads }, // LOADS dst,base,index,size
+ { uml::OP_STORE, &drcbe_arm64::op_store }, // STORE base,index,src,size
+ { uml::OP_READ, &drcbe_arm64::op_read }, // READ dst,src1,spacesize
+ { uml::OP_READM, &drcbe_arm64::op_readm }, // READM dst,src1,mask,spacesize
+ { uml::OP_WRITE, &drcbe_arm64::op_write }, // WRITE dst,src1,spacesize
+ { uml::OP_WRITEM, &drcbe_arm64::op_writem }, // WRITEM dst,src1,spacesize
+ { uml::OP_CARRY, &drcbe_arm64::op_carry }, // CARRY src,bitnum
+ { uml::OP_SET, &drcbe_arm64::op_set }, // SET dst,c
+ { uml::OP_MOV, &drcbe_arm64::op_mov }, // MOV dst,src[,c]
+ { uml::OP_SEXT, &drcbe_arm64::op_sext }, // SEXT dst,src
+ { uml::OP_ROLAND, &drcbe_arm64::op_roland }, // ROLAND dst,src1,src2,src3
+ { uml::OP_ROLINS, &drcbe_arm64::op_rolins }, // ROLINS dst,src1,src2,src3
+ { uml::OP_ADD, &drcbe_arm64::op_add<a64::Inst::kIdAdds> }, // ADD dst,src1,src2[,f]
+ { uml::OP_ADDC, &drcbe_arm64::op_add<a64::Inst::kIdAdcs> }, // ADDC dst,src1,src2[,f]
+ { uml::OP_SUB, &drcbe_arm64::op_sub<a64::Inst::kIdSubs> }, // SUB dst,src1,src2[,f]
+ { uml::OP_SUBB, &drcbe_arm64::op_sub<a64::Inst::kIdSbcs> }, // SUBB dst,src1,src2[,f]
+ { uml::OP_CMP, &drcbe_arm64::op_cmp }, // CMP src1,src2[,f]
+ { uml::OP_MULU, &drcbe_arm64::op_mulu }, // MULU dst,edst,src1,src2[,f]
+ { uml::OP_MULULW, &drcbe_arm64::op_mululw }, // MULULW dst,src1,src2[,f]
+ { uml::OP_MULS, &drcbe_arm64::op_muls }, // MULS dst,edst,src1,src2[,f]
+ { uml::OP_MULSLW, &drcbe_arm64::op_mulslw }, // MULSLW dst,src1,src2[,f]
+ { uml::OP_DIVU, &drcbe_arm64::op_div<a64::Inst::kIdUdiv> }, // DIVU dst,edst,src1,src2[,f]
+ { uml::OP_DIVS, &drcbe_arm64::op_div<a64::Inst::kIdSdiv> }, // DIVS dst,edst,src1,src2[,f]
+ { uml::OP_AND, &drcbe_arm64::op_and }, // AND dst,src1,src2[,f]
+ { uml::OP_TEST, &drcbe_arm64::op_test }, // TEST src1,src2[,f]
+ { uml::OP_OR, &drcbe_arm64::op_or }, // OR dst,src1,src2[,f]
+ { uml::OP_XOR, &drcbe_arm64::op_xor }, // XOR dst,src1,src2[,f]
+ { uml::OP_LZCNT, &drcbe_arm64::op_lzcnt }, // LZCNT dst,src[,f]
+ { uml::OP_TZCNT, &drcbe_arm64::op_tzcnt }, // TZCNT dst,src[,f]
+ { uml::OP_BSWAP, &drcbe_arm64::op_bswap }, // BSWAP dst,src
+ { uml::OP_SHL, &drcbe_arm64::op_shift<a64::Inst::kIdLsl> }, // SHL dst,src,count[,f]
+ { uml::OP_SHR, &drcbe_arm64::op_shift<a64::Inst::kIdLsr> }, // SHR dst,src,count[,f]
+ { uml::OP_SAR, &drcbe_arm64::op_shift<a64::Inst::kIdAsr> }, // SAR dst,src,count[,f]
+ { uml::OP_ROL, &drcbe_arm64::op_rol }, // ROL dst,src,count[,f]
+ { uml::OP_ROLC, &drcbe_arm64::op_rolc }, // ROLC dst,src,count[,f]
{ uml::OP_ROR, &drcbe_arm64::op_shift<a64::Inst::kIdRor> }, // ROR dst,src,count[,f]
- { uml::OP_RORC, &drcbe_arm64::op_rorc }, // RORC dst,src,count[,f]
+ { uml::OP_RORC, &drcbe_arm64::op_rorc }, // RORC dst,src,count[,f]
// Floating Point Operations
- { uml::OP_FLOAD, &drcbe_arm64::op_fload }, // FLOAD dst,base,index
- { uml::OP_FSTORE, &drcbe_arm64::op_fstore }, // FSTORE base,index,src
- { uml::OP_FREAD, &drcbe_arm64::op_fread }, // FREAD dst,space,src1
- { uml::OP_FWRITE, &drcbe_arm64::op_fwrite }, // FWRITE space,dst,src1
- { uml::OP_FMOV, &drcbe_arm64::op_fmov }, // FMOV dst,src1[,c]
- { uml::OP_FTOINT, &drcbe_arm64::op_ftoint }, // FTOINT dst,src1,size,round
- { uml::OP_FFRINT, &drcbe_arm64::op_ffrint }, // FFRINT dst,src1,size
- { uml::OP_FFRFLT, &drcbe_arm64::op_ffrflt }, // FFRFLT dst,src1,size
- { uml::OP_FRNDS, &drcbe_arm64::op_frnds }, // FRNDS dst,src1
- { uml::OP_FADD, &drcbe_arm64::op_float_alu<a64::Inst::kIdFadd_v> }, // FADD dst,src1,src2
- { uml::OP_FSUB, &drcbe_arm64::op_float_alu<a64::Inst::kIdFsub_v> }, // FSUB dst,src1,src2
- { uml::OP_FCMP, &drcbe_arm64::op_fcmp }, // FCMP src1,src2
- { uml::OP_FMUL, &drcbe_arm64::op_float_alu<a64::Inst::kIdFmul_v> }, // FMUL dst,src1,src2
- { uml::OP_FDIV, &drcbe_arm64::op_float_alu<a64::Inst::kIdFdiv_v> }, // FDIV dst,src1,src2
- { uml::OP_FNEG, &drcbe_arm64::op_float_alu2<a64::Inst::kIdFneg_v> }, // FNEG dst,src1
- { uml::OP_FABS, &drcbe_arm64::op_float_alu2<a64::Inst::kIdFabs_v> }, // FABS dst,src1
- { uml::OP_FSQRT, &drcbe_arm64::op_float_alu2<a64::Inst::kIdFsqrt_v> }, // FSQRT dst,src1
- { uml::OP_FRECIP, &drcbe_arm64::op_float_alu2<a64::Inst::kIdFrecpe_v> }, // FRECIP dst,src1
- { uml::OP_FRSQRT, &drcbe_arm64::op_float_alu2<a64::Inst::kIdFrsqrte_v> }, // FRSQRT dst,src1
- { uml::OP_FCOPYI, &drcbe_arm64::op_fcopyi }, // FCOPYI dst,src
- { uml::OP_ICOPYF, &drcbe_arm64::op_icopyf } // ICOPYF dst,src
+ { uml::OP_FLOAD, &drcbe_arm64::op_fload }, // FLOAD dst,base,index
+ { uml::OP_FSTORE, &drcbe_arm64::op_fstore }, // FSTORE base,index,src
+ { uml::OP_FREAD, &drcbe_arm64::op_fread }, // FREAD dst,space,src1
+ { uml::OP_FWRITE, &drcbe_arm64::op_fwrite }, // FWRITE space,dst,src1
+ { uml::OP_FMOV, &drcbe_arm64::op_fmov }, // FMOV dst,src1[,c]
+ { uml::OP_FTOINT, &drcbe_arm64::op_ftoint }, // FTOINT dst,src1,size,round
+ { uml::OP_FFRINT, &drcbe_arm64::op_ffrint }, // FFRINT dst,src1,size
+ { uml::OP_FFRFLT, &drcbe_arm64::op_ffrflt }, // FFRFLT dst,src1,size
+ { uml::OP_FRNDS, &drcbe_arm64::op_frnds }, // FRNDS dst,src1
+ { uml::OP_FADD, &drcbe_arm64::op_float_alu<a64::Inst::kIdFadd_v> }, // FADD dst,src1,src2
+ { uml::OP_FSUB, &drcbe_arm64::op_float_alu<a64::Inst::kIdFsub_v> }, // FSUB dst,src1,src2
+ { uml::OP_FCMP, &drcbe_arm64::op_fcmp }, // FCMP src1,src2
+ { uml::OP_FMUL, &drcbe_arm64::op_float_alu<a64::Inst::kIdFmul_v> }, // FMUL dst,src1,src2
+ { uml::OP_FDIV, &drcbe_arm64::op_float_alu<a64::Inst::kIdFdiv_v> }, // FDIV dst,src1,src2
+ { uml::OP_FNEG, &drcbe_arm64::op_float_alu2<a64::Inst::kIdFneg_v> }, // FNEG dst,src1
+ { uml::OP_FABS, &drcbe_arm64::op_float_alu2<a64::Inst::kIdFabs_v> }, // FABS dst,src1
+ { uml::OP_FSQRT, &drcbe_arm64::op_float_alu2<a64::Inst::kIdFsqrt_v> }, // FSQRT dst,src1
+ { uml::OP_FRECIP, &drcbe_arm64::op_float_alu2<a64::Inst::kIdFrecpe_v> }, // FRECIP dst,src1
+ { uml::OP_FRSQRT, &drcbe_arm64::op_float_alu2<a64::Inst::kIdFrsqrte_v> }, // FRSQRT dst,src1
+ { uml::OP_FCOPYI, &drcbe_arm64::op_fcopyi }, // FCOPYI dst,src
+ { uml::OP_ICOPYF, &drcbe_arm64::op_icopyf } // ICOPYF dst,src
};
drcbe_arm64::be_parameter::be_parameter(drcbe_arm64 &drcbe, const parameter &param, uint32_t allowed)
@@ -300,108 +474,6 @@ a64::Gp drcbe_arm64::be_parameter::select_register(a64::Gp const &reg, uint32_t
return reg.x();
}
-a64::Vec drcbe_arm64::select_register(a64::Vec const &reg, uint32_t regsize) const
-{
- if (regsize == 4)
- return reg.s();
- return reg.d();
-}
-
-a64::Gp drcbe_arm64::select_register(a64::Gp const &reg, uint32_t regsize) const
-{
- if (regsize == 4)
- return reg.w();
- return reg.x();
-}
-
-bool drcbe_arm64::is_valid_immediate_mask(uint64_t val, size_t bytes)
-{
- // all zeros and all ones aren't allowed, and disallow any value with bits outside of the max bit range
- if (val == 0 || val == make_bitmask<uint64_t>(bytes * 8))
- return false;
-
- uint32_t head = 64 - count_leading_zeros_64(val);
- if (head >= (bytes * 8))
- return false;
-
- uint32_t tail = 0;
- while (tail < head)
- {
- if (BIT(val, tail))
- break;
- tail++;
- }
-
- return population_count_64(val) == head - tail;
-}
-
-bool drcbe_arm64::is_valid_immediate(uint64_t val, size_t bits)
-{
- assert(bits < 64);
- return val < (uint64_t(1) << bits);
-}
-
-bool drcbe_arm64::is_valid_immediate_signed(int64_t val, size_t bits)
-{
- return util::sext(val, bits) == val;
-}
-
-arm::Mem drcbe_arm64::get_mem_absolute(a64::Assembler &a, const void *ptr) const
-{
- const uint64_t codeoffs = a.code()->baseAddress() + a.offset();
- const int64_t reloffs = codeoffs - (int64_t)ptr;
- if (is_valid_immediate_signed(reloffs, 21))
- {
- a.adr(MEM_SCRATCH_REG, ptr);
- return arm::Mem(MEM_SCRATCH_REG);
- }
-
- const uint64_t pagebase = codeoffs & ~make_bitmask<uint64_t>(12);
- const int64_t pagerel = (int64_t)ptr - pagebase;
- if (is_valid_immediate_signed(pagerel, 33))
- {
- const uint64_t targetpage = (uint64_t)ptr & ~make_bitmask<uint64_t>(12);
- const uint64_t pageoffs = (uint64_t)ptr & util::make_bitmask<uint64_t>(12);
-
- a.adrp(MEM_SCRATCH_REG, targetpage);
-
- if (is_valid_immediate_signed(pageoffs, 9))
- return arm::Mem(MEM_SCRATCH_REG, pageoffs);
- else if (emit_add_optimized(a, MEM_SCRATCH_REG, MEM_SCRATCH_REG, pageoffs))
- return arm::Mem(MEM_SCRATCH_REG);
- }
-
- a.mov(MEM_SCRATCH_REG, ptr);
- return arm::Mem(MEM_SCRATCH_REG);
-}
-
-bool drcbe_arm64::emit_add_optimized(a64::Assembler &a, const a64::Gp &dst, const a64::Gp &src, int64_t val) const
-{
- // If the bottom 12 bits are 0s then an optimized form can be used if the remaining bits are <= 12
- if (is_valid_immediate(val, 12) || ((val & 0xfff) == 0 && is_valid_immediate(val >> 12, 12)))
- {
- a.add(dst, src, val);
- return true;
- }
-
- return false;
-}
-
-bool drcbe_arm64::emit_sub_optimized(a64::Assembler &a, const a64::Gp &dst, const a64::Gp &src, int64_t val) const
-{
- if (val < 0)
- val = -val;
-
- // If the bottom 12 bits are 0s then an optimized form can be used if the remaining bits are <= 12
- if (is_valid_immediate(val, 12) || ((val & 0xfff) == 0 && is_valid_immediate(val >> 12, 12)))
- {
- a.sub(dst, src, val);
- return true;
- }
-
- return false;
-}
-
void drcbe_arm64::get_imm_relative(a64::Assembler &a, const a64::Gp &reg, const uint64_t ptr) const
{
// If a value can be expressed relative to the base register then it's worth using it instead of a mov
@@ -765,7 +837,7 @@ void drcbe_arm64::store_unordered(a64::Assembler &a) const
void drcbe_arm64::get_unordered(a64::Assembler &a, const a64::Gp &reg) const
{
- get_shifted_bit(a, reg.x(), FLAGS_REG, 1, 4);
+ a.ubfx(reg.x(), FLAGS_REG, 4, 1);
}
void drcbe_arm64::store_carry_reg(a64::Assembler &a, const a64::Gp &reg) const
@@ -802,12 +874,6 @@ void drcbe_arm64::load_carry(a64::Assembler &a, bool inverted) const
a.msr(a64::Predicate::SysReg::kNZCV, SCRATCH_REG1);
}
-void drcbe_arm64::get_shifted_bit(a64::Assembler &a, const a64::Gp &dst, const a64::Gp &src, uint32_t bits, uint32_t shift) const
-{
- a.lsr(dst.x(), src.x(), shift);
- a.and_(dst.x(), dst.x(), bits);
-}
-
void drcbe_arm64::calculate_carry_shift_left(a64::Assembler &a, const a64::Gp &reg, const a64::Gp &shift, int maxBits) const
{
Label calc = a.newLabel();
@@ -890,11 +956,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)
@@ -907,38 +968,18 @@ 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
- auto const resolve_accessor =
- [] (resolved_handler &handler, address_space &space, auto accessor)
- {
- auto const [entrypoint, adjusted] = util::resolve_member_function(accessor, space);
- handler.func = reinterpret_cast<uint8_t *>(entrypoint);
- handler.obj = adjusted;
- };
-
+ // 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));
+ }
m_resolved_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space)
{
if (m_space[space])
- {
- resolve_accessor(m_resolved_accessors[space].read_byte, *m_space[space], static_cast<u8 (address_space::*)(offs_t) >(&address_space::read_byte));
- resolve_accessor(m_resolved_accessors[space].read_byte_masked, *m_space[space], static_cast<u8 (address_space::*)(offs_t, u8) >(&address_space::read_byte));
- resolve_accessor(m_resolved_accessors[space].read_word, *m_space[space], static_cast<u16 (address_space::*)(offs_t) >(&address_space::read_word));
- resolve_accessor(m_resolved_accessors[space].read_word_masked, *m_space[space], static_cast<u16 (address_space::*)(offs_t, u16)>(&address_space::read_word));
- resolve_accessor(m_resolved_accessors[space].read_dword, *m_space[space], static_cast<u32 (address_space::*)(offs_t) >(&address_space::read_dword));
- resolve_accessor(m_resolved_accessors[space].read_dword_masked, *m_space[space], static_cast<u32 (address_space::*)(offs_t, u32)>(&address_space::read_dword));
- resolve_accessor(m_resolved_accessors[space].read_qword, *m_space[space], static_cast<u64 (address_space::*)(offs_t) >(&address_space::read_qword));
- resolve_accessor(m_resolved_accessors[space].read_qword_masked, *m_space[space], static_cast<u64 (address_space::*)(offs_t, u64)>(&address_space::read_qword));
-
- resolve_accessor(m_resolved_accessors[space].write_byte, *m_space[space], static_cast<void (address_space::*)(offs_t, u8) >(&address_space::write_byte));
- resolve_accessor(m_resolved_accessors[space].write_byte_masked, *m_space[space], static_cast<void (address_space::*)(offs_t, u8, u8) >(&address_space::write_byte));
- resolve_accessor(m_resolved_accessors[space].write_word, *m_space[space], static_cast<void (address_space::*)(offs_t, u16) >(&address_space::write_word));
- resolve_accessor(m_resolved_accessors[space].write_word_masked, *m_space[space], static_cast<void (address_space::*)(offs_t, u16, u16)>(&address_space::write_word));
- resolve_accessor(m_resolved_accessors[space].write_dword, *m_space[space], static_cast<void (address_space::*)(offs_t, u32) >(&address_space::write_dword));
- resolve_accessor(m_resolved_accessors[space].write_dword_masked, *m_space[space], static_cast<void (address_space::*)(offs_t, u32, u32)>(&address_space::write_dword));
- resolve_accessor(m_resolved_accessors[space].write_qword, *m_space[space], static_cast<void (address_space::*)(offs_t, u64) >(&address_space::write_qword));
- resolve_accessor(m_resolved_accessors[space].write_qword_masked, *m_space[space], static_cast<void (address_space::*)(offs_t, u64, u64)>(&address_space::write_qword));
- }
+ m_resolved_accessors[space].set(*m_space[space]);
}
}
@@ -1048,6 +1089,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<uint8_t *>(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);
@@ -1233,11 +1287,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);
}
@@ -1556,13 +1609,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);
}
@@ -2007,7 +2058,7 @@ void drcbe_arm64::op_read(a64::Assembler &a, const uml::instruction &inst)
if (spacesizep.size() == SIZE_BYTE)
{
- if (resolved.read_byte.func)
+ if (resolved.read_byte)
{
get_imm_relative(a, REG_PARAM1, resolved.read_byte.obj);
call_arm_addr(a, resolved.read_byte.func);
@@ -2021,7 +2072,7 @@ void drcbe_arm64::op_read(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_WORD)
{
- if (resolved.read_word.func)
+ if (resolved.read_word)
{
get_imm_relative(a, REG_PARAM1, resolved.read_word.obj);
call_arm_addr(a, resolved.read_word.func);
@@ -2035,7 +2086,7 @@ void drcbe_arm64::op_read(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_DWORD)
{
- if (resolved.read_dword.func)
+ if (resolved.read_dword)
{
get_imm_relative(a, REG_PARAM1, resolved.read_dword.obj);
call_arm_addr(a, resolved.read_dword.func);
@@ -2049,7 +2100,7 @@ void drcbe_arm64::op_read(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_QWORD)
{
- if (resolved.read_qword.func)
+ if (resolved.read_qword)
{
get_imm_relative(a, REG_PARAM1, resolved.read_qword.obj);
call_arm_addr(a, resolved.read_qword.func);
@@ -2085,7 +2136,7 @@ void drcbe_arm64::op_readm(a64::Assembler &a, const uml::instruction &inst)
if (spacesizep.size() == SIZE_BYTE)
{
- if (resolved.read_byte_masked.func)
+ if (resolved.read_byte_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.read_byte_masked.obj);
call_arm_addr(a, resolved.read_byte_masked.func);
@@ -2099,7 +2150,7 @@ void drcbe_arm64::op_readm(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_WORD)
{
- if (resolved.read_word_masked.func)
+ if (resolved.read_word_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.read_word_masked.obj);
call_arm_addr(a, resolved.read_word_masked.func);
@@ -2113,7 +2164,7 @@ void drcbe_arm64::op_readm(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_DWORD)
{
- if (resolved.read_dword_masked.func)
+ if (resolved.read_dword_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.read_dword_masked.obj);
call_arm_addr(a, resolved.read_dword_masked.func);
@@ -2127,7 +2178,7 @@ void drcbe_arm64::op_readm(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_QWORD)
{
- if (resolved.read_qword_masked.func)
+ if (resolved.read_qword_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.read_qword_masked.obj);
call_arm_addr(a, resolved.read_qword_masked.func);
@@ -2162,7 +2213,7 @@ void drcbe_arm64::op_write(a64::Assembler &a, const uml::instruction &inst)
if (spacesizep.size() == SIZE_BYTE)
{
- if (resolved.write_byte.func)
+ if (resolved.write_byte)
{
get_imm_relative(a, REG_PARAM1, resolved.write_byte.obj);
call_arm_addr(a, resolved.write_byte.func);
@@ -2176,7 +2227,7 @@ void drcbe_arm64::op_write(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_WORD)
{
- if (resolved.write_word.func)
+ if (resolved.write_word)
{
get_imm_relative(a, REG_PARAM1, resolved.write_word.obj);
call_arm_addr(a, resolved.write_word.func);
@@ -2190,7 +2241,7 @@ void drcbe_arm64::op_write(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_DWORD)
{
- if (resolved.write_dword.func)
+ if (resolved.write_dword)
{
get_imm_relative(a, REG_PARAM1, resolved.write_dword.obj);
call_arm_addr(a, resolved.write_dword.func);
@@ -2204,7 +2255,7 @@ void drcbe_arm64::op_write(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_QWORD)
{
- if (resolved.write_qword.func)
+ if (resolved.write_qword)
{
get_imm_relative(a, REG_PARAM1, resolved.write_qword.obj);
call_arm_addr(a, resolved.write_qword.func);
@@ -2240,7 +2291,7 @@ void drcbe_arm64::op_writem(a64::Assembler &a, const uml::instruction &inst)
if (spacesizep.size() == SIZE_BYTE)
{
- if (resolved.write_byte_masked.func)
+ if (resolved.write_byte_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.write_byte_masked.obj);
call_arm_addr(a, resolved.write_byte_masked.func);
@@ -2254,7 +2305,7 @@ void drcbe_arm64::op_writem(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_WORD)
{
- if (resolved.write_word_masked.func)
+ if (resolved.write_word_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.write_word_masked.obj);
call_arm_addr(a, resolved.write_word_masked.func);
@@ -2268,7 +2319,7 @@ void drcbe_arm64::op_writem(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_DWORD)
{
- if (resolved.write_dword_masked.func)
+ if (resolved.write_dword_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.write_dword_masked.obj);
call_arm_addr(a, resolved.write_dword_masked.func);
@@ -2282,7 +2333,7 @@ void drcbe_arm64::op_writem(a64::Assembler &a, const uml::instruction &inst)
}
else if (spacesizep.size() == SIZE_QWORD)
{
- if (resolved.write_qword_masked.func)
+ if (resolved.write_qword_masked)
{
get_imm_relative(a, REG_PARAM1, resolved.write_qword_masked.obj);
call_arm_addr(a, resolved.write_qword_masked.func);
@@ -2676,12 +2727,12 @@ void drcbe_arm64::op_rolins(a64::Assembler &a, const uml::instruction &inst)
if (is_right_aligned || is_contiguous)
{
- uint32_t rot = 0;
- uint32_t lsb = 0;
-
dst = can_use_dst_reg ? dstp.select_register(SCRATCH_REG1, inst.size()) : select_register(SCRATCH_REG1, inst.size());
mov_reg_param(a, inst.size(), dst, dstp);
+ uint32_t rot = 0;
+ uint32_t lsb = 0;
+
if (is_right_aligned)
{
// Optimize a contiguous right-aligned mask
@@ -2707,10 +2758,6 @@ void drcbe_arm64::op_rolins(a64::Assembler &a, const uml::instruction &inst)
result = rotr_64(srcp.immediate(), rot);
a.mov(src, result);
-
- a.bfi(dst, src, lsb, pop);
-
- optimized = true;
}
else
{
@@ -2718,11 +2765,11 @@ void drcbe_arm64::op_rolins(a64::Assembler &a, const uml::instruction &inst)
if (rot > 0)
a.ror(src, src, rot);
+ }
- a.bfi(dst, src, lsb, pop);
+ a.bfi(dst, src, lsb, pop);
- optimized = true;
- }
+ optimized = true;
}
else if (srcp.is_immediate())
{
@@ -3881,7 +3928,7 @@ void drcbe_arm64::op_fread(a64::Assembler &a, const uml::instruction &inst)
if (inst.size() == 4)
{
- if (resolved.read_dword.func)
+ if (resolved.read_dword)
{
get_imm_relative(a, REG_PARAM1, resolved.read_dword.obj);
call_arm_addr(a, resolved.read_dword.func);
@@ -3897,7 +3944,7 @@ void drcbe_arm64::op_fread(a64::Assembler &a, const uml::instruction &inst)
}
else if (inst.size() == 8)
{
- if (resolved.read_qword.func)
+ if (resolved.read_qword)
{
get_imm_relative(a, REG_PARAM1, resolved.read_qword.obj);
call_arm_addr(a, resolved.read_qword.func);
@@ -3935,7 +3982,7 @@ void drcbe_arm64::op_fwrite(a64::Assembler &a, const uml::instruction &inst)
if (inst.size() == 4)
{
- if (resolved.write_dword.func)
+ if (resolved.write_dword)
{
get_imm_relative(a, REG_PARAM1, resolved.write_dword.obj);
call_arm_addr(a, resolved.write_dword.func);
@@ -3949,7 +3996,7 @@ void drcbe_arm64::op_fwrite(a64::Assembler &a, const uml::instruction &inst)
}
else if (inst.size() == 8)
{
- if (resolved.write_qword.func)
+ if (resolved.write_qword)
{
get_imm_relative(a, REG_PARAM1, resolved.write_qword.obj);
call_arm_addr(a, resolved.write_qword.func);
diff --git a/src/devices/cpu/drcbearm64.h b/src/devices/cpu/drcbearm64.h
index 20938f214fe..258d2947d3e 100644
--- a/src/devices/cpu/drcbearm64.h
+++ b/src/devices/cpu/drcbearm64.h
@@ -167,19 +167,8 @@ private:
// helper functions
- asmjit::a64::Vec select_register(asmjit::a64::Vec const &reg, uint32_t regsize) const;
- asmjit::a64::Gp select_register(asmjit::a64::Gp const &reg, uint32_t regsize) const;
-
- static bool is_valid_immediate(uint64_t val, size_t bits);
- static bool is_valid_immediate_signed(int64_t val, size_t bits);
- static bool is_valid_immediate_mask(uint64_t val, size_t bytes);
-
- asmjit::arm::Mem get_mem_absolute(asmjit::a64::Assembler &a, const void *ptr) const;
void get_imm_relative(asmjit::a64::Assembler &a, const asmjit::a64::Gp &reg, const uint64_t ptr) const;
- bool emit_add_optimized(asmjit::a64::Assembler &a, const asmjit::a64::Gp &dst, const asmjit::a64::Gp &src, int64_t val) const;
- bool emit_sub_optimized(asmjit::a64::Assembler &a, const asmjit::a64::Gp &dst, const asmjit::a64::Gp &src, int64_t val) const;
-
void emit_ldr_str_base_mem(asmjit::a64::Assembler &a, asmjit::a64::Inst::Id opcode, const asmjit::a64::Reg &reg, const void *ptr) const;
void emit_ldr_mem(asmjit::a64::Assembler &a, const asmjit::a64::Gp &reg, const void *ptr) const;
void emit_ldrb_mem(asmjit::a64::Assembler &a, const asmjit::a64::Gp &reg, const void *ptr) const;
@@ -203,8 +192,6 @@ private:
void get_unordered(asmjit::a64::Assembler &a, const asmjit::a64::Gp &reg) const;
void check_unordered_condition(asmjit::a64::Assembler &a, uml::condition_t cond, asmjit::Label condition_met, bool not_equal) const;
- void get_shifted_bit(asmjit::a64::Assembler &a, const asmjit::a64::Gp &dst, const asmjit::a64::Gp &src, uint32_t bits, uint32_t shift) const;
-
void calculate_carry_shift_left(asmjit::a64::Assembler &a, const asmjit::a64::Gp &reg, const asmjit::a64::Gp &shift, int maxBits) const;
void calculate_carry_shift_left_imm(asmjit::a64::Assembler &a, const asmjit::a64::Gp &reg, const int shift, int maxBits) const;
@@ -238,9 +225,6 @@ private:
struct near_state
{
- void *debug_cpu_instruction_hook;
- void *drcmap_get_value;
-
uint32_t emulated_flags;
};
near_state &m_near;
@@ -254,33 +238,12 @@ private:
static const opcode_table_entry s_opcode_table_source[];
static opcode_generate_func s_opcode_table[uml::OP_MAX];
- struct resolved_handler { uintptr_t obj = 0; void *func = nullptr; };
- struct resolved_accessors
- {
-
- resolved_handler read_byte;
- resolved_handler read_byte_masked;
- resolved_handler read_word;
- resolved_handler read_word_masked;
- resolved_handler read_dword;
- resolved_handler read_dword_masked;
- resolved_handler read_qword;
- resolved_handler read_qword_masked;
-
- resolved_handler write_byte;
- resolved_handler write_byte_masked;
- resolved_handler write_word;
- resolved_handler write_word_masked;
- resolved_handler write_dword;
- resolved_handler write_dword_masked;
- resolved_handler write_qword;
- resolved_handler write_qword_masked;
- };
- using resolved_accessors_vector = std::vector<resolved_accessors>;
- resolved_accessors_vector m_resolved_accessors;
+ 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/drcbec.cpp b/src/devices/cpu/drcbec.cpp
index c058d256a18..8758b1989c7 100644
--- a/src/devices/cpu/drcbec.cpp
+++ b/src/devices/cpu/drcbec.cpp
@@ -14,6 +14,8 @@
#include <cmath>
+namespace drc {
+
using namespace uml;
@@ -2436,3 +2438,5 @@ uint64_t drcbe_c::tzcount64(uint64_t value)
}
return 64;
}
+
+} // namespace drc
diff --git a/src/devices/cpu/drcbec.h b/src/devices/cpu/drcbec.h
index a4bc68b5168..6c572fb65b0 100644
--- a/src/devices/cpu/drcbec.h
+++ b/src/devices/cpu/drcbec.h
@@ -17,6 +17,7 @@
#include "drcbeut.h"
+namespace drc {
//**************************************************************************
// TYPE DEFINITIONS
@@ -57,5 +58,8 @@ private:
static uint64_t s_immediate_zero;
};
+} // namespace drc
+
+using drc::drcbe_c;
#endif // MAME_CPU_DRCBEC_H
diff --git a/src/devices/cpu/drcbeut.cpp b/src/devices/cpu/drcbeut.cpp
index 8ccd8d31fb3..3d990d37455 100644
--- a/src/devices/cpu/drcbeut.cpp
+++ b/src/devices/cpu/drcbeut.cpp
@@ -11,6 +11,8 @@
#include "emu.h"
#include "drcbeut.h"
+namespace drc {
+
using namespace uml;
@@ -30,19 +32,19 @@ using namespace uml;
// drc_hash_table - constructor
//-------------------------------------------------
-drc_hash_table::drc_hash_table(drc_cache &cache, uint32_t modes, uint8_t addrbits, uint8_t ignorebits)
- : m_cache(cache),
- m_modes(modes),
- m_nocodeptr(nullptr),
- m_l1bits((addrbits - ignorebits) / 2),
- m_l2bits((addrbits - ignorebits) - m_l1bits),
- m_l1shift(ignorebits + m_l2bits),
- m_l2shift(ignorebits),
- m_l1mask((1 << m_l1bits) - 1),
- m_l2mask((1 << m_l2bits) - 1),
- m_base(reinterpret_cast<drccodeptr ***>(cache.alloc(modes * sizeof(**m_base)))),
- m_emptyl1(nullptr),
- m_emptyl2(nullptr)
+drc_hash_table::drc_hash_table(drc_cache &cache, uint32_t modes, uint8_t addrbits, uint8_t ignorebits) :
+ m_cache(cache),
+ m_modes(modes),
+ m_nocodeptr(nullptr),
+ m_l1bits((addrbits - ignorebits) / 2),
+ m_l2bits((addrbits - ignorebits) - m_l1bits),
+ m_l1shift(ignorebits + m_l2bits),
+ m_l2shift(ignorebits),
+ m_l1mask((1 << m_l1bits) - 1),
+ m_l2mask((1 << m_l2bits) - 1),
+ m_base(reinterpret_cast<drccodeptr ***>(cache.alloc(modes * sizeof(**m_base)))),
+ m_emptyl1(nullptr),
+ m_emptyl2(nullptr)
{
reset();
}
@@ -577,3 +579,36 @@ void drc_label_list::oob_callback(drccodeptr *codeptr, void *param1, void *param
label_fixup *fixup = reinterpret_cast<label_fixup *>(param1);
fixup->m_callback(param2, fixup->m_label->m_codeptr);
}
+
+
+
+//**************************************************************************
+// RESOLVED MEMORY ACCESSORS
+//**************************************************************************
+
+//-------------------------------------------------
+// set - bind to address space
+//-------------------------------------------------
+
+void resolved_memory_accessors::set(address_space &space) noexcept
+{
+ read_byte .set(space, static_cast<u8 (address_space::*)(offs_t) >(&address_space::read_byte));
+ read_byte_masked .set(space, static_cast<u8 (address_space::*)(offs_t, u8) >(&address_space::read_byte));
+ read_word .set(space, static_cast<u16 (address_space::*)(offs_t) >(&address_space::read_word));
+ read_word_masked .set(space, static_cast<u16 (address_space::*)(offs_t, u16)>(&address_space::read_word));
+ read_dword .set(space, static_cast<u32 (address_space::*)(offs_t) >(&address_space::read_dword));
+ read_dword_masked .set(space, static_cast<u32 (address_space::*)(offs_t, u32)>(&address_space::read_dword));
+ read_qword .set(space, static_cast<u64 (address_space::*)(offs_t) >(&address_space::read_qword));
+ read_qword_masked .set(space, static_cast<u64 (address_space::*)(offs_t, u64)>(&address_space::read_qword));
+
+ write_byte .set(space, static_cast<void (address_space::*)(offs_t, u8) >(&address_space::write_byte));
+ write_byte_masked .set(space, static_cast<void (address_space::*)(offs_t, u8, u8) >(&address_space::write_byte));
+ write_word .set(space, static_cast<void (address_space::*)(offs_t, u16) >(&address_space::write_word));
+ write_word_masked .set(space, static_cast<void (address_space::*)(offs_t, u16, u16)>(&address_space::write_word));
+ write_dword .set(space, static_cast<void (address_space::*)(offs_t, u32) >(&address_space::write_dword));
+ write_dword_masked .set(space, static_cast<void (address_space::*)(offs_t, u32, u32)>(&address_space::write_dword));
+ write_qword .set(space, static_cast<void (address_space::*)(offs_t, u64) >(&address_space::write_qword));
+ write_qword_masked .set(space, static_cast<void (address_space::*)(offs_t, u64, u64)>(&address_space::write_qword));
+}
+
+} // namespace drc
diff --git a/src/devices/cpu/drcbeut.h b/src/devices/cpu/drcbeut.h
index ee398e168f1..f020b6b5ef6 100644
--- a/src/devices/cpu/drcbeut.h
+++ b/src/devices/cpu/drcbeut.h
@@ -15,6 +15,13 @@
#include "drcuml.h"
+#include "mfpresolve.h"
+
+#include <utility>
+#include <vector>
+
+
+namespace drc {
//**************************************************************************
// TYPE DEFINITIONS
@@ -55,14 +62,14 @@ public:
private:
// internal state
drc_cache & m_cache; // cache where allocations come from
- uint32_t m_modes; // number of modes supported
+ uint32_t m_modes; // number of modes supported
drccodeptr m_nocodeptr; // pointer to code which will handle missing entries
- uint8_t m_l1bits; // bits worth of entries in l1 hash tables
- uint8_t m_l2bits; // bits worth of entries in l2 hash tables
- uint8_t m_l1shift; // shift to apply to the PC to get the l1 hash entry
- uint8_t m_l2shift; // shift to apply to the PC to get the l2 hash entry
+ uint8_t m_l1bits; // bits worth of entries in l1 hash tables
+ uint8_t m_l2bits; // bits worth of entries in l2 hash tables
+ uint8_t m_l1shift; // shift to apply to the PC to get the l1 hash entry
+ uint8_t m_l2shift; // shift to apply to the PC to get the l2 hash entry
offs_t m_l1mask; // mask to apply after shifting
offs_t m_l2mask; // mask to apply after shifting
@@ -97,8 +104,8 @@ public:
private:
// internal state
drc_cache & m_cache; // pointer to the cache
- uint64_t m_uniquevalue; // unique value used to find the table
- uint32_t m_mapvalue[uml::MAPVAR_END - uml::MAPVAR_M0]; // array of current values
+ uint64_t m_uniquevalue; // unique value used to find the table
+ uint32_t m_mapvalue[uml::MAPVAR_END - uml::MAPVAR_M0]; // array of current values
// list of entries
struct map_entry
@@ -106,8 +113,8 @@ private:
map_entry *next() const { return m_next; }
map_entry * m_next; // pointer to next map entry
drccodeptr m_codeptr; // pointer to the relevant code
- uint32_t m_mapvar; // map variable id
- uint32_t m_newval; // value of the variable starting at codeptr
+ uint32_t m_mapvar; // map variable id
+ uint32_t m_newval; // value of the variable starting at codeptr
};
simple_list<map_entry> m_entry_list; // list of entries
};
@@ -163,4 +170,56 @@ private:
};
+// ======================> resolved_member_function
+
+struct resolved_member_function
+{
+ uintptr_t obj = uintptr_t(nullptr);
+ uint8_t *func = nullptr;
+
+ explicit operator bool() const noexcept
+ {
+ return bool(func);
+ }
+
+ template <typename C, typename F>
+ void set(C &&instance, F &&mfp) noexcept
+ {
+ auto const [entrypoint, adjusted] = util::resolve_member_function(std::forward<F>(mfp), std::forward<C>(instance));
+ obj = adjusted;
+ func = reinterpret_cast<uint8_t *>(entrypoint);
+ }
+};
+
+
+// ======================> resolved_memory_accessors
+
+struct resolved_memory_accessors
+{
+ resolved_member_function read_byte;
+ resolved_member_function read_byte_masked;
+ resolved_member_function read_word;
+ resolved_member_function read_word_masked;
+ resolved_member_function read_dword;
+ resolved_member_function read_dword_masked;
+ resolved_member_function read_qword;
+ resolved_member_function read_qword_masked;
+
+ resolved_member_function write_byte;
+ resolved_member_function write_byte_masked;
+ resolved_member_function write_word;
+ resolved_member_function write_word_masked;
+ resolved_member_function write_dword;
+ resolved_member_function write_dword_masked;
+ resolved_member_function write_qword;
+ resolved_member_function write_qword_masked;
+
+ void set(address_space &space) noexcept;
+};
+
+using resolved_memory_accessors_vector = std::vector<resolved_memory_accessors>;
+
+} // namespace drc
+
+
#endif // MAME_CPU_DRCBEUT_H
diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp
index 14f89a35cbd..b57c48828d1 100644
--- a/src/devices/cpu/drcbex64.cpp
+++ b/src/devices/cpu/drcbex64.cpp
@@ -172,8 +172,6 @@
#include "debug/debugcpu.h"
#include "emuopts.h"
-#include "mfpresolve.h"
-
#include <cstddef>
@@ -660,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++)
@@ -692,37 +686,18 @@ 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
- auto const resolve_accessor =
- [] (resolved_handler &handler, address_space &space, auto accessor)
- {
- auto const [entrypoint, adjusted] = util::resolve_member_function(accessor, space);
- handler.func = reinterpret_cast<x86code *>(entrypoint);
- handler.obj = adjusted;
- };
+ // 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));
+ }
m_resolved_accessors.resize(m_space.size());
for (int space = 0; m_space.size() > space; ++space)
{
if (m_space[space])
- {
- resolve_accessor(m_resolved_accessors[space].read_byte, *m_space[space], static_cast<u8 (address_space::*)(offs_t) >(&address_space::read_byte));
- resolve_accessor(m_resolved_accessors[space].read_byte_masked, *m_space[space], static_cast<u8 (address_space::*)(offs_t, u8) >(&address_space::read_byte));
- resolve_accessor(m_resolved_accessors[space].read_word, *m_space[space], static_cast<u16 (address_space::*)(offs_t) >(&address_space::read_word));
- resolve_accessor(m_resolved_accessors[space].read_word_masked, *m_space[space], static_cast<u16 (address_space::*)(offs_t, u16)>(&address_space::read_word));
- resolve_accessor(m_resolved_accessors[space].read_dword, *m_space[space], static_cast<u32 (address_space::*)(offs_t) >(&address_space::read_dword));
- resolve_accessor(m_resolved_accessors[space].read_dword_masked, *m_space[space], static_cast<u32 (address_space::*)(offs_t, u32)>(&address_space::read_dword));
- resolve_accessor(m_resolved_accessors[space].read_qword, *m_space[space], static_cast<u64 (address_space::*)(offs_t) >(&address_space::read_qword));
- resolve_accessor(m_resolved_accessors[space].read_qword_masked, *m_space[space], static_cast<u64 (address_space::*)(offs_t, u64)>(&address_space::read_qword));
-
- resolve_accessor(m_resolved_accessors[space].write_byte, *m_space[space], static_cast<void (address_space::*)(offs_t, u8) >(&address_space::write_byte));
- resolve_accessor(m_resolved_accessors[space].write_byte_masked, *m_space[space], static_cast<void (address_space::*)(offs_t, u8, u8) >(&address_space::write_byte));
- resolve_accessor(m_resolved_accessors[space].write_word, *m_space[space], static_cast<void (address_space::*)(offs_t, u16) >(&address_space::write_word));
- resolve_accessor(m_resolved_accessors[space].write_word_masked, *m_space[space], static_cast<void (address_space::*)(offs_t, u16, u16)>(&address_space::write_word));
- resolve_accessor(m_resolved_accessors[space].write_dword, *m_space[space], static_cast<void (address_space::*)(offs_t, u32) >(&address_space::write_dword));
- resolve_accessor(m_resolved_accessors[space].write_dword_masked, *m_space[space], static_cast<void (address_space::*)(offs_t, u32, u32)>(&address_space::write_dword));
- resolve_accessor(m_resolved_accessors[space].write_qword, *m_space[space], static_cast<void (address_space::*)(offs_t, u64) >(&address_space::write_qword));
- resolve_accessor(m_resolved_accessors[space].write_qword_masked, *m_space[space], static_cast<void (address_space::*)(offs_t, u64, u64)>(&address_space::write_qword));
- }
+ m_resolved_accessors[space].set(*m_space[space]);
}
// build the opcode table (static but it doesn't hurt to regenerate it)
@@ -892,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<uint8_t *>(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);
@@ -1556,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);
}
@@ -1861,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
}
@@ -2523,7 +2511,7 @@ void drcbe_x64::op_read(Assembler &a, const instruction &inst)
mov_reg_param(a, Gpd(REG_PARAM2), addrp); // mov param2,addrp
if (spacesizep.size() == SIZE_BYTE)
{
- if (resolved.read_byte.func)
+ if (resolved.read_byte)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.read_byte.obj); // mov param1,space
smart_call_r64(a, resolved.read_byte.func, rax); // call read_byte
@@ -2537,7 +2525,7 @@ void drcbe_x64::op_read(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_WORD)
{
- if (resolved.read_word.func)
+ if (resolved.read_word)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.read_word.obj); // mov param1,space
smart_call_r64(a, resolved.read_word.func, rax); // call read_word
@@ -2551,7 +2539,7 @@ void drcbe_x64::op_read(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_DWORD)
{
- if (resolved.read_dword.func)
+ if (resolved.read_dword)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.read_dword.obj); // mov param1,space
smart_call_r64(a, resolved.read_dword.func, rax); // call read_dword
@@ -2566,7 +2554,7 @@ void drcbe_x64::op_read(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_QWORD)
{
- if (resolved.read_qword.func)
+ if (resolved.read_qword)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.read_qword.obj); // mov param1,space
smart_call_r64(a, resolved.read_qword.func, rax); // call read_qword
@@ -2619,7 +2607,7 @@ void drcbe_x64::op_readm(Assembler &a, const instruction &inst)
mov_reg_param(a, Gpq(REG_PARAM3), maskp); // mov param3,maskp
if (spacesizep.size() == SIZE_BYTE)
{
- if (resolved.read_byte_masked.func)
+ if (resolved.read_byte_masked)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.read_byte_masked.obj); // mov param1,space
smart_call_r64(a, resolved.read_byte_masked.func, rax); // call read_byte_masked
@@ -2633,7 +2621,7 @@ void drcbe_x64::op_readm(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_WORD)
{
- if (resolved.read_word_masked.func)
+ if (resolved.read_word_masked)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.read_word_masked.obj); // mov param1,space
smart_call_r64(a, resolved.read_word_masked.func, rax); // call read_word_masked
@@ -2647,7 +2635,7 @@ void drcbe_x64::op_readm(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_DWORD)
{
- if (resolved.read_dword_masked.func)
+ if (resolved.read_dword_masked)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.read_dword_masked.obj); // mov param1,space
smart_call_r64(a, resolved.read_dword_masked.func, rax); // call read_dword_masked
@@ -2662,7 +2650,7 @@ void drcbe_x64::op_readm(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_QWORD)
{
- if (resolved.read_qword_masked.func)
+ if (resolved.read_qword_masked)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.read_qword_masked.obj); // mov param1,space
smart_call_r64(a, resolved.read_qword_masked.func, rax); // call read_qword_masked
@@ -2711,7 +2699,7 @@ void drcbe_x64::op_write(Assembler &a, const instruction &inst)
mov_reg_param(a, Gpq(REG_PARAM3), srcp); // mov param3,srcp
if (spacesizep.size() == SIZE_BYTE)
{
- if (resolved.write_byte.func)
+ if (resolved.write_byte)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.write_byte.obj); // mov param1,space
smart_call_r64(a, resolved.write_byte.func, rax); // call write_byte
@@ -2724,7 +2712,7 @@ void drcbe_x64::op_write(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_WORD)
{
- if (resolved.write_word.func)
+ if (resolved.write_word)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.write_word.obj); // mov param1,space
smart_call_r64(a, resolved.write_word.func, rax); // call write_word
@@ -2737,7 +2725,7 @@ void drcbe_x64::op_write(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_DWORD)
{
- if (resolved.write_dword.func)
+ if (resolved.write_dword)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.write_dword.obj); // mov param1,space
smart_call_r64(a, resolved.write_dword.func, rax); // call write_dword
@@ -2750,7 +2738,7 @@ void drcbe_x64::op_write(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_QWORD)
{
- if (resolved.write_qword.func)
+ if (resolved.write_qword)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.write_qword.obj); // mov param1,space
smart_call_r64(a, resolved.write_qword.func, rax); // call write_qword
@@ -2798,7 +2786,7 @@ void drcbe_x64::op_writem(Assembler &a, const instruction &inst)
}
if (spacesizep.size() == SIZE_BYTE)
{
- if (resolved.write_byte.func)
+ if (resolved.write_byte)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.write_byte_masked.obj); // mov param1,space
smart_call_r64(a, resolved.write_byte_masked.func, rax); // call write_byte_masked
@@ -2811,7 +2799,7 @@ void drcbe_x64::op_writem(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_WORD)
{
- if (resolved.write_word.func)
+ if (resolved.write_word)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.write_word_masked.obj); // mov param1,space
smart_call_r64(a, resolved.write_word_masked.func, rax); // call write_word_masked
@@ -2824,7 +2812,7 @@ void drcbe_x64::op_writem(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_DWORD)
{
- if (resolved.write_word.func)
+ if (resolved.write_word)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.write_dword_masked.obj); // mov param1,space
smart_call_r64(a, resolved.write_dword_masked.func, rax); // call write_dword_masked
@@ -2837,7 +2825,7 @@ void drcbe_x64::op_writem(Assembler &a, const instruction &inst)
}
else if (spacesizep.size() == SIZE_QWORD)
{
- if (resolved.write_word.func)
+ if (resolved.write_word)
{
mov_r64_imm(a, Gpq(REG_PARAM1), resolved.write_qword_masked.obj); // mov param1,space
smart_call_r64(a, resolved.write_qword_masked.func, rax); // call write_qword_masked
diff --git a/src/devices/cpu/drcbex64.h b/src/devices/cpu/drcbex64.h
index b2c9195bd9e..18c5f1d59b8 100644
--- a/src/devices/cpu/drcbex64.h
+++ b/src/devices/cpu/drcbex64.h
@@ -251,10 +251,8 @@ private:
// 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,30 +268,9 @@ private:
near_state & m_near;
// resolved memory handler functions
- struct resolved_handler { uintptr_t obj = 0; x86code *func = nullptr; };
- struct resolved_accessors
- {
-
- resolved_handler read_byte;
- resolved_handler read_byte_masked;
- resolved_handler read_word;
- resolved_handler read_word_masked;
- resolved_handler read_dword;
- resolved_handler read_dword_masked;
- resolved_handler read_qword;
- resolved_handler read_qword_masked;
-
- resolved_handler write_byte;
- resolved_handler write_byte_masked;
- resolved_handler write_word;
- resolved_handler write_word_masked;
- resolved_handler write_dword;
- resolved_handler write_dword_masked;
- resolved_handler write_qword;
- resolved_handler write_qword_masked;
- };
- using resolved_accessors_vector = std::vector<resolved_accessors>;
- resolved_accessors_vector m_resolved_accessors;
+ resolved_member_function m_debug_cpu_instruction_hook;
+ resolved_member_function m_drcmap_get_value;
+ resolved_memory_accessors_vector m_resolved_accessors;
// globals
using opcode_generate_func = void (drcbe_x64::*)(asmjit::x86::Assembler &, const uml::instruction &);