diff --git a/ARMeilleure/Decoders/Decoder.cs b/ARMeilleure/Decoders/Decoder.cs
index 4dd8742cab..426465aaab 100644
--- a/ARMeilleure/Decoders/Decoder.cs
+++ b/ARMeilleure/Decoders/Decoder.cs
@@ -251,6 +251,13 @@ namespace ARMeilleure.Decoders
                 return false;
             }
 
+            // Compare and branch instructions are always conditional.
+            if (opCode.Instruction.Name == InstName.Cbz ||
+                opCode.Instruction.Name == InstName.Cbnz)
+            {
+                return false;
+            }
+
             // Note: On ARM32, most instructions have conditional execution,
             // so there's no "Always" (unconditional) branch like on ARM64.
             // We need to check if the condition is "Always" instead.
diff --git a/ARMeilleure/Decoders/DecoderHelper.cs b/ARMeilleure/Decoders/DecoderHelper.cs
index 6fe4678f96..38f98c39cc 100644
--- a/ARMeilleure/Decoders/DecoderHelper.cs
+++ b/ARMeilleure/Decoders/DecoderHelper.cs
@@ -151,7 +151,7 @@ namespace ARMeilleure.Decoders
 
         public static bool VectorArgumentsInvalid(bool q, params int[] args)
         {
-            if (q) 
+            if (q)
             {
                 for (int i = 0; i < args.Length; i++)
                 {
diff --git a/ARMeilleure/Decoders/IOpCode32Mem.cs b/ARMeilleure/Decoders/IOpCode32Mem.cs
index 145bc618e6..6664ddffdf 100644
--- a/ARMeilleure/Decoders/IOpCode32Mem.cs
+++ b/ARMeilleure/Decoders/IOpCode32Mem.cs
@@ -3,6 +3,7 @@ namespace ARMeilleure.Decoders
     interface IOpCode32Mem : IOpCode32
     {
         int Rt { get; }
+        int Rt2 => Rt | 1;
         int Rn { get; }
 
         bool WBack { get; }
diff --git a/ARMeilleure/Decoders/OpCodeT16Adr.cs b/ARMeilleure/Decoders/OpCodeT16Adr.cs
index ef14791d93..03abd499d9 100644
--- a/ARMeilleure/Decoders/OpCodeT16Adr.cs
+++ b/ARMeilleure/Decoders/OpCodeT16Adr.cs
@@ -4,14 +4,13 @@ namespace ARMeilleure.Decoders
     {
         public int Rd { get; }
 
-        public bool Add => true;
         public int Immediate { get; }
 
         public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT16Adr(inst, address, opCode);
 
         public OpCodeT16Adr(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
         {
-            Rd  = (opCode >> 8) & 7;
+            Rd = (opCode >> 8) & 7;
 
             int imm = (opCode & 0xff) << 2;
             Immediate = (int)(GetPc() & 0xfffffffc) + imm;
diff --git a/ARMeilleure/Decoders/OpCodeT32AluImm12.cs b/ARMeilleure/Decoders/OpCodeT32AluImm12.cs
new file mode 100644
index 0000000000..31de63dd3e
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT32AluImm12.cs
@@ -0,0 +1,16 @@
+namespace ARMeilleure.Decoders
+{
+    class OpCodeT32AluImm12 : OpCodeT32Alu, IOpCode32AluImm
+    {
+        public int Immediate { get; }
+
+        public bool IsRotated => false;
+
+        public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluImm12(inst, address, opCode);
+
+        public OpCodeT32AluImm12(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+        {
+            Immediate = (opCode & 0xff) | ((opCode >> 4) & 0x700) | ((opCode >> 15) & 0x800);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeT32AluReg.cs b/ARMeilleure/Decoders/OpCodeT32AluReg.cs
new file mode 100644
index 0000000000..a487f55a64
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT32AluReg.cs
@@ -0,0 +1,14 @@
+namespace ARMeilleure.Decoders
+{
+    class OpCodeT32AluReg : OpCodeT32Alu, IOpCode32AluReg
+    {
+        public int Rm { get; }
+
+        public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluReg(inst, address, opCode);
+
+        public OpCodeT32AluReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+        {
+            Rm = (opCode >> 0) & 0xf;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeT32MemImm8D.cs b/ARMeilleure/Decoders/OpCodeT32MemImm8D.cs
index 18eeffa43f..7a078c489f 100644
--- a/ARMeilleure/Decoders/OpCodeT32MemImm8D.cs
+++ b/ARMeilleure/Decoders/OpCodeT32MemImm8D.cs
@@ -23,7 +23,7 @@ namespace ARMeilleure.Decoders
             Add   = ((opCode >> 23) & 1) != 0;
             WBack = ((opCode >> 21) & 1) != 0;
 
-            Immediate = opCode & 0xff;
+            Immediate = (opCode & 0xff) << 2;
 
             IsLoad = ((opCode >> 20) & 1) != 0;
         }
diff --git a/ARMeilleure/Decoders/OpCodeT32MovImm16.cs b/ARMeilleure/Decoders/OpCodeT32MovImm16.cs
new file mode 100644
index 0000000000..55db012ca7
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT32MovImm16.cs
@@ -0,0 +1,19 @@
+using ARMeilleure.Common;
+using System.Runtime.Intrinsics;
+
+namespace ARMeilleure.Decoders
+{
+    class OpCodeT32MovImm16 : OpCodeT32Alu, IOpCode32AluImm
+    {
+        public int Immediate { get; }
+
+        public bool IsRotated => false;
+
+        public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32MovImm16(inst, address, opCode);
+
+        public OpCodeT32MovImm16(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+        {
+            Immediate = (opCode & 0xff) | ((opCode >> 4) & 0x700) | ((opCode >> 15) & 0x800) | ((opCode >> 4) & 0xf000);
+        }
+    }
+}
\ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeT32ShiftReg.cs b/ARMeilleure/Decoders/OpCodeT32ShiftReg.cs
new file mode 100644
index 0000000000..360559756d
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT32ShiftReg.cs
@@ -0,0 +1,19 @@
+namespace ARMeilleure.Decoders
+{
+    class OpCodeT32ShiftReg : OpCodeT32Alu, IOpCode32AluRsReg
+    {
+        public int Rm => Rn;
+        public int Rs { get; }
+
+        public ShiftType ShiftType { get; }
+
+        public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32ShiftReg(inst, address, opCode);
+
+        public OpCodeT32ShiftReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+        {
+            Rs = (opCode >> 0) & 0xf;
+
+            ShiftType = (ShiftType)((opCode >> 21) & 3);
+        }
+    }
+}
diff --git a/ARMeilleure/Decoders/OpCodeT32Tb.cs b/ARMeilleure/Decoders/OpCodeT32Tb.cs
new file mode 100644
index 0000000000..527754b1f8
--- /dev/null
+++ b/ARMeilleure/Decoders/OpCodeT32Tb.cs
@@ -0,0 +1,16 @@
+namespace ARMeilleure.Decoders
+{
+    class OpCodeT32Tb : OpCodeT32, IOpCode32BReg
+    {
+        public int Rm { get; }
+        public int Rn { get; }
+
+        public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32Tb(inst, address, opCode);
+
+        public OpCodeT32Tb(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
+        {
+            Rm = (opCode >> 0) & 0xf;
+            Rn = (opCode >> 16) & 0xf;
+        }
+    }
+}
\ No newline at end of file
diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs
index ed77b99c2b..a7793681de 100644
--- a/ARMeilleure/Decoders/OpCodeTable.cs
+++ b/ARMeilleure/Decoders/OpCodeTable.cs
@@ -1021,7 +1021,7 @@ namespace ARMeilleure.Decoders
             SetT16("01000101xxxxxxxx", InstName.Cmp,    InstEmit32.Cmp,     OpCodeT16AluRegHigh.Create);
             SetT16("01000110xxxxxxxx", InstName.Mov,    InstEmit32.Mov,     OpCodeT16AluRegHigh.Create);
             SetT16("010001110xxxx000", InstName.Bx,     InstEmit32.Bx,      OpCodeT16BReg.Create);
-            SetT16("010001111xxxx000", InstName.Blx,    InstEmit32.Blx,     OpCodeT16BReg.Create);
+            SetT16("010001111xxxx000", InstName.Blx,    InstEmit32.Blxr,    OpCodeT16BReg.Create);
             SetT16("01001xxxxxxxxxxx", InstName.Ldr,    InstEmit32.Ldr,     OpCodeT16MemLit.Create);
             SetT16("0101000xxxxxxxxx", InstName.Str,    InstEmit32.Str,     OpCodeT16MemReg.Create);
             SetT16("0101001xxxxxxxxx", InstName.Strh,   InstEmit32.Strh,    OpCodeT16MemReg.Create);
@@ -1069,6 +1069,7 @@ namespace ARMeilleure.Decoders
             SetT32("11110x01010xxxxx0xxxxxxxxxxxxxxx", InstName.Adc,      InstEmit32.Adc,      OpCodeT32AluImm.Create);
             SetT32("11101011000<xxxx0xxx<<<<xxxxxxxx", InstName.Add,      InstEmit32.Add,      OpCodeT32AluRsImm.Create);
             SetT32("11110x01000<xxxx0xxx<<<<xxxxxxxx", InstName.Add,      InstEmit32.Add,      OpCodeT32AluImm.Create);
+            SetT32("11110x100000xxxx0xxxxxxxxxxxxxxx", InstName.Add,      InstEmit32.Add,      OpCodeT32AluImm12.Create);
             SetT32("11101010000<xxxx0xxx<<<<xxxxxxxx", InstName.And,      InstEmit32.And,      OpCodeT32AluRsImm.Create);
             SetT32("11110x00000<xxxx0xxx<<<<xxxxxxxx", InstName.And,      InstEmit32.And,      OpCodeT32AluImm.Create);
             SetT32("11110x<<<xxxxxxx10x0xxxxxxxxxxxx", InstName.B,        InstEmit32.B,        OpCodeT32BImm20.Create);
@@ -1077,12 +1078,14 @@ namespace ARMeilleure.Decoders
             SetT32("11110x00001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic,      InstEmit32.Bic,      OpCodeT32AluImm.Create);
             SetT32("11110xxxxxxxxxxx11x1xxxxxxxxxxxx", InstName.Bl,       InstEmit32.Bl,       OpCodeT32BImm24.Create);
             SetT32("11110xxxxxxxxxxx11x0xxxxxxxxxxx0", InstName.Blx,      InstEmit32.Blx,      OpCodeT32BImm24.Create);
+            SetT32("111110101011xxxx1111xxxx1000xxxx", InstName.Clz,      InstEmit32.Clz,      OpCodeT32AluReg.Create);
             SetT32("111010110001xxxx0xxx1111xxxxxxxx", InstName.Cmn,      InstEmit32.Cmn,      OpCodeT32AluRsImm.Create);
             SetT32("11110x010001xxxx0xxx1111xxxxxxxx", InstName.Cmn,      InstEmit32.Cmn,      OpCodeT32AluImm.Create);
             SetT32("111010111011xxxx0xxx1111xxxxxxxx", InstName.Cmp,      InstEmit32.Cmp,      OpCodeT32AluRsImm.Create);
             SetT32("11110x011011xxxx0xxx1111xxxxxxxx", InstName.Cmp,      InstEmit32.Cmp,      OpCodeT32AluImm.Create);
             SetT32("11101010100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor,      InstEmit32.Eor,      OpCodeT32AluRsImm.Create);
             SetT32("11110x00100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor,      InstEmit32.Eor,      OpCodeT32AluImm.Create);
+            SetT32("111010001101xxxxxxxx111110101111", InstName.Lda,      InstEmit32.Lda,      OpCodeT32MemLdEx.Create);
             SetT32("111010001101xxxxxxxx111111101111", InstName.Ldaex,    InstEmit32.Ldaex,    OpCodeT32MemLdEx.Create);
             SetT32("1110100010x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm,      InstEmit32.Ldm,      OpCodeT32MemMult.Create);
             SetT32("1110100100x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm,      InstEmit32.Ldm,      OpCodeT32MemMult.Create);
@@ -1095,7 +1098,8 @@ namespace ARMeilleure.Decoders
             SetT32("111110000001xxxx<<<<1100xxxxxxxx", InstName.Ldrb,     InstEmit32.Ldrb,     OpCodeT32MemImm8.Create);
             SetT32("111110000001xxxx<<<<11x1xxxxxxxx", InstName.Ldrb,     InstEmit32.Ldrb,     OpCodeT32MemImm8.Create);
             SetT32("111110001001xxxxxxxxxxxxxxxxxxxx", InstName.Ldrb,     InstEmit32.Ldrb,     OpCodeT32MemImm12.Create);
-            SetT32("1110100>x1>1<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd,     InstEmit32.Ldrd,     OpCodeT32MemImm8D.Create);
+            SetT32("11101000x111<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd,     InstEmit32.Ldrd,     OpCodeT32MemImm8D.Create);
+            SetT32("11101001x1x1<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd,     InstEmit32.Ldrd,     OpCodeT32MemImm8D.Create);
             SetT32("111110000011xxxx<<<<10x1xxxxxxxx", InstName.Ldrh,     InstEmit32.Ldrh,     OpCodeT32MemImm8.Create);
             SetT32("111110000011xxxx<<<<1100xxxxxxxx", InstName.Ldrh,     InstEmit32.Ldrh,     OpCodeT32MemImm8.Create);
             SetT32("111110000011xxxx<<<<11x1xxxxxxxx", InstName.Ldrh,     InstEmit32.Ldrh,     OpCodeT32MemImm8.Create);
@@ -1109,9 +1113,12 @@ namespace ARMeilleure.Decoders
             SetT32("111110010011xxxx<<<<11x1xxxxxxxx", InstName.Ldrsh,    InstEmit32.Ldrsh,    OpCodeT32MemImm8.Create);
             SetT32("111110011011xxxxxxxxxxxxxxxxxxxx", InstName.Ldrsh,    InstEmit32.Ldrsh,    OpCodeT32MemImm12.Create);
             SetT32("11101010010x11110xxxxxxxxxxxxxxx", InstName.Mov,      InstEmit32.Mov,      OpCodeT32AluRsImm.Create);
+            SetT32("111110100xxxxxxx1111xxxx0000xxxx", InstName.Mov,      InstEmit32.Mov,      OpCodeT32ShiftReg.Create);
             SetT32("11110x00010x11110xxxxxxxxxxxxxxx", InstName.Mov,      InstEmit32.Mov,      OpCodeT32AluImm.Create);
+            SetT32("11110x100100xxxx0xxxxxxxxxxxxxxx", InstName.Mov,      InstEmit32.Mov,      OpCodeT32MovImm16.Create);
             SetT32("11101010011x11110xxxxxxxxxxxxxxx", InstName.Mvn,      InstEmit32.Mvn,      OpCodeT32AluRsImm.Create);
             SetT32("11110x00011x11110xxxxxxxxxxxxxxx", InstName.Mvn,      InstEmit32.Mvn,      OpCodeT32AluImm.Create);
+            SetT32("11110011101011111000000000000000", InstName.Nop,      InstEmit32.Nop,      OpCodeT32.Create);
             SetT32("11101010011x<<<<0xxxxxxxxxxxxxxx", InstName.Orn,      InstEmit32.Orn,      OpCodeT32AluRsImm.Create);
             SetT32("11110x00011x<<<<0xxxxxxxxxxxxxxx", InstName.Orn,      InstEmit32.Orn,      OpCodeT32AluImm.Create);
             SetT32("11101010010x<<<<0xxxxxxxxxxxxxxx", InstName.Orr,      InstEmit32.Orr,      OpCodeT32AluRsImm.Create);
@@ -1128,11 +1135,14 @@ namespace ARMeilleure.Decoders
             SetT32("111110000100<<<<xxxx000000xxxxxx", InstName.Str,      InstEmit32.Str,      OpCodeT32MemRsImm.Create);
             SetT32("111110000000xxxxxxxx1<<>xxxxxxxx", InstName.Strb,     InstEmit32.Strb,     OpCodeT32MemImm8.Create);
             SetT32("111110001000xxxxxxxxxxxxxxxxxxxx", InstName.Strb,     InstEmit32.Strb,     OpCodeT32MemImm12.Create);
-            SetT32("1110100>x1>0<<<<xxxxxxxxxxxxxxxx", InstName.Strd,     InstEmit32.Strd,     OpCodeT32MemImm8D.Create);
+            SetT32("11101000x110<<<<xxxxxxxxxxxxxxxx", InstName.Strd,     InstEmit32.Strd,     OpCodeT32MemImm8D.Create);
+            SetT32("11101001x1x0<<<<xxxxxxxxxxxxxxxx", InstName.Strd,     InstEmit32.Strd,     OpCodeT32MemImm8D.Create);
             SetT32("111110000010xxxxxxxx1<<>xxxxxxxx", InstName.Strh,     InstEmit32.Strh,     OpCodeT32MemImm8.Create);
             SetT32("111110001010xxxxxxxxxxxxxxxxxxxx", InstName.Strh,     InstEmit32.Strh,     OpCodeT32MemImm12.Create);
             SetT32("11101011101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub,      InstEmit32.Sub,      OpCodeT32AluRsImm.Create);
             SetT32("11110x01101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub,      InstEmit32.Sub,      OpCodeT32AluImm.Create);
+            SetT32("111010001101xxxx111100000000xxxx", InstName.Tbb,      InstEmit32.Tbb,      OpCodeT32Tb.Create);
+            SetT32("111010001101xxxx111100000001xxxx", InstName.Tbh,      InstEmit32.Tbh,      OpCodeT32Tb.Create);
             SetT32("111010101001xxxx0xxx1111xxxxxxxx", InstName.Teq,      InstEmit32.Teq,      OpCodeT32AluRsImm.Create);
             SetT32("11110x001001xxxx0xxx1111xxxxxxxx", InstName.Teq,      InstEmit32.Teq,      OpCodeT32AluImm.Create);
             SetT32("111010100001xxxx0xxx1111xxxxxxxx", InstName.Tst,      InstEmit32.Tst,      OpCodeT32AluRsImm.Create);
diff --git a/ARMeilleure/Instructions/InstEmitFlow32.cs b/ARMeilleure/Instructions/InstEmitFlow32.cs
index 030713fbe3..19524b4272 100644
--- a/ARMeilleure/Instructions/InstEmitFlow32.cs
+++ b/ARMeilleure/Instructions/InstEmitFlow32.cs
@@ -107,5 +107,30 @@ namespace ARMeilleure.Instructions
 
             context.SetIfThenBlockState(op.IfThenBlockConds);
         }
+
+        public static void Tbb(ArmEmitterContext context) => EmitTb(context, halfword: false);
+        public static void Tbh(ArmEmitterContext context)  => EmitTb(context, halfword: true);
+
+        private static void EmitTb(ArmEmitterContext context, bool halfword)
+        {
+            OpCodeT32Tb op = (OpCodeT32Tb)context.CurrOp;
+
+            Operand halfwords;
+
+            if (halfword)
+            {
+                Operand address = context.Add(GetIntA32(context, op.Rn), context.ShiftLeft(GetIntA32(context, op.Rm), Const(1)));
+                halfwords = InstEmitMemoryHelper.EmitReadInt(context, address, 1);
+            }
+            else
+            {
+                Operand address = context.Add(GetIntA32(context, op.Rn), GetIntA32(context, op.Rm));
+                halfwords = InstEmitMemoryHelper.EmitReadIntAligned(context, address, 0);
+            }
+
+            Operand targetAddress = context.Add(Const((int)op.GetPc()), context.ShiftLeft(halfwords, Const(1)));
+
+            EmitVirtualJump(context, targetAddress, isReturn: false);
+        }
     }
 }
\ No newline at end of file
diff --git a/ARMeilleure/Instructions/InstEmitMemory32.cs b/ARMeilleure/Instructions/InstEmitMemory32.cs
index e15f6a5b16..17ec97aa6c 100644
--- a/ARMeilleure/Instructions/InstEmitMemory32.cs
+++ b/ARMeilleure/Instructions/InstEmitMemory32.cs
@@ -204,15 +204,15 @@ namespace ARMeilleure.Instructions
 
                     context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
 
-                    Load(op.Rt,     0, WordSizeLog2);
-                    Load(op.Rt | 1, 4, WordSizeLog2);
+                    Load(op.Rt, 0, WordSizeLog2);
+                    Load(op.Rt2, 4, WordSizeLog2);
 
                     context.Branch(lblEnd);
 
                     context.MarkLabel(lblBigEndian);
 
-                    Load(op.Rt | 1, 0, WordSizeLog2);
-                    Load(op.Rt,     4, WordSizeLog2);
+                    Load(op.Rt2, 0, WordSizeLog2);
+                    Load(op.Rt, 4, WordSizeLog2);
 
                     context.MarkLabel(lblEnd);
                 }
@@ -237,15 +237,15 @@ namespace ARMeilleure.Instructions
 
                     context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
 
-                    Store(op.Rt,     0, WordSizeLog2);
-                    Store(op.Rt | 1, 4, WordSizeLog2);
+                    Store(op.Rt, 0, WordSizeLog2);
+                    Store(op.Rt2, 4, WordSizeLog2);
 
                     context.Branch(lblEnd);
 
                     context.MarkLabel(lblBigEndian);
 
-                    Store(op.Rt | 1, 0, WordSizeLog2);
-                    Store(op.Rt,     4, WordSizeLog2);
+                    Store(op.Rt2, 0, WordSizeLog2);
+                    Store(op.Rt, 4, WordSizeLog2);
 
                     context.MarkLabel(lblEnd);
                 }
diff --git a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs
index 2877d53e65..f97e395ce0 100644
--- a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs
+++ b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs
@@ -123,6 +123,41 @@ namespace ARMeilleure.Instructions
                    context.CurrOp is OpCodeSimdMemSs);
         }
 
+        public static Operand EmitReadInt(ArmEmitterContext context, Operand address, int size)
+        {
+            Operand temp = context.AllocateLocal(size == 3 ? OperandType.I64 : OperandType.I32);
+
+            Operand lblSlowPath = Label();
+            Operand lblEnd      = Label();
+
+            Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath, write: false, size);
+
+            Operand value = default;
+
+            switch (size)
+            {
+                case 0: value = context.Load8 (physAddr);                  break;
+                case 1: value = context.Load16(physAddr);                  break;
+                case 2: value = context.Load  (OperandType.I32, physAddr); break;
+                case 3: value = context.Load  (OperandType.I64, physAddr); break;
+            }
+
+            context.Copy(temp, value);
+
+            if (!context.Memory.Type.IsHostMapped())
+            {
+                context.Branch(lblEnd);
+
+                context.MarkLabel(lblSlowPath, BasicBlockFrequency.Cold);
+
+                context.Copy(temp, EmitReadIntFallback(context, address, size));
+
+                context.MarkLabel(lblEnd);
+            }
+
+            return temp;
+        }
+
         private static void EmitReadInt(ArmEmitterContext context, Operand address, int rt, int size)
         {
             Operand lblSlowPath = Label();
@@ -419,6 +454,11 @@ namespace ARMeilleure.Instructions
         }
 
         private static void EmitReadIntFallback(ArmEmitterContext context, Operand address, int rt, int size)
+        {
+            SetInt(context, rt, EmitReadIntFallback(context, address, size));
+        }
+
+        private static Operand EmitReadIntFallback(ArmEmitterContext context, Operand address, int size)
         {
             MethodInfo info = null;
 
@@ -430,7 +470,7 @@ namespace ARMeilleure.Instructions
                 case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break;
             }
 
-            SetInt(context, rt, context.Call(info, address));
+            return context.Call(info, address);
         }
 
         private static void EmitReadVectorFallback(
diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs
index 0d63820b75..f2c95ae98b 100644
--- a/ARMeilleure/Instructions/InstName.cs
+++ b/ARMeilleure/Instructions/InstName.cs
@@ -545,6 +545,8 @@ namespace ARMeilleure.Instructions
         Strexh,
         Strh,
         Sxtb16,
+        Tbb,
+        Tbh,
         Teq,
         Trap,
         Tst,
diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs
index dd24e37334..3a950354e8 100644
--- a/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/ARMeilleure/Translation/PTC/Ptc.cs
@@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
         private const string OuterHeaderMagicString = "PTCohd\0\0";
         private const string InnerHeaderMagicString = "PTCihd\0\0";
 
-        private const uint InternalVersion = 3677; //! To be incremented manually for each change to the ARMeilleure project.
+        private const uint InternalVersion = 3683; //! To be incremented manually for each change to the ARMeilleure project.
 
         private const string ActualDir = "0";
         private const string BackupDir = "1";