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

@ -279,106 +279,7 @@ namespace ChocolArm64.Instruction
return InsertVec(new AVec(), 0, Size, Low + High);
}
public static AVec Addp64(AVec LHS, AVec RHS, int Size)
{
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)
public static int CountSetBits8(byte Value)
{
return (Value >> 0) & 1 + (Value >> 1) & 1 +
(Value >> 2) & 1 + (Value >> 3) & 1 +
@ -413,248 +314,11 @@ namespace ChocolArm64.Instruction
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)
{
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)
{
return Tbl(Vector, 8, Tb0);
@ -720,173 +384,6 @@ namespace ChocolArm64.Instruction
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)
{
switch (Size)