aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Translation
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/Translation')
-rw-r--r--ARMeilleure/Translation/RegisterUsage.cs37
-rw-r--r--ARMeilleure/Translation/RejitRequest.cs16
-rw-r--r--ARMeilleure/Translation/SsaConstruction.cs12
-rw-r--r--ARMeilleure/Translation/Translator.cs14
4 files changed, 55 insertions, 24 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;
}
diff --git a/ARMeilleure/Translation/RejitRequest.cs b/ARMeilleure/Translation/RejitRequest.cs
new file mode 100644
index 00000000..e0b0e0b9
--- /dev/null
+++ b/ARMeilleure/Translation/RejitRequest.cs
@@ -0,0 +1,16 @@
+using ARMeilleure.State;
+
+namespace ARMeilleure.Translation
+{
+ struct RejitRequest
+ {
+ public ulong Address;
+ public ExecutionMode Mode;
+
+ public RejitRequest(ulong address, ExecutionMode mode)
+ {
+ Address = address;
+ Mode = mode;
+ }
+ }
+}
diff --git a/ARMeilleure/Translation/SsaConstruction.cs b/ARMeilleure/Translation/SsaConstruction.cs
index 292e74e3..46435f44 100644
--- a/ARMeilleure/Translation/SsaConstruction.cs
+++ b/ARMeilleure/Translation/SsaConstruction.cs
@@ -268,10 +268,14 @@ namespace ARMeilleure.Translation
{
return RegisterConsts.IntRegsCount + reg.Index;
}
- else /* if (reg.Type == RegisterType.Flag) */
+ else if (reg.Type == RegisterType.Flag)
{
return RegisterConsts.IntAndVecRegsCount + reg.Index;
}
+ else /* if (reg.Type == RegisterType.FpFlag) */
+ {
+ return RegisterConsts.FpFlagsOffset + reg.Index;
+ }
}
private static Register GetRegisterFromId(int id)
@@ -284,10 +288,14 @@ namespace ARMeilleure.Translation
{
return new Register(id - RegisterConsts.IntRegsCount, RegisterType.Vector);
}
- else /* if (id < RegisterConsts.TotalCount) */
+ else if (id < RegisterConsts.FpFlagsOffset)
{
return new Register(id - RegisterConsts.IntAndVecRegsCount, RegisterType.Flag);
}
+ else /* if (id < RegisterConsts.TotalCount) */
+ {
+ return new Register(id - RegisterConsts.FpFlagsOffset, RegisterType.FpFlag);
+ }
}
}
} \ No newline at end of file
diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs
index 4725ca59..3008303e 100644
--- a/ARMeilleure/Translation/Translator.cs
+++ b/ARMeilleure/Translation/Translator.cs
@@ -20,7 +20,7 @@ namespace ARMeilleure.Translation
private ConcurrentDictionary<ulong, TranslatedFunction> _funcs;
- private PriorityQueue<ulong> _backgroundQueue;
+ private PriorityQueue<RejitRequest> _backgroundQueue;
private AutoResetEvent _backgroundTranslatorEvent;
@@ -32,7 +32,7 @@ namespace ARMeilleure.Translation
_funcs = new ConcurrentDictionary<ulong, TranslatedFunction>();
- _backgroundQueue = new PriorityQueue<ulong>(2);
+ _backgroundQueue = new PriorityQueue<RejitRequest>(2);
_backgroundTranslatorEvent = new AutoResetEvent(false);
}
@@ -41,11 +41,11 @@ namespace ARMeilleure.Translation
{
while (_threadCount != 0)
{
- if (_backgroundQueue.TryDequeue(out ulong address))
+ if (_backgroundQueue.TryDequeue(out RejitRequest request))
{
- TranslatedFunction func = Translate(address, ExecutionMode.Aarch64, highCq: true);
+ TranslatedFunction func = Translate(request.Address, request.Mode, highCq: true);
- _funcs.AddOrUpdate(address, func, (key, oldFunc) => func);
+ _funcs.AddOrUpdate(request.Address, func, (key, oldFunc) => func);
}
else
{
@@ -114,7 +114,7 @@ namespace ARMeilleure.Translation
}
else if (isCallTarget && func.ShouldRejit())
{
- _backgroundQueue.Enqueue(0, address);
+ _backgroundQueue.Enqueue(0, new RejitRequest(address, mode));
_backgroundTranslatorEvent.Set();
}
@@ -149,7 +149,7 @@ namespace ARMeilleure.Translation
Logger.StartPass(PassName.RegisterUsage);
- RegisterUsage.RunPass(cfg, isCompleteFunction: false);
+ RegisterUsage.RunPass(cfg, mode, isCompleteFunction: false);
Logger.EndPass(PassName.RegisterUsage);