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;
|
int rt, rn;
|
||||||
|
|
||||||
bool wBack;
|
bool wBack, isLoad;
|
||||||
|
|
||||||
if (opCode is IOpCode32Mem opMem)
|
if (opCode is IOpCode32Mem opMem)
|
||||||
{
|
{
|
||||||
rt = opMem.Rt;
|
rt = opMem.Rt;
|
||||||
rn = opMem.Rn;
|
rn = opMem.Rn;
|
||||||
wBack = opMem.WBack;
|
wBack = opMem.WBack;
|
||||||
|
isLoad = opMem.IsLoad;
|
||||||
}
|
}
|
||||||
else if (opCode is IOpCode32MemMult opMemMult)
|
else if (opCode is IOpCode32MemMult opMemMult)
|
||||||
{
|
{
|
||||||
const int pcMask = 1 << RegisterAlias.Aarch32Pc;
|
const int pcMask = 1 << RegisterAlias.Aarch32Pc;
|
||||||
|
|
||||||
rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0;
|
rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0;
|
||||||
rn = opMemMult.Rn;
|
rn = opMemMult.Rn;
|
||||||
wBack = opMemMult.PostOffset != 0;
|
wBack = opMemMult.PostOffset != 0;
|
||||||
|
isLoad = opMemMult.IsLoad;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new NotImplementedException($"The type \"{opCode.GetType().Name}\" is not implemented on the decoder.");
|
throw new NotImplementedException($"The type \"{opCode.GetType().Name}\" is not implemented on the decoder.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rn == RegisterAlias.Aarch32Pc && wBack) ||
|
if ((rt == RegisterAlias.Aarch32Pc && isLoad) ||
|
||||||
rt == RegisterAlias.Aarch32Pc)
|
(rn == RegisterAlias.Aarch32Pc && wBack))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,5 +6,7 @@ namespace ChocolArm64.Decoders
|
||||||
int Rn { get; }
|
int Rn { get; }
|
||||||
|
|
||||||
bool WBack { get; }
|
bool WBack { get; }
|
||||||
|
|
||||||
|
bool IsLoad { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,5 +7,7 @@ namespace ChocolArm64.Decoders
|
||||||
int RegisterMask { get; }
|
int RegisterMask { get; }
|
||||||
|
|
||||||
int PostOffset { get; }
|
int PostOffset { get; }
|
||||||
|
|
||||||
|
bool IsLoad { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,19 +14,24 @@ namespace ChocolArm64.Decoders
|
||||||
public bool WBack { get; private set; }
|
public bool WBack { get; private set; }
|
||||||
public bool Unprivileged { 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)
|
public OpCode32Mem(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
{
|
{
|
||||||
Rt = (opCode >> 12) & 0xf;
|
Rt = (opCode >> 12) & 0xf;
|
||||||
Rn = (opCode >> 16) & 0xf;
|
Rn = (opCode >> 16) & 0xf;
|
||||||
|
|
||||||
bool w = (opCode & (1 << 21)) != 0;
|
bool isLoad = (opCode & (1 << 20)) != 0;
|
||||||
bool u = (opCode & (1 << 23)) != 0;
|
bool w = (opCode & (1 << 21)) != 0;
|
||||||
bool p = (opCode & (1 << 24)) != 0;
|
bool u = (opCode & (1 << 23)) != 0;
|
||||||
|
bool p = (opCode & (1 << 24)) != 0;
|
||||||
|
|
||||||
Index = p;
|
Index = p;
|
||||||
Add = u;
|
Add = u;
|
||||||
WBack = !p || w;
|
WBack = !p || w;
|
||||||
Unprivileged = !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 Offset { get; private set; }
|
||||||
public int PostOffset { 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)
|
public OpCode32MemMult(Inst inst, long position, int opCode) : base(inst, position, opCode)
|
||||||
{
|
{
|
||||||
Rn = (opCode >> 16) & 0xf;
|
Rn = (opCode >> 16) & 0xf;
|
||||||
|
|
||||||
bool w = (opCode & (1 << 21)) != 0;
|
bool isLoad = (opCode & (1 << 20)) != 0;
|
||||||
bool u = (opCode & (1 << 23)) != 0;
|
bool w = (opCode & (1 << 21)) != 0;
|
||||||
bool p = (opCode & (1 << 24)) != 0;
|
bool u = (opCode & (1 << 23)) != 0;
|
||||||
|
bool p = (opCode & (1 << 24)) != 0;
|
||||||
|
|
||||||
RegisterMask = opCode & 0xffff;
|
RegisterMask = opCode & 0xffff;
|
||||||
|
|
||||||
|
@ -47,6 +50,8 @@ namespace ChocolArm64.Decoders
|
||||||
{
|
{
|
||||||
PostOffset = 0;
|
PostOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IsLoad = isLoad;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -530,7 +530,15 @@ namespace ChocolArm64.Translation
|
||||||
public void EmitLdflg(int index) => Ldloc(index, IoType.Flag);
|
public void EmitLdflg(int index) => Ldloc(index, IoType.Flag);
|
||||||
public void EmitStflg(int index)
|
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);
|
Stloc(index, IoType.Flag);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue