From 97d8b50c25d42bfc6364e4603860e10ab40c3a79 Mon Sep 17 00:00:00 2001
From: MerryMage <MerryMage@users.noreply.github.com>
Date: Sun, 7 Feb 2021 20:33:20 +0000
Subject: [PATCH] A32: Ensure existing thumb code is ITState-correct

---
 src/frontend/A32/translate/impl/thumb16.cpp | 244 ++++++++++++++------
 src/frontend/A32/translate/impl/thumb32.cpp |  13 +-
 2 files changed, 179 insertions(+), 78 deletions(-)

diff --git a/src/frontend/A32/translate/impl/thumb16.cpp b/src/frontend/A32/translate/impl/thumb16.cpp
index d7c9e4cd..2ded96c1 100644
--- a/src/frontend/A32/translate/impl/thumb16.cpp
+++ b/src/frontend/A32/translate/impl/thumb16.cpp
@@ -12,13 +12,19 @@ namespace Dynarmic::A32 {
 // LSLS <Rd>, <Rm>, #<imm5>
 bool ThumbTranslatorVisitor::thumb16_LSL_imm(Imm<5> imm5, Reg m, Reg d) {
     const u8 shift_n = imm5.ZeroExtend<u8>();
+    if (shift_n == 0 && ir.current_location.IT().IsInITBlock()) {
+        return UnpredictableInstruction();
+    }
+
     const auto cpsr_c = ir.GetCFlag();
     const auto result = ir.LogicalShiftLeft(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+    }
     return true;
 }
 
@@ -29,9 +35,11 @@ bool ThumbTranslatorVisitor::thumb16_LSR_imm(Imm<5> imm5, Reg m, Reg d) {
     const auto result = ir.LogicalShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+    }
     return true;
 }
 
@@ -42,9 +50,11 @@ bool ThumbTranslatorVisitor::thumb16_ASR_imm(Imm<5> imm5, Reg m, Reg d) {
     const auto result = ir.ArithmeticShiftRight(ir.GetRegister(m), ir.Imm8(shift_n), cpsr_c);
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+    }
     return true;
 }
 
@@ -52,11 +62,14 @@ bool ThumbTranslatorVisitor::thumb16_ASR_imm(Imm<5> imm5, Reg m, Reg d) {
 // Note that it is not possible to encode Rd == R15.
 bool ThumbTranslatorVisitor::thumb16_ADD_reg_t1(Reg m, Reg n, Reg d) {
     const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0));
+
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
-    ir.SetVFlag(result.overflow);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+        ir.SetVFlag(result.overflow);
+    }
     return true;
 }
 
@@ -64,11 +77,14 @@ bool ThumbTranslatorVisitor::thumb16_ADD_reg_t1(Reg m, Reg n, Reg d) {
 // Note that it is not possible to encode Rd == R15.
 bool ThumbTranslatorVisitor::thumb16_SUB_reg(Reg m, Reg n, Reg d) {
     const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(1));
+
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
-    ir.SetVFlag(result.overflow);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+        ir.SetVFlag(result.overflow);
+    }
     return true;
 }
 
@@ -79,10 +95,12 @@ bool ThumbTranslatorVisitor::thumb16_ADD_imm_t1(Imm<3> imm3, Reg n, Reg d) {
     const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
-    ir.SetVFlag(result.overflow);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+        ir.SetVFlag(result.overflow);
+    }
     return true;
 }
 
@@ -93,10 +111,12 @@ bool ThumbTranslatorVisitor::thumb16_SUB_imm_t1(Imm<3> imm3, Reg n, Reg d) {
     const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
-    ir.SetVFlag(result.overflow);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+        ir.SetVFlag(result.overflow);
+    }
     return true;
 }
 
@@ -107,8 +127,10 @@ bool ThumbTranslatorVisitor::thumb16_MOV_imm(Reg d, Imm<8> imm8) {
     const auto result = ir.Imm32(imm32);
 
     ir.SetRegister(d, result);
-    ir.SetNFlag(ir.MostSignificantBit(result));
-    ir.SetZFlag(ir.IsZero(result));
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result));
+        ir.SetZFlag(ir.IsZero(result));
+    }
     return true;
 }
 
@@ -133,10 +155,12 @@ bool ThumbTranslatorVisitor::thumb16_ADD_imm_t2(Reg d_n, Imm<8> imm8) {
     const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(0));
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
-    ir.SetVFlag(result.overflow);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+        ir.SetVFlag(result.overflow);
+    }
     return true;
 }
 
@@ -149,10 +173,12 @@ bool ThumbTranslatorVisitor::thumb16_SUB_imm_t2(Reg d_n, Imm<8> imm8) {
     const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.Imm32(imm32), ir.Imm1(1));
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
-    ir.SetVFlag(result.overflow);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+        ir.SetVFlag(result.overflow);
+    }
     return true;
 }
 
@@ -164,8 +190,10 @@ bool ThumbTranslatorVisitor::thumb16_AND_reg(Reg m, Reg d_n) {
     const auto result = ir.And(ir.GetRegister(n), ir.GetRegister(m));
 
     ir.SetRegister(d, result);
-    ir.SetNFlag(ir.MostSignificantBit(result));
-    ir.SetZFlag(ir.IsZero(result));
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result));
+        ir.SetZFlag(ir.IsZero(result));
+    }
     return true;
 }
 
@@ -177,8 +205,10 @@ bool ThumbTranslatorVisitor::thumb16_EOR_reg(Reg m, Reg d_n) {
     const auto result = ir.Eor(ir.GetRegister(n), ir.GetRegister(m));
 
     ir.SetRegister(d, result);
-    ir.SetNFlag(ir.MostSignificantBit(result));
-    ir.SetZFlag(ir.IsZero(result));
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result));
+        ir.SetZFlag(ir.IsZero(result));
+    }
     return true;
 }
 
@@ -191,9 +221,11 @@ bool ThumbTranslatorVisitor::thumb16_LSL_reg(Reg m, Reg d_n) {
     const auto result_carry = ir.LogicalShiftLeft(ir.GetRegister(n), shift_n, apsr_c);
 
     ir.SetRegister(d, result_carry.result);
-    ir.SetNFlag(ir.MostSignificantBit(result_carry.result));
-    ir.SetZFlag(ir.IsZero(result_carry.result));
-    ir.SetCFlag(result_carry.carry);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result_carry.result));
+        ir.SetZFlag(ir.IsZero(result_carry.result));
+        ir.SetCFlag(result_carry.carry);
+    }
     return true;
 }
 
@@ -206,9 +238,11 @@ bool ThumbTranslatorVisitor::thumb16_LSR_reg(Reg m, Reg d_n) {
     const auto result = ir.LogicalShiftRight(ir.GetRegister(n), shift_n, cpsr_c);
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+    }
     return true;
 }
 
@@ -221,9 +255,11 @@ bool ThumbTranslatorVisitor::thumb16_ASR_reg(Reg m, Reg d_n) {
     const auto result = ir.ArithmeticShiftRight(ir.GetRegister(n), shift_n, cpsr_c);
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+    }
     return true;
 }
 
@@ -236,10 +272,12 @@ bool ThumbTranslatorVisitor::thumb16_ADC_reg(Reg m, Reg d_n) {
     const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), aspr_c);
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
-    ir.SetVFlag(result.overflow);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+        ir.SetVFlag(result.overflow);
+    }
     return true;
 }
 
@@ -252,10 +290,12 @@ bool ThumbTranslatorVisitor::thumb16_SBC_reg(Reg m, Reg d_n) {
     const auto result = ir.SubWithCarry(ir.GetRegister(n), ir.GetRegister(m), aspr_c);
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
-    ir.SetVFlag(result.overflow);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+        ir.SetVFlag(result.overflow);
+    }
     return true;
 }
 
@@ -268,9 +308,11 @@ bool ThumbTranslatorVisitor::thumb16_ROR_reg(Reg m, Reg d_n) {
     const auto result = ir.RotateRight(ir.GetRegister(n), shift_n, cpsr_c);
 
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+    }
     return true;
 }
 
@@ -287,10 +329,12 @@ bool ThumbTranslatorVisitor::thumb16_TST_reg(Reg m, Reg n) {
 bool ThumbTranslatorVisitor::thumb16_RSB_imm(Reg n, Reg d) {
     const auto result = ir.SubWithCarry(ir.Imm32(0), ir.GetRegister(n), ir.Imm1(1));
     ir.SetRegister(d, result.result);
-    ir.SetNFlag(ir.MostSignificantBit(result.result));
-    ir.SetZFlag(ir.IsZero(result.result));
-    ir.SetCFlag(result.carry);
-    ir.SetVFlag(result.overflow);
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result.result));
+        ir.SetZFlag(ir.IsZero(result.result));
+        ir.SetCFlag(result.carry);
+        ir.SetVFlag(result.overflow);
+    }
     return true;
 }
 
@@ -322,8 +366,10 @@ bool ThumbTranslatorVisitor::thumb16_ORR_reg(Reg m, Reg d_n) {
     const auto result = ir.Or(ir.GetRegister(m), ir.GetRegister(n));
 
     ir.SetRegister(d, result);
-    ir.SetNFlag(ir.MostSignificantBit(result));
-    ir.SetZFlag(ir.IsZero(result));
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result));
+        ir.SetZFlag(ir.IsZero(result));
+    }
     return true;
 }
 
@@ -335,8 +381,10 @@ bool ThumbTranslatorVisitor::thumb16_MUL_reg(Reg n, Reg d_m) {
     const auto result = ir.Mul(ir.GetRegister(m), ir.GetRegister(n));
 
     ir.SetRegister(d, result);
-    ir.SetNFlag(ir.MostSignificantBit(result));
-    ir.SetZFlag(ir.IsZero(result));
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result));
+        ir.SetZFlag(ir.IsZero(result));
+    }
     return true;
 }
 
@@ -348,8 +396,10 @@ bool ThumbTranslatorVisitor::thumb16_BIC_reg(Reg m, Reg d_n) {
     const auto result = ir.And(ir.GetRegister(n), ir.Not(ir.GetRegister(m)));
 
     ir.SetRegister(d, result);
-    ir.SetNFlag(ir.MostSignificantBit(result));
-    ir.SetZFlag(ir.IsZero(result));
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result));
+        ir.SetZFlag(ir.IsZero(result));
+    }
     return true;
 }
 
@@ -357,9 +407,12 @@ bool ThumbTranslatorVisitor::thumb16_BIC_reg(Reg m, Reg d_n) {
 // Rd cannot encode R15.
 bool ThumbTranslatorVisitor::thumb16_MVN_reg(Reg m, Reg d) {
     const auto result = ir.Not(ir.GetRegister(m));
+
     ir.SetRegister(d, result);
-    ir.SetNFlag(ir.MostSignificantBit(result));
-    ir.SetZFlag(ir.IsZero(result));
+    if (!ir.current_location.IT().IsInITBlock()) {
+        ir.SetNFlag(ir.MostSignificantBit(result));
+        ir.SetZFlag(ir.IsZero(result));
+    }
     return true;
 }
 
@@ -367,13 +420,17 @@ bool ThumbTranslatorVisitor::thumb16_MVN_reg(Reg m, Reg d) {
 bool ThumbTranslatorVisitor::thumb16_ADD_reg_t2(bool d_n_hi, Reg m, Reg d_n_lo) {
     const Reg d_n = d_n_hi ? (d_n_lo + 8) : d_n_lo;
     const Reg n = d_n;
+    const Reg d = d_n;
     if (n == Reg::PC && m == Reg::PC) {
         return UnpredictableInstruction();
     }
+    if (d == Reg::PC && ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock()) {
+        return UnpredictableInstruction();
+    }
 
-    const Reg d = d_n;
     const auto result = ir.AddWithCarry(ir.GetRegister(n), ir.GetRegister(m), ir.Imm1(0));
     if (d == Reg::PC) {
+        ir.UpdateUpperLocationDescriptor();
         ir.ALUWritePC(result.result);
         // Return to dispatch as we can't predict what PC is going to be. Stop compilation.
         ir.SetTerm(IR::Term::FastDispatchHint{});
@@ -405,9 +462,14 @@ bool ThumbTranslatorVisitor::thumb16_CMP_reg_t2(bool n_hi, Reg m, Reg n_lo) {
 // MOV <Rd>, <Rm>
 bool ThumbTranslatorVisitor::thumb16_MOV_reg(bool d_hi, Reg m, Reg d_lo) {
     const Reg d = d_hi ? (d_lo + 8) : d_lo;
+    if (d == Reg::PC && ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock()) {
+        return UnpredictableInstruction();
+    }
+
     const auto result = ir.GetRegister(m);
 
     if (d == Reg::PC) {
+        ir.UpdateUpperLocationDescriptor();
         ir.ALUWritePC(result);
         ir.SetTerm(IR::Term::FastDispatchHint{});
         return false;
@@ -761,6 +823,7 @@ bool ThumbTranslatorVisitor::thumb16_POP(bool P, RegList reg_list) {
     if (Common::Bit<15>(reg_list)) {
         // TODO(optimization): Possible location for an RSB pop.
         const auto data = ir.ReadMemory32(address);
+        ir.UpdateUpperLocationDescriptor();
         ir.LoadWritePC(data);
         address = ir.Add(address, ir.Imm32(4));
         ir.SetRegister(Reg::SP, address);
@@ -774,6 +837,10 @@ bool ThumbTranslatorVisitor::thumb16_POP(bool P, RegList reg_list) {
 
 // SETEND <endianness>
 bool ThumbTranslatorVisitor::thumb16_SETEND(bool E) {
+    if (ir.current_location.IT().IsInITBlock()) {
+        return UnpredictableInstruction();
+    }
+
     if (E == ir.current_location.EFlag()) {
         return true;
     }
@@ -822,6 +889,8 @@ bool ThumbTranslatorVisitor::thumb16_REVSH(Reg m, Reg d) {
 // BKPT #<imm8>
 bool ThumbTranslatorVisitor::thumb16_BKPT([[maybe_unused]] Imm<8> imm8) {
     ir.ExceptionRaised(Exception::Breakpoint);
+    ir.UpdateUpperLocationDescriptor();
+    ir.LoadWritePC(ir.Imm32(ir.current_location.PC()));
     ir.SetTerm(IR::Term::CheckHalt{IR::Term::ReturnToDispatch{}});
     return false;
 }
@@ -873,6 +942,10 @@ bool ThumbTranslatorVisitor::thumb16_LDMIA(Reg n, RegList reg_list) {
 
 // CB{N}Z <Rn>, <label>
 bool ThumbTranslatorVisitor::thumb16_CBZ_CBNZ(bool nonzero, Imm<1> i, Imm<5> imm5, Reg n) {
+    if (ir.current_location.IT().IsInITBlock()) {
+        return UnpredictableInstruction();
+    }
+
     const u32 imm = concatenate(i, imm5, Imm<1>{0}).ZeroExtend();
     const IR::U32 rn = ir.GetRegister(n);
 
@@ -889,7 +962,7 @@ bool ThumbTranslatorVisitor::thumb16_CBZ_CBNZ(bool nonzero, Imm<1> i, Imm<5> imm
         }
     }();
 
-     ir.SetTerm(IR::Term::CheckBit{cond_pass, cond_fail});
+    ir.SetTerm(IR::Term::CheckBit{cond_pass, cond_fail});
     return false;
 }
 
@@ -899,6 +972,11 @@ bool ThumbTranslatorVisitor::thumb16_UDF() {
 
 // BX <Rm>
 bool ThumbTranslatorVisitor::thumb16_BX(Reg m) {
+    if (ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock()) {
+        return UnpredictableInstruction();
+    }
+
+    ir.UpdateUpperLocationDescriptor();
     ir.BXWritePC(ir.GetRegister(m));
     if (m == Reg::R14)
         ir.SetTerm(IR::Term::PopRSBHint{});
@@ -909,7 +987,12 @@ bool ThumbTranslatorVisitor::thumb16_BX(Reg m) {
 
 // BLX <Rm>
 bool ThumbTranslatorVisitor::thumb16_BLX_reg(Reg m) {
+    if (ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock()) {
+        return UnpredictableInstruction();
+    }
+
     ir.PushRSB(ir.current_location.AdvancePC(2));
+    ir.UpdateUpperLocationDescriptor();
     ir.BXWritePC(ir.GetRegister(m));
     ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 2) | 1));
     ir.SetTerm(IR::Term::FastDispatchHint{});
@@ -919,6 +1002,7 @@ bool ThumbTranslatorVisitor::thumb16_BLX_reg(Reg m) {
 // SVC #<imm8>
 bool ThumbTranslatorVisitor::thumb16_SVC(Imm<8> imm8) {
     const u32 imm32 = imm8.ZeroExtend();
+    ir.UpdateUpperLocationDescriptor();
     ir.BranchWritePC(ir.Imm32(ir.current_location.PC() + 2));
     ir.PushRSB(ir.current_location.AdvancePC(2));
     ir.CallSupervisor(ir.Imm32(imm32));
@@ -928,13 +1012,17 @@ bool ThumbTranslatorVisitor::thumb16_SVC(Imm<8> imm8) {
 
 // B<cond> <label>
 bool ThumbTranslatorVisitor::thumb16_B_t1(Cond cond, Imm<8> imm8) {
+    if (ir.current_location.IT().IsInITBlock()) {
+        return UnpredictableInstruction();
+    }
+
     if (cond == Cond::AL) {
         return thumb16_UDF();
     }
 
     const s32 imm32 = static_cast<s32>((imm8.SignExtend<u32>() << 1) + 4);
-    const auto then_location = ir.current_location.AdvancePC(imm32);
-    const auto else_location = ir.current_location.AdvancePC(2);
+    const auto then_location = ir.current_location.AdvancePC(imm32).AdvanceIT();
+    const auto else_location = ir.current_location.AdvancePC(2).AdvanceIT();
 
     ir.SetTerm(IR::Term::If{cond, IR::Term::LinkBlock{then_location}, IR::Term::LinkBlock{else_location}});
     return false;
@@ -942,8 +1030,12 @@ bool ThumbTranslatorVisitor::thumb16_B_t1(Cond cond, Imm<8> imm8) {
 
 // B <label>
 bool ThumbTranslatorVisitor::thumb16_B_t2(Imm<11> imm11) {
+    if (ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock()) {
+        return UnpredictableInstruction();
+    }
+
     const s32 imm32 = static_cast<s32>((imm11.SignExtend<u32>() << 1) + 4);
-    const auto next_location = ir.current_location.AdvancePC(imm32);
+    const auto next_location = ir.current_location.AdvancePC(imm32).AdvanceIT();
 
     ir.SetTerm(IR::Term::LinkBlock{next_location});
     return false;
diff --git a/src/frontend/A32/translate/impl/thumb32.cpp b/src/frontend/A32/translate/impl/thumb32.cpp
index c27e5ff9..d79e4f5b 100644
--- a/src/frontend/A32/translate/impl/thumb32.cpp
+++ b/src/frontend/A32/translate/impl/thumb32.cpp
@@ -9,17 +9,25 @@ namespace Dynarmic::A32 {
 
 // BL <label>
 bool ThumbTranslatorVisitor::thumb32_BL_imm(Imm<11> hi, Imm<11> lo) {
+    if (ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock()) {
+        return UnpredictableInstruction();
+    }
+
     ir.PushRSB(ir.current_location.AdvancePC(4));
     ir.SetRegister(Reg::LR, ir.Imm32((ir.current_location.PC() + 4) | 1));
 
     const s32 imm32 = static_cast<s32>((concatenate(hi, lo).SignExtend<u32>() << 1) + 4);
-    const auto new_location = ir.current_location.AdvancePC(imm32);
+    const auto new_location = ir.current_location.AdvancePC(imm32).AdvanceIT();
     ir.SetTerm(IR::Term::LinkBlock{new_location});
     return false;
 }
 
 // BLX <label>
 bool ThumbTranslatorVisitor::thumb32_BLX_imm(Imm<11> hi, Imm<11> lo) {
+    if (ir.current_location.IT().IsInITBlock() && !ir.current_location.IT().IsLastInITBlock()) {
+        return UnpredictableInstruction();
+    }
+
     if (lo.Bit<0>()) {
         return UnpredictableInstruction();
     }
@@ -30,7 +38,8 @@ bool ThumbTranslatorVisitor::thumb32_BLX_imm(Imm<11> hi, Imm<11> lo) {
     const s32 imm32 = static_cast<s32>(concatenate(hi, lo).SignExtend<u32>() << 1);
     const auto new_location = ir.current_location
                                 .SetPC(ir.AlignPC(4) + imm32)
-                                .SetTFlag(false);
+                                .SetTFlag(false)
+                                .AdvanceIT();
     ir.SetTerm(IR::Term::LinkBlock{new_location});
     return false;
 }