aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Instructions/InstEmitFlow32.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/Instructions/InstEmitFlow32.cs')
-rw-r--r--ARMeilleure/Instructions/InstEmitFlow32.cs50
1 files changed, 37 insertions, 13 deletions
diff --git a/ARMeilleure/Instructions/InstEmitFlow32.cs b/ARMeilleure/Instructions/InstEmitFlow32.cs
index 27addc78..cbb9ad5b 100644
--- a/ARMeilleure/Instructions/InstEmitFlow32.cs
+++ b/ARMeilleure/Instructions/InstEmitFlow32.cs
@@ -1,7 +1,9 @@
using ARMeilleure.Decoders;
+using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
+using static ARMeilleure.Instructions.InstEmitFlowHelper;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@@ -20,7 +22,6 @@ namespace ARMeilleure.Instructions
else
{
context.StoreToContext();
-
context.Return(Const(op.Immediate));
}
}
@@ -35,15 +36,6 @@ namespace ARMeilleure.Instructions
Blx(context, x: true);
}
- public static void Bx(ArmEmitterContext context)
- {
- IOpCode32BReg op = (IOpCode32BReg)context.CurrOp;
-
- context.StoreToContext();
-
- EmitBxWritePc(context, GetIntA32(context, op.Rm));
- }
-
private static void Blx(ArmEmitterContext context, bool x)
{
IOpCode32BImm op = (IOpCode32BImm)context.CurrOp;
@@ -53,10 +45,10 @@ namespace ARMeilleure.Instructions
bool isThumb = IsThumb(context.CurrOp);
uint currentPc = isThumb
- ? op.GetPc() | 1
- : op.GetPc() - 4;
+ ? pc | 1
+ : pc - 4;
- SetIntOrSP(context, GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr), Const(currentPc));
+ SetIntA32(context, GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr), Const(currentPc));
// If x is true, then this is a branch with link and exchange.
// In this case we need to swap the mode between Arm <-> Thumb.
@@ -67,5 +59,37 @@ namespace ARMeilleure.Instructions
InstEmitFlowHelper.EmitCall(context, (ulong)op.Immediate);
}
+
+ public static void Blxr(ArmEmitterContext context)
+ {
+ IOpCode32BReg op = (IOpCode32BReg)context.CurrOp;
+
+ uint pc = op.GetPc();
+
+ Operand addr = GetIntA32(context, op.Rm);
+ Operand bitOne = context.BitwiseAnd(addr, Const(1));
+ addr = context.BitwiseOr(addr, Const((int)CallFlag)); // Set call flag.
+
+ bool isThumb = IsThumb(context.CurrOp);
+
+ uint currentPc = isThumb
+ ? pc | 1
+ : pc - 4;
+
+ SetIntA32(context, GetBankedRegisterAlias(context.Mode, RegisterAlias.Aarch32Lr), Const(currentPc));
+
+ SetFlag(context, PState.TFlag, bitOne);
+
+ context.Return(addr); // Call.
+ }
+
+ public static void Bx(ArmEmitterContext context)
+ {
+ IOpCode32BReg op = (IOpCode32BReg)context.CurrOp;
+
+ context.StoreToContext();
+
+ EmitBxWritePc(context, GetIntA32(context, op.Rm));
+ }
}
} \ No newline at end of file