aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Translation/RegisterUsage.cs
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/Translation/RegisterUsage.cs')
-rw-r--r--ARMeilleure/Translation/RegisterUsage.cs37
1 files changed, 22 insertions, 15 deletions
diff --git a/ARMeilleure/Translation/RegisterUsage.cs b/ARMeilleure/Translation/RegisterUsage.cs
index becaa24c..84dfce7b 100644
--- a/ARMeilleure/Translation/RegisterUsage.cs
+++ b/ARMeilleure/Translation/RegisterUsage.cs
@@ -10,6 +10,7 @@ namespace ARMeilleure.Translation
{
private const long CallerSavedIntRegistersMask = 0x7fL << 9;
private const long PStateNzcvFlagsMask = 0xfL << 60;
+ private const long FpStateNzcvFlagsMask = 0xfL << 60;
private const long CallerSavedVecRegistersMask = 0xffffL << 16;
@@ -68,7 +69,7 @@ namespace ARMeilleure.Translation
}
}
- public static void RunPass(ControlFlowGraph cfg, bool isCompleteFunction)
+ public static void RunPass(ControlFlowGraph cfg, ExecutionMode mode, bool isCompleteFunction)
{
// Compute local register inputs and outputs used inside blocks.
RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count];
@@ -205,8 +206,8 @@ namespace ARMeilleure.Translation
// It always needs a context load as it is the first block to run.
if (block.Predecessors.Count == 0 || hasContextLoad)
{
- LoadLocals(block, globalInputs[block.Index].VecMask, RegisterType.Vector);
- LoadLocals(block, globalInputs[block.Index].IntMask, RegisterType.Integer);
+ LoadLocals(block, globalInputs[block.Index].VecMask, RegisterType.Vector, mode);
+ LoadLocals(block, globalInputs[block.Index].IntMask, RegisterType.Integer, mode);
}
bool hasContextStore = HasContextStore(block);
@@ -218,8 +219,8 @@ namespace ARMeilleure.Translation
if (EndsWithReturn(block) || hasContextStore)
{
- StoreLocals(block, globalOutputs[block.Index].IntMask, RegisterType.Integer, isCompleteFunction);
- StoreLocals(block, globalOutputs[block.Index].VecMask, RegisterType.Vector, isCompleteFunction);
+ StoreLocals(block, globalOutputs[block.Index].IntMask, RegisterType.Integer, mode, isCompleteFunction);
+ StoreLocals(block, globalOutputs[block.Index].VecMask, RegisterType.Vector, mode, isCompleteFunction);
}
}
}
@@ -263,6 +264,7 @@ namespace ARMeilleure.Translation
{
case RegisterType.Flag: intMask = (1L << RegsCount) << register.Index; break;
case RegisterType.Integer: intMask = 1L << register.Index; break;
+ case RegisterType.FpFlag: vecMask = (1L << RegsCount) << register.Index; break;
case RegisterType.Vector: vecMask = 1L << register.Index; break;
}
@@ -278,7 +280,7 @@ namespace ARMeilleure.Translation
return oldValue != value;
}
- private static void LoadLocals(BasicBlock block, long inputs, RegisterType baseType)
+ private static void LoadLocals(BasicBlock block, long inputs, RegisterType baseType, ExecutionMode mode)
{
Operand arg0 = Local(OperandType.I64);
@@ -291,7 +293,7 @@ namespace ARMeilleure.Translation
continue;
}
- Operand dest = GetRegFromBit(bit, baseType);
+ Operand dest = GetRegFromBit(bit, baseType, mode);
long offset = NativeContext.GetRegisterOffset(dest.GetRegister());
@@ -311,7 +313,7 @@ namespace ARMeilleure.Translation
block.Operations.AddFirst(loadArg0);
}
- private static void StoreLocals(BasicBlock block, long outputs, RegisterType baseType, bool isCompleteFunction)
+ private static void StoreLocals(BasicBlock block, long outputs, RegisterType baseType, ExecutionMode mode, bool isCompleteFunction)
{
if (Optimizations.AssumeStrictAbiCompliance && isCompleteFunction)
{
@@ -319,7 +321,7 @@ namespace ARMeilleure.Translation
{
outputs = ClearCallerSavedIntRegs(outputs);
}
- else /* if (baseType == RegisterType.Vector) */
+ else /* if (baseType == RegisterType.Vector || baseType == RegisterType.FpFlag) */
{
outputs = ClearCallerSavedVecRegs(outputs);
}
@@ -340,7 +342,7 @@ namespace ARMeilleure.Translation
continue;
}
- Operand source = GetRegFromBit(bit, baseType);
+ Operand source = GetRegFromBit(bit, baseType, mode);
long offset = NativeContext.GetRegisterOffset(source.GetRegister());
@@ -356,28 +358,33 @@ namespace ARMeilleure.Translation
}
}
- private static Operand GetRegFromBit(int bit, RegisterType baseType)
+ private static Operand GetRegFromBit(int bit, RegisterType baseType, ExecutionMode mode)
{
if (bit < RegsCount)
{
- return new Operand(bit, baseType, GetOperandType(baseType));
+ return new Operand(bit, baseType, GetOperandType(baseType, mode));
}
else if (baseType == RegisterType.Integer)
{
return new Operand(bit & RegsMask, RegisterType.Flag, OperandType.I32);
}
+ else if (baseType == RegisterType.Vector)
+ {
+ return new Operand(bit & RegsMask, RegisterType.FpFlag, OperandType.I32);
+ }
else
{
throw new ArgumentOutOfRangeException(nameof(bit));
}
}
- private static OperandType GetOperandType(RegisterType type)
+ private static OperandType GetOperandType(RegisterType type, ExecutionMode mode)
{
switch (type)
{
case RegisterType.Flag: return OperandType.I32;
- case RegisterType.Integer: return OperandType.I64;
+ case RegisterType.FpFlag: return OperandType.I32;
+ case RegisterType.Integer: return (mode == ExecutionMode.Aarch64) ? OperandType.I64 : OperandType.I32;
case RegisterType.Vector: return OperandType.V128;
}
@@ -405,7 +412,7 @@ namespace ARMeilleure.Translation
private static long ClearCallerSavedVecRegs(long mask)
{
// TODO: ARM32 support.
- mask &= ~CallerSavedVecRegistersMask;
+ mask &= ~(CallerSavedVecRegistersMask | FpStateNzcvFlagsMask);
return mask;
}