forked from Mirror/Ryujinx
Fix cpu issue with cmp optimization, add HINT and FRINTX (scalar) instructions, fix for NvFlinger sometimes missing free buffers
This commit is contained in:
parent
3936c93448
commit
035efc913e
10 changed files with 96 additions and 24 deletions
|
@ -51,6 +51,7 @@ namespace ChocolArm64
|
||||||
Set("x10100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm));
|
Set("x10100100xxxxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluImm));
|
||||||
Set("x1001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs));
|
Set("x1001010xx0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Eor, typeof(AOpCodeAluRs));
|
||||||
Set("x00100111x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs));
|
Set("x00100111x0xxxxxxxxxxxxxxxxxxxxx", AInstEmit.Extr, typeof(AOpCodeAluRs));
|
||||||
|
Set("11010101000000110010xxxxxxx11111", AInstEmit.Hint, typeof(AOpCodeSystem));
|
||||||
Set("xx001000110xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldar, typeof(AOpCodeMemEx));
|
Set("xx001000110xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldar, typeof(AOpCodeMemEx));
|
||||||
Set("1x001000011xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxp, typeof(AOpCodeMemEx));
|
Set("1x001000011xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxp, typeof(AOpCodeMemEx));
|
||||||
Set("xx001000010xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxr, typeof(AOpCodeMemEx));
|
Set("xx001000010xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Ldaxr, typeof(AOpCodeMemEx));
|
||||||
|
@ -193,6 +194,7 @@ namespace ChocolArm64
|
||||||
Set("000111100x100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd));
|
Set("000111100x100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd));
|
||||||
Set("000111100x100101010000xxxxxxxxxx", AInstEmit.Frintm_S, typeof(AOpCodeSimd));
|
Set("000111100x100101010000xxxxxxxxxx", AInstEmit.Frintm_S, typeof(AOpCodeSimd));
|
||||||
Set("000111100x100100110000xxxxxxxxxx", AInstEmit.Frintp_S, typeof(AOpCodeSimd));
|
Set("000111100x100100110000xxxxxxxxxx", AInstEmit.Frintp_S, typeof(AOpCodeSimd));
|
||||||
|
Set("000111100x100111010000xxxxxxxxxx", AInstEmit.Frintx_S, typeof(AOpCodeSimd));
|
||||||
Set("000111100x100001110000xxxxxxxxxx", AInstEmit.Fsqrt_S, typeof(AOpCodeSimd));
|
Set("000111100x100001110000xxxxxxxxxx", AInstEmit.Fsqrt_S, typeof(AOpCodeSimd));
|
||||||
Set("000111100x1xxxxx001110xxxxxxxxxx", AInstEmit.Fsub_S, typeof(AOpCodeSimdReg));
|
Set("000111100x1xxxxx001110xxxxxxxxxx", AInstEmit.Fsub_S, typeof(AOpCodeSimdReg));
|
||||||
Set("0>0011101<1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg));
|
Set("0>0011101<1xxxxx110101xxxxxxxxxx", AInstEmit.Fsub_V, typeof(AOpCodeSimdReg));
|
||||||
|
|
|
@ -6,7 +6,7 @@ using System.Reflection.Emit;
|
||||||
|
|
||||||
namespace ChocolArm64
|
namespace ChocolArm64
|
||||||
{
|
{
|
||||||
class ATranslator
|
public class ATranslator
|
||||||
{
|
{
|
||||||
public AThread Thread { get; private set; }
|
public AThread Thread { get; private set; }
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ namespace ChocolArm64
|
||||||
while (Position != 0 && KeepRunning);
|
while (Position != 0 && KeepRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub)
|
internal bool TryGetCachedSub(AOpCode OpCode, out ATranslatedSub Sub)
|
||||||
{
|
{
|
||||||
if (OpCode.Emitter != AInstEmit.Bl)
|
if (OpCode.Emitter != AInstEmit.Bl)
|
||||||
{
|
{
|
||||||
|
@ -53,7 +53,7 @@ namespace ChocolArm64
|
||||||
return TryGetCachedSub(((AOpCodeBImmAl)OpCode).Imm, out Sub);
|
return TryGetCachedSub(((AOpCodeBImmAl)OpCode).Imm, out Sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetCachedSub(long Position, out ATranslatedSub Sub)
|
internal bool TryGetCachedSub(long Position, out ATranslatedSub Sub)
|
||||||
{
|
{
|
||||||
return CachedSubs.TryGetValue(Position, out Sub);
|
return CachedSubs.TryGetValue(Position, out Sub);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,8 +10,6 @@ namespace ChocolArm64.Decoder
|
||||||
public int Opc { get; private set; }
|
public int Opc { get; private set; }
|
||||||
public int Size { get; protected set; }
|
public int Size { get; protected set; }
|
||||||
|
|
||||||
public int SizeF => Size & 1;
|
|
||||||
|
|
||||||
public AOpCodeSimd(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
public AOpCodeSimd(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
|
||||||
{
|
{
|
||||||
Rd = (OpCode >> 0) & 0x1f;
|
Rd = (OpCode >> 0) & 0x1f;
|
||||||
|
|
|
@ -265,6 +265,32 @@ namespace ChocolArm64.Instruction
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Frintx_S(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
|
EmitVectorExtractF(Context, Op.Rn, 0, Op.Size);
|
||||||
|
|
||||||
|
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||||
|
|
||||||
|
Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpcr));
|
||||||
|
|
||||||
|
if (Op.Size == 0)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.RoundF));
|
||||||
|
}
|
||||||
|
else if (Op.Size == 1)
|
||||||
|
{
|
||||||
|
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.Round));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
EmitScalarSetF(Context, Op.Rd, Op.Size);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Fsqrt_S(AILEmitterCtx Context)
|
public static void Fsqrt_S(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitScalarUnaryOpF(Context, () =>
|
EmitScalarUnaryOpF(Context, () =>
|
||||||
|
|
|
@ -9,6 +9,11 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
static partial class AInstEmit
|
static partial class AInstEmit
|
||||||
{
|
{
|
||||||
|
public static void Hint(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
//Execute as no-op.
|
||||||
|
}
|
||||||
|
|
||||||
public static void Mrs(AILEmitterCtx Context)
|
public static void Mrs(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
|
AOpCodeSystem Op = (AOpCodeSystem)Context.CurrOp;
|
||||||
|
|
|
@ -189,6 +189,32 @@ namespace ChocolArm64.Instruction
|
||||||
(Value >> 6) & 1 + (Value >> 7);
|
(Value >> 6) & 1 + (Value >> 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float RoundF(float Value, int Fpcr)
|
||||||
|
{
|
||||||
|
switch ((ARoundMode)((Fpcr >> 22) & 3))
|
||||||
|
{
|
||||||
|
case ARoundMode.ToNearest: return MathF.Round (Value);
|
||||||
|
case ARoundMode.TowardsPlusInfinity: return MathF.Ceiling (Value);
|
||||||
|
case ARoundMode.TowardsMinusInfinity: return MathF.Floor (Value);
|
||||||
|
case ARoundMode.TowardsZero: return MathF.Truncate(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double Round(double Value, int Fpcr)
|
||||||
|
{
|
||||||
|
switch ((ARoundMode)((Fpcr >> 22) & 3))
|
||||||
|
{
|
||||||
|
case ARoundMode.ToNearest: return Math.Round (Value);
|
||||||
|
case ARoundMode.TowardsPlusInfinity: return Math.Ceiling (Value);
|
||||||
|
case ARoundMode.TowardsMinusInfinity: return Math.Floor (Value);
|
||||||
|
case ARoundMode.TowardsZero: return Math.Truncate(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
public static AVec Tbl1_V64(AVec Vector, AVec Tb0)
|
public static AVec Tbl1_V64(AVec Vector, AVec Tb0)
|
||||||
{
|
{
|
||||||
return Tbl(Vector, 8, Tb0);
|
return Tbl(Vector, 8, Tb0);
|
||||||
|
|
10
ChocolArm64/State/ARoundMode.cs
Normal file
10
ChocolArm64/State/ARoundMode.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace ChocolArm64.State
|
||||||
|
{
|
||||||
|
public enum ARoundMode
|
||||||
|
{
|
||||||
|
ToNearest = 0,
|
||||||
|
TowardsPlusInfinity = 1,
|
||||||
|
TowardsMinusInfinity = 2,
|
||||||
|
TowardsZero = 3
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,8 +18,8 @@ namespace ChocolArm64.Translation
|
||||||
|
|
||||||
private AILBlock ILBlock;
|
private AILBlock ILBlock;
|
||||||
|
|
||||||
private AOpCode LastCmpOp;
|
private AOpCode OptOpLastCompare;
|
||||||
private AOpCode LastFlagOp;
|
private AOpCode OptOpLastFlagSet;
|
||||||
|
|
||||||
private int BlkIndex;
|
private int BlkIndex;
|
||||||
private int OpcIndex;
|
private int OpcIndex;
|
||||||
|
@ -75,6 +75,9 @@ namespace ChocolArm64.Translation
|
||||||
BlkIndex++;
|
BlkIndex++;
|
||||||
OpcIndex = -1;
|
OpcIndex = -1;
|
||||||
|
|
||||||
|
OptOpLastFlagSet = null;
|
||||||
|
OptOpLastCompare = null;
|
||||||
|
|
||||||
ILBlock = Emitter.GetILBlock(BlkIndex);
|
ILBlock = Emitter.GetILBlock(BlkIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +123,7 @@ namespace ChocolArm64.Translation
|
||||||
|
|
||||||
public void TryOptMarkCondWithoutCmp()
|
public void TryOptMarkCondWithoutCmp()
|
||||||
{
|
{
|
||||||
LastCmpOp = CurrOp;
|
OptOpLastCompare = CurrOp;
|
||||||
|
|
||||||
AInstEmitAluHelper.EmitDataLoadOpers(this);
|
AInstEmitAluHelper.EmitDataLoadOpers(this);
|
||||||
|
|
||||||
|
@ -146,14 +149,15 @@ namespace ChocolArm64.Translation
|
||||||
{
|
{
|
||||||
OpCode ILOp;
|
OpCode ILOp;
|
||||||
|
|
||||||
int IntCond = (int)Cond;
|
int IntCond = (int)Cond;
|
||||||
|
|
||||||
if (LastCmpOp != null && LastFlagOp == LastCmpOp && BranchOps.ContainsKey(Cond))
|
if (OptOpLastCompare != null &&
|
||||||
|
OptOpLastCompare == OptOpLastFlagSet && BranchOps.ContainsKey(Cond))
|
||||||
{
|
{
|
||||||
Ldloc(Tmp3Index, AIoType.Int, LastCmpOp.RegisterSize);
|
Ldloc(Tmp3Index, AIoType.Int, OptOpLastCompare.RegisterSize);
|
||||||
Ldloc(Tmp4Index, AIoType.Int, LastCmpOp.RegisterSize);
|
Ldloc(Tmp4Index, AIoType.Int, OptOpLastCompare.RegisterSize);
|
||||||
|
|
||||||
if (LastCmpOp.Emitter == AInstEmit.Adds)
|
if (OptOpLastCompare.Emitter == AInstEmit.Adds)
|
||||||
{
|
{
|
||||||
Emit(OpCodes.Neg);
|
Emit(OpCodes.Neg);
|
||||||
}
|
}
|
||||||
|
@ -356,7 +360,7 @@ namespace ChocolArm64.Translation
|
||||||
public void EmitLdflg(int Index) => Ldloc(Index, AIoType.Flag);
|
public void EmitLdflg(int Index) => Ldloc(Index, AIoType.Flag);
|
||||||
public void EmitStflg(int Index)
|
public void EmitStflg(int Index)
|
||||||
{
|
{
|
||||||
LastFlagOp = CurrOp;
|
OptOpLastFlagSet = CurrOp;
|
||||||
|
|
||||||
Stloc(Index, AIoType.Flag);
|
Stloc(Index, AIoType.Flag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
using ChocolArm64.Memory;
|
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle
|
namespace Ryujinx.Core.OsHle
|
||||||
{
|
{
|
||||||
static class MemoryRegions
|
static class MemoryRegions
|
||||||
|
|
|
@ -291,7 +291,10 @@ namespace Ryujinx.Core.OsHle.Objects.Android
|
||||||
|
|
||||||
BufferQueue[Slot].State = BufferState.Free;
|
BufferQueue[Slot].State = BufferState.Free;
|
||||||
|
|
||||||
WaitBufferFree.Set();
|
lock (WaitBufferFree)
|
||||||
|
{
|
||||||
|
WaitBufferFree.Set();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,15 +320,15 @@ namespace Ryujinx.Core.OsHle.Objects.Android
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if ((Slot = GetFreeSlot(Width, Height)) != -1)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Logging.Debug("Waiting for a free BufferQueue slot...");
|
|
||||||
|
|
||||||
lock (WaitBufferFree)
|
lock (WaitBufferFree)
|
||||||
{
|
{
|
||||||
|
if ((Slot = GetFreeSlot(Width, Height)) != -1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logging.Debug("Waiting for a free BufferQueue slot...");
|
||||||
|
|
||||||
if (!KeepRunning)
|
if (!KeepRunning)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue