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:
parent
9f55d3b77c
commit
266a703c67
6 changed files with 40 additions and 16 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -6,5 +6,7 @@ namespace ChocolArm64.Decoders
|
|||
int Rn { get; }
|
||||
|
||||
bool WBack { get; }
|
||||
|
||||
bool IsLoad { get; }
|
||||
}
|
||||
}
|
|
@ -7,5 +7,7 @@ namespace ChocolArm64.Decoders
|
|||
int RegisterMask { get; }
|
||||
|
||||
int PostOffset { get; }
|
||||
|
||||
bool IsLoad { get; }
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue