Emit CIL directly for more SIMD instructions, add UCVTF (vector, scalar) and UZP2, fix XTN (?)

This commit is contained in:
gdkchan 2018-02-15 01:32:25 -03:00
parent 7c4346685c
commit 7c314eadcf
15 changed files with 674 additions and 1052 deletions

View file

@ -168,7 +168,7 @@ namespace ChocolArm64
Set("00011110xx1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx010110xxxxxxxxxx", AInstEmit.Fmin_S, typeof(AOpCodeSimdReg));
Set("00011110xx1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx011110xxxxxxxxxx", AInstEmit.Fminnm_S, typeof(AOpCodeSimdReg));
Set("0x0011100x1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg)); Set("0x0011100x1xxxxx110011xxxxxxxxxx", AInstEmit.Fmla_V, typeof(AOpCodeSimdReg));
Set("0x0011111<<xxxxx0001x0xxxxxxxxxx", AInstEmit.Fmla_Vs, typeof(AOpCodeSimdRegElem)); Set("0x0011111<<xxxxx0001x0xxxxxxxxxx", AInstEmit.Fmla_Ve, typeof(AOpCodeSimdRegElem));
Set("00011110xx100000010000xxxxxxxxxx", AInstEmit.Fmov_S, typeof(AOpCodeSimd)); Set("00011110xx100000010000xxxxxxxxxx", AInstEmit.Fmov_S, typeof(AOpCodeSimd));
Set("00011110xx1xxxxxxxx100xxxxxxxxxx", AInstEmit.Fmov_Si, typeof(AOpCodeSimdFmov)); Set("00011110xx1xxxxxxxx100xxxxxxxxxx", AInstEmit.Fmov_Si, typeof(AOpCodeSimdFmov));
Set("0xx0111100000xxx111101xxxxxxxxxx", AInstEmit.Fmov_V, typeof(AOpCodeSimdImm)); Set("0xx0111100000xxx111101xxxxxxxxxx", AInstEmit.Fmov_V, typeof(AOpCodeSimdImm));
@ -179,7 +179,7 @@ namespace ChocolArm64
Set("00011111xx0xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fmsub_S, typeof(AOpCodeSimdReg)); Set("00011111xx0xxxxx1xxxxxxxxxxxxxxx", AInstEmit.Fmsub_S, typeof(AOpCodeSimdReg));
Set("00011110xx1xxxxx000010xxxxxxxxxx", AInstEmit.Fmul_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx000010xxxxxxxxxx", AInstEmit.Fmul_S, typeof(AOpCodeSimdReg));
Set("0x1011100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg)); Set("0x1011100x1xxxxx110111xxxxxxxxxx", AInstEmit.Fmul_V, typeof(AOpCodeSimdReg));
Set("0x0011111<<xxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Vs, typeof(AOpCodeSimdRegElem)); Set("0x0011111<<xxxxx1001x0xxxxxxxxxx", AInstEmit.Fmul_Ve, typeof(AOpCodeSimdRegElem));
Set("00011110xx100001010000xxxxxxxxxx", AInstEmit.Fneg_S, typeof(AOpCodeSimdReg)); Set("00011110xx100001010000xxxxxxxxxx", AInstEmit.Fneg_S, typeof(AOpCodeSimdReg));
Set("00011110xx1xxxxx100010xxxxxxxxxx", AInstEmit.Fnmul_S, typeof(AOpCodeSimdReg)); Set("00011110xx1xxxxx100010xxxxxxxxxx", AInstEmit.Fnmul_S, typeof(AOpCodeSimdReg));
Set("00011110xx100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd)); Set("00011110xx100110010000xxxxxxxxxx", AInstEmit.Frinta_S, typeof(AOpCodeSimd));
@ -243,13 +243,15 @@ namespace ChocolArm64
Set("01101110<<110000001110xxxxxxxxxx", AInstEmit.Uaddlv_V, typeof(AOpCodeSimd)); Set("01101110<<110000001110xxxxxxxxxx", AInstEmit.Uaddlv_V, typeof(AOpCodeSimd));
Set("0x101110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Uaddw_V, typeof(AOpCodeSimdReg)); Set("0x101110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Uaddw_V, typeof(AOpCodeSimdReg));
Set("x0011110xx100011000000xxxxxxxxxx", AInstEmit.Ucvtf_Gp, typeof(AOpCodeSimdCvt)); Set("x0011110xx100011000000xxxxxxxxxx", AInstEmit.Ucvtf_Gp, typeof(AOpCodeSimdCvt));
Set("011111100x100001110110xxxxxxxxxx", AInstEmit.Ucvtf_V, typeof(AOpCodeSimdReg)); Set("011111100x100001110110xxxxxxxxxx", AInstEmit.Ucvtf_S, typeof(AOpCodeSimd));
Set("0x1011100x100001110110xxxxxxxxxx", AInstEmit.Ucvtf_V, typeof(AOpCodeSimd));
Set("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns)); Set("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns));
Set("0>101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg)); Set("0>101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg));
Set("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm)); Set("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm));
Set("0x1011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm)); Set("0x1011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
Set("0x1011110>>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm)); Set("0x1011110>>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
Set("0x001110xx0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg)); Set("0x001110xx0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg));
Set("0x001110xx0xxxxx010110xxxxxxxxxx", AInstEmit.Uzp2_V, typeof(AOpCodeSimdReg));
Set("0x001110<<100001001010xxxxxxxxxx", AInstEmit.Xtn_V, typeof(AOpCodeSimd)); Set("0x001110<<100001001010xxxxxxxxxx", AInstEmit.Xtn_V, typeof(AOpCodeSimd));
#endregion #endregion
} }
@ -317,7 +319,7 @@ namespace ChocolArm64
} }
else if (ZCount != 0 && OCount != 0) else if (ZCount != 0 && OCount != 0)
{ {
//When both the > and the <, then a value is blacklisted, //When both the > and the < are used, then a value is blacklisted,
//with > indicating 0, and < indicating 1. So, for example, ><< //with > indicating 0, and < indicating 1. So, for example, ><<
//blacklists the pattern 011, but 000, 001, 010, 100, 101, //blacklists the pattern 011, but 000, 001, 010, 100, 101,
//110 and 111 are valid. //110 and 111 are valid.

View file

@ -4,10 +4,10 @@ namespace ChocolArm64.Decoder
{ {
class AOpCodeMem : AOpCode class AOpCodeMem : AOpCode
{ {
public int Rt { get; protected set; } public int Rt { get; protected set; }
public int Rn { get; protected set; } public int Rn { get; protected set; }
public int Size { get; protected set; } public int Size { get; protected set; }
public bool Extend64 { get; protected set; } public bool Extend64 { get; protected set; }
public AOpCodeMem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) public AOpCodeMem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
{ {

View file

@ -3,12 +3,8 @@ using ChocolArm64.State;
namespace ChocolArm64.Decoder namespace ChocolArm64.Decoder
{ {
class AOpCodeSimdMemMs : AOpCode, IAOpCodeSimd class AOpCodeSimdMemMs : AOpCodeMemReg, IAOpCodeSimd
{ {
public int Rt { get; private set; }
public int Rn { get; private set; }
public int Size { get; private set; }
public int Rm { get; private set; }
public int Reps { get; private set; } public int Reps { get; private set; }
public int SElems { get; private set; } public int SElems { get; private set; }
public int Elems { get; private set; } public int Elems { get; private set; }
@ -29,10 +25,7 @@ namespace ChocolArm64.Decoder
default: Inst = AInst.Undefined; return; default: Inst = AInst.Undefined; return;
} }
Rt = (OpCode >> 0) & 0x1f;
Rn = (OpCode >> 5) & 0x1f;
Size = (OpCode >> 10) & 0x3; Size = (OpCode >> 10) & 0x3;
Rm = (OpCode >> 16) & 0x1f;
WBack = ((OpCode >> 23) & 0x1) != 0; WBack = ((OpCode >> 23) & 0x1) != 0;
bool Q = ((OpCode >> 30) & 1) != 0; bool Q = ((OpCode >> 30) & 1) != 0;

View file

@ -3,12 +3,8 @@ using ChocolArm64.State;
namespace ChocolArm64.Decoder namespace ChocolArm64.Decoder
{ {
class AOpCodeSimdMemSs : AOpCode, IAOpCodeSimd class AOpCodeSimdMemSs : AOpCodeMemReg, IAOpCodeSimd
{ {
public int Rt { get; private set; }
public int Rn { get; private set; }
public int Size { get; private set; }
public int Rm { get; private set; }
public int SElems { get; private set; } public int SElems { get; private set; }
public int Index { get; private set; } public int Index { get; private set; }
public bool Replicate { get; private set; } public bool Replicate { get; private set; }
@ -91,9 +87,6 @@ namespace ChocolArm64.Decoder
this.SElems = SElems; this.SElems = SElems;
this.Size = Scale; this.Size = Scale;
Rt = (OpCode >> 0) & 0x1f;
Rn = (OpCode >> 5) & 0x1f;
Rm = (OpCode >> 16) & 0x1f;
WBack = ((OpCode >> 23) & 0x1) != 0; WBack = ((OpCode >> 23) & 0x1) != 0;
RegisterSize = Q != 0 RegisterSize = Q != 0

View file

@ -2,17 +2,13 @@ using ChocolArm64.Instruction;
namespace ChocolArm64.Decoder namespace ChocolArm64.Decoder
{ {
class AOpCodeSimdRegElem : AOpCodeSimd class AOpCodeSimdRegElem : AOpCodeSimdReg
{ {
public int Rm { get; private set; }
public int Index { get; private set; } public int Index { get; private set; }
public AOpCodeSimdRegElem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode) public AOpCodeSimdRegElem(AInst Inst, long Position, int OpCode) : base(Inst, Position, OpCode)
{ {
Rm = (OpCode >> 16) & 0x1f; if ((Size & 1) != 0)
Size = (OpCode >> 22) & 0x1;
if (Size != 0)
{ {
Index = (OpCode >> 11) & 1; Index = (OpCode >> 11) & 1;
} }

View file

@ -21,13 +21,22 @@ namespace ChocolArm64.Instruction
public static void EmitAddsVCheck(AILEmitterCtx Context) public static void EmitAddsVCheck(AILEmitterCtx Context)
{ {
//V = (Rd ^ Rn) & ~(Rn ^ Rm) < 0 //V = (Rd ^ Rn) & (Rd ^ Rm) & ~(Rn ^ Rm) < 0
Context.Emit(OpCodes.Dup); Context.EmitSttmp();
Context.EmitLdtmp();
Context.EmitLdtmp();
EmitDataLoadRn(Context); EmitDataLoadRn(Context);
Context.Emit(OpCodes.Xor); Context.Emit(OpCodes.Xor);
Context.EmitLdtmp();
EmitDataLoadOper2(Context);
Context.Emit(OpCodes.Xor);
Context.Emit(OpCodes.And);
EmitDataLoadOpers(Context); EmitDataLoadOpers(Context);
Context.Emit(OpCodes.Xor); Context.Emit(OpCodes.Xor);
@ -47,7 +56,10 @@ namespace ChocolArm64.Instruction
EmitDataLoadOpers(Context); EmitDataLoadOpers(Context);
Context.Emit(OpCodes.Clt_Un); Context.Emit(OpCodes.Clt_Un);
Context.Emit(OpCodes.Not);
Context.EmitLdc_I4(1);
Context.Emit(OpCodes.Xor);
Context.EmitStflg((int)APState.CBit); Context.EmitStflg((int)APState.CBit);
} }

View file

@ -507,6 +507,32 @@ namespace ChocolArm64.Instruction
Context.EmitStvecsf(Op.Rd); Context.EmitStvecsf(Op.Rd);
} }
public static void Ucvtf_S(AILEmitterCtx Context)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
Context.EmitLdvecsi(Op.Rn);
Context.Emit(OpCodes.Conv_R_Un);
EmitFloatCast(Context, Op.Size);
Context.EmitStvecsf(Op.Rd);
}
public static void Umov_S(AILEmitterCtx Context)
{
AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
Context.EmitLdvec(Op.Rn);
Context.EmitLdc_I4(Op.DstIndex);
Context.EmitLdc_I4(Op.Size);
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ExtractVec));
Context.EmitStintzr(Op.Rd);
}
private static void EmitScalarOp(AILEmitterCtx Context, OpCode ILOp) private static void EmitScalarOp(AILEmitterCtx Context, OpCode ILOp)
{ {
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;

File diff suppressed because it is too large Load diff

View file

@ -279,106 +279,7 @@ namespace ChocolArm64.Instruction
return InsertVec(new AVec(), 0, Size, Low + High); return InsertVec(new AVec(), 0, Size, Low + High);
} }
public static AVec Addp64(AVec LHS, AVec RHS, int Size) public static int CountSetBits8(byte Value)
{
return Addp(LHS, RHS, Size, 8);
}
public static AVec Addp128(AVec LHS, AVec RHS, int Size)
{
return Addp(LHS, RHS, Size, 16);
}
private static AVec Addp(AVec LHS, AVec RHS, int Size, int Bytes)
{
AVec Res = new AVec();
int Elems = Bytes >> Size;
int Half = Elems >> 1;
for (int Index = 0; Index < Elems; Index++)
{
int Elem = (Index & (Half - 1)) << 1;
ulong L = Index < Half
? ExtractVec(LHS, Elem + 0, Size)
: ExtractVec(RHS, Elem + 0, Size);
ulong R = Index < Half
? ExtractVec(LHS, Elem + 1, Size)
: ExtractVec(RHS, Elem + 1, Size);
Res = InsertVec(Res, Index, Size, L + R);
}
return Res;
}
public static AVec Bic_Vi64(AVec Res, ulong Imm, int Size)
{
return Bic_Vi(Res, Imm, Size, 8);
}
public static AVec Bic_Vi128(AVec Res, ulong Imm, int Size)
{
return Bic_Vi(Res, Imm, Size, 16);
}
private static AVec Bic_Vi(AVec Res, ulong Imm, int Size, int Bytes)
{
int Elems = Bytes >> Size;
for (int Index = 0; Index < Elems; Index++)
{
ulong Value = ExtractVec(Res, Index, Size);
Res = InsertVec(Res, Index, Size, Value & ~Imm);
}
return Res;
}
public static AVec Cnt64(AVec Vector)
{
AVec Res = new AVec();
Res.B0 = (byte)CountSetBits8(Vector.B0);
Res.B1 = (byte)CountSetBits8(Vector.B1);
Res.B2 = (byte)CountSetBits8(Vector.B2);
Res.B3 = (byte)CountSetBits8(Vector.B3);
Res.B4 = (byte)CountSetBits8(Vector.B4);
Res.B5 = (byte)CountSetBits8(Vector.B5);
Res.B6 = (byte)CountSetBits8(Vector.B6);
Res.B7 = (byte)CountSetBits8(Vector.B7);
return Res;
}
public static AVec Cnt128(AVec Vector)
{
AVec Res = new AVec();
Res.B0 = (byte)CountSetBits8(Vector.B0);
Res.B1 = (byte)CountSetBits8(Vector.B1);
Res.B2 = (byte)CountSetBits8(Vector.B2);
Res.B3 = (byte)CountSetBits8(Vector.B3);
Res.B4 = (byte)CountSetBits8(Vector.B4);
Res.B5 = (byte)CountSetBits8(Vector.B5);
Res.B6 = (byte)CountSetBits8(Vector.B6);
Res.B7 = (byte)CountSetBits8(Vector.B7);
Res.B8 = (byte)CountSetBits8(Vector.B8);
Res.B9 = (byte)CountSetBits8(Vector.B9);
Res.B10 = (byte)CountSetBits8(Vector.B10);
Res.B11 = (byte)CountSetBits8(Vector.B11);
Res.B12 = (byte)CountSetBits8(Vector.B12);
Res.B13 = (byte)CountSetBits8(Vector.B13);
Res.B14 = (byte)CountSetBits8(Vector.B14);
Res.B15 = (byte)CountSetBits8(Vector.B15);
return Res;
}
private static int CountSetBits8(byte Value)
{ {
return (Value >> 0) & 1 + (Value >> 1) & 1 + return (Value >> 0) & 1 + (Value >> 1) & 1 +
(Value >> 2) & 1 + (Value >> 3) & 1 + (Value >> 2) & 1 + (Value >> 3) & 1 +
@ -413,248 +314,11 @@ namespace ChocolArm64.Instruction
return InsertVec(new AVec(), 0, Size, ExtractVec(Vector, Elem, Size)); return InsertVec(new AVec(), 0, Size, ExtractVec(Vector, Elem, Size));
} }
public static AVec Dup_V64(AVec Vector, int Elem, int Size)
{
return Dup_V(Vector, Elem, Size, 8);
}
public static AVec Dup_V128(AVec Vector, int Elem, int Size)
{
return Dup_V(Vector, Elem, Size, 16);
}
private static AVec Dup_V(AVec Vector, int Elem, int Size, int Bytes)
{
AVec Res = new AVec();
ulong Value = ExtractVec(Vector, Elem, Size);
for (Elem = 0; Elem < (Bytes >> Size); Elem++)
{
Res = InsertVec(Res, Elem, Size, Value);
}
return Res;
}
public static AVec Fmla64(AVec Res, AVec LHS, AVec RHS, int Size)
{
return Fmla(Res, LHS, RHS, Size, 2);
}
public static AVec Fmla128(AVec Res, AVec LHS, AVec RHS, int Size)
{
return Fmla(Res, LHS, RHS, Size, 4);
}
private static AVec Fmla(AVec Res, AVec LHS, AVec RHS, int Size, int Bytes)
{
int Elems = Bytes >> Size;
if (Size == 0)
{
for (int Index = 0; Index < Elems; Index++)
{
float L = LHS.ExtractSingle(Index);
float R = RHS.ExtractSingle(Index);
float Addend = Res.ExtractSingle(Index);
Res = AVec.InsertSingle(Res, Index, Addend + L * R);
}
}
else
{
for (int Index = 0; Index < Elems; Index++)
{
double L = LHS.ExtractDouble(Index);
double R = RHS.ExtractDouble(Index);
double Addend = Res.ExtractDouble(Index);
Res = AVec.InsertDouble(Res, Index, Addend + L * R);
}
}
return Res;
}
public static AVec Fmla_Ve64(AVec Res, AVec LHS, AVec RHS, int SIdx, int Size)
{
return Fmla_Ve(Res, LHS, RHS, SIdx, Size, 2);
}
public static AVec Fmla_Ve128(AVec Res, AVec LHS, AVec RHS, int SIdx, int Size)
{
return Fmla_Ve(Res, LHS, RHS, SIdx, Size, 4);
}
private static AVec Fmla_Ve(AVec Res, AVec LHS, AVec RHS, int SIdx, int Size, int Bytes)
{
int Elems = Bytes >> Size;
if (Size == 0)
{
float R = RHS.ExtractSingle(SIdx);
for (int Index = 0; Index < Elems; Index++)
{
float L = LHS.ExtractSingle(Index);
float Addend = Res.ExtractSingle(Index);
Res = AVec.InsertSingle(Res, Index, Addend + L * R);
}
}
else
{
double R = RHS.ExtractDouble(SIdx);
for (int Index = 0; Index < Elems; Index++)
{
double L = LHS.ExtractDouble(Index);
double Addend = Res.ExtractDouble(Index);
Res = AVec.InsertDouble(Res, Index, Addend + L * R);
}
}
return Res;
}
public static AVec Fmov_S(ulong Value, int Elem, int Size) public static AVec Fmov_S(ulong Value, int Elem, int Size)
{ {
return InsertVec(new AVec(), Elem, Size, Value); return InsertVec(new AVec(), Elem, Size, Value);
} }
public static AVec Fmul_Ve64(AVec LHS, AVec RHS, int SIdx, int Size)
{
return Fmul_Ve(LHS, RHS, SIdx, Size, 2);
}
public static AVec Fmul_Ve128(AVec LHS, AVec RHS, int SIdx, int Size)
{
return Fmul_Ve(LHS, RHS, SIdx, Size, 4);
}
private static AVec Fmul_Ve(AVec LHS, AVec RHS, int SIdx, int Size, int Bytes)
{
AVec Res = new AVec();
int Elems = Bytes >> Size;
if (Size == 0)
{
float R = RHS.ExtractSingle(SIdx);
for (int Index = 0; Index < Elems; Index++)
{
float L = LHS.ExtractSingle(Index);
Res = AVec.InsertSingle(Res, Index, L * R);
}
}
else
{
double R = RHS.ExtractDouble(SIdx);
for (int Index = 0; Index < Elems; Index++)
{
double L = LHS.ExtractDouble(Index);
Res = AVec.InsertDouble(Res, Index, L * R);
}
}
return Res;
}
public static AVec Ins_Gp(AVec Res, ulong Value, int Elem, int Size)
{
return InsertVec(Res, Elem, Size, Value);
}
public static AVec Ins_V(AVec Res, AVec Value, int Src, int Dst, int Size)
{
return InsertVec(Res, Dst, Size, ExtractVec(Value, Src, Size));;
}
public static AVec Orr_Vi64(AVec Res, ulong Imm, int Size)
{
return Orr_Vi(Res, Imm, Size, 8);
}
public static AVec Orr_Vi128(AVec Res, ulong Imm, int Size)
{
return Orr_Vi(Res, Imm, Size, 16);
}
private static AVec Orr_Vi(AVec Res, ulong Imm, int Size, int Bytes)
{
int Elems = Bytes >> Size;
for (int Index = 0; Index < Elems; Index++)
{
ulong Value = ExtractVec(Res, Index, Size);
Res = InsertVec(Res, Index, Size, Value | Imm);
}
return Res;
}
public static AVec Saddw(AVec LHS, AVec RHS, int Size)
{
return Saddw_(LHS, RHS, Size, false);
}
public static AVec Saddw2(AVec LHS, AVec RHS, int Size)
{
return Saddw_(LHS, RHS, Size, true);
}
private static AVec Saddw_(AVec LHS, AVec RHS, int Size, bool High)
{
AVec Res = new AVec();
int Elems = 8 >> Size;
int Part = High ? Elems : 0;
for (int Index = 0; Index < Elems; Index++)
{
long L = ExtractSVec(LHS, Index, Size + 1);
long R = ExtractSVec(RHS, Index + Part, Size);
Res = InsertSVec(Res, Index, Size + 1, L + R);
}
return Res;
}
public static AVec Sshll(AVec Vector, int Shift, int Size)
{
return Sshll_(Vector, Shift, Size, false);
}
public static AVec Sshll2(AVec Vector, int Shift, int Size)
{
return Sshll_(Vector, Shift, Size, true);
}
private static AVec Sshll_(AVec Vector, int Shift, int Size, bool High)
{
AVec Res = new AVec();
int Elems = 8 >> Size;
int Part = High ? Elems : 0;
for (int Index = 0; Index < Elems; Index++)
{
long Value = ExtractSVec(Vector, Index + Part, Size);
Res = InsertSVec(Res, Index, Size + 1, Value << Shift);
}
return Res;
}
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);
@ -720,173 +384,6 @@ namespace ChocolArm64.Instruction
return Res; return Res;
} }
public static AVec Uaddlv64(AVec Vector, int Size)
{
return Uaddlv(Vector, Size, 8);
}
public static AVec Uaddlv128(AVec Vector, int Size)
{
return Uaddlv(Vector, Size, 16);
}
private static AVec Uaddlv(AVec Vector, int Size, int Bytes)
{
int Elems = Bytes >> Size;
ulong Sum = 0;
for (int Index = 0; Index < Elems; Index++)
{
Sum += ExtractVec(Vector, Index, Size);
}
return InsertVec(new AVec(), 0, 3, Sum);
}
public static AVec Uaddw(AVec LHS, AVec RHS, int Size)
{
return Uaddw_(LHS, RHS, Size, false);
}
public static AVec Uaddw2(AVec LHS, AVec RHS, int Size)
{
return Uaddw_(LHS, RHS, Size, true);
}
private static AVec Uaddw_(AVec LHS, AVec RHS, int Size, bool High)
{
AVec Res = new AVec();
int Elems = 8 >> Size;
int Part = High ? Elems : 0;
for (int Index = 0; Index < Elems; Index++)
{
ulong L = ExtractVec(LHS, Index, Size + 1);
ulong R = ExtractVec(RHS, Index + Part, Size);
Res = InsertVec(Res, Index, Size + 1, L + R);
}
return Res;
}
public static AVec Ucvtf_V_F(AVec Vector)
{
return new AVec()
{
S0 = (uint)Vector.W0,
S1 = (uint)Vector.W1,
S2 = (uint)Vector.W2,
S3 = (uint)Vector.W3
};
}
public static AVec Ucvtf_V_D(AVec Vector)
{
return new AVec()
{
D0 = (ulong)Vector.X0,
D1 = (ulong)Vector.X1
};
}
public static AVec Ushll(AVec Vector, int Shift, int Size)
{
return Ushll_(Vector, Shift, Size, false);
}
public static AVec Ushll2(AVec Vector, int Shift, int Size)
{
return Ushll_(Vector, Shift, Size, true);
}
private static AVec Ushll_(AVec Vector, int Shift, int Size, bool High)
{
AVec Res = new AVec();
int Elems = 8 >> Size;
int Part = High ? Elems : 0;
for (int Index = 0; Index < Elems; Index++)
{
ulong Value = ExtractVec(Vector, Index + Part, Size);
Res = InsertVec(Res, Index, Size + 1, Value << Shift);
}
return Res;
}
public static AVec Uzp1_V64(AVec LHS, AVec RHS, int Size)
{
return Uzp(LHS, RHS, Size, 0, 8);
}
public static AVec Uzp1_V128(AVec LHS, AVec RHS, int Size)
{
return Uzp(LHS, RHS, Size, 0, 16);
}
public static AVec Uzp2_V64(AVec LHS, AVec RHS, int Size)
{
return Uzp(LHS, RHS, Size, 1, 8);
}
public static AVec Uzp2_V128(AVec LHS, AVec RHS, int Size)
{
return Uzp(LHS, RHS, Size, 1, 16);
}
private static AVec Uzp(AVec LHS, AVec RHS, int Size, int Part, int Bytes)
{
AVec Res = new AVec();
int Elems = Bytes >> Size;
int Half = Elems >> 1;
for (int Index = 0; Index < Elems; Index++)
{
int Elem = (Index & (Half - 1)) << 1;
ulong Value = Index < Half
? ExtractVec(LHS, Elem + Part, Size)
: ExtractVec(RHS, Elem + Part, Size);
Res = InsertVec(Res, Index, Size, Value);
}
return Res;
}
public static AVec Xtn(AVec Vector, int Size)
{
return Xtn_(Vector, Size, false);
}
public static AVec Xtn2(AVec Vector, int Size)
{
return Xtn_(Vector, Size, true);
}
private static AVec Xtn_(AVec Vector, int Size, bool High)
{
AVec Res = new AVec();
int Elems = 8 >> Size;
int Part = High ? Elems : 0;
for (int Index = 0; Index < Elems; Index++)
{
ulong Value = ExtractVec(Vector, Index, Size + 1);
Res = InsertVec(Res, Index + Part, Size, Value);
}
return Res;
}
public static ulong ExtractVec(AVec Vector, int Index, int Size) public static ulong ExtractVec(AVec Vector, int Index, int Size)
{ {
switch (Size) switch (Size)

View file

@ -37,6 +37,7 @@ namespace ChocolArm64.Translation
private const int Tmp2Index = -2; private const int Tmp2Index = -2;
private const int Tmp3Index = -3; private const int Tmp3Index = -3;
private const int Tmp4Index = -4; private const int Tmp4Index = -4;
private const int Tmp5Index = -5;
public AILEmitterCtx(ATranslator Translator, ABlock[] Graph, ABlock Root) public AILEmitterCtx(ATranslator Translator, ABlock[] Graph, ABlock Root)
{ {
@ -91,7 +92,7 @@ namespace ChocolArm64.Translation
} }
public bool TryOptEmitSubroutineCall() public bool TryOptEmitSubroutineCall()
{ {
if (!Translator.TryGetCachedSub(CurrOp, out ATranslatedSub Sub)) if (!Translator.TryGetCachedSub(CurrOp, out ATranslatedSub Sub))
{ {
return false; return false;
@ -343,6 +344,9 @@ namespace ChocolArm64.Translation
public void EmitLdtmp() => EmitLdint(Tmp1Index); public void EmitLdtmp() => EmitLdint(Tmp1Index);
public void EmitSttmp() => EmitStint(Tmp1Index); public void EmitSttmp() => EmitStint(Tmp1Index);
public void EmitLdvectmp() => EmitLdvec(Tmp5Index);
public void EmitStvectmp() => EmitStvec(Tmp5Index);
public void EmitLdint(int Index) => Ldloc(Index, AIoType.Int); public void EmitLdint(int Index) => Ldloc(Index, AIoType.Int);
public void EmitStint(int Index) => Stloc(Index, AIoType.Int); public void EmitStint(int Index) => Stloc(Index, AIoType.Int);
@ -427,7 +431,8 @@ namespace ChocolArm64.Translation
Size |= 2; Size |= 2;
} }
if (Op is AOpCodeMem || Op is IAOpCodeLit) if ((Op is AOpCodeMem || Op is IAOpCodeLit) &&
!(Op is AOpCodeSimdMemMs || Op is AOpCodeSimdMemSs))
{ {
return Size < 4 ? typeof(ulong) : typeof(AVec); return Size < 4 ? typeof(ulong) : typeof(AVec);
} }

View file

@ -1,7 +1,6 @@
using ChocolArm64.Memory; using ChocolArm64.Memory;
using Ryujinx.OsHle.Handles; using Ryujinx.OsHle.Handles;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading;
namespace Ryujinx.OsHle namespace Ryujinx.OsHle
{ {

View file

@ -28,7 +28,7 @@ namespace Ryujinx.OsHle.Objects.Time
{ {
DateTime CurrentTime = DateTime.Now; DateTime CurrentTime = DateTime.Now;
if (ClockType == SystemClockType.Standard || if (ClockType == SystemClockType.User ||
ClockType == SystemClockType.Network) ClockType == SystemClockType.Network)
{ {
CurrentTime = CurrentTime.ToUniversalTime(); CurrentTime = CurrentTime.ToUniversalTime();

View file

@ -2,7 +2,7 @@ namespace Ryujinx.OsHle.Objects.Time
{ {
enum SystemClockType enum SystemClockType
{ {
Standard, User,
Network, Network,
Local Local
} }

View file

@ -8,7 +8,7 @@ namespace Ryujinx.OsHle.Services
{ {
public static long TimeGetStandardUserSystemClock(ServiceCtx Context) public static long TimeGetStandardUserSystemClock(ServiceCtx Context)
{ {
MakeObject(Context, new ISystemClock(SystemClockType.Standard)); MakeObject(Context, new ISystemClock(SystemClockType.User));
return 0; return 0;
} }

View file

@ -1,4 +1,3 @@
using ChocolArm64;
using ChocolArm64.State; using ChocolArm64.State;
using Ryujinx.OsHle.Handles; using Ryujinx.OsHle.Handles;