aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Instructions
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/Instructions')
-rw-r--r--ARMeilleure/Instructions/InstEmitFlow32.cs25
-rw-r--r--ARMeilleure/Instructions/InstEmitMemory32.cs16
-rw-r--r--ARMeilleure/Instructions/InstEmitMemoryHelper.cs42
-rw-r--r--ARMeilleure/Instructions/InstName.cs2
4 files changed, 76 insertions, 9 deletions
diff --git a/ARMeilleure/Instructions/InstEmitFlow32.cs b/ARMeilleure/Instructions/InstEmitFlow32.cs
index 030713fb..19524b42 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 e15f6a5b..17ec97aa 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 2877d53e..f97e395c 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();
@@ -420,6 +455,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;
switch (size)
@@ -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 0d63820b..f2c95ae9 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,