From 9cf25e276dd1688af4fa037616082f3f71f5b942 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Thu, 18 Sep 2025 15:46:11 -0700 Subject: [PATCH] CodeEmitter: Return bool if Label instructions can't be encoded Programming error if they aren't checked, as they will encode incorrectly if they are too large for their respective instructions. --- CodeEmitter/CodeEmitter/ALUOps.inl | 76 +++++++---- CodeEmitter/CodeEmitter/BranchOps.inl | 186 +++++++++++++++++--------- CodeEmitter/CodeEmitter/Emitter.h | 72 +++++++--- 3 files changed, 227 insertions(+), 107 deletions(-) diff --git a/CodeEmitter/CodeEmitter/ALUOps.inl b/CodeEmitter/CodeEmitter/ALUOps.inl index 91dea40a3..11e031c00 100644 --- a/CodeEmitter/CodeEmitter/ALUOps.inl +++ b/CodeEmitter/CodeEmitter/ALUOps.inl @@ -36,24 +36,33 @@ public: DataProcessing_PCRel_Imm(Op, rd, Imm); } - void adr(ARMEmitter::Register rd, const BackwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded adr(ARMEmitter::Register rd, const BackwardLabel* Label) { int32_t Imm = static_cast(Label->Location - GetCursorAddress()); LOGMAN_THROW_A_FMT(IsADRRange(Imm), "Unscaled offset too large"); - constexpr uint32_t Op = 0b0001'0000 << 24; - DataProcessing_PCRel_Imm(Op, rd, Imm); + if (IsADRRange(Imm)) [[likely]] { + constexpr uint32_t Op = 0b0001'0000 << 24; + DataProcessing_PCRel_Imm(Op, rd, Imm); + return true; + } + + // Can't encode. + return false; } - void adr(ARMEmitter::Register rd, ForwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded adr(ARMEmitter::Register rd, ForwardLabel* Label) { AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress(), .Type = ForwardLabel::InstType::ADR}); constexpr uint32_t Op = 0b0001'0000 << 24; DataProcessing_PCRel_Imm(Op, rd, 0); + + // Forward label doesn't know if it can encode until Bind. + return true; } - void adr(ARMEmitter::Register rd, BiDirectionalLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded adr(ARMEmitter::Register rd, BiDirectionalLabel* Label) { if (Label->Backward.Location) { - adr(rd, &Label->Backward); + return adr(rd, &Label->Backward); } else { - adr(rd, &Label->Forward); + return adr(rd, &Label->Forward); } } @@ -62,32 +71,42 @@ public: DataProcessing_PCRel_Imm(Op, rd, Imm); } - void adrp(ARMEmitter::Register rd, const BackwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded adrp(ARMEmitter::Register rd, const BackwardLabel* Label) { int64_t Imm = reinterpret_cast(Label->Location) - (GetCursorAddress() & ~0xFFFLL); LOGMAN_THROW_A_FMT(IsADRPRange(Imm) && IsADRPAligned(Imm), "Unscaled offset too large"); - constexpr uint32_t Op = 0b1001'0000 << 24; - DataProcessing_PCRel_Imm(Op, rd, Imm); + if (IsADRPRange(Imm) && IsADRPAligned(Imm)) [[likely]] { + constexpr uint32_t Op = 0b1001'0000 << 24; + DataProcessing_PCRel_Imm(Op, rd, Imm); + return true; + } + + // Can't encode. + return false; } - void adrp(ARMEmitter::Register rd, ForwardLabel* Label) { + + [[nodiscard]] BranchEncodeSucceeded adrp(ARMEmitter::Register rd, ForwardLabel* Label) { AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress(), .Type = ForwardLabel::InstType::ADRP}); constexpr uint32_t Op = 0b1001'0000 << 24; DataProcessing_PCRel_Imm(Op, rd, 0); + + // Forward label doesn't know if it can encode until Bind. + return true; } - void adrp(ARMEmitter::Register rd, BiDirectionalLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded adrp(ARMEmitter::Register rd, BiDirectionalLabel* Label) { if (Label->Backward.Location) { - adrp(rd, &Label->Backward); + return adrp(rd, &Label->Backward); } else { - adrp(rd, &Label->Forward); + return adrp(rd, &Label->Forward); } } - void LongAddressGen(ARMEmitter::Register rd, const BackwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded LongAddressGen(ARMEmitter::Register rd, const BackwardLabel* Label) { int64_t Imm = reinterpret_cast(Label->Location) - (GetCursorAddress()); if (IsADRRange(Imm)) { // If the range is in ADR range then we can just use ADR. - adr(rd, Label); + return adr(rd, Label); } else if (IsADRPRange(Imm)) { int64_t ADRPImm = (reinterpret_cast(Label->Location) & ~0xFFFLL) - (GetCursorAddress() & ~0xFFFLL); @@ -102,23 +121,28 @@ public: // Now even an add add(ARMEmitter::Size::i64Bit, rd, rd, AlignedOffset); } - } else { - LOGMAN_MSG_A_FMT("Unscaled offset too large"); - FEX_UNREACHABLE; + + return true; } + + // Can't encode. + return false; } - void LongAddressGen(ARMEmitter::Register rd, ForwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded LongAddressGen(ARMEmitter::Register rd, ForwardLabel* Label) { AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress(), .Type = ForwardLabel::InstType::LONG_ADDRESS_GEN}); // Emit a register index and a nop. These will be backpatched. dc32(rd.Idx()); nop(); + + // Forward label doesn't know if it can encode until Bind. + return true; } - void LongAddressGen(ARMEmitter::Register rd, BiDirectionalLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded LongAddressGen(ARMEmitter::Register rd, BiDirectionalLabel* Label) { if (Label->Backward.Location) { - LongAddressGen(rd, &Label->Backward); + return LongAddressGen(rd, &Label->Backward); } else { - LongAddressGen(rd, &Label->Forward); + return LongAddressGen(rd, &Label->Forward); } } @@ -862,12 +886,6 @@ public: } private: - static constexpr Condition InvertCondition(Condition cond) { - // These behave as always, so it makes no sense to allow inverting these. - LOGMAN_THROW_A_FMT(cond != Condition::CC_AL && cond != Condition::CC_NV, "Cannot invert CC_AL or CC_NV"); - return static_cast(FEXCore::ToUnderlying(cond) ^ 1); - } - void and_(ARMEmitter::Size s, ARMEmitter::Register rd, ARMEmitter::Register rn, uint32_t n, uint32_t immr, uint32_t imms) { constexpr uint32_t Op = 0b001'0010'00 << 22; DataProcessing_Logical_Imm(Op, s, rd, rn, n, immr, imms); diff --git a/CodeEmitter/CodeEmitter/BranchOps.inl b/CodeEmitter/CodeEmitter/BranchOps.inl index 850501f55..617ece007 100644 --- a/CodeEmitter/CodeEmitter/BranchOps.inl +++ b/CodeEmitter/CodeEmitter/BranchOps.inl @@ -20,23 +20,31 @@ public: constexpr uint32_t Op = 0b0101'010 << 25; Branch_Conditional(Op, 0, 0, Cond, Imm); } - void b(ARMEmitter::Condition Cond, const BackwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded b(ARMEmitter::Condition Cond, const BackwardLabel* Label) { int32_t Imm = static_cast(Label->Location - GetCursorAddress()); - LOGMAN_THROW_A_FMT(Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0), "Unscaled offset too large"); - constexpr uint32_t Op = 0b0101'010 << 25; - Branch_Conditional(Op, 0, 0, Cond, Imm >> 2); + if (Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0)) [[likely]] { + constexpr uint32_t Op = 0b0101'010 << 25; + Branch_Conditional(Op, 0, 0, Cond, Imm >> 2); + return true; + } + + // Can't encode. + return false; } - void b(ARMEmitter::Condition Cond, ForwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded b(ARMEmitter::Condition Cond, ForwardLabel* Label) { AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress(), .Type = ForwardLabel::InstType::BC}); constexpr uint32_t Op = 0b0101'010 << 25; Branch_Conditional(Op, 0, 0, Cond, 0); + + // Forward label doesn't know if it can encode until Bind. + return true; } - void b(ARMEmitter::Condition Cond, BiDirectionalLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded b(ARMEmitter::Condition Cond, BiDirectionalLabel* Label) { if (Label->Backward.Location) { - b(Cond, &Label->Backward); + return b(Cond, &Label->Backward); } else { - b(Cond, &Label->Forward); + return b(Cond, &Label->Forward); } } @@ -45,24 +53,32 @@ public: constexpr uint32_t Op = 0b0101'010 << 25; Branch_Conditional(Op, 0, 1, Cond, Imm); } - void bc(ARMEmitter::Condition Cond, const BackwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded bc(ARMEmitter::Condition Cond, const BackwardLabel* Label) { int32_t Imm = static_cast(Label->Location - GetCursorAddress()); - LOGMAN_THROW_A_FMT(Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0), "Unscaled offset too large"); - constexpr uint32_t Op = 0b0101'010 << 25; - Branch_Conditional(Op, 0, 1, Cond, Imm >> 2); + if (Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0)) [[likely]] { + constexpr uint32_t Op = 0b0101'010 << 25; + Branch_Conditional(Op, 0, 1, Cond, Imm >> 2); + return true; + } + + // Can't encode. + return false; } - void bc(ARMEmitter::Condition Cond, ForwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded bc(ARMEmitter::Condition Cond, ForwardLabel* Label) { AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress(), .Type = ForwardLabel::InstType::BC}); constexpr uint32_t Op = 0b0101'010 << 25; Branch_Conditional(Op, 0, 1, Cond, 0); + + // Forward label doesn't know if it can encode until Bind. + return true; } - void bc(ARMEmitter::Condition Cond, BiDirectionalLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded bc(ARMEmitter::Condition Cond, BiDirectionalLabel* Label) { if (Label->Backward.Location) { - bc(Cond, &Label->Backward); + return bc(Cond, &Label->Backward); } else { - bc(Cond, &Label->Forward); + return bc(Cond, &Label->Forward); } } @@ -98,25 +114,32 @@ public: UnconditionalBranch(Op, Imm); } - void b(const BackwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded b(const BackwardLabel* Label) { int32_t Imm = static_cast(Label->Location - GetCursorAddress()); - LOGMAN_THROW_A_FMT(Imm >= -134217728 && Imm <= 134217724 && ((Imm & 0b11) == 0), "Unscaled offset too large"); - constexpr uint32_t Op = 0b0001'01 << 26; + if (Imm >= -134217728 && Imm <= 134217724 && ((Imm & 0b11) == 0)) [[likely]] { + constexpr uint32_t Op = 0b0001'01 << 26; + UnconditionalBranch(Op, Imm >> 2); + return true; + } - UnconditionalBranch(Op, Imm >> 2); + // Can't encode. + return false; } - void b(ForwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded b(ForwardLabel* Label) { AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress(), .Type = ForwardLabel::InstType::B}); constexpr uint32_t Op = 0b0001'01 << 26; UnconditionalBranch(Op, 0); + + // Forward label doesn't know if it can encode until Bind. + return true; } - void b(BiDirectionalLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded b(BiDirectionalLabel* Label) { if (Label->Backward.Location) { - b(&Label->Backward); + return b(&Label->Backward); } else { - b(&Label->Forward); + return b(&Label->Forward); } } @@ -126,25 +149,33 @@ public: UnconditionalBranch(Op, Imm); } - void bl(const BackwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded bl(const BackwardLabel* Label) { int32_t Imm = static_cast(Label->Location - GetCursorAddress()); - LOGMAN_THROW_A_FMT(Imm >= -134217728 && Imm <= 134217724 && ((Imm & 0b11) == 0), "Unscaled offset too large"); - constexpr uint32_t Op = 0b1001'01 << 26; + if (Imm >= -134217728 && Imm <= 134217724 && ((Imm & 0b11) == 0)) [[likely]] { + constexpr uint32_t Op = 0b1001'01 << 26; + UnconditionalBranch(Op, Imm >> 2); - UnconditionalBranch(Op, Imm >> 2); + return true; + } + + // Can't encode. + return false; } - void bl(ForwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded bl(ForwardLabel* Label) { AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress(), .Type = ForwardLabel::InstType::B}); constexpr uint32_t Op = 0b1001'01 << 26; UnconditionalBranch(Op, 0); + + // Forward label doesn't know if it can encode until Bind. + return true; } - void bl(BiDirectionalLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded bl(BiDirectionalLabel* Label) { if (Label->Backward.Location) { - bl(&Label->Backward); + return bl(&Label->Backward); } else { - bl(&Label->Forward); + return bl(&Label->Forward); } } @@ -155,28 +186,35 @@ public: CompareAndBranch(Op, s, rt, Imm); } - void cbz(ARMEmitter::Size s, ARMEmitter::Register rt, const BackwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded cbz(ARMEmitter::Size s, ARMEmitter::Register rt, const BackwardLabel* Label) { int32_t Imm = static_cast(Label->Location - GetCursorAddress()); - LOGMAN_THROW_A_FMT(Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0), "Unscaled offset too large"); - constexpr uint32_t Op = 0b0011'0100 << 24; + if (Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0)) [[likely]] { + constexpr uint32_t Op = 0b0011'0100 << 24; + CompareAndBranch(Op, s, rt, Imm >> 2); + return true; + } - CompareAndBranch(Op, s, rt, Imm >> 2); + // Can't encode. + return false; } - void cbz(ARMEmitter::Size s, ARMEmitter::Register rt, ForwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded cbz(ARMEmitter::Size s, ARMEmitter::Register rt, ForwardLabel* Label) { AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress(), .Type = ForwardLabel::InstType::BC}); constexpr uint32_t Op = 0b0011'0100 << 24; CompareAndBranch(Op, s, rt, 0); + + // Forward label doesn't know if it can encode until Bind. + return true; } - void cbz(ARMEmitter::Size s, ARMEmitter::Register rt, BiDirectionalLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded cbz(ARMEmitter::Size s, ARMEmitter::Register rt, BiDirectionalLabel* Label) { if (Label->Backward.Location) { - cbz(s, rt, &Label->Backward); + return cbz(s, rt, &Label->Backward); } else { - cbz(s, rt, &Label->Forward); + return cbz(s, rt, &Label->Forward); } } @@ -186,28 +224,35 @@ public: CompareAndBranch(Op, s, rt, Imm); } - void cbnz(ARMEmitter::Size s, ARMEmitter::Register rt, const BackwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded cbnz(ARMEmitter::Size s, ARMEmitter::Register rt, const BackwardLabel* Label) { int32_t Imm = static_cast(Label->Location - GetCursorAddress()); - LOGMAN_THROW_A_FMT(Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0), "Unscaled offset too large"); - constexpr uint32_t Op = 0b0011'0101 << 24; + if (Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0)) [[likely]] { + constexpr uint32_t Op = 0b0011'0101 << 24; + CompareAndBranch(Op, s, rt, Imm >> 2); + return true; + } - CompareAndBranch(Op, s, rt, Imm >> 2); + // Can't encode. + return false; } - void cbnz(ARMEmitter::Size s, ARMEmitter::Register rt, ForwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded cbnz(ARMEmitter::Size s, ARMEmitter::Register rt, ForwardLabel* Label) { AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress(), .Type = ForwardLabel::InstType::BC}); constexpr uint32_t Op = 0b0011'0101 << 24; CompareAndBranch(Op, s, rt, 0); + + // Forward label doesn't know if it can encode until Bind. + return true; } - void cbnz(ARMEmitter::Size s, ARMEmitter::Register rt, BiDirectionalLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded cbnz(ARMEmitter::Size s, ARMEmitter::Register rt, BiDirectionalLabel* Label) { if (Label->Backward.Location) { - cbnz(s, rt, &Label->Backward); + return cbnz(s, rt, &Label->Backward); } else { - cbnz(s, rt, &Label->Forward); + return cbnz(s, rt, &Label->Forward); } } @@ -217,28 +262,35 @@ public: TestAndBranch(Op, rt, Bit, Imm); } - void tbz(ARMEmitter::Register rt, uint32_t Bit, const BackwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded tbz(ARMEmitter::Register rt, uint32_t Bit, const BackwardLabel* Label) { int32_t Imm = static_cast(Label->Location - GetCursorAddress()); - LOGMAN_THROW_A_FMT(Imm >= -32768 && Imm <= 32764 && ((Imm & 0b11) == 0), "Unscaled offset too large"); - constexpr uint32_t Op = 0b0011'0110 << 24; + if (Imm >= -32768 && Imm <= 32764 && ((Imm & 0b11) == 0)) [[likely]] { + constexpr uint32_t Op = 0b0011'0110 << 24; + TestAndBranch(Op, rt, Bit, Imm >> 2); + return true; + } - TestAndBranch(Op, rt, Bit, Imm >> 2); + // Can't encode. + return false; } - void tbz(ARMEmitter::Register rt, uint32_t Bit, ForwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded tbz(ARMEmitter::Register rt, uint32_t Bit, ForwardLabel* Label) { AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress(), .Type = ForwardLabel::InstType::TEST_BRANCH}); constexpr uint32_t Op = 0b0011'0110 << 24; TestAndBranch(Op, rt, Bit, 0); + + // Forward label doesn't know if it can encode until Bind. + return true; } - void tbz(ARMEmitter::Register rt, uint32_t Bit, BiDirectionalLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded tbz(ARMEmitter::Register rt, uint32_t Bit, BiDirectionalLabel* Label) { if (Label->Backward.Location) { - tbz(rt, Bit, &Label->Backward); + return tbz(rt, Bit, &Label->Backward); } else { - tbz(rt, Bit, &Label->Forward); + return tbz(rt, Bit, &Label->Forward); } } @@ -247,27 +299,35 @@ public: TestAndBranch(Op, rt, Bit, Imm); } - void tbnz(ARMEmitter::Register rt, uint32_t Bit, const BackwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded tbnz(ARMEmitter::Register rt, uint32_t Bit, const BackwardLabel* Label) { int32_t Imm = static_cast(Label->Location - GetCursorAddress()); LOGMAN_THROW_A_FMT(Imm >= -32768 && Imm <= 32764 && ((Imm & 0b11) == 0), "Unscaled offset too large"); - constexpr uint32_t Op = 0b0011'0111 << 24; + if (Imm >= -32768 && Imm <= 32764 && ((Imm & 0b11) == 0)) [[likely]] { + constexpr uint32_t Op = 0b0011'0111 << 24; + TestAndBranch(Op, rt, Bit, Imm >> 2); + return true; + } - TestAndBranch(Op, rt, Bit, Imm >> 2); + // Can't encode. + return false; } - void tbnz(ARMEmitter::Register rt, uint32_t Bit, ForwardLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded tbnz(ARMEmitter::Register rt, uint32_t Bit, ForwardLabel* Label) { AddLocationToLabel(Label, ForwardLabel::Reference {.Location = GetCursorAddress(), .Type = ForwardLabel::InstType::TEST_BRANCH}); constexpr uint32_t Op = 0b0011'0111 << 24; TestAndBranch(Op, rt, Bit, 0); + + // Forward label doesn't know if it can encode until Bind. + return true; } - void tbnz(ARMEmitter::Register rt, uint32_t Bit, BiDirectionalLabel* Label) { + [[nodiscard]] BranchEncodeSucceeded tbnz(ARMEmitter::Register rt, uint32_t Bit, BiDirectionalLabel* Label) { if (Label->Backward.Location) { - tbnz(rt, Bit, &Label->Backward); + return tbnz(rt, Bit, &Label->Backward); } else { - tbnz(rt, Bit, &Label->Forward); + return tbnz(rt, Bit, &Label->Forward); } } diff --git a/CodeEmitter/CodeEmitter/Emitter.h b/CodeEmitter/CodeEmitter/Emitter.h index 41dbf4db6..bfedaec03 100644 --- a/CodeEmitter/CodeEmitter/Emitter.h +++ b/CodeEmitter/CodeEmitter/Emitter.h @@ -586,6 +586,16 @@ concept IsXOrWRegister = std::is_same_v || std::is_same_v concept IsQOrDRegister = std::is_same_v || std::is_same_v; +struct BranchEncodeSucceeded final { + bool _________; + + explicit operator bool() const { + return _________; + } + BranchEncodeSucceeded(bool a) + : _________ {a} {} +}; + // Whether or not a given set of vector registers are sequential // in increasing order as far as the register file is concerned (modulo its size) // @@ -638,19 +648,25 @@ public: // Bind a backward label to an address. // Address that is bound is the current emitter location. - void Bind(BackwardLabel* Label) { + [[nodiscard]] bool Bind(BackwardLabel* Label) { LOGMAN_THROW_A_FMT(Label->Location == nullptr, "Trying to bind a label twice"); Label->Location = GetCursorAddress(); + + // Always binds because it is only storing a location. + return true; } - void Bind(const ForwardLabel::Reference* Label) { + [[nodiscard]] bool Bind(const ForwardLabel::Reference* Label) { uint8_t* CurrentAddress = GetCursorAddress(); // Patch up the instructions switch (Label->Type) { case ForwardLabel::InstType::ADR: { uint32_t* Instruction = reinterpret_cast(Label->Location); int64_t Imm = reinterpret_cast(CurrentAddress) - reinterpret_cast(Instruction); - LOGMAN_THROW_A_FMT(IsADRRange(Imm), "Unscaled offset too large"); + if (!IsADRRange(Imm)) [[unlikely]] { + // Can't bind. + return false; + } uint32_t InstMask = 0b11 << 29 | 0b1111'1111'1111'1111'111 << 5; uint32_t Offset = static_cast(Imm) & 0x3F'FFFF; uint32_t Inst = *Instruction & ~InstMask; @@ -662,7 +678,12 @@ public: case ForwardLabel::InstType::ADRP: { uint32_t* Instruction = reinterpret_cast(Label->Location); int64_t Imm = reinterpret_cast(CurrentAddress) - reinterpret_cast(Instruction); - LOGMAN_THROW_A_FMT(IsADRPRange(Imm) && IsADRPAligned(Imm), "Unscaled offset too large"); + + if (!(IsADRPRange(Imm) && IsADRPAligned(Imm))) [[unlikely]] { + // Can't bind. + return false; + } + Imm >>= 12; uint32_t InstMask = 0b11 << 29 | 0b1111'1111'1111'1111'111 << 5; uint32_t Offset = static_cast(Imm) & 0x3F'FFFF; @@ -672,11 +693,13 @@ public: *Instruction = Inst; break; } - case ForwardLabel::InstType::B: { uint32_t* Instruction = reinterpret_cast(Label->Location); int64_t Imm = reinterpret_cast(CurrentAddress) - reinterpret_cast(Instruction); - LOGMAN_THROW_A_FMT(Imm >= -134217728 && Imm <= 134217724 && ((Imm & 0b11) == 0), "Unscaled offset too large"); + if (!(Imm >= -134217728 && Imm <= 134217724 && ((Imm & 0b11) == 0))) [[unlikely]] { + // Can't bind. + return false; + } Imm >>= 2; uint32_t InstMask = 0x3FF'FFFF; uint32_t Offset = static_cast(Imm) & InstMask; @@ -686,11 +709,13 @@ public: break; } - case ForwardLabel::InstType::TEST_BRANCH: { uint32_t* Instruction = reinterpret_cast(Label->Location); int64_t Imm = reinterpret_cast(CurrentAddress) - reinterpret_cast(Instruction); - LOGMAN_THROW_A_FMT(Imm >= -32768 && Imm <= 32764 && ((Imm & 0b11) == 0), "Unscaled offset too large"); + if (!(Imm >= -32768 && Imm <= 32764 && ((Imm & 0b11) == 0))) [[unlikely]] { + // Can't bind. + return false; + } Imm >>= 2; uint32_t InstMask = 0x3FFF; uint32_t Offset = static_cast(Imm) & InstMask; @@ -704,7 +729,10 @@ public: case ForwardLabel::InstType::RELATIVE_LOAD: { uint32_t* Instruction = reinterpret_cast(Label->Location); int64_t Imm = reinterpret_cast(CurrentAddress) - reinterpret_cast(Instruction); - LOGMAN_THROW_A_FMT(Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0), "Unscaled offset too large"); + if (!(Imm >= -1048576 && Imm <= 1048575 && ((Imm & 0b11) == 0))) [[unlikely]] { + // Can't bind. + return false; + } Imm >>= 2; uint32_t InstMask = 0x7'FFFF; uint32_t Offset = static_cast(Imm) & InstMask; @@ -753,27 +781,41 @@ public: } default: LOGMAN_MSG_A_FMT("Unexpected inst type in label fixup"); } + + return true; } // Bind a forward label to a location. // This walks all the instructions in the label's vector. // Then backpatching all instructions that have used the label. - void Bind(ForwardLabel* Label) { + [[nodiscard]] bool Bind(ForwardLabel* Label) { + bool Bound = true; if (Label->FirstInst.Location) { - Bind(&Label->FirstInst); + Bound &= Bind(&Label->FirstInst); } for (auto& Inst : Label->Insts) { - Bind(&Inst); + Bound &= Bind(&Inst); } + + return Bound; } // Bind a bidirectional location to a location. // Binds both forwards and backwards depending on how the label was used. - void Bind(BiDirectionalLabel* Label) { + [[nodiscard]] bool Bind(BiDirectionalLabel* Label) { + bool Bound = true; if (!Label->Backward.Location) { - Bind(&Label->Backward); + Bound &= Bind(&Label->Backward); } - Bind(&Label->Forward); + Bound &= Bind(&Label->Forward); + + return Bound; + } + + static constexpr Condition InvertCondition(Condition cond) { + // These behave as always, so it makes no sense to allow inverting these. + LOGMAN_THROW_A_FMT(cond != Condition::CC_AL && cond != Condition::CC_NV, "Cannot invert CC_AL or CC_NV"); + return static_cast(FEXCore::ToUnderlying(cond) ^ 1); } #include