diff --git a/src/backend/x64/a64_emit_x64.cpp b/src/backend/x64/a64_emit_x64.cpp index df575757..06188e2c 100644 --- a/src/backend/x64/a64_emit_x64.cpp +++ b/src/backend/x64/a64_emit_x64.cpp @@ -790,19 +790,30 @@ Xbyak::RegExp EmitVAddrLookup(BlockOfCode& code, A64EmitContext& ctx, size_t bit EmitDetectMisaignedVAddr(code, ctx, bitsize, abort, vaddr, tmp); - code.mov(tmp, vaddr); if (unused_top_bits == 0) { + code.mov(tmp, vaddr); code.shr(tmp, int(page_bits)); } else if (ctx.conf.silently_mirror_page_table) { if (valid_page_index_bits >= 32) { - code.shl(tmp, int(unused_top_bits)); - code.shr(tmp, int(unused_top_bits + page_bits)); + if (code.HasBMI2()) { + const Xbyak::Reg64 bit_count = ctx.reg_alloc.ScratchGpr(); + code.mov(bit_count, unused_top_bits); + code.bzhi(tmp, vaddr, bit_count); + code.shr(tmp, int(page_bits)); + ctx.reg_alloc.Release(bit_count); + } else { + code.mov(tmp, vaddr); + code.shl(tmp, int(unused_top_bits)); + code.shr(tmp, int(unused_top_bits + page_bits)); + } } else { + code.mov(tmp, vaddr); code.shr(tmp, int(page_bits)); code.and_(tmp, u32((1 << valid_page_index_bits) - 1)); } } else { ASSERT(valid_page_index_bits < 32); + code.mov(tmp, vaddr); code.shr(tmp, int(page_bits)); code.test(tmp, u32(-(1 << valid_page_index_bits))); code.jnz(abort, code.T_NEAR);