Fix a few suboptimal ARM32 codegen issues, only loads should be considered on decoder when checking if Rt == PC, and only NZCV flags should be considered for comparison optimizations

This commit is contained in:
gdkchan 2019-01-27 12:36:53 -02:00
commit 266a703c67
6 changed files with 40 additions and 16 deletions

View file

@ -181,29 +181,31 @@ namespace ChocolArm64.Decoders
{
int rt, rn;
bool wBack;
bool wBack, isLoad;
if (opCode is IOpCode32Mem opMem)
{
rt = opMem.Rt;
rn = opMem.Rn;
wBack = opMem.WBack;
rt = opMem.Rt;
rn = opMem.Rn;
wBack = opMem.WBack;
isLoad = opMem.IsLoad;
}
else if (opCode is IOpCode32MemMult opMemMult)
{
const int pcMask = 1 << RegisterAlias.Aarch32Pc;
rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0;
rn = opMemMult.Rn;
wBack = opMemMult.PostOffset != 0;
rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0;
rn = opMemMult.Rn;
wBack = opMemMult.PostOffset != 0;
isLoad = opMemMult.IsLoad;
}
else
{
throw new NotImplementedException($"The type \"{opCode.GetType().Name}\" is not implemented on the decoder.");
}
if ((rn == RegisterAlias.Aarch32Pc && wBack) ||
rt == RegisterAlias.Aarch32Pc)
if ((rt == RegisterAlias.Aarch32Pc && isLoad) ||
(rn == RegisterAlias.Aarch32Pc && wBack))
{
return true;
}

View file

@ -6,5 +6,7 @@ namespace ChocolArm64.Decoders
int Rn { get; }
bool WBack { get; }
bool IsLoad { get; }
}
}

View file

@ -7,5 +7,7 @@ namespace ChocolArm64.Decoders
int RegisterMask { get; }
int PostOffset { get; }
bool IsLoad { get; }
}
}

View file

@ -14,19 +14,24 @@ namespace ChocolArm64.Decoders
public bool WBack { get; private set; }
public bool Unprivileged { get; private set; }
public bool IsLoad { get; private set; }
public OpCode32Mem(Inst inst, long position, int opCode) : base(inst, position, opCode)
{
Rt = (opCode >> 12) & 0xf;
Rn = (opCode >> 16) & 0xf;
bool w = (opCode & (1 << 21)) != 0;
bool u = (opCode & (1 << 23)) != 0;
bool p = (opCode & (1 << 24)) != 0;
bool isLoad = (opCode & (1 << 20)) != 0;
bool w = (opCode & (1 << 21)) != 0;
bool u = (opCode & (1 << 23)) != 0;
bool p = (opCode & (1 << 24)) != 0;
Index = p;
Add = u;
WBack = !p || w;
Unprivileged = !p && w;
IsLoad = isLoad || inst.Emitter == InstEmit32.Ldrd;
}
}
}

View file

@ -10,13 +10,16 @@ namespace ChocolArm64.Decoders
public int Offset { get; private set; }
public int PostOffset { get; private set; }
public bool IsLoad { get; private set; }
public OpCode32MemMult(Inst inst, long position, int opCode) : base(inst, position, opCode)
{
Rn = (opCode >> 16) & 0xf;
bool w = (opCode & (1 << 21)) != 0;
bool u = (opCode & (1 << 23)) != 0;
bool p = (opCode & (1 << 24)) != 0;
bool isLoad = (opCode & (1 << 20)) != 0;
bool w = (opCode & (1 << 21)) != 0;
bool u = (opCode & (1 << 23)) != 0;
bool p = (opCode & (1 << 24)) != 0;
RegisterMask = opCode & 0xffff;
@ -47,6 +50,8 @@ namespace ChocolArm64.Decoders
{
PostOffset = 0;
}
IsLoad = isLoad;
}
}
}

View file

@ -530,7 +530,15 @@ namespace ChocolArm64.Translation
public void EmitLdflg(int index) => Ldloc(index, IoType.Flag);
public void EmitStflg(int index)
{
_optOpLastFlagSet = CurrOp;
//Set this only if any of the NZCV flag bits were modified.
//This is used to ensure that, when emiting a direct IL branch
//instruction for compare + branch sequences, we're not expecting
//to use comparison values from an old instruction, when in fact
//the flags were already overwritten by another instruction further along.
if (index >= (int)PState.VBit)
{
_optOpLastFlagSet = CurrOp;
}
Stloc(index, IoType.Flag);
}