diff --git a/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h b/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h index 2eae740f20..83ce16d753 100644 --- a/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h +++ b/src/dynarmic/src/dynarmic/backend/arm64/fastmem.h @@ -24,7 +24,7 @@ using DoNotFastmemMarker = std::tuple; 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; } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp index 827600c7c2..756a6f0a36 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_floating_point.cpp @@ -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(*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(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); } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp index 74e8c76275..e116382b93 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp @@ -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((std::numeric_limits>::max)()); + constexpr u64 int_max = u64((std::numeric_limits>>::max)()); if constexpr (size < 64) { code.xor_(overflow.cvt32(), overflow.cvt32()); code.bt(result.cvt32(), size - 1); diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp index b5ec6ec7cf..d2edea780c 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp @@ -3553,7 +3553,7 @@ void EmitX64::EmitVectorPopulationCount(EmitContext& ctx, IR::Inst* inst) { EmitOneArgumentFallback(code, ctx, inst, [](VectorArray& result, const VectorArray& a) { std::transform(a.begin(), a.end(), result.begin(), [](u8 val) { - return static_cast(mcl::bit::count_ones(val)); + return static_cast(std::popcount(val)); }); }); } diff --git a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp index 926653a920..68ffb2475b 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector_floating_point.cpp @@ -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(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(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); diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h index 82e919720e..dd88b79237 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/a32_translate_impl.h @@ -52,7 +52,7 @@ struct TranslatorVisitor final { u32 imm32 = imm8.ZeroExtend(); auto carry_out = carry_in; if (rotate) { - imm32 = mcl::bit::rotate_right(imm8.ZeroExtend(), rotate * 2); + imm32 = std::rotr(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((1 << 7) | imm12.Bits<0, 6>(), imm12.Bits<7, 11>()); + const u32 imm32 = std::rotr((1 << 7) | imm12.Bits<0, 6>(), imm12.Bits<7, 11>()); return {imm32, ir.Imm1(mcl::bit::get_bit<31>(imm32))}; } diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp index 6ccfe1e3bc..d255ad8b2c 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/asimd_misc.cpp @@ -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); diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp index d7c667aecf..208e7d1122 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/load_store.cpp @@ -799,7 +799,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s // LDM {!}, 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(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 {!}, 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(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 {!}, 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(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 {!}, 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(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 {!}, 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 {!}, 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 {!}, 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 {!}, 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); } diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp index a8c75e22b9..082cd30db2 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb16.cpp @@ -688,7 +688,7 @@ bool TranslatorVisitor::thumb16_NOP() { // IT{{{}}} 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(4 * mcl::bit::count_ones(reg_list)); + const u32 num_bytes_to_push = static_cast(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 !, 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(n), reg_list) && n != static_cast(mcl::bit::lowest_set_bit(reg_list))) { + if (mcl::bit::get_bit(static_cast(n), reg_list) && n != static_cast(std::countr_zero(reg_list))) { return UnpredictableInstruction(); } @@ -873,7 +873,7 @@ bool TranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) { // LDM !, 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(); } diff --git a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp index b68a2cb7c5..e829c6fb42 100644 --- a/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A32/translate/impl/thumb32_load_store_multiple.cpp @@ -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(mcl::bit::count_ones(regs_imm)); + const auto num_regs = static_cast(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(mcl::bit::count_ones(regs_imm)); + const auto num_regs = static_cast(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(mcl::bit::count_ones(regs_imm)); + const auto num_regs = static_cast(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(mcl::bit::count_ones(regs_imm)); + const auto num_regs = static_cast(std::popcount(regs_imm)); if (n == Reg::PC || num_regs < 2) { return UnpredictableInstruction(); diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp index f3ecd7c604..998fa4c13b 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/impl.cpp @@ -55,7 +55,7 @@ std::optional TranslatorVisitor::DecodeBitMasks(boo const size_t esize = size_t{1} << len; const u64 welem = mcl::bit::ones(S + 1); const u64 telem = mcl::bit::ones(d + 1); - const u64 wmask = mcl::bit::rotate_right(mcl::bit::replicate_element(esize, welem), R); + const u64 wmask = std::rotr(mcl::bit::replicate_element(esize, welem), R); const u64 tmask = mcl::bit::replicate_element(esize, telem); return BitMasks{wmask, tmask}; diff --git a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp index 9354b54fa5..0d6ec29417 100644 --- a/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp +++ b/src/dynarmic/src/dynarmic/frontend/A64/translate/impl/simd_copy.cpp @@ -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(); } diff --git a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp index 999d4c49bc..fb51ba4998 100644 --- a/src/dynarmic/src/dynarmic/ir/opt_passes.cpp +++ b/src/dynarmic/src/dynarmic/ir/opt_passes.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #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(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU8())); + ReplaceUsesWith(inst, true, std::rotr(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU8())); } break; case Op::BitRotateRight64: if (FoldShifts(inst)) { - ReplaceUsesWith(inst, false, mcl::bit::rotate_right(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU8())); + ReplaceUsesWith(inst, false, std::rotr(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(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU32())); + ReplaceUsesWith(inst, true, std::rotr(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU32())); } break; case Op::RotateRightMasked64: if (inst.AreAllArgsImmediates()) { - ReplaceUsesWith(inst, false, mcl::bit::rotate_right(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU64())); + ReplaceUsesWith(inst, false, std::rotr(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU64())); } break; case Op::Add32: diff --git a/src/dynarmic/src/dynarmic/mcl/bit.hpp b/src/dynarmic/src/dynarmic/mcl/bit.hpp index bbedffd8ae..ea4d6c057f 100644 --- a/src/dynarmic/src/dynarmic/mcl/bit.hpp +++ b/src/dynarmic/src/dynarmic/mcl/bit.hpp @@ -8,26 +8,15 @@ #include #include #include +#include +#include #include "common/common_types.h" #include "common/assert.h" namespace mcl { -namespace detail { -template -concept SameHelper = std::is_same_v; -} // namespace detail -template -concept SameAs = detail::SameHelper && detail::SameHelper; -template -concept IsAnyOf = (SameAs || ...); -/// Integral upon which bit operations can be safely performed. -template -concept BitIntegral = IsAnyOf; - template 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 -constexpr T rotate_right(T x, size_t amount) { - amount %= bitsizeof; - if (amount == 0) { - return x; - } - return static_cast((x >> amount) | (x << (bitsizeof - amount))); -} - -template -constexpr T rotate_left(T x, size_t amount) { - amount %= bitsizeof; - if (amount == 0) { - return x; - } - return static_cast((x << amount) | (x >> (bitsizeof - amount))); -} - /// Create a mask with `count` number of one bits. -template +template constexpr T ones() { static_assert(count <= bitsizeof, "count larger than bitsize of T"); - if constexpr (count == 0) { return 0; } else { - return static_cast(~static_cast(0)) >> (bitsizeof - count); + return T(~T(0)) >> (bitsizeof - count); } } /// Create a mask with `count` number of one bits. -template +template constexpr T ones(size_t count) { ASSERT(count <= bitsizeof && "count larger than bitsize of T"); - if (count == 0) { + if (count == 0) return 0; - } - return static_cast(~static_cast(0)) >> (bitsizeof - count); + return T(~T(0)) >> (bitsizeof - count); } /// Create a mask of type T for bits [begin_bit, end_bit] inclusive. -template +template 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, "begin_bit must be smaller than size of T"); static_assert(end_bit < bitsizeof, "end_bit must be smaller than size of T"); - return ones() << begin_bit; } /// Create a mask of type T for bits [begin_bit, end_bit] inclusive. -template +template 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 && "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 +template constexpr T get_bits(T value) { constexpr T m = mask(); return (value & m) >> begin_bit; } /// Extract bits [begin_bit, end_bit] inclusive from value of type T. -template +template constexpr T get_bits(size_t begin_bit, size_t end_bit, T value) { const T m = mask(begin_bit, end_bit); return (value & m) >> begin_bit; } /// Clears bits [begin_bit, end_bit] inclusive of value of type T. -template +template constexpr T clear_bits(T value) { constexpr T m = mask(); return value & ~m; } /// Clears bits [begin_bit, end_bit] inclusive of value of type T. -template +template constexpr T clear_bits(size_t begin_bit, size_t end_bit, T value) { const T m = mask(begin_bit, end_bit); return value & ~m; } /// Modifies bits [begin_bit, end_bit] inclusive of value of type T. -template +template constexpr T set_bits(T value, T new_bits) { constexpr T m = mask(); return (value & ~m) | ((new_bits << begin_bit) & m); } /// Modifies bits [begin_bit, end_bit] inclusive of value of type T. -template +template constexpr T set_bits(size_t begin_bit, size_t end_bit, T value, T new_bits) { const T m = mask(begin_bit, end_bit); return (value & ~m) | ((new_bits << begin_bit) & m); } /// Extract bit at bit_position from value of type T. -template +template constexpr bool get_bit(T value) { constexpr T m = mask(); return (value & m) != 0; } /// Extract bit at bit_position from value of type T. -template +template constexpr bool get_bit(size_t bit_position, T value) { const T m = mask(bit_position, bit_position); return (value & m) != 0; } /// Clears bit at bit_position of value of type T. -template +template constexpr T clear_bit(T value) { constexpr T m = mask(); return value & ~m; } /// Clears bit at bit_position of value of type T. -template +template constexpr T clear_bit(size_t bit_position, T value) { const T m = mask(bit_position, bit_position); return value & ~m; } /// Modifies bit at bit_position of value of type T. -template +template constexpr T set_bit(T value, bool new_bit) { constexpr T m = mask(); - return (value & ~m) | (new_bit ? m : static_cast(0)); + return (value & ~m) | (new_bit ? m : T(0)); } /// Modifies bit at bit_position of value of type T. -template +template constexpr T set_bit(size_t bit_position, T value, bool new_bit) { const T m = mask(bit_position, bit_position); - return (value & ~m) | (new_bit ? m : static_cast(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 +template constexpr T sign_extend(T value) { static_assert(bit_count != 0, "cannot sign-extend zero-sized value"); - using S = std::make_signed_t; constexpr size_t shift_amount = bitsizeof - bit_count; - return static_cast(static_cast(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 +template 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; @@ -234,78 +201,42 @@ constexpr T sign_extend(size_t bit_count, T value) { } /// Replicate an element across a value of type T. -template +template constexpr T replicate_element(T value) { static_assert(element_size <= bitsizeof, "element_size is too large"); static_assert(bitsizeof % element_size == 0, "bitsize of T not divisible by element_size"); - if constexpr (element_size == bitsizeof) { return value; } else { - return replicate_element(static_cast(value | (value << element_size))); + return replicate_element(T(value | (value << element_size))); } } /// Replicate an element of type U across a value of type T. -template +template constexpr T replicate_element(T value) { static_assert(bitsizeof <= bitsizeof, "element_size is too large"); - return replicate_element, T>(value); } /// Replicate an element across a value of type T. -template +template constexpr T replicate_element(size_t element_size, T value) { ASSERT(element_size <= bitsizeof && "element_size is too large"); ASSERT(bitsizeof % element_size == 0 && "bitsize of T not divisible by element_size"); if (element_size == bitsizeof) return value; - return replicate_element(element_size * 2, static_cast(value | (value << element_size))); + return replicate_element(element_size * 2, T(value | (value << element_size))); } -template +template constexpr bool most_significant_bit(T value) { return get_bit - 1, T>(value); } -template -inline size_t count_ones(T x) { - return std::bitset>(x).count(); -} - -template -constexpr size_t count_leading_zeros(T x) { - size_t result = bitsizeof; - while (x != 0) { - x >>= 1; - result--; - } - return result; -} - -template +template constexpr int highest_set_bit(T x) { - int result = -1; - while (x != 0) { - x >>= 1; - result++; - } - return result; -} - -template -constexpr size_t lowest_set_bit(T x) { - if (x == 0) { - return bitsizeof; - } - - size_t result = 0; - while ((x & 1) == 0) { - x >>= 1; - result++; - } - return result; + return std::bit_width(x) - 1; } } // namespace mcl::bit diff --git a/src/dynarmic/src/dynarmic/mcl/integer_of_size.hpp b/src/dynarmic/src/dynarmic/mcl/integer_of_size.hpp index 1d54e9e3ef..6f05ea8eac 100644 --- a/src/dynarmic/src/dynarmic/mcl/integer_of_size.hpp +++ b/src/dynarmic/src/dynarmic/mcl/integer_of_size.hpp @@ -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; }; template<> struct integer_of_size_impl<16> { using unsigned_type = u16; - using signed_type = s16; + using signed_type = std::make_signed_t; }; template<> struct integer_of_size_impl<32> { using unsigned_type = u32; - using signed_type = s32; + using signed_type = std::make_signed_t; }; template<> struct integer_of_size_impl<64> { using unsigned_type = u64; - using signed_type = s64; + using signed_type = std::make_signed_t; }; } // namespace detail diff --git a/src/dynarmic/src/dynarmic/mcl/is_instance_of_template.hpp b/src/dynarmic/src/dynarmic/mcl/is_instance_of_template.hpp index 0cb143430d..272b15add3 100644 --- a/src/dynarmic/src/dynarmic/mcl/is_instance_of_template.hpp +++ b/src/dynarmic/src/dynarmic/mcl/is_instance_of_template.hpp @@ -10,23 +10,12 @@ namespace mcl { -/// A metavalue (of type VT and value v). -template using value = std::integral_constant; -/// A metavalue of type size_t (and value v). -template using size_value = value; -/// A metavalue of type bool (and value v). (Aliases to std::bool_constant.) -template using bool_value = value; -/// true metavalue (Aliases to std::true_type). -using true_type = bool_value; -/// false metavalue (Aliases to std::false_type). -using false_type = bool_value; - /// Is type T an instance of template class C? template class, class> -struct is_instance_of_template : false_type {}; +struct is_instance_of_template : std::false_type {}; template class C, class... As> -struct is_instance_of_template> : true_type {}; +struct is_instance_of_template> : std::true_type {}; /// Is type T an instance of template class C? template class C, class T> diff --git a/src/dynarmic/tests/A32/fuzz_arm.cpp b/src/dynarmic/tests/A32/fuzz_arm.cpp index e2546de635..922f1e4f26 100644 --- a/src/dynarmic/tests/A32/fuzz_arm.cpp +++ b/src/dynarmic/tests/A32/fuzz_arm.cpp @@ -665,7 +665,7 @@ TEST_CASE("A32: Test thumb IT instruction", "[thumb]") { A32::ITState it_state = [&] { while (true) { const u16 imm8 = RandInt(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); diff --git a/tools/gendynarm.cpp b/tools/gendynarm.cpp index 3d1588e7e8..3e28363a10 100644 --- a/tools/gendynarm.cpp +++ b/tools/gendynarm.cpp @@ -17,12 +17,6 @@ namespace mcl { template constexpr std::size_t bitsizeof = CHAR_BIT * sizeof(T); } -namespace mcl::bit { -template -inline size_t count_ones(T x) { - return std::bitset>(x).count(); -} -} template inline consteval std::array StringToArray(const char (&str)[N + 1]) { std::array 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) {