Refactoring
This commit is contained in:
parent
b73a8ef01d
commit
18678035f5
15 changed files with 102 additions and 103 deletions
|
@ -41,18 +41,18 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
switch (ld.IoType)
|
switch (ld.IoType)
|
||||||
{
|
{
|
||||||
case IoType.Flag: IntInputs |= ((1L << ld.Index) << 32) & ~_intAwOutputs; break;
|
case VarType.Flag: IntInputs |= ((1L << ld.Index) << 32) & ~_intAwOutputs; break;
|
||||||
case IoType.Int: IntInputs |= (1L << ld.Index) & ~_intAwOutputs; break;
|
case VarType.Int: IntInputs |= (1L << ld.Index) & ~_intAwOutputs; break;
|
||||||
case IoType.Vector: VecInputs |= (1L << ld.Index) & ~_vecAwOutputs; break;
|
case VarType.Vector: VecInputs |= (1L << ld.Index) & ~_vecAwOutputs; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (emitter is ILOpCodeStore st && ILMethodBuilder.IsRegIndex(st.Index))
|
else if (emitter is ILOpCodeStore st && ILMethodBuilder.IsRegIndex(st.Index))
|
||||||
{
|
{
|
||||||
switch (st.IoType)
|
switch (st.IoType)
|
||||||
{
|
{
|
||||||
case IoType.Flag: IntOutputs |= (1L << st.Index) << 32; break;
|
case VarType.Flag: IntOutputs |= (1L << st.Index) << 32; break;
|
||||||
case IoType.Int: IntOutputs |= 1L << st.Index; break;
|
case VarType.Int: IntOutputs |= 1L << st.Index; break;
|
||||||
case IoType.Vector: VecOutputs |= 1L << st.Index; break;
|
case VarType.Vector: VecOutputs |= 1L << st.Index; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (emitter is ILOpCodeStoreState)
|
else if (emitter is ILOpCodeStoreState)
|
||||||
|
|
|
@ -336,8 +336,8 @@ namespace ChocolArm64.Translation
|
||||||
|
|
||||||
InstEmitAluHelper.EmitAluLoadOpers(this);
|
InstEmitAluHelper.EmitAluLoadOpers(this);
|
||||||
|
|
||||||
Stloc(CmpOptTmp2Index, IoType.Int);
|
Stloc(CmpOptTmp2Index, VarType.Int);
|
||||||
Stloc(CmpOptTmp1Index, IoType.Int);
|
Stloc(CmpOptTmp1Index, VarType.Int);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<Condition, OpCode> _branchOps = new Dictionary<Condition, OpCode>()
|
private Dictionary<Condition, OpCode> _branchOps = new Dictionary<Condition, OpCode>()
|
||||||
|
@ -361,8 +361,8 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
if (_optOpLastCompare.Emitter == InstEmit.Subs)
|
if (_optOpLastCompare.Emitter == InstEmit.Subs)
|
||||||
{
|
{
|
||||||
Ldloc(CmpOptTmp1Index, IoType.Int, _optOpLastCompare.RegisterSize);
|
Ldloc(CmpOptTmp1Index, VarType.Int, _optOpLastCompare.RegisterSize);
|
||||||
Ldloc(CmpOptTmp2Index, IoType.Int, _optOpLastCompare.RegisterSize);
|
Ldloc(CmpOptTmp2Index, VarType.Int, _optOpLastCompare.RegisterSize);
|
||||||
|
|
||||||
Emit(_branchOps[cond], target);
|
Emit(_branchOps[cond], target);
|
||||||
|
|
||||||
|
@ -384,7 +384,7 @@ namespace ChocolArm64.Translation
|
||||||
//Such invalid values can't be encoded on the immediate encodings.
|
//Such invalid values can't be encoded on the immediate encodings.
|
||||||
if (_optOpLastCompare is IOpCodeAluImm64 op)
|
if (_optOpLastCompare is IOpCodeAluImm64 op)
|
||||||
{
|
{
|
||||||
Ldloc(CmpOptTmp1Index, IoType.Int, _optOpLastCompare.RegisterSize);
|
Ldloc(CmpOptTmp1Index, VarType.Int, _optOpLastCompare.RegisterSize);
|
||||||
|
|
||||||
if (_optOpLastCompare.RegisterSize == RegisterSize.Int32)
|
if (_optOpLastCompare.RegisterSize == RegisterSize.Int32)
|
||||||
{
|
{
|
||||||
|
@ -506,14 +506,14 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
if (amount > 0)
|
if (amount > 0)
|
||||||
{
|
{
|
||||||
Stloc(RorTmpIndex, IoType.Int);
|
Stloc(RorTmpIndex, VarType.Int);
|
||||||
Ldloc(RorTmpIndex, IoType.Int);
|
Ldloc(RorTmpIndex, VarType.Int);
|
||||||
|
|
||||||
EmitLdc_I4(amount);
|
EmitLdc_I4(amount);
|
||||||
|
|
||||||
Emit(OpCodes.Shr_Un);
|
Emit(OpCodes.Shr_Un);
|
||||||
|
|
||||||
Ldloc(RorTmpIndex, IoType.Int);
|
Ldloc(RorTmpIndex, VarType.Int);
|
||||||
|
|
||||||
EmitLdc_I4(CurrOp.GetBitsCount() - amount);
|
EmitLdc_I4(CurrOp.GetBitsCount() - amount);
|
||||||
|
|
||||||
|
@ -561,7 +561,7 @@ namespace ChocolArm64.Translation
|
||||||
|
|
||||||
public void EmitLdarg(int index)
|
public void EmitLdarg(int index)
|
||||||
{
|
{
|
||||||
_ilBlock.Add(new ILOpCodeLoad(index, IoType.Arg));
|
_ilBlock.Add(new ILOpCodeLoad(index, VarType.Arg));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EmitLdintzr(int index)
|
public void EmitLdintzr(int index)
|
||||||
|
@ -615,13 +615,13 @@ namespace ChocolArm64.Translation
|
||||||
public void EmitLdvectmp2() => EmitLdvec(VecGpTmp2Index);
|
public void EmitLdvectmp2() => EmitLdvec(VecGpTmp2Index);
|
||||||
public void EmitStvectmp2() => EmitStvec(VecGpTmp2Index);
|
public void EmitStvectmp2() => EmitStvec(VecGpTmp2Index);
|
||||||
|
|
||||||
public void EmitLdint(int index) => Ldloc(index, IoType.Int);
|
public void EmitLdint(int index) => Ldloc(index, VarType.Int);
|
||||||
public void EmitStint(int index) => Stloc(index, IoType.Int);
|
public void EmitStint(int index) => Stloc(index, VarType.Int);
|
||||||
|
|
||||||
public void EmitLdvec(int index) => Ldloc(index, IoType.Vector);
|
public void EmitLdvec(int index) => Ldloc(index, VarType.Vector);
|
||||||
public void EmitStvec(int index) => Stloc(index, IoType.Vector);
|
public void EmitStvec(int index) => Stloc(index, VarType.Vector);
|
||||||
|
|
||||||
public void EmitLdflg(int index) => Ldloc(index, IoType.Flag);
|
public void EmitLdflg(int index) => Ldloc(index, VarType.Flag);
|
||||||
public void EmitStflg(int index)
|
public void EmitStflg(int index)
|
||||||
{
|
{
|
||||||
//Set this only if any of the NZCV flag bits were modified.
|
//Set this only if any of the NZCV flag bits were modified.
|
||||||
|
@ -634,20 +634,20 @@ namespace ChocolArm64.Translation
|
||||||
_optOpLastFlagSet = CurrOp;
|
_optOpLastFlagSet = CurrOp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stloc(index, IoType.Flag);
|
Stloc(index, VarType.Flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Ldloc(int index, IoType ioType)
|
private void Ldloc(int index, VarType ioType)
|
||||||
{
|
{
|
||||||
_ilBlock.Add(new ILOpCodeLoad(index, ioType, CurrOp.RegisterSize));
|
_ilBlock.Add(new ILOpCodeLoad(index, ioType, CurrOp.RegisterSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Ldloc(int index, IoType ioType, RegisterSize registerSize)
|
private void Ldloc(int index, VarType ioType, RegisterSize registerSize)
|
||||||
{
|
{
|
||||||
_ilBlock.Add(new ILOpCodeLoad(index, ioType, registerSize));
|
_ilBlock.Add(new ILOpCodeLoad(index, ioType, registerSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Stloc(int index, IoType ioType)
|
private void Stloc(int index, VarType ioType)
|
||||||
{
|
{
|
||||||
_ilBlock.Add(new ILOpCodeStore(index, ioType, CurrOp.RegisterSize));
|
_ilBlock.Add(new ILOpCodeStore(index, ioType, CurrOp.RegisterSize));
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,10 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
class ILMethodBuilder
|
class ILMethodBuilder
|
||||||
{
|
{
|
||||||
public LocalAlloc LocalAlloc { get; private set; }
|
private const int RegsCount = 32;
|
||||||
|
private const int RegsMask = RegsCount - 1;
|
||||||
|
|
||||||
|
public RegisterUsage RegUsage { get; private set; }
|
||||||
|
|
||||||
public ILGenerator Generator { get; private set; }
|
public ILGenerator Generator { get; private set; }
|
||||||
|
|
||||||
|
@ -38,20 +41,20 @@ namespace ChocolArm64.Translation
|
||||||
|
|
||||||
public TranslatedSub GetSubroutine(TranslationTier tier)
|
public TranslatedSub GetSubroutine(TranslationTier tier)
|
||||||
{
|
{
|
||||||
LocalAlloc = new LocalAlloc();
|
RegUsage = new RegisterUsage();
|
||||||
|
|
||||||
LocalAlloc.BuildUses(_ilBlocks[0]);
|
RegUsage.BuildUses(_ilBlocks[0]);
|
||||||
|
|
||||||
DynamicMethod method = new DynamicMethod(_subName, typeof(long), TranslatedSub.FixedArgTypes);
|
DynamicMethod method = new DynamicMethod(_subName, typeof(long), TranslatedSub.FixedArgTypes);
|
||||||
|
|
||||||
Generator = method.GetILGenerator();
|
|
||||||
|
|
||||||
TranslatedSub subroutine = new TranslatedSub(method, tier);
|
TranslatedSub subroutine = new TranslatedSub(method, tier);
|
||||||
|
|
||||||
_locals = new Dictionary<Register, int>();
|
_locals = new Dictionary<Register, int>();
|
||||||
|
|
||||||
_localsCount = 0;
|
_localsCount = 0;
|
||||||
|
|
||||||
|
Generator = method.GetILGenerator();
|
||||||
|
|
||||||
foreach (ILBlock ilBlock in _ilBlocks)
|
foreach (ILBlock ilBlock in _ilBlocks)
|
||||||
{
|
{
|
||||||
ilBlock.Emit(this);
|
ilBlock.Emit(this);
|
||||||
|
@ -90,13 +93,13 @@ namespace ChocolArm64.Translation
|
||||||
|
|
||||||
public static Register GetRegFromBit(int bit, RegisterType baseType)
|
public static Register GetRegFromBit(int bit, RegisterType baseType)
|
||||||
{
|
{
|
||||||
if (bit < 32)
|
if (bit < RegsCount)
|
||||||
{
|
{
|
||||||
return new Register(bit, baseType);
|
return new Register(bit, baseType);
|
||||||
}
|
}
|
||||||
else if (baseType == RegisterType.Int)
|
else if (baseType == RegisterType.Int)
|
||||||
{
|
{
|
||||||
return new Register(bit & 0x1f, RegisterType.Flag);
|
return new Register(bit & RegsMask, RegisterType.Flag);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -106,7 +109,7 @@ namespace ChocolArm64.Translation
|
||||||
|
|
||||||
public static bool IsRegIndex(int index)
|
public static bool IsRegIndex(int index)
|
||||||
{
|
{
|
||||||
return (uint)index < 32;
|
return (uint)index < RegsCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,16 +4,16 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
struct ILOpCode : IILEmit
|
struct ILOpCode : IILEmit
|
||||||
{
|
{
|
||||||
private OpCode _ilOp;
|
public OpCode ILOp { get; }
|
||||||
|
|
||||||
public ILOpCode(OpCode ilOp)
|
public ILOpCode(OpCode ilOp)
|
||||||
{
|
{
|
||||||
_ilOp = ilOp;
|
ILOp = ilOp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Emit(ILMethodBuilder context)
|
public void Emit(ILMethodBuilder context)
|
||||||
{
|
{
|
||||||
context.Generator.Emit(_ilOp);
|
context.Generator.Emit(ILOp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,18 +4,18 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
struct ILOpCodeBranch : IILEmit
|
struct ILOpCodeBranch : IILEmit
|
||||||
{
|
{
|
||||||
private OpCode _ilOp;
|
public OpCode ILOp { get; }
|
||||||
private ILLabel _label;
|
public ILLabel Label { get; }
|
||||||
|
|
||||||
public ILOpCodeBranch(OpCode ilOp, ILLabel label)
|
public ILOpCodeBranch(OpCode ilOp, ILLabel label)
|
||||||
{
|
{
|
||||||
_ilOp = ilOp;
|
ILOp = ilOp;
|
||||||
_label = label;
|
Label = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Emit(ILMethodBuilder context)
|
public void Emit(ILMethodBuilder context)
|
||||||
{
|
{
|
||||||
context.Generator.Emit(_ilOp, _label.GetLabel(context));
|
context.Generator.Emit(ILOp, Label.GetLabel(context));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,9 +5,9 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
struct ILOpCodeCall : IILEmit
|
struct ILOpCodeCall : IILEmit
|
||||||
{
|
{
|
||||||
public MethodInfo Info { get; private set; }
|
public MethodInfo Info { get; }
|
||||||
|
|
||||||
public bool IsVirtual { get; private set; }
|
public bool IsVirtual { get; }
|
||||||
|
|
||||||
public ILOpCodeCall(MethodInfo info, bool isVirtual)
|
public ILOpCodeCall(MethodInfo info, bool isVirtual)
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,6 +16,8 @@ namespace ChocolArm64.Translation
|
||||||
|
|
||||||
private ImmVal _value;
|
private ImmVal _value;
|
||||||
|
|
||||||
|
public long Value => _value.I8;
|
||||||
|
|
||||||
private enum ConstType
|
private enum ConstType
|
||||||
{
|
{
|
||||||
Int32,
|
Int32,
|
||||||
|
|
|
@ -5,13 +5,13 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
struct ILOpCodeLoad : IILEmit
|
struct ILOpCodeLoad : IILEmit
|
||||||
{
|
{
|
||||||
public int Index { get; private set; }
|
public int Index { get; }
|
||||||
|
|
||||||
public IoType IoType { get; private set; }
|
public VarType IoType { get; }
|
||||||
|
|
||||||
public RegisterSize RegisterSize { get; private set; }
|
public RegisterSize RegisterSize { get; }
|
||||||
|
|
||||||
public ILOpCodeLoad(int index, IoType ioType, RegisterSize registerSize = 0)
|
public ILOpCodeLoad(int index, VarType ioType, RegisterSize registerSize = 0)
|
||||||
{
|
{
|
||||||
Index = index;
|
Index = index;
|
||||||
IoType = ioType;
|
IoType = ioType;
|
||||||
|
@ -22,11 +22,11 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
switch (IoType)
|
switch (IoType)
|
||||||
{
|
{
|
||||||
case IoType.Arg: context.Generator.EmitLdarg(Index); break;
|
case VarType.Arg: context.Generator.EmitLdarg(Index); break;
|
||||||
|
|
||||||
case IoType.Flag: EmitLdloc(context, Index, RegisterType.Flag); break;
|
case VarType.Flag: EmitLdloc(context, Index, RegisterType.Flag); break;
|
||||||
case IoType.Int: EmitLdloc(context, Index, RegisterType.Int); break;
|
case VarType.Int: EmitLdloc(context, Index, RegisterType.Int); break;
|
||||||
case IoType.Vector: EmitLdloc(context, Index, RegisterType.Vector); break;
|
case VarType.Vector: EmitLdloc(context, Index, RegisterType.Vector); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
struct ILOpCodeLoadField : IILEmit
|
struct ILOpCodeLoadField : IILEmit
|
||||||
{
|
{
|
||||||
public FieldInfo Info { get; private set; }
|
public FieldInfo Info { get; }
|
||||||
|
|
||||||
public ILOpCodeLoadField(FieldInfo info)
|
public ILOpCodeLoadField(FieldInfo info)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,13 +17,13 @@ namespace ChocolArm64.Translation
|
||||||
|
|
||||||
public void Emit(ILMethodBuilder context)
|
public void Emit(ILMethodBuilder context)
|
||||||
{
|
{
|
||||||
long intInputs = context.LocalAlloc.GetIntInputs(_block);
|
long intInputs = context.RegUsage.GetIntInputs(_block);
|
||||||
long vecInputs = context.LocalAlloc.GetVecInputs(_block);
|
long vecInputs = context.RegUsage.GetVecInputs(_block);
|
||||||
|
|
||||||
if (Optimizations.AssumeStrictAbiCompliance && context.IsSubComplete)
|
if (Optimizations.AssumeStrictAbiCompliance && context.IsSubComplete)
|
||||||
{
|
{
|
||||||
intInputs = LocalAlloc.ClearCallerSavedIntRegs(intInputs, context.IsAarch64);
|
intInputs = RegisterUsage.ClearCallerSavedIntRegs(intInputs, context.IsAarch64);
|
||||||
vecInputs = LocalAlloc.ClearCallerSavedVecRegs(vecInputs, context.IsAarch64);
|
vecInputs = RegisterUsage.ClearCallerSavedVecRegs(vecInputs, context.IsAarch64);
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadLocals(context, intInputs, RegisterType.Int);
|
LoadLocals(context, intInputs, RegisterType.Int);
|
||||||
|
|
|
@ -2,16 +2,16 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
struct ILOpCodeLog : IILEmit
|
struct ILOpCodeLog : IILEmit
|
||||||
{
|
{
|
||||||
private string _text;
|
public string Text { get; }
|
||||||
|
|
||||||
public ILOpCodeLog(string text)
|
public ILOpCodeLog(string text)
|
||||||
{
|
{
|
||||||
_text = text;
|
Text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Emit(ILMethodBuilder context)
|
public void Emit(ILMethodBuilder context)
|
||||||
{
|
{
|
||||||
context.Generator.EmitWriteLine(_text);
|
context.Generator.EmitWriteLine(Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,13 +5,13 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
struct ILOpCodeStore : IILEmit
|
struct ILOpCodeStore : IILEmit
|
||||||
{
|
{
|
||||||
public int Index { get; private set; }
|
public int Index { get; }
|
||||||
|
|
||||||
public IoType IoType { get; private set; }
|
public VarType IoType { get; }
|
||||||
|
|
||||||
public RegisterSize RegisterSize { get; private set; }
|
public RegisterSize RegisterSize { get; }
|
||||||
|
|
||||||
public ILOpCodeStore(int index, IoType ioType, RegisterSize registerSize = 0)
|
public ILOpCodeStore(int index, VarType ioType, RegisterSize registerSize = 0)
|
||||||
{
|
{
|
||||||
Index = index;
|
Index = index;
|
||||||
IoType = ioType;
|
IoType = ioType;
|
||||||
|
@ -22,11 +22,11 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
switch (IoType)
|
switch (IoType)
|
||||||
{
|
{
|
||||||
case IoType.Arg: context.Generator.EmitStarg(Index); break;
|
case VarType.Arg: context.Generator.EmitStarg(Index); break;
|
||||||
|
|
||||||
case IoType.Flag: EmitStloc(context, Index, RegisterType.Flag); break;
|
case VarType.Flag: EmitStloc(context, Index, RegisterType.Flag); break;
|
||||||
case IoType.Int: EmitStloc(context, Index, RegisterType.Int); break;
|
case VarType.Int: EmitStloc(context, Index, RegisterType.Int); break;
|
||||||
case IoType.Vector: EmitStloc(context, Index, RegisterType.Vector); break;
|
case VarType.Vector: EmitStloc(context, Index, RegisterType.Vector); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ namespace ChocolArm64.Translation
|
||||||
|
|
||||||
public void Emit(ILMethodBuilder context)
|
public void Emit(ILMethodBuilder context)
|
||||||
{
|
{
|
||||||
long intOutputs = context.LocalAlloc.GetIntOutputs(_block);
|
long intOutputs = context.RegUsage.GetIntOutputs(_block);
|
||||||
long vecOutputs = context.LocalAlloc.GetVecOutputs(_block);
|
long vecOutputs = context.RegUsage.GetVecOutputs(_block);
|
||||||
|
|
||||||
if (Optimizations.AssumeStrictAbiCompliance && context.IsSubComplete)
|
if (Optimizations.AssumeStrictAbiCompliance && context.IsSubComplete)
|
||||||
{
|
{
|
||||||
intOutputs = LocalAlloc.ClearCallerSavedIntRegs(intOutputs, context.IsAarch64);
|
intOutputs = RegisterUsage.ClearCallerSavedIntRegs(intOutputs, context.IsAarch64);
|
||||||
vecOutputs = LocalAlloc.ClearCallerSavedVecRegs(vecOutputs, context.IsAarch64);
|
vecOutputs = RegisterUsage.ClearCallerSavedVecRegs(vecOutputs, context.IsAarch64);
|
||||||
}
|
}
|
||||||
|
|
||||||
StoreLocals(context, intOutputs, RegisterType.Int);
|
StoreLocals(context, intOutputs, RegisterType.Int);
|
||||||
|
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace ChocolArm64.Translation
|
namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
class LocalAlloc
|
class RegisterUsage
|
||||||
{
|
{
|
||||||
public const long CallerSavedIntRegistersMask = 0x7fL << 9;
|
public const long CallerSavedIntRegistersMask = 0x7fL << 9;
|
||||||
public const long PStateNzcvFlagsMask = 0xfL << 60;
|
public const long PStateNzcvFlagsMask = 0xfL << 60;
|
||||||
|
@ -23,31 +23,30 @@ namespace ChocolArm64.Translation
|
||||||
_cmnOutputs = new Dictionary<ILBlock, long>();
|
_cmnOutputs = new Dictionary<ILBlock, long>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PathIo(ILBlock root, long inputs, long outputs) : this()
|
public void Set(ILBlock entry, long inputs, long outputs)
|
||||||
{
|
{
|
||||||
Set(root, inputs, outputs);
|
if (!_allInputs.TryAdd(entry, inputs))
|
||||||
|
{
|
||||||
|
_allInputs[entry] |= inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Set(ILBlock root, long inputs, long outputs)
|
if (!_cmnOutputs.TryAdd(entry, outputs))
|
||||||
{
|
{
|
||||||
if (!_allInputs.TryAdd(root, inputs))
|
_cmnOutputs[entry] &= outputs;
|
||||||
{
|
|
||||||
_allInputs[root] |= inputs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_cmnOutputs.TryAdd(root, outputs))
|
|
||||||
{
|
|
||||||
_cmnOutputs[root] &= outputs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_allOutputs |= outputs;
|
_allOutputs |= outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetInputs(ILBlock root)
|
public long GetInputs(ILBlock entry)
|
||||||
{
|
{
|
||||||
if (_allInputs.TryGetValue(root, out long inputs))
|
if (_allInputs.TryGetValue(entry, out long inputs))
|
||||||
{
|
{
|
||||||
return inputs | (_allOutputs & ~_cmnOutputs[root]);
|
//We also need to read the registers that may not be written
|
||||||
|
//by all paths that can reach a exit point, to ensure that
|
||||||
|
//the local variable will not remain uninitialized depending
|
||||||
|
//on the flow path taken.
|
||||||
|
return inputs | (_allOutputs & ~_cmnOutputs[entry]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -62,9 +61,7 @@ namespace ChocolArm64.Translation
|
||||||
private Dictionary<ILBlock, PathIo> _intPaths;
|
private Dictionary<ILBlock, PathIo> _intPaths;
|
||||||
private Dictionary<ILBlock, PathIo> _vecPaths;
|
private Dictionary<ILBlock, PathIo> _vecPaths;
|
||||||
|
|
||||||
private HashSet<ILBlock> _entryBlocks;
|
private struct BlockIo : IEquatable<BlockIo>
|
||||||
|
|
||||||
private struct BlockIo
|
|
||||||
{
|
{
|
||||||
public ILBlock Block { get; }
|
public ILBlock Block { get; }
|
||||||
public ILBlock Entry { get; }
|
public ILBlock Entry { get; }
|
||||||
|
@ -104,6 +101,11 @@ namespace ChocolArm64.Translation
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return Equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(BlockIo other)
|
||||||
|
{
|
||||||
return other.Block == Block &&
|
return other.Block == Block &&
|
||||||
other.Entry == Entry &&
|
other.Entry == Entry &&
|
||||||
other.IntInputs == IntInputs &&
|
other.IntInputs == IntInputs &&
|
||||||
|
@ -128,12 +130,10 @@ namespace ChocolArm64.Translation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalAlloc()
|
public RegisterUsage()
|
||||||
{
|
{
|
||||||
_intPaths = new Dictionary<ILBlock, PathIo>();
|
_intPaths = new Dictionary<ILBlock, PathIo>();
|
||||||
_vecPaths = new Dictionary<ILBlock, PathIo>();
|
_vecPaths = new Dictionary<ILBlock, PathIo>();
|
||||||
|
|
||||||
_entryBlocks = new HashSet<ILBlock>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BuildUses(ILBlock entry)
|
public void BuildUses(ILBlock entry)
|
||||||
|
@ -144,7 +144,7 @@ namespace ChocolArm64.Translation
|
||||||
//When a block can be reached by more than one path, then the
|
//When a block can be reached by more than one path, then the
|
||||||
//output from all paths needs to be set for this block, and
|
//output from all paths needs to be set for this block, and
|
||||||
//only outputs present in all of the parent blocks can be considered
|
//only outputs present in all of the parent blocks can be considered
|
||||||
//when doing input elimination. Each block chain have a entry, that's where
|
//when doing input elimination. Each block chain has a entry, that's where
|
||||||
//the code starts executing. They are present on the subroutine start point,
|
//the code starts executing. They are present on the subroutine start point,
|
||||||
//and on call return points too (address written to X30 by BL).
|
//and on call return points too (address written to X30 by BL).
|
||||||
HashSet<BlockIo> visited = new HashSet<BlockIo>();
|
HashSet<BlockIo> visited = new HashSet<BlockIo>();
|
||||||
|
@ -159,8 +159,6 @@ namespace ChocolArm64.Translation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_entryBlocks.Add(entry);
|
|
||||||
|
|
||||||
Enqueue(new BlockIo(entry, entry));
|
Enqueue(new BlockIo(entry, entry));
|
||||||
|
|
||||||
while (unvisited.Count > 0)
|
while (unvisited.Count > 0)
|
||||||
|
@ -198,8 +196,6 @@ namespace ChocolArm64.Translation
|
||||||
if (retTarget)
|
if (retTarget)
|
||||||
{
|
{
|
||||||
blockIo = new BlockIo(block, block);
|
blockIo = new BlockIo(block, block);
|
||||||
|
|
||||||
_entryBlocks.Add(block);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -227,16 +223,16 @@ namespace ChocolArm64.Translation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long GetIntInputs(ILBlock root) => GetInputsImpl(root, _intPaths.Values);
|
public long GetIntInputs(ILBlock entry) => GetInputsImpl(entry, _intPaths.Values);
|
||||||
public long GetVecInputs(ILBlock root) => GetInputsImpl(root, _vecPaths.Values);
|
public long GetVecInputs(ILBlock entry) => GetInputsImpl(entry, _vecPaths.Values);
|
||||||
|
|
||||||
private long GetInputsImpl(ILBlock root, IEnumerable<PathIo> values)
|
private long GetInputsImpl(ILBlock entry, IEnumerable<PathIo> values)
|
||||||
{
|
{
|
||||||
long inputs = 0;
|
long inputs = 0;
|
||||||
|
|
||||||
foreach (PathIo path in values)
|
foreach (PathIo path in values)
|
||||||
{
|
{
|
||||||
inputs |= path.GetInputs(root);
|
inputs |= path.GetInputs(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
return inputs;
|
return inputs;
|
||||||
|
@ -250,11 +246,9 @@ namespace ChocolArm64.Translation
|
||||||
//TODO: ARM32 support.
|
//TODO: ARM32 support.
|
||||||
if (isAarch64)
|
if (isAarch64)
|
||||||
{
|
{
|
||||||
mask &= ~CallerSavedIntRegistersMask;
|
mask &= ~(CallerSavedIntRegistersMask | PStateNzcvFlagsMask);
|
||||||
mask &= ~PStateNzcvFlagsMask;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace ChocolArm64.Translation
|
namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
enum IoType
|
enum VarType
|
||||||
{
|
{
|
||||||
Arg,
|
Arg,
|
||||||
Flag,
|
Flag,
|
Loading…
Add table
Add a link
Reference in a new issue