emit_x64_memory: Share EmitDetectMisalignedVAddr
This commit is contained in:
parent
fb586604b4
commit
3d657c450a
3 changed files with 47 additions and 86 deletions
|
@ -160,52 +160,11 @@ FakeCall A32EmitX64::FastmemCallback(u64 rip_) {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void EmitDetectMisaignedVAddr(BlockOfCode& code, A32EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg32 vaddr, Xbyak::Reg32 tmp) {
|
|
||||||
if (bitsize == 8 || (ctx.conf.detect_misaligned_access_via_page_table & bitsize) == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 align_mask = [bitsize]() -> u32 {
|
|
||||||
switch (bitsize) {
|
|
||||||
case 16:
|
|
||||||
return 0b1;
|
|
||||||
case 32:
|
|
||||||
return 0b11;
|
|
||||||
case 64:
|
|
||||||
return 0b111;
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
}();
|
|
||||||
|
|
||||||
code.test(vaddr, align_mask);
|
|
||||||
|
|
||||||
if (!ctx.conf.only_detect_misalignment_via_page_table_on_page_boundary) {
|
|
||||||
code.jnz(abort, code.T_NEAR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 page_align_mask = static_cast<u32>(page_size - 1) & ~align_mask;
|
|
||||||
|
|
||||||
Xbyak::Label detect_boundary, resume;
|
|
||||||
|
|
||||||
code.jnz(detect_boundary, code.T_NEAR);
|
|
||||||
code.L(resume);
|
|
||||||
|
|
||||||
code.SwitchToFarCode();
|
|
||||||
code.L(detect_boundary);
|
|
||||||
code.mov(tmp, vaddr);
|
|
||||||
code.and_(tmp, page_align_mask);
|
|
||||||
code.cmp(tmp, page_align_mask);
|
|
||||||
code.jne(resume, code.T_NEAR);
|
|
||||||
// NOTE: We expect to fallthrough into abort code here.
|
|
||||||
code.SwitchToNearCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A32EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr) {
|
Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A32EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr) {
|
||||||
const Xbyak::Reg64 page = ctx.reg_alloc.ScratchGpr();
|
const Xbyak::Reg64 page = ctx.reg_alloc.ScratchGpr();
|
||||||
const Xbyak::Reg32 tmp = ctx.conf.absolute_offset_page_table ? page.cvt32() : ctx.reg_alloc.ScratchGpr().cvt32();
|
const Xbyak::Reg32 tmp = ctx.conf.absolute_offset_page_table ? page.cvt32() : ctx.reg_alloc.ScratchGpr().cvt32();
|
||||||
|
|
||||||
EmitDetectMisaignedVAddr(code, ctx, bitsize, abort, vaddr.cvt32(), tmp);
|
EmitDetectMisalignedVAddr(code, ctx, bitsize, abort, vaddr, tmp.cvt64());
|
||||||
|
|
||||||
// TODO: This code assumes vaddr has been zext from 32-bits to 64-bits.
|
// TODO: This code assumes vaddr has been zext from 32-bits to 64-bits.
|
||||||
|
|
||||||
|
|
|
@ -302,49 +302,6 @@ FakeCall A64EmitX64::FastmemCallback(u64 rip_) {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
void EmitDetectMisaignedVAddr(BlockOfCode& code, A64EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr, Xbyak::Reg64 tmp) {
|
|
||||||
if (bitsize == 8 || (ctx.conf.detect_misaligned_access_via_page_table & bitsize) == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 align_mask = [bitsize]() -> u32 {
|
|
||||||
switch (bitsize) {
|
|
||||||
case 16:
|
|
||||||
return 0b1;
|
|
||||||
case 32:
|
|
||||||
return 0b11;
|
|
||||||
case 64:
|
|
||||||
return 0b111;
|
|
||||||
case 128:
|
|
||||||
return 0b1111;
|
|
||||||
}
|
|
||||||
UNREACHABLE();
|
|
||||||
}();
|
|
||||||
|
|
||||||
code.test(vaddr, align_mask);
|
|
||||||
|
|
||||||
if (!ctx.conf.only_detect_misalignment_via_page_table_on_page_boundary) {
|
|
||||||
code.jnz(abort, code.T_NEAR);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 page_align_mask = static_cast<u32>(page_size - 1) & ~align_mask;
|
|
||||||
|
|
||||||
Xbyak::Label detect_boundary, resume;
|
|
||||||
|
|
||||||
code.jnz(detect_boundary, code.T_NEAR);
|
|
||||||
code.L(resume);
|
|
||||||
|
|
||||||
code.SwitchToFarCode();
|
|
||||||
code.L(detect_boundary);
|
|
||||||
code.mov(tmp, vaddr);
|
|
||||||
code.and_(tmp, page_align_mask);
|
|
||||||
code.cmp(tmp, page_align_mask);
|
|
||||||
code.jne(resume, code.T_NEAR);
|
|
||||||
// NOTE: We expect to fallthrough into abort code here.
|
|
||||||
code.SwitchToNearCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A64EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr) {
|
Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A64EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr) {
|
||||||
const size_t valid_page_index_bits = ctx.conf.page_table_address_space_bits - page_bits;
|
const size_t valid_page_index_bits = ctx.conf.page_table_address_space_bits - page_bits;
|
||||||
const size_t unused_top_bits = 64 - ctx.conf.page_table_address_space_bits;
|
const size_t unused_top_bits = 64 - ctx.conf.page_table_address_space_bits;
|
||||||
|
@ -352,7 +309,7 @@ Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A64EmitContext& ctx, size_t bit
|
||||||
const Xbyak::Reg64 page = ctx.reg_alloc.ScratchGpr();
|
const Xbyak::Reg64 page = ctx.reg_alloc.ScratchGpr();
|
||||||
const Xbyak::Reg64 tmp = ctx.conf.absolute_offset_page_table ? page : ctx.reg_alloc.ScratchGpr();
|
const Xbyak::Reg64 tmp = ctx.conf.absolute_offset_page_table ? page : ctx.reg_alloc.ScratchGpr();
|
||||||
|
|
||||||
EmitDetectMisaignedVAddr(code, ctx, bitsize, abort, vaddr, tmp);
|
EmitDetectMisalignedVAddr(code, ctx, bitsize, abort, vaddr, tmp);
|
||||||
|
|
||||||
if (unused_top_bits == 0) {
|
if (unused_top_bits == 0) {
|
||||||
code.mov(tmp, vaddr);
|
code.mov(tmp, vaddr);
|
||||||
|
|
|
@ -20,6 +20,51 @@ constexpr size_t page_bits = 12;
|
||||||
constexpr size_t page_size = 1 << page_bits;
|
constexpr size_t page_size = 1 << page_bits;
|
||||||
constexpr size_t page_mask = (1 << page_bits) - 1;
|
constexpr size_t page_mask = (1 << page_bits) - 1;
|
||||||
|
|
||||||
|
template<typename EmitContext>
|
||||||
|
void EmitDetectMisalignedVAddr(BlockOfCode& code, EmitContext& ctx, size_t bitsize, Xbyak::Label& abort, Xbyak::Reg64 vaddr, Xbyak::Reg64 tmp) {
|
||||||
|
if (bitsize == 8 || (ctx.conf.detect_misaligned_access_via_page_table & bitsize) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 align_mask = [bitsize]() -> u32 {
|
||||||
|
switch (bitsize) {
|
||||||
|
case 16:
|
||||||
|
return 0b1;
|
||||||
|
case 32:
|
||||||
|
return 0b11;
|
||||||
|
case 64:
|
||||||
|
return 0b111;
|
||||||
|
case 128:
|
||||||
|
return 0b1111;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
code.test(vaddr, align_mask);
|
||||||
|
|
||||||
|
if (!ctx.conf.only_detect_misalignment_via_page_table_on_page_boundary) {
|
||||||
|
code.jnz(abort, code.T_NEAR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 page_align_mask = static_cast<u32>(page_size - 1) & ~align_mask;
|
||||||
|
|
||||||
|
Xbyak::Label detect_boundary, resume;
|
||||||
|
|
||||||
|
code.jnz(detect_boundary, code.T_NEAR);
|
||||||
|
code.L(resume);
|
||||||
|
|
||||||
|
code.SwitchToFarCode();
|
||||||
|
code.L(detect_boundary);
|
||||||
|
code.mov(tmp, vaddr);
|
||||||
|
code.and_(tmp, page_align_mask);
|
||||||
|
code.cmp(tmp, page_align_mask);
|
||||||
|
code.jne(resume, code.T_NEAR);
|
||||||
|
// NOTE: We expect to fallthrough into abort code here.
|
||||||
|
code.SwitchToNearCode();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename UserConfig>
|
template<typename UserConfig>
|
||||||
void EmitExclusiveLock(BlockOfCode& code, const UserConfig& conf, Xbyak::Reg64 pointer, Xbyak::Reg32 tmp) {
|
void EmitExclusiveLock(BlockOfCode& code, const UserConfig& conf, Xbyak::Reg64 pointer, Xbyak::Reg32 tmp) {
|
||||||
if (conf.HasOptimization(OptimizationFlag::Unsafe_IgnoreGlobalMonitor)) {
|
if (conf.HasOptimization(OptimizationFlag::Unsafe_IgnoreGlobalMonitor)) {
|
||||||
|
|
Loading…
Reference in a new issue