diff options
Diffstat (limited to 'ARMeilleure/Translation/RegisterUsage.cs')
| -rw-r--r-- | ARMeilleure/Translation/RegisterUsage.cs | 37 |
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; } |
