Browse Source

boost::stable_Vector evil

lizzie/attempt2-better-list-dynarmic
lizzie 4 days ago
parent
commit
5abe0ff4df
  1. 26
      src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_data_processing.cpp
  2. 21
      src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_packed.cpp
  3. 10
      src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_saturation.cpp
  4. 11
      src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64_data_processing.cpp
  5. 24
      src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp
  6. 20
      src/dynarmic/src/dynarmic/backend/x64/emit_x64_packed.cpp
  7. 6
      src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp
  8. 16
      src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp
  9. 2
      src/dynarmic/src/dynarmic/ir/basic_block.h
  10. 4
      src/dynarmic/src/dynarmic/ir/microinstruction.cpp
  11. 7
      src/dynarmic/src/dynarmic/ir/microinstruction.h
  12. 28
      src/dynarmic/src/dynarmic/ir/opt_passes.cpp

26
src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_data_processing.cpp

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project.
@ -133,7 +133,7 @@ void EmitIR<IR::Opcode::LeastSignificantByte>(oaknut::CodeGenerator& code, EmitC
template<>
void EmitIR<IR::Opcode::MostSignificantWord>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -242,7 +242,7 @@ void EmitIR<IR::Opcode::ConditionalSelectNZCV>(oaknut::CodeGenerator& code, Emit
template<>
void EmitIR<IR::Opcode::LogicalShiftLeft32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0];
@ -379,7 +379,7 @@ void EmitIR<IR::Opcode::LogicalShiftLeft64>(oaknut::CodeGenerator& code, EmitCon
template<>
void EmitIR<IR::Opcode::LogicalShiftRight32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0];
@ -517,7 +517,7 @@ void EmitIR<IR::Opcode::LogicalShiftRight64>(oaknut::CodeGenerator& code, EmitCo
template<>
void EmitIR<IR::Opcode::ArithmeticShiftRight32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0];
@ -643,7 +643,7 @@ void EmitIR<IR::Opcode::ArithmeticShiftRight64>(oaknut::CodeGenerator& code, Emi
template<>
void EmitIR<IR::Opcode::RotateRight32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0];
@ -730,7 +730,7 @@ void EmitIR<IR::Opcode::RotateRight64>(oaknut::CodeGenerator& code, EmitContext&
template<>
void EmitIR<IR::Opcode::RotateRightExtended>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Wresult = ctx.reg_alloc.WriteW(inst);
@ -884,8 +884,8 @@ static void MaybeAddSubImm(oaknut::CodeGenerator& code, u64 imm, EmitFn emit_fn)
template<size_t bitsize, bool sub>
static void EmitAddSub(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetNZCVFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetNZCVFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetOverflowFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -1133,8 +1133,8 @@ static void EmitBitOp(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* i
auto Ra = ctx.reg_alloc.ReadReg<bitsize>(args[0]);
if constexpr (!std::is_same_v<EmitFn2, std::nullptr_t>) {
const auto nz_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetNZFromOp);
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetNZCVFromOp);
const auto nz_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetNZFromOp);
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetNZCVFromOp);
ASSERT(!(nz_inst && nzcv_inst));
const auto flag_inst = nz_inst ? nz_inst : nzcv_inst;
@ -1170,8 +1170,8 @@ static void EmitBitOp(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* i
template<size_t bitsize>
static void EmitAndNot(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto nz_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetNZFromOp);
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetNZCVFromOp);
const auto nz_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetNZFromOp);
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetNZCVFromOp);
ASSERT(!(nz_inst && nzcv_inst));
const auto flag_inst = nz_inst ? nz_inst : nzcv_inst;

21
src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_packed.cpp

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project.
* Copyright (c) 2022 MerryMage
* SPDX-License-Identifier: 0BSD
@ -46,7 +49,7 @@ static void EmitSaturatedPackedOp(oaknut::CodeGenerator&, EmitContext& ctx, IR::
template<>
void EmitIR<IR::Opcode::PackedAddU8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Vresult = ctx.reg_alloc.WriteD(inst);
@ -66,7 +69,7 @@ void EmitIR<IR::Opcode::PackedAddU8>(oaknut::CodeGenerator& code, EmitContext& c
template<>
void EmitIR<IR::Opcode::PackedAddS8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Vresult = ctx.reg_alloc.WriteD(inst);
@ -87,7 +90,7 @@ void EmitIR<IR::Opcode::PackedAddS8>(oaknut::CodeGenerator& code, EmitContext& c
template<>
void EmitIR<IR::Opcode::PackedSubU8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Vresult = ctx.reg_alloc.WriteD(inst);
@ -108,7 +111,7 @@ void EmitIR<IR::Opcode::PackedSubU8>(oaknut::CodeGenerator& code, EmitContext& c
template<>
void EmitIR<IR::Opcode::PackedSubS8>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Vresult = ctx.reg_alloc.WriteD(inst);
@ -129,7 +132,7 @@ void EmitIR<IR::Opcode::PackedSubS8>(oaknut::CodeGenerator& code, EmitContext& c
template<>
void EmitIR<IR::Opcode::PackedAddU16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Vresult = ctx.reg_alloc.WriteD(inst);
@ -149,7 +152,7 @@ void EmitIR<IR::Opcode::PackedAddU16>(oaknut::CodeGenerator& code, EmitContext&
template<>
void EmitIR<IR::Opcode::PackedAddS16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Vresult = ctx.reg_alloc.WriteD(inst);
@ -170,7 +173,7 @@ void EmitIR<IR::Opcode::PackedAddS16>(oaknut::CodeGenerator& code, EmitContext&
template<>
void EmitIR<IR::Opcode::PackedSubU16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Vresult = ctx.reg_alloc.WriteD(inst);
@ -191,7 +194,7 @@ void EmitIR<IR::Opcode::PackedSubU16>(oaknut::CodeGenerator& code, EmitContext&
template<>
void EmitIR<IR::Opcode::PackedSubS16>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Vresult = ctx.reg_alloc.WriteD(inst);
@ -212,7 +215,7 @@ void EmitIR<IR::Opcode::PackedSubS16>(oaknut::CodeGenerator& code, EmitContext&
template<bool add_is_hi, bool is_signed, bool is_halving>
static void EmitPackedAddSub(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Vresult = ctx.reg_alloc.WriteD(inst);

10
src/dynarmic/src/dynarmic/backend/arm64/emit_arm64_saturation.cpp

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project.
@ -23,7 +23,7 @@ using namespace oaknut::util;
template<>
void EmitIR<IR::Opcode::SignedSaturatedAddWithFlag32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetOverflowFromOp);
ASSERT(overflow_inst);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -43,7 +43,7 @@ void EmitIR<IR::Opcode::SignedSaturatedAddWithFlag32>(oaknut::CodeGenerator& cod
template<>
void EmitIR<IR::Opcode::SignedSaturatedSubWithFlag32>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetOverflowFromOp);
ASSERT(overflow_inst);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -63,7 +63,7 @@ void EmitIR<IR::Opcode::SignedSaturatedSubWithFlag32>(oaknut::CodeGenerator& cod
template<>
void EmitIR<IR::Opcode::SignedSaturation>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetOverflowFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const size_t N = args[1].GetImmediateU8();
@ -104,7 +104,7 @@ void EmitIR<IR::Opcode::SignedSaturation>(oaknut::CodeGenerator& code, EmitConte
template<>
void EmitIR<IR::Opcode::UnsignedSaturation>(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst) {
const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetOverflowFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto Wresult = ctx.reg_alloc.WriteW(inst);

11
src/dynarmic/src/dynarmic/backend/riscv64/emit_riscv64_data_processing.cpp

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project.
* Copyright (c) 2024 MerryMage
* SPDX-License-Identifier: 0BSD
@ -84,7 +87,7 @@ void EmitIR<IR::Opcode::ConditionalSelectNZCV>(biscuit::Assembler&, EmitContext&
template<>
void EmitIR<IR::Opcode::LogicalShiftLeft32>(biscuit::Assembler& as, EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0];
@ -126,7 +129,7 @@ void EmitIR<IR::Opcode::LogicalShiftLeft64>(biscuit::Assembler&, EmitContext&, I
template<>
void EmitIR<IR::Opcode::LogicalShiftRight32>(biscuit::Assembler& as, EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0];
@ -267,8 +270,8 @@ static void AddImmWithFlags(biscuit::Assembler& as, biscuit::GPR rd, biscuit::GP
template<size_t bitsize, bool sub>
static void EmitAddSub(biscuit::Assembler& as, EmitContext& ctx, IR::Inst* inst) {
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetNZCVFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetNZCVFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetOverflowFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);

24
src/dynarmic/src/dynarmic/backend/x64/emit_x64_data_processing.cpp

@ -63,7 +63,7 @@ void EmitX64::EmitLeastSignificantWord(EmitContext& ctx, IR::Inst* inst) {
}
void EmitX64::EmitMostSignificantWord(EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Reg64 result = ctx.reg_alloc.UseScratchGpr(code, args[0]);
@ -265,7 +265,7 @@ void EmitX64::EmitReplicateBit64(Dynarmic::Backend::X64::EmitContext& ctx, IR::I
}
void EmitX64::EmitLogicalShiftLeft32(EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0];
@ -401,7 +401,7 @@ void EmitX64::EmitLogicalShiftLeft64(EmitContext& ctx, IR::Inst* inst) {
}
void EmitX64::EmitLogicalShiftRight32(EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0];
@ -535,7 +535,7 @@ void EmitX64::EmitLogicalShiftRight64(EmitContext& ctx, IR::Inst* inst) {
}
void EmitX64::EmitArithmeticShiftRight32(EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0];
@ -664,7 +664,7 @@ void EmitX64::EmitArithmeticShiftRight64(EmitContext& ctx, IR::Inst* inst) {
}
void EmitX64::EmitRotateRight32(EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& operand_arg = args[0];
@ -768,7 +768,7 @@ void EmitX64::EmitRotateRight64(EmitContext& ctx, IR::Inst* inst) {
}
void EmitX64::EmitRotateRightExtended(EmitContext& ctx, IR::Inst* inst) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Reg32 result = ctx.reg_alloc.UseScratchGpr(code, args[0]).cvt32();
@ -919,9 +919,9 @@ static Xbyak::Reg64 DoNZCV(BlockOfCode& code, RegAlloc& reg_alloc, IR::Inst* nzc
}
static void EmitAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, size_t bitsize) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetNZCVFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetOverflowFromOp);
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetNZCVFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& carry_in = args[2];
@ -1006,9 +1006,9 @@ void EmitX64::EmitAdd64(EmitContext& ctx, IR::Inst* inst) {
}
static void EmitSub(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, int bitsize) {
const auto carry_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetCarryFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetNZCVFromOp);
const auto carry_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetCarryFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetOverflowFromOp);
const auto nzcv_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetNZCVFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
auto& carry_in = args[2];

20
src/dynarmic/src/dynarmic/backend/x64/emit_x64_packed.cpp

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project.
@ -17,7 +17,7 @@ using namespace Xbyak::util;
void EmitX64::EmitPackedAddU8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(code, args[0]);
const Xbyak::Xmm xmm_b = ctx.reg_alloc.UseXmm(code, args[1]);
@ -43,7 +43,7 @@ void EmitX64::EmitPackedAddU8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64::EmitPackedAddS8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(code, args[0]);
const Xbyak::Xmm xmm_b = ctx.reg_alloc.UseXmm(code, args[1]);
@ -67,7 +67,7 @@ void EmitX64::EmitPackedAddS8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(code, args[0]);
const Xbyak::Xmm xmm_b = ctx.reg_alloc.UseXmm(code, args[1]);
@ -107,7 +107,7 @@ void EmitX64::EmitPackedAddU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64::EmitPackedAddS16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(code, args[0]);
const Xbyak::Xmm xmm_b = ctx.reg_alloc.UseXmm(code, args[1]);
@ -131,7 +131,7 @@ void EmitX64::EmitPackedAddS16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64::EmitPackedSubU8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(code, args[0]);
const Xbyak::Xmm xmm_b = ctx.reg_alloc.UseXmm(code, args[1]);
@ -153,7 +153,7 @@ void EmitX64::EmitPackedSubU8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64::EmitPackedSubS8(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(code, args[0]);
const Xbyak::Xmm xmm_b = ctx.reg_alloc.UseXmm(code, args[1]);
@ -177,7 +177,7 @@ void EmitX64::EmitPackedSubS8(EmitContext& ctx, IR::Inst* inst) {
void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
if (!ge_inst) {
const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(code, args[0]);
@ -226,7 +226,7 @@ void EmitX64::EmitPackedSubU16(EmitContext& ctx, IR::Inst* inst) {
void EmitX64::EmitPackedSubS16(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(code, args[0]);
const Xbyak::Xmm xmm_b = ctx.reg_alloc.UseXmm(code, args[1]);
@ -493,7 +493,7 @@ void EmitX64::EmitPackedHalvingSubS16(EmitContext& ctx, IR::Inst* inst) {
static void EmitPackedSubAdd(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, bool hi_is_sum, bool is_signed, bool is_halving) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const auto ge_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetGEFromOp);
const auto ge_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetGEFromOp);
const Xbyak::Reg32 reg_a_hi = ctx.reg_alloc.UseScratchGpr(code, args[0]).cvt32();
const Xbyak::Reg32 reg_b_hi = ctx.reg_alloc.UseScratchGpr(code, args[1]).cvt32();

6
src/dynarmic/src/dynarmic/backend/x64/emit_x64_saturation.cpp

@ -65,7 +65,7 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst)
code.seto(overflow.cvt8());
if constexpr (has_overflow_inst) {
if (const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp)) {
if (const auto overflow_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetOverflowFromOp)) {
ctx.reg_alloc.DefineValue(code, overflow_inst, overflow);
}
} else {
@ -114,7 +114,7 @@ void EmitX64::EmitSignedSaturatedSubWithFlag32(EmitContext& ctx, IR::Inst* inst)
}
void EmitX64::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) {
const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetOverflowFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const size_t N = args[1].GetImmediateU8();
@ -163,7 +163,7 @@ void EmitX64::EmitSignedSaturation(EmitContext& ctx, IR::Inst* inst) {
}
void EmitX64::EmitUnsignedSaturation(EmitContext& ctx, IR::Inst* inst) {
const auto overflow_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetOverflowFromOp);
const auto overflow_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetOverflowFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const size_t N = args[1].GetImmediateU8();

16
src/dynarmic/src/dynarmic/backend/x64/emit_x64_vector.cpp

@ -3910,8 +3910,8 @@ void EmitX64::EmitVectorSignedAbsoluteDifference32(EmitContext& ctx, IR::Inst* i
}
void EmitX64::EmitVectorSignedMultiply16(EmitContext& ctx, IR::Inst* inst) {
const auto upper_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetUpperFromOp);
const auto lower_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetLowerFromOp);
const auto upper_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetUpperFromOp);
const auto lower_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetLowerFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm x = ctx.reg_alloc.UseXmm(code, args[0]);
@ -3942,8 +3942,8 @@ void EmitX64::EmitVectorSignedMultiply16(EmitContext& ctx, IR::Inst* inst) {
}
void EmitX64::EmitVectorSignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
const auto upper_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetUpperFromOp);
const auto lower_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetLowerFromOp);
const auto upper_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetUpperFromOp);
const auto lower_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetLowerFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
@ -5508,8 +5508,8 @@ void EmitX64::EmitVectorUnsignedAbsoluteDifference32(EmitContext& ctx, IR::Inst*
}
void EmitX64::EmitVectorUnsignedMultiply16(EmitContext& ctx, IR::Inst* inst) {
const auto upper_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetUpperFromOp);
const auto lower_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetLowerFromOp);
const auto upper_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetUpperFromOp);
const auto lower_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetLowerFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm x = ctx.reg_alloc.UseXmm(code, args[0]);
@ -5540,8 +5540,8 @@ void EmitX64::EmitVectorUnsignedMultiply16(EmitContext& ctx, IR::Inst* inst) {
}
void EmitX64::EmitVectorUnsignedMultiply32(EmitContext& ctx, IR::Inst* inst) {
const auto upper_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetUpperFromOp);
const auto lower_inst = inst->GetAssociatedPseudoOperation(IR::Opcode::GetLowerFromOp);
const auto upper_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetUpperFromOp);
const auto lower_inst = inst->GetAssociatedPseudoOperation(ctx.block, IR::Opcode::GetLowerFromOp);
auto args = ctx.reg_alloc.GetArgumentInfo(inst);

2
src/dynarmic/src/dynarmic/ir/basic_block.h

@ -35,7 +35,7 @@ enum class Opcode;
/// order memory accesses.
class Block final {
public:
using instruction_list_type = std::list<Inst>;
using instruction_list_type = boost::container::stable_vector<Inst>;
using iterator = instruction_list_type::iterator;
using const_iterator = instruction_list_type::const_iterator;
using reverse_iterator = instruction_list_type::reverse_iterator;

4
src/dynarmic/src/dynarmic/ir/microinstruction.cpp

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project.
@ -23,7 +23,7 @@ bool Inst::AreAllArgsImmediates() const {
});
}
Inst* Inst::GetAssociatedPseudoOperation(Opcode opcode) {
Inst* Inst::GetAssociatedPseudoOperation(Block& block, Opcode opcode) {
Inst* pseudoop = next_pseudoop;
while (pseudoop) {
if (pseudoop->GetOpcode() == opcode) {

7
src/dynarmic/src/dynarmic/ir/microinstruction.h

@ -18,6 +18,7 @@ namespace Dynarmic::IR {
enum class Opcode;
enum class Type : u16;
class Block;
constexpr size_t max_arg_count = 4;
@ -38,7 +39,7 @@ public:
return next_pseudoop && !IsAPseudoOperation(op);
}
/// Gets a pseudo-operation associated with this instruction.
Inst* GetAssociatedPseudoOperation(Opcode opcode);
Inst* GetAssociatedPseudoOperation(Block& block, Opcode opcode);
/// Get the microop this microinstruction represents.
Opcode GetOpcode() const { return op; }
@ -76,12 +77,12 @@ public:
// TODO: so much padding wasted with mcl::intrusive_node
// 16 + 1, 24
Opcode op; //2 (6)
std::array<Value, max_arg_count> args; //16 * 4 = 64 (1 cache line)
// Linked list of pseudooperations associated with this instruction.
Inst* next_pseudoop = nullptr; //8 (14)
unsigned use_count = 0; //4 (0)
unsigned name = 0; //4 (4)
alignas(64) std::array<Value, max_arg_count> args; //16 * 4 = 64 (1 cache line)
Opcode op; //2 (6)
};
//static_assert(sizeof(Inst) == 128);

28
src/dynarmic/src/dynarmic/ir/opt_passes.cpp

@ -868,8 +868,8 @@ static void FoldMostSignificantBit(IR::Inst& inst) {
inst.ReplaceUsesWith(IR::Value{(operand.GetImmediateAsU64() >> 31) != 0});
}
static void FoldMostSignificantWord(IR::Inst& inst) {
IR::Inst* carry_inst = inst.GetAssociatedPseudoOperation(Op::GetCarryFromOp);
static void FoldMostSignificantWord(IR::Block& block, IR::Inst& inst) {
IR::Inst* carry_inst = inst.GetAssociatedPseudoOperation(block, Op::GetCarryFromOp);
if (!inst.AreAllArgsImmediates()) {
return;
@ -928,8 +928,8 @@ static void FoldOR(IR::Inst& inst, bool is_32_bit) {
}
}
static bool FoldShifts(IR::Inst& inst) {
IR::Inst* carry_inst = inst.GetAssociatedPseudoOperation(Op::GetCarryFromOp);
static bool FoldShifts(IR::Block& block, IR::Inst& inst) {
IR::Inst* carry_inst = inst.GetAssociatedPseudoOperation(block, Op::GetCarryFromOp);
// The 32-bit variants can contain 3 arguments, while the
// 64-bit variants only contain 2.
@ -1013,14 +1013,14 @@ static void ConstantPropagation(IR::Block& block) {
// skip NZCV so we dont end up discarding side effects :)
// TODO(lizzie): hey stupid maybe fix the A64 codegen for folded constants AND
// redirect the mfer properly?!??! just saying :)
if (IR::MayGetNZCVFromOp(opcode) && inst.GetAssociatedPseudoOperation(IR::Opcode::GetNZCVFromOp))
if (IR::MayGetNZCVFromOp(opcode) && inst.GetAssociatedPseudoOperation(block, IR::Opcode::GetNZCVFromOp))
continue;
switch (opcode) {
case Op::LeastSignificantWord:
FoldLeastSignificantWord(inst);
break;
case Op::MostSignificantWord:
FoldMostSignificantWord(inst);
FoldMostSignificantWord(block, inst);
break;
case Op::LeastSignificantHalf:
FoldLeastSignificantHalf(inst);
@ -1042,42 +1042,42 @@ static void ConstantPropagation(IR::Block& block) {
}
break;
case Op::LogicalShiftLeft32:
if (FoldShifts(inst)) {
if (FoldShifts(block, inst)) {
ReplaceUsesWith(inst, true, Safe::LogicalShiftLeft<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU8()));
}
break;
case Op::LogicalShiftLeft64:
if (FoldShifts(inst)) {
if (FoldShifts(block, inst)) {
ReplaceUsesWith(inst, false, Safe::LogicalShiftLeft<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU8()));
}
break;
case Op::LogicalShiftRight32:
if (FoldShifts(inst)) {
if (FoldShifts(block, inst)) {
ReplaceUsesWith(inst, true, Safe::LogicalShiftRight<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU8()));
}
break;
case Op::LogicalShiftRight64:
if (FoldShifts(inst)) {
if (FoldShifts(block, inst)) {
ReplaceUsesWith(inst, false, Safe::LogicalShiftRight<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU8()));
}
break;
case Op::ArithmeticShiftRight32:
if (FoldShifts(inst)) {
if (FoldShifts(block, inst)) {
ReplaceUsesWith(inst, true, Safe::ArithmeticShiftRight<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU8()));
}
break;
case Op::ArithmeticShiftRight64:
if (FoldShifts(inst)) {
if (FoldShifts(block, inst)) {
ReplaceUsesWith(inst, false, Safe::ArithmeticShiftRight<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU8()));
}
break;
case Op::RotateRight32:
if (FoldShifts(inst)) {
if (FoldShifts(block, inst)) {
ReplaceUsesWith(inst, true, mcl::bit::rotate_right<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU8()));
}
break;
case Op::RotateRight64:
if (FoldShifts(inst)) {
if (FoldShifts(block, inst)) {
ReplaceUsesWith(inst, false, mcl::bit::rotate_right<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU8()));
}
break;

Loading…
Cancel
Save