mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-05-31 20:57:07 +02:00
[dynarmic] cleanup duplicate code and reimpls of std::* bit stuff (#4017)
A bit of a minor cleanup - std::rotr instead of mcl::bit::rotate_right - std::rotl likewise - std::popcount instaed of "count ones" - use ConvertRoundingModeToX64Immediate where appropiate - std integral Signed-off-by: lizzie <lizzie@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4017 Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: crueter <crueter@eden-emu.dev>
This commit is contained in:
parent
b7fcec4985
commit
5f4a286046
18 changed files with 96 additions and 204 deletions
|
|
@ -24,7 +24,7 @@ using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, unsigned>;
|
|||
constexpr std::size_t xmrx(std::size_t x) noexcept {
|
||||
x ^= x >> 32;
|
||||
x *= 0xff51afd7ed558ccd;
|
||||
x ^= mcl::bit::rotate_right(x, 47) ^ mcl::bit::rotate_right(x, 23);
|
||||
x ^= std::rotr(x, 47) ^ std::rotr(x, 23);
|
||||
return x;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1532,7 +1532,7 @@ void EmitX64::EmitFPSingleToHalf(EmitContext& ctx, IR::Inst* inst) {
|
|||
if (ctx.FPCR().DN()) {
|
||||
ForceToDefaultNaN<32>(code, result);
|
||||
}
|
||||
code.vcvtps2ph(result, result, static_cast<u8>(*round_imm));
|
||||
code.vcvtps2ph(result, result, u8(*round_imm));
|
||||
|
||||
ctx.reg_alloc.DefineValue(code, inst, result);
|
||||
return;
|
||||
|
|
@ -1540,7 +1540,7 @@ void EmitX64::EmitFPSingleToHalf(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
ctx.reg_alloc.HostCall(code, inst, args[0]);
|
||||
code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value());
|
||||
code.mov(code.ABI_PARAM3.cvt32(), static_cast<u32>(rounding_mode));
|
||||
code.mov(code.ABI_PARAM3.cvt32(), u32(rounding_mode));
|
||||
code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]);
|
||||
code.CallFunction(&FP::FPConvert<u16, u32>);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst)
|
|||
Xbyak::Reg addend = ctx.reg_alloc.UseGpr(code, args[1]).changeBit(size);
|
||||
Xbyak::Reg overflow = ctx.reg_alloc.ScratchGpr(code).changeBit(size);
|
||||
|
||||
constexpr u64 int_max = static_cast<u64>((std::numeric_limits<mcl::signed_integer_of_size<size>>::max)());
|
||||
constexpr u64 int_max = u64((std::numeric_limits<std::make_signed_t<mcl::unsigned_integer_of_size<size>>>::max)());
|
||||
if constexpr (size < 64) {
|
||||
code.xor_(overflow.cvt32(), overflow.cvt32());
|
||||
code.bt(result.cvt32(), size - 1);
|
||||
|
|
|
|||
|
|
@ -3553,7 +3553,7 @@ void EmitX64::EmitVectorPopulationCount(EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
EmitOneArgumentFallback(code, ctx, inst, [](VectorArray<u8>& result, const VectorArray<u8>& a) {
|
||||
std::transform(a.begin(), a.end(), result.begin(), [](u8 val) {
|
||||
return static_cast<u8>(mcl::bit::count_ones(val));
|
||||
return static_cast<u8>(std::popcount(val));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1657,20 +1657,10 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
|
||||
if constexpr (fsize != 16) {
|
||||
if (code.HasHostFeature(HostFeature::SSE41) && rounding != FP::RoundingMode::ToNearest_TieAwayFromZero && !exact) {
|
||||
const u8 round_imm = [&]() -> u8 {
|
||||
switch (rounding) {
|
||||
case FP::RoundingMode::ToNearest_TieEven: return 0b00;
|
||||
case FP::RoundingMode::TowardsPlusInfinity: return 0b10;
|
||||
case FP::RoundingMode::TowardsMinusInfinity: return 0b01;
|
||||
case FP::RoundingMode::TowardsZero: return 0b11;
|
||||
default: UNREACHABLE();
|
||||
}
|
||||
}();
|
||||
|
||||
const auto round_imm = ConvertRoundingModeToX64Immediate(rounding);
|
||||
EmitTwoOpVectorOperation<fsize, DefaultIndexer, 3>(code, ctx, inst, [&](const Xbyak::Xmm& result, const Xbyak::Xmm& xmm_a) {
|
||||
FCODE(roundp)(result, xmm_a, round_imm);
|
||||
FCODE(roundp)(result, xmm_a, *round_imm);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -2002,19 +1992,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||
const Xbyak::Xmm src = ctx.reg_alloc.UseScratchXmm(code, args[0]);
|
||||
MaybeStandardFPSCRValue(code, ctx, fpcr_controlled, [&] {
|
||||
const int round_imm = [&] {
|
||||
switch (rounding) {
|
||||
case FP::RoundingMode::ToNearest_TieEven:
|
||||
default:
|
||||
return 0b00;
|
||||
case FP::RoundingMode::TowardsPlusInfinity:
|
||||
return 0b10;
|
||||
case FP::RoundingMode::TowardsMinusInfinity:
|
||||
return 0b01;
|
||||
case FP::RoundingMode::TowardsZero:
|
||||
return 0b11;
|
||||
}
|
||||
}();
|
||||
const auto round_imm = ConvertRoundingModeToX64Immediate(rounding);
|
||||
const auto perform_conversion = [&code, &ctx](const Xbyak::Xmm& src) {
|
||||
// MSVC doesn't allow us to use a [&] capture, so we have to do this instead.
|
||||
(void)ctx;
|
||||
|
|
@ -2046,7 +2024,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
|||
FCODE(mulp)(src, GetVectorOf<fsize>(code, scale_factor));
|
||||
}
|
||||
|
||||
FCODE(roundp)(src, src, u8(round_imm));
|
||||
FCODE(roundp)(src, src, u8(*round_imm));
|
||||
const Xbyak::Xmm nan_mask = xmm0;
|
||||
if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) {
|
||||
static constexpr u32 nan_to_zero = FixupLUT(FpFixup::PosZero, FpFixup::PosZero);
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ struct TranslatorVisitor final {
|
|||
u32 imm32 = imm8.ZeroExtend();
|
||||
auto carry_out = carry_in;
|
||||
if (rotate) {
|
||||
imm32 = mcl::bit::rotate_right<u32>(imm8.ZeroExtend(), rotate * 2);
|
||||
imm32 = std::rotr<u32>(imm8.ZeroExtend(), rotate * 2);
|
||||
carry_out = ir.Imm1(mcl::bit::get_bit<31>(imm32));
|
||||
}
|
||||
return {imm32, carry_out};
|
||||
|
|
@ -81,7 +81,7 @@ struct TranslatorVisitor final {
|
|||
}();
|
||||
return {imm32, carry_in};
|
||||
}
|
||||
const u32 imm32 = mcl::bit::rotate_right<u32>((1 << 7) | imm12.Bits<0, 6>(), imm12.Bits<7, 11>());
|
||||
const u32 imm32 = std::rotr<u32>((1 << 7) | imm12.Bits<0, 6>(), imm12.Bits<7, 11>());
|
||||
return {imm32, ir.Imm1(mcl::bit::get_bit<31>(imm32))};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ bool TranslatorVisitor::asimd_VDUP_scalar(bool D, Imm<4> imm4, size_t Vd, bool Q
|
|||
return UndefinedInstruction();
|
||||
}
|
||||
|
||||
const size_t imm4_lsb = mcl::bit::lowest_set_bit(imm4.ZeroExtend());
|
||||
const size_t imm4_lsb = std::countr_zero(imm4.ZeroExtend());
|
||||
const size_t esize = 8u << imm4_lsb;
|
||||
const size_t index = imm4.ZeroExtend() >> (imm4_lsb + 1);
|
||||
const auto d = ToVector(Q, Vd, D);
|
||||
|
|
|
|||
|
|
@ -799,7 +799,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s
|
|||
|
||||
// LDM <Rn>{!}, <reg_list>
|
||||
bool TranslatorVisitor::arm_LDM(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
|
||||
if (n == Reg::PC || std::popcount(list) < 1) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
if (W && mcl::bit::get_bit(static_cast<size_t>(n), list)) {
|
||||
|
|
@ -811,13 +811,13 @@ bool TranslatorVisitor::arm_LDM(Cond cond, bool W, Reg n, RegList list) {
|
|||
}
|
||||
|
||||
const auto start_address = ir.GetRegister(n);
|
||||
const auto writeback_address = ir.Add(start_address, ir.Imm32(u32(mcl::bit::count_ones(list) * 4)));
|
||||
const auto writeback_address = ir.Add(start_address, ir.Imm32(u32(std::popcount(list) * 4)));
|
||||
return LDMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
|
||||
// LDMDA <Rn>{!}, <reg_list>
|
||||
bool TranslatorVisitor::arm_LDMDA(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
|
||||
if (n == Reg::PC || std::popcount(list) < 1) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
if (W && mcl::bit::get_bit(static_cast<size_t>(n), list)) {
|
||||
|
|
@ -828,14 +828,14 @@ bool TranslatorVisitor::arm_LDMDA(Cond cond, bool W, Reg n, RegList list) {
|
|||
return true;
|
||||
}
|
||||
|
||||
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list) - 4)));
|
||||
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list) - 4)));
|
||||
const auto writeback_address = ir.Sub(start_address, ir.Imm32(4));
|
||||
return LDMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
|
||||
// LDMDB <Rn>{!}, <reg_list>
|
||||
bool TranslatorVisitor::arm_LDMDB(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
|
||||
if (n == Reg::PC || std::popcount(list) < 1) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
if (W && mcl::bit::get_bit(static_cast<size_t>(n), list)) {
|
||||
|
|
@ -846,14 +846,14 @@ bool TranslatorVisitor::arm_LDMDB(Cond cond, bool W, Reg n, RegList list) {
|
|||
return true;
|
||||
}
|
||||
|
||||
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list))));
|
||||
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list))));
|
||||
const auto writeback_address = start_address;
|
||||
return LDMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
|
||||
// LDMIB <Rn>{!}, <reg_list>
|
||||
bool TranslatorVisitor::arm_LDMIB(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
|
||||
if (n == Reg::PC || std::popcount(list) < 1) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
if (W && mcl::bit::get_bit(static_cast<size_t>(n), list)) {
|
||||
|
|
@ -865,7 +865,7 @@ bool TranslatorVisitor::arm_LDMIB(Cond cond, bool W, Reg n, RegList list) {
|
|||
}
|
||||
|
||||
const auto start_address = ir.Add(ir.GetRegister(n), ir.Imm32(4));
|
||||
const auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list))));
|
||||
const auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list))));
|
||||
return LDMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
|
||||
|
|
@ -896,7 +896,7 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s
|
|||
|
||||
// STM <Rn>{!}, <reg_list>
|
||||
bool TranslatorVisitor::arm_STM(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
|
||||
if (n == Reg::PC || std::popcount(list) < 1) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
|
||||
|
|
@ -905,13 +905,13 @@ bool TranslatorVisitor::arm_STM(Cond cond, bool W, Reg n, RegList list) {
|
|||
}
|
||||
|
||||
const auto start_address = ir.GetRegister(n);
|
||||
const auto writeback_address = ir.Add(start_address, ir.Imm32(u32(mcl::bit::count_ones(list) * 4)));
|
||||
const auto writeback_address = ir.Add(start_address, ir.Imm32(u32(std::popcount(list) * 4)));
|
||||
return STMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
|
||||
// STMDA <Rn>{!}, <reg_list>
|
||||
bool TranslatorVisitor::arm_STMDA(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
|
||||
if (n == Reg::PC || std::popcount(list) < 1) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
|
||||
|
|
@ -919,14 +919,14 @@ bool TranslatorVisitor::arm_STMDA(Cond cond, bool W, Reg n, RegList list) {
|
|||
return true;
|
||||
}
|
||||
|
||||
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list) - 4)));
|
||||
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list) - 4)));
|
||||
const auto writeback_address = ir.Sub(start_address, ir.Imm32(4));
|
||||
return STMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
|
||||
// STMDB <Rn>{!}, <reg_list>
|
||||
bool TranslatorVisitor::arm_STMDB(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
|
||||
if (n == Reg::PC || std::popcount(list) < 1) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
|
||||
|
|
@ -934,14 +934,14 @@ bool TranslatorVisitor::arm_STMDB(Cond cond, bool W, Reg n, RegList list) {
|
|||
return true;
|
||||
}
|
||||
|
||||
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list))));
|
||||
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list))));
|
||||
const auto writeback_address = start_address;
|
||||
return STMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
|
||||
// STMIB <Rn>{!}, <reg_list>
|
||||
bool TranslatorVisitor::arm_STMIB(Cond cond, bool W, Reg n, RegList list) {
|
||||
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
|
||||
if (n == Reg::PC || std::popcount(list) < 1) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
|
||||
|
|
@ -950,7 +950,7 @@ bool TranslatorVisitor::arm_STMIB(Cond cond, bool W, Reg n, RegList list) {
|
|||
}
|
||||
|
||||
const auto start_address = ir.Add(ir.GetRegister(n), ir.Imm32(4));
|
||||
const auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list))));
|
||||
const auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list))));
|
||||
return STMHelper(ir, W, n, list, start_address, writeback_address);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -688,7 +688,7 @@ bool TranslatorVisitor::thumb16_NOP() {
|
|||
// IT{<x>{<y>{<z>}}} <cond>
|
||||
bool TranslatorVisitor::thumb16_IT(Imm<8> imm8) {
|
||||
ASSERT((imm8.Bits<0, 3>() != 0b0000) && "Decode Error");
|
||||
if (imm8.Bits<4, 7>() == 0b1111 || (imm8.Bits<4, 7>() == 0b1110 && mcl::bit::count_ones(imm8.Bits<0, 3>()) != 1)) {
|
||||
if (imm8.Bits<4, 7>() == 0b1111 || (imm8.Bits<4, 7>() == 0b1110 && std::popcount(imm8.Bits<0, 3>()) != 1)) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
if (ir.current_location.IT().IsInITBlock()) {
|
||||
|
|
@ -738,11 +738,11 @@ bool TranslatorVisitor::thumb16_PUSH(bool M, RegList reg_list) {
|
|||
if (M) {
|
||||
reg_list |= 1 << 14;
|
||||
}
|
||||
if (mcl::bit::count_ones(reg_list) < 1) {
|
||||
if (std::popcount(reg_list) < 1) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
|
||||
const u32 num_bytes_to_push = static_cast<u32>(4 * mcl::bit::count_ones(reg_list));
|
||||
const u32 num_bytes_to_push = static_cast<u32>(4 * std::popcount(reg_list));
|
||||
const auto final_address = ir.Sub(ir.GetRegister(Reg::SP), ir.Imm32(num_bytes_to_push));
|
||||
auto address = final_address;
|
||||
for (size_t i = 0; i < 16; i++) {
|
||||
|
|
@ -764,7 +764,7 @@ bool TranslatorVisitor::thumb16_POP(bool P, RegList reg_list) {
|
|||
if (P) {
|
||||
reg_list |= 1 << 15;
|
||||
}
|
||||
if (mcl::bit::count_ones(reg_list) < 1) {
|
||||
if (std::popcount(reg_list) < 1) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
|
||||
|
|
@ -851,10 +851,10 @@ bool TranslatorVisitor::thumb16_BKPT(Imm<8> /*imm8*/) {
|
|||
|
||||
// STM <Rn>!, <reg_list>
|
||||
bool TranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) {
|
||||
if (mcl::bit::count_ones(reg_list) == 0) {
|
||||
if (std::popcount(reg_list) == 0) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
if (mcl::bit::get_bit(static_cast<size_t>(n), reg_list) && n != static_cast<Reg>(mcl::bit::lowest_set_bit(reg_list))) {
|
||||
if (mcl::bit::get_bit(static_cast<size_t>(n), reg_list) && n != static_cast<Reg>(std::countr_zero(reg_list))) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
|
||||
|
|
@ -873,7 +873,7 @@ bool TranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) {
|
|||
|
||||
// LDM <Rn>!, <reg_list>
|
||||
bool TranslatorVisitor::thumb16_LDMIA(Reg n, RegList reg_list) {
|
||||
if (mcl::bit::count_ones(reg_list) == 0) {
|
||||
if (std::popcount(reg_list) == 0) {
|
||||
return UnpredictableInstruction();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, const IR::U32
|
|||
|
||||
bool TranslatorVisitor::thumb32_LDMDB(bool W, Reg n, Imm<16> reg_list) {
|
||||
const auto regs_imm = reg_list.ZeroExtend();
|
||||
const auto num_regs = static_cast<u32>(mcl::bit::count_ones(regs_imm));
|
||||
const auto num_regs = static_cast<u32>(std::popcount(regs_imm));
|
||||
|
||||
if (n == Reg::PC || num_regs < 2) {
|
||||
return UnpredictableInstruction();
|
||||
|
|
@ -78,7 +78,7 @@ bool TranslatorVisitor::thumb32_LDMDB(bool W, Reg n, Imm<16> reg_list) {
|
|||
|
||||
bool TranslatorVisitor::thumb32_LDMIA(bool W, Reg n, Imm<16> reg_list) {
|
||||
const auto regs_imm = reg_list.ZeroExtend();
|
||||
const auto num_regs = static_cast<u32>(mcl::bit::count_ones(regs_imm));
|
||||
const auto num_regs = static_cast<u32>(std::popcount(regs_imm));
|
||||
|
||||
if (n == Reg::PC || num_regs < 2) {
|
||||
return UnpredictableInstruction();
|
||||
|
|
@ -111,7 +111,7 @@ bool TranslatorVisitor::thumb32_PUSH(Imm<15> reg_list) {
|
|||
|
||||
bool TranslatorVisitor::thumb32_STMIA(bool W, Reg n, Imm<15> reg_list) {
|
||||
const auto regs_imm = reg_list.ZeroExtend();
|
||||
const auto num_regs = static_cast<u32>(mcl::bit::count_ones(regs_imm));
|
||||
const auto num_regs = static_cast<u32>(std::popcount(regs_imm));
|
||||
|
||||
if (n == Reg::PC || num_regs < 2) {
|
||||
return UnpredictableInstruction();
|
||||
|
|
@ -130,7 +130,7 @@ bool TranslatorVisitor::thumb32_STMIA(bool W, Reg n, Imm<15> reg_list) {
|
|||
|
||||
bool TranslatorVisitor::thumb32_STMDB(bool W, Reg n, Imm<15> reg_list) {
|
||||
const auto regs_imm = reg_list.ZeroExtend();
|
||||
const auto num_regs = static_cast<u32>(mcl::bit::count_ones(regs_imm));
|
||||
const auto num_regs = static_cast<u32>(std::popcount(regs_imm));
|
||||
|
||||
if (n == Reg::PC || num_regs < 2) {
|
||||
return UnpredictableInstruction();
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ std::optional<TranslatorVisitor::BitMasks> TranslatorVisitor::DecodeBitMasks(boo
|
|||
const size_t esize = size_t{1} << len;
|
||||
const u64 welem = mcl::bit::ones<u64>(S + 1);
|
||||
const u64 telem = mcl::bit::ones<u64>(d + 1);
|
||||
const u64 wmask = mcl::bit::rotate_right(mcl::bit::replicate_element<u64>(esize, welem), R);
|
||||
const u64 wmask = std::rotr(mcl::bit::replicate_element<u64>(esize, welem), R);
|
||||
const u64 tmask = mcl::bit::replicate_element<u64>(esize, telem);
|
||||
|
||||
return BitMasks{wmask, tmask};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
namespace Dynarmic::A64 {
|
||||
|
||||
bool TranslatorVisitor::DUP_elt_1(Imm<5> imm5, Vec Vn, Vec Vd) {
|
||||
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
|
||||
const size_t size = std::countr_zero(imm5.ZeroExtend());
|
||||
if (size > 3) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ bool TranslatorVisitor::DUP_elt_1(Imm<5> imm5, Vec Vn, Vec Vd) {
|
|||
}
|
||||
|
||||
bool TranslatorVisitor::DUP_elt_2(bool Q, Imm<5> imm5, Vec Vn, Vec Vd) {
|
||||
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
|
||||
const size_t size = std::countr_zero(imm5.ZeroExtend());
|
||||
if (size > 3) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
|
@ -51,7 +51,7 @@ bool TranslatorVisitor::DUP_elt_2(bool Q, Imm<5> imm5, Vec Vn, Vec Vd) {
|
|||
}
|
||||
|
||||
bool TranslatorVisitor::DUP_gen(bool Q, Imm<5> imm5, Reg Rn, Vec Vd) {
|
||||
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
|
||||
const size_t size = std::countr_zero(imm5.ZeroExtend());
|
||||
if (size > 3) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@ bool TranslatorVisitor::DUP_gen(bool Q, Imm<5> imm5, Reg Rn, Vec Vd) {
|
|||
}
|
||||
|
||||
bool TranslatorVisitor::SMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
|
||||
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
|
||||
const size_t size = std::countr_zero(imm5.ZeroExtend());
|
||||
if (size == 2 && !Q) {
|
||||
return UnallocatedEncoding();
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ bool TranslatorVisitor::SMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
|
|||
}
|
||||
|
||||
bool TranslatorVisitor::UMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
|
||||
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
|
||||
const size_t size = std::countr_zero(imm5.ZeroExtend());
|
||||
if (size < 3 && Q) {
|
||||
return UnallocatedEncoding();
|
||||
}
|
||||
|
|
@ -123,7 +123,7 @@ bool TranslatorVisitor::UMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
|
|||
}
|
||||
|
||||
bool TranslatorVisitor::INS_gen(Imm<5> imm5, Reg Rn, Vec Vd) {
|
||||
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
|
||||
const size_t size = std::countr_zero(imm5.ZeroExtend());
|
||||
if (size > 3) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
|
@ -140,7 +140,7 @@ bool TranslatorVisitor::INS_gen(Imm<5> imm5, Reg Rn, Vec Vd) {
|
|||
}
|
||||
|
||||
bool TranslatorVisitor::INS_elt(Imm<5> imm5, Imm<4> imm4, Vec Vn, Vec Vd) {
|
||||
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
|
||||
const size_t size = std::countr_zero(imm5.ZeroExtend());
|
||||
if (size > 3) {
|
||||
return ReservedValue();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <bit>
|
||||
|
||||
#include <ankerl/unordered_dense.h>
|
||||
#include "boost/container/small_vector.hpp"
|
||||
|
|
@ -28,7 +29,6 @@
|
|||
#include "dynarmic/ir/opt_passes.h"
|
||||
#include "dynarmic/ir/type.h"
|
||||
#include "dynarmic/mcl/bit.hpp"
|
||||
#include "dynarmic/mcl/bit.hpp"
|
||||
|
||||
namespace Dynarmic::Optimization {
|
||||
|
||||
|
|
@ -1074,12 +1074,12 @@ static void ConstantPropagation(IR::Block& block) {
|
|||
break;
|
||||
case Op::BitRotateRight32:
|
||||
if (FoldShifts(inst)) {
|
||||
ReplaceUsesWith(inst, true, mcl::bit::rotate_right<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU8()));
|
||||
ReplaceUsesWith(inst, true, std::rotr<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU8()));
|
||||
}
|
||||
break;
|
||||
case Op::BitRotateRight64:
|
||||
if (FoldShifts(inst)) {
|
||||
ReplaceUsesWith(inst, false, mcl::bit::rotate_right<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU8()));
|
||||
ReplaceUsesWith(inst, false, std::rotr<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU8()));
|
||||
}
|
||||
break;
|
||||
case Op::LogicalShiftLeftMasked32:
|
||||
|
|
@ -1114,12 +1114,12 @@ static void ConstantPropagation(IR::Block& block) {
|
|||
break;
|
||||
case Op::RotateRightMasked32:
|
||||
if (inst.AreAllArgsImmediates()) {
|
||||
ReplaceUsesWith(inst, true, mcl::bit::rotate_right<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU32()));
|
||||
ReplaceUsesWith(inst, true, std::rotr<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU32()));
|
||||
}
|
||||
break;
|
||||
case Op::RotateRightMasked64:
|
||||
if (inst.AreAllArgsImmediates()) {
|
||||
ReplaceUsesWith(inst, false, mcl::bit::rotate_right<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU64()));
|
||||
ReplaceUsesWith(inst, false, std::rotr<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU64()));
|
||||
}
|
||||
break;
|
||||
case Op::Add32:
|
||||
|
|
|
|||
|
|
@ -8,26 +8,15 @@
|
|||
#include <bitset>
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <concepts>
|
||||
#include <bit>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "common/assert.h"
|
||||
|
||||
namespace mcl {
|
||||
namespace detail {
|
||||
template<typename T, typename U>
|
||||
concept SameHelper = std::is_same_v<T, U>;
|
||||
} // namespace detail
|
||||
template<typename T, typename U>
|
||||
concept SameAs = detail::SameHelper<T, U> && detail::SameHelper<U, T>;
|
||||
template<typename T, typename... U>
|
||||
concept IsAnyOf = (SameAs<T, U> || ...);
|
||||
/// Integral upon which bit operations can be safely performed.
|
||||
template<typename T>
|
||||
concept BitIntegral = IsAnyOf<T, u8, u16, u32, u64, std::uintptr_t, size_t>;
|
||||
|
||||
template<typename T>
|
||||
constexpr std::size_t bitsizeof = CHAR_BIT * sizeof(T);
|
||||
|
||||
} // namespace mcl
|
||||
|
||||
namespace mcl::bit {
|
||||
|
|
@ -71,58 +60,37 @@ constexpr u64 swap_words_64(u64 value) {
|
|||
| ((value & 0x00000000ffffffffull) << 32);
|
||||
}
|
||||
|
||||
template<BitIntegral T>
|
||||
constexpr T rotate_right(T x, size_t amount) {
|
||||
amount %= bitsizeof<T>;
|
||||
if (amount == 0) {
|
||||
return x;
|
||||
}
|
||||
return static_cast<T>((x >> amount) | (x << (bitsizeof<T> - amount)));
|
||||
}
|
||||
|
||||
template<BitIntegral T>
|
||||
constexpr T rotate_left(T x, size_t amount) {
|
||||
amount %= bitsizeof<T>;
|
||||
if (amount == 0) {
|
||||
return x;
|
||||
}
|
||||
return static_cast<T>((x << amount) | (x >> (bitsizeof<T> - amount)));
|
||||
}
|
||||
|
||||
/// Create a mask with `count` number of one bits.
|
||||
template<size_t count, BitIntegral T>
|
||||
template<size_t count, std::integral T>
|
||||
constexpr T ones() {
|
||||
static_assert(count <= bitsizeof<T>, "count larger than bitsize of T");
|
||||
|
||||
if constexpr (count == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return static_cast<T>(~static_cast<T>(0)) >> (bitsizeof<T> - count);
|
||||
return T(~T(0)) >> (bitsizeof<T> - count);
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a mask with `count` number of one bits.
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr T ones(size_t count) {
|
||||
ASSERT(count <= bitsizeof<T> && "count larger than bitsize of T");
|
||||
if (count == 0) {
|
||||
if (count == 0)
|
||||
return 0;
|
||||
}
|
||||
return static_cast<T>(~static_cast<T>(0)) >> (bitsizeof<T> - count);
|
||||
return T(~T(0)) >> (bitsizeof<T> - count);
|
||||
}
|
||||
|
||||
/// Create a mask of type T for bits [begin_bit, end_bit] inclusive.
|
||||
template<size_t begin_bit, size_t end_bit, BitIntegral T>
|
||||
template<size_t begin_bit, size_t end_bit, std::integral T>
|
||||
constexpr T mask() {
|
||||
static_assert(begin_bit <= end_bit, "invalid bit range (position of beginning bit cannot be greater than that of end bit)");
|
||||
static_assert(begin_bit < bitsizeof<T>, "begin_bit must be smaller than size of T");
|
||||
static_assert(end_bit < bitsizeof<T>, "end_bit must be smaller than size of T");
|
||||
|
||||
return ones<end_bit - begin_bit + 1, T>() << begin_bit;
|
||||
}
|
||||
|
||||
/// Create a mask of type T for bits [begin_bit, end_bit] inclusive.
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr T mask(size_t begin_bit, size_t end_bit) {
|
||||
ASSERT(begin_bit <= end_bit && "invalid bit range (position of beginning bit cannot be greater than that of end bit)");
|
||||
ASSERT(begin_bit < bitsizeof<T> && "begin_bit must be smaller than size of T");
|
||||
|
|
@ -131,101 +99,100 @@ constexpr T mask(size_t begin_bit, size_t end_bit) {
|
|||
}
|
||||
|
||||
/// Extract bits [begin_bit, end_bit] inclusive from value of type T.
|
||||
template<size_t begin_bit, size_t end_bit, BitIntegral T>
|
||||
template<size_t begin_bit, size_t end_bit, std::integral T>
|
||||
constexpr T get_bits(T value) {
|
||||
constexpr T m = mask<begin_bit, end_bit, T>();
|
||||
return (value & m) >> begin_bit;
|
||||
}
|
||||
|
||||
/// Extract bits [begin_bit, end_bit] inclusive from value of type T.
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr T get_bits(size_t begin_bit, size_t end_bit, T value) {
|
||||
const T m = mask<T>(begin_bit, end_bit);
|
||||
return (value & m) >> begin_bit;
|
||||
}
|
||||
|
||||
/// Clears bits [begin_bit, end_bit] inclusive of value of type T.
|
||||
template<size_t begin_bit, size_t end_bit, BitIntegral T>
|
||||
template<size_t begin_bit, size_t end_bit, std::integral T>
|
||||
constexpr T clear_bits(T value) {
|
||||
constexpr T m = mask<begin_bit, end_bit, T>();
|
||||
return value & ~m;
|
||||
}
|
||||
|
||||
/// Clears bits [begin_bit, end_bit] inclusive of value of type T.
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr T clear_bits(size_t begin_bit, size_t end_bit, T value) {
|
||||
const T m = mask<T>(begin_bit, end_bit);
|
||||
return value & ~m;
|
||||
}
|
||||
|
||||
/// Modifies bits [begin_bit, end_bit] inclusive of value of type T.
|
||||
template<size_t begin_bit, size_t end_bit, BitIntegral T>
|
||||
template<size_t begin_bit, size_t end_bit, std::integral T>
|
||||
constexpr T set_bits(T value, T new_bits) {
|
||||
constexpr T m = mask<begin_bit, end_bit, T>();
|
||||
return (value & ~m) | ((new_bits << begin_bit) & m);
|
||||
}
|
||||
|
||||
/// Modifies bits [begin_bit, end_bit] inclusive of value of type T.
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr T set_bits(size_t begin_bit, size_t end_bit, T value, T new_bits) {
|
||||
const T m = mask<T>(begin_bit, end_bit);
|
||||
return (value & ~m) | ((new_bits << begin_bit) & m);
|
||||
}
|
||||
|
||||
/// Extract bit at bit_position from value of type T.
|
||||
template<size_t bit_position, BitIntegral T>
|
||||
template<size_t bit_position, std::integral T>
|
||||
constexpr bool get_bit(T value) {
|
||||
constexpr T m = mask<bit_position, bit_position, T>();
|
||||
return (value & m) != 0;
|
||||
}
|
||||
|
||||
/// Extract bit at bit_position from value of type T.
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr bool get_bit(size_t bit_position, T value) {
|
||||
const T m = mask<T>(bit_position, bit_position);
|
||||
return (value & m) != 0;
|
||||
}
|
||||
|
||||
/// Clears bit at bit_position of value of type T.
|
||||
template<size_t bit_position, BitIntegral T>
|
||||
template<size_t bit_position, std::integral T>
|
||||
constexpr T clear_bit(T value) {
|
||||
constexpr T m = mask<bit_position, bit_position, T>();
|
||||
return value & ~m;
|
||||
}
|
||||
|
||||
/// Clears bit at bit_position of value of type T.
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr T clear_bit(size_t bit_position, T value) {
|
||||
const T m = mask<T>(bit_position, bit_position);
|
||||
return value & ~m;
|
||||
}
|
||||
|
||||
/// Modifies bit at bit_position of value of type T.
|
||||
template<size_t bit_position, BitIntegral T>
|
||||
template<size_t bit_position, std::integral T>
|
||||
constexpr T set_bit(T value, bool new_bit) {
|
||||
constexpr T m = mask<bit_position, bit_position, T>();
|
||||
return (value & ~m) | (new_bit ? m : static_cast<T>(0));
|
||||
return (value & ~m) | (new_bit ? m : T(0));
|
||||
}
|
||||
|
||||
/// Modifies bit at bit_position of value of type T.
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr T set_bit(size_t bit_position, T value, bool new_bit) {
|
||||
const T m = mask<T>(bit_position, bit_position);
|
||||
return (value & ~m) | (new_bit ? m : static_cast<T>(0));
|
||||
return (value & ~m) | (new_bit ? m : T(0));
|
||||
}
|
||||
|
||||
/// Sign-extends a value that has bit_count bits to the full bitwidth of type T.
|
||||
template<size_t bit_count, BitIntegral T>
|
||||
template<size_t bit_count, std::integral T>
|
||||
constexpr T sign_extend(T value) {
|
||||
static_assert(bit_count != 0, "cannot sign-extend zero-sized value");
|
||||
|
||||
using S = std::make_signed_t<T>;
|
||||
constexpr size_t shift_amount = bitsizeof<T> - bit_count;
|
||||
return static_cast<T>(static_cast<S>(value << shift_amount) >> shift_amount);
|
||||
return T(S(value << shift_amount) >> shift_amount);
|
||||
}
|
||||
|
||||
/// Sign-extends a value that has bit_count bits to the full bitwidth of type T.
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr T sign_extend(size_t bit_count, T value) {
|
||||
ASSERT(bit_count != 0 && "cannot sign-extend zero-sized value");
|
||||
using S = std::make_signed_t<T>;
|
||||
|
|
@ -234,78 +201,42 @@ constexpr T sign_extend(size_t bit_count, T value) {
|
|||
}
|
||||
|
||||
/// Replicate an element across a value of type T.
|
||||
template<size_t element_size, BitIntegral T>
|
||||
template<size_t element_size, std::integral T>
|
||||
constexpr T replicate_element(T value) {
|
||||
static_assert(element_size <= bitsizeof<T>, "element_size is too large");
|
||||
static_assert(bitsizeof<T> % element_size == 0, "bitsize of T not divisible by element_size");
|
||||
|
||||
if constexpr (element_size == bitsizeof<T>) {
|
||||
return value;
|
||||
} else {
|
||||
return replicate_element<element_size * 2, T>(static_cast<T>(value | (value << element_size)));
|
||||
return replicate_element<element_size * 2, T>(T(value | (value << element_size)));
|
||||
}
|
||||
}
|
||||
|
||||
/// Replicate an element of type U across a value of type T.
|
||||
template<BitIntegral U, BitIntegral T>
|
||||
template<std::integral U, std::integral T>
|
||||
constexpr T replicate_element(T value) {
|
||||
static_assert(bitsizeof<U> <= bitsizeof<T>, "element_size is too large");
|
||||
|
||||
return replicate_element<bitsizeof<U>, T>(value);
|
||||
}
|
||||
|
||||
/// Replicate an element across a value of type T.
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr T replicate_element(size_t element_size, T value) {
|
||||
ASSERT(element_size <= bitsizeof<T> && "element_size is too large");
|
||||
ASSERT(bitsizeof<T> % element_size == 0 && "bitsize of T not divisible by element_size");
|
||||
if (element_size == bitsizeof<T>)
|
||||
return value;
|
||||
return replicate_element<T>(element_size * 2, static_cast<T>(value | (value << element_size)));
|
||||
return replicate_element<T>(element_size * 2, T(value | (value << element_size)));
|
||||
}
|
||||
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr bool most_significant_bit(T value) {
|
||||
return get_bit<bitsizeof<T> - 1, T>(value);
|
||||
}
|
||||
|
||||
template<BitIntegral T>
|
||||
inline size_t count_ones(T x) {
|
||||
return std::bitset<bitsizeof<T>>(x).count();
|
||||
}
|
||||
|
||||
template<BitIntegral T>
|
||||
constexpr size_t count_leading_zeros(T x) {
|
||||
size_t result = bitsizeof<T>;
|
||||
while (x != 0) {
|
||||
x >>= 1;
|
||||
result--;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<BitIntegral T>
|
||||
template<std::integral T>
|
||||
constexpr int highest_set_bit(T x) {
|
||||
int result = -1;
|
||||
while (x != 0) {
|
||||
x >>= 1;
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<BitIntegral T>
|
||||
constexpr size_t lowest_set_bit(T x) {
|
||||
if (x == 0) {
|
||||
return bitsizeof<T>;
|
||||
}
|
||||
|
||||
size_t result = 0;
|
||||
while ((x & 1) == 0) {
|
||||
x >>= 1;
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
return std::bit_width(x) - 1;
|
||||
}
|
||||
|
||||
} // namespace mcl::bit
|
||||
|
|
|
|||
|
|
@ -17,25 +17,25 @@ struct integer_of_size_impl {};
|
|||
template<>
|
||||
struct integer_of_size_impl<8> {
|
||||
using unsigned_type = u8;
|
||||
using signed_type = s8;
|
||||
using signed_type = std::make_signed_t<unsigned_type>;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct integer_of_size_impl<16> {
|
||||
using unsigned_type = u16;
|
||||
using signed_type = s16;
|
||||
using signed_type = std::make_signed_t<unsigned_type>;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct integer_of_size_impl<32> {
|
||||
using unsigned_type = u32;
|
||||
using signed_type = s32;
|
||||
using signed_type = std::make_signed_t<unsigned_type>;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct integer_of_size_impl<64> {
|
||||
using unsigned_type = u64;
|
||||
using signed_type = s64;
|
||||
using signed_type = std::make_signed_t<unsigned_type>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
|
|
|||
|
|
@ -10,23 +10,12 @@
|
|||
|
||||
namespace mcl {
|
||||
|
||||
/// A metavalue (of type VT and value v).
|
||||
template<class VT, VT v> using value = std::integral_constant<VT, v>;
|
||||
/// A metavalue of type size_t (and value v).
|
||||
template<size_t v> using size_value = value<size_t, v>;
|
||||
/// A metavalue of type bool (and value v). (Aliases to std::bool_constant.)
|
||||
template<bool v> using bool_value = value<bool, v>;
|
||||
/// true metavalue (Aliases to std::true_type).
|
||||
using true_type = bool_value<true>;
|
||||
/// false metavalue (Aliases to std::false_type).
|
||||
using false_type = bool_value<false>;
|
||||
|
||||
/// Is type T an instance of template class C?
|
||||
template<template<class...> class, class>
|
||||
struct is_instance_of_template : false_type {};
|
||||
struct is_instance_of_template : std::false_type {};
|
||||
|
||||
template<template<class...> class C, class... As>
|
||||
struct is_instance_of_template<C, C<As...>> : true_type {};
|
||||
struct is_instance_of_template<C, C<As...>> : std::true_type {};
|
||||
|
||||
/// Is type T an instance of template class C?
|
||||
template<template<class...> class C, class T>
|
||||
|
|
|
|||
|
|
@ -665,7 +665,7 @@ TEST_CASE("A32: Test thumb IT instruction", "[thumb]") {
|
|||
A32::ITState it_state = [&] {
|
||||
while (true) {
|
||||
const u16 imm8 = RandInt<u16>(0, 0xFF);
|
||||
if (mcl::bit::get_bits<0, 3>(imm8) == 0b0000 || mcl::bit::get_bits<4, 7>(imm8) == 0b1111 || (mcl::bit::get_bits<4, 7>(imm8) == 0b1110 && mcl::bit::count_ones(mcl::bit::get_bits<0, 3>(imm8)) != 1)) {
|
||||
if (mcl::bit::get_bits<0, 3>(imm8) == 0b0000 || mcl::bit::get_bits<4, 7>(imm8) == 0b1111 || (mcl::bit::get_bits<4, 7>(imm8) == 0b1110 && std::popcount(mcl::bit::get_bits<0, 3>(imm8)) != 1)) {
|
||||
continue;
|
||||
}
|
||||
instructions.push_back(0b1011111100000000 | imm8);
|
||||
|
|
|
|||
|
|
@ -17,12 +17,6 @@ namespace mcl {
|
|||
template<typename T>
|
||||
constexpr std::size_t bitsizeof = CHAR_BIT * sizeof(T);
|
||||
}
|
||||
namespace mcl::bit {
|
||||
template<typename T>
|
||||
inline size_t count_ones(T x) {
|
||||
return std::bitset<bitsizeof<T>>(x).count();
|
||||
}
|
||||
}
|
||||
template<size_t N>
|
||||
inline consteval std::array<char, N> StringToArray(const char (&str)[N + 1]) {
|
||||
std::array<char, N> result{};
|
||||
|
|
@ -380,7 +374,7 @@ INST(arm_SRS, "SRS", "1111100--1-0110100000101000-----
|
|||
};
|
||||
// If a matcher has more bits in its mask it is more specific, so it should come first.
|
||||
std::stable_sort(list.begin(), list.end(), [](const auto& matcher1, const auto& matcher2) {
|
||||
return mcl::bit::count_ones(matcher1.second) > mcl::bit::count_ones(matcher2.second);
|
||||
return std::popcount(matcher1.second) > std::popcount(matcher2.second);
|
||||
});
|
||||
for (auto const& e : list)
|
||||
printf("%s\n", e.inst_final);
|
||||
|
|
@ -587,7 +581,7 @@ INST(v8_VLD_single, "VLD{1-4} (single)", "111101001D10nnnnddddzzN
|
|||
});
|
||||
// If a matcher has more bits in its mask it is more specific, so it should come first.
|
||||
std::stable_sort(sort_begin, sort_end, [](const auto& a, const auto& b) {
|
||||
return mcl::bit::count_ones(a.second) > mcl::bit::count_ones(b.second);
|
||||
return std::popcount(a.second) > std::popcount(b.second);
|
||||
});
|
||||
for (auto const& e : table)
|
||||
printf("%s\n", e.inst_final);
|
||||
|
|
@ -1628,7 +1622,7 @@ INST(FNMSUB_float, "FNMSUB", "00011
|
|||
// If a matcher has more bits in its mask it is more specific, so it should come first.
|
||||
std::stable_sort(list.begin(), list.end(), [](const auto& a, const auto& b) {
|
||||
// If a matcher has more bits in its mask it is more specific, so it should come first.
|
||||
return mcl::bit::count_ones(a.second) > mcl::bit::count_ones(b.second);
|
||||
return std::popcount(a.second) > std::popcount(b.second);
|
||||
});
|
||||
// Exceptions to the above rule of thumb.
|
||||
std::stable_partition(list.begin(), list.end(), [&](const auto& e) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue