Compare commits
60 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7c1d2bbb98 | ||
|
beacf8c1c8 | ||
|
0dbe45ae37 | ||
|
2b50e52e48 | ||
|
49eadbc209 | ||
|
2df16ded9b | ||
|
e43390c723 | ||
|
5af1327068 | ||
|
88a8d1e567 | ||
|
bf77d1cab9 | ||
|
1ca0517c99 | ||
|
599d485bff | ||
|
60e16c15b6 | ||
|
2068445939 | ||
|
a4fc9f8050 | ||
|
5437d6cb13 | ||
|
7539e26144 | ||
|
1c3697b6a4 | ||
|
81f848e54f | ||
|
358a781639 | ||
|
45ce540b9b | ||
|
96bf7f8522 | ||
|
33e673ceb8 | ||
|
9c2500de5f | ||
|
dbe43c1719 | ||
|
f502cfaf62 | ||
|
1fd5cf2b4a | ||
|
814f75142e | ||
|
4c0eb91d7e | ||
|
da75a9a6ea | ||
|
41790aa743 | ||
|
0cb1e926b5 | ||
|
6f0395538b | ||
|
b9f1ff3c77 | ||
|
a77af4c5e9 | ||
|
fbcf802fbc | ||
|
c3c41fa4bb | ||
|
356e480bf5 | ||
|
8e119a1e96 | ||
|
e05bf90af6 | ||
|
66f16f4392 | ||
|
729ff5337c | ||
|
2492e7e808 | ||
|
36172ab43b | ||
|
4d69286a9c | ||
|
1529e6cf0d | ||
|
f468db7602 | ||
|
c5f1d1749a | ||
|
7dd69f2d0e | ||
|
c646638680 | ||
|
65f2a82b97 | ||
|
93dd6d525a | ||
|
96d4ad952c | ||
|
6a07f80b76 | ||
|
22214ac664 | ||
|
45e520a27c | ||
|
5b5810a46a | ||
|
619ac86bd0 | ||
|
7a1ab71c73 | ||
|
dc4ba3993b |
@@ -113,6 +113,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Add(X86Instruction.Divps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex));
|
Add(X86Instruction.Divps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex));
|
||||||
Add(X86Instruction.Divsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
Add(X86Instruction.Divsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||||
Add(X86Instruction.Divss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
Add(X86Instruction.Divss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstructionFlags.Vex | InstructionFlags.PrefixF3));
|
||||||
|
Add(X86Instruction.Gf2p8affineqb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3ace, InstructionFlags.Prefix66));
|
||||||
Add(X86Instruction.Haddpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
Add(X86Instruction.Haddpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||||
Add(X86Instruction.Haddps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
Add(X86Instruction.Haddps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstructionFlags.Vex | InstructionFlags.PrefixF2));
|
||||||
Add(X86Instruction.Idiv, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x070000f7, InstructionFlags.None));
|
Add(X86Instruction.Idiv, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x070000f7, InstructionFlags.None));
|
||||||
|
@@ -20,8 +20,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
if (maxNum >= 7)
|
if (maxNum >= 7)
|
||||||
{
|
{
|
||||||
(_, int ebx7, _, _) = X86Base.CpuId(0x00000007, 0x00000000);
|
(_, int ebx7, int ecx7, _) = X86Base.CpuId(0x00000007, 0x00000000);
|
||||||
FeatureInfo7Ebx = (FeatureFlags7Ebx)ebx7;
|
FeatureInfo7Ebx = (FeatureFlags7Ebx)ebx7;
|
||||||
|
FeatureInfo7Ecx = (FeatureFlags7Ecx)ecx7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,9 +55,16 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Sha = 1 << 29
|
Sha = 1 << 29
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum FeatureFlags7Ecx
|
||||||
|
{
|
||||||
|
Gfni = 1 << 8,
|
||||||
|
}
|
||||||
|
|
||||||
public static FeatureFlags1Edx FeatureInfo1Edx { get; }
|
public static FeatureFlags1Edx FeatureInfo1Edx { get; }
|
||||||
public static FeatureFlags1Ecx FeatureInfo1Ecx { get; }
|
public static FeatureFlags1Ecx FeatureInfo1Ecx { get; }
|
||||||
public static FeatureFlags7Ebx FeatureInfo7Ebx { get; } = 0;
|
public static FeatureFlags7Ebx FeatureInfo7Ebx { get; } = 0;
|
||||||
|
public static FeatureFlags7Ecx FeatureInfo7Ecx { get; } = 0;
|
||||||
|
|
||||||
public static bool SupportsSse => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse);
|
public static bool SupportsSse => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse);
|
||||||
public static bool SupportsSse2 => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse2);
|
public static bool SupportsSse2 => FeatureInfo1Edx.HasFlag(FeatureFlags1Edx.Sse2);
|
||||||
@@ -72,6 +80,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
public static bool SupportsAvx2 => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx2) && SupportsAvx;
|
public static bool SupportsAvx2 => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx2) && SupportsAvx;
|
||||||
public static bool SupportsF16c => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.F16c);
|
public static bool SupportsF16c => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.F16c);
|
||||||
public static bool SupportsSha => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Sha);
|
public static bool SupportsSha => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Sha);
|
||||||
|
public static bool SupportsGfni => FeatureInfo7Ecx.HasFlag(FeatureFlags7Ecx.Gfni);
|
||||||
|
|
||||||
public static bool ForceLegacySse { get; set; }
|
public static bool ForceLegacySse { get; set; }
|
||||||
|
|
||||||
|
@@ -58,6 +58,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Add(Intrinsic.X86Divps, new IntrinsicInfo(X86Instruction.Divps, IntrinsicType.Binary));
|
Add(Intrinsic.X86Divps, new IntrinsicInfo(X86Instruction.Divps, IntrinsicType.Binary));
|
||||||
Add(Intrinsic.X86Divsd, new IntrinsicInfo(X86Instruction.Divsd, IntrinsicType.Binary));
|
Add(Intrinsic.X86Divsd, new IntrinsicInfo(X86Instruction.Divsd, IntrinsicType.Binary));
|
||||||
Add(Intrinsic.X86Divss, new IntrinsicInfo(X86Instruction.Divss, IntrinsicType.Binary));
|
Add(Intrinsic.X86Divss, new IntrinsicInfo(X86Instruction.Divss, IntrinsicType.Binary));
|
||||||
|
Add(Intrinsic.X86Gf2p8affineqb, new IntrinsicInfo(X86Instruction.Gf2p8affineqb, IntrinsicType.TernaryImm));
|
||||||
Add(Intrinsic.X86Haddpd, new IntrinsicInfo(X86Instruction.Haddpd, IntrinsicType.Binary));
|
Add(Intrinsic.X86Haddpd, new IntrinsicInfo(X86Instruction.Haddpd, IntrinsicType.Binary));
|
||||||
Add(Intrinsic.X86Haddps, new IntrinsicInfo(X86Instruction.Haddps, IntrinsicType.Binary));
|
Add(Intrinsic.X86Haddps, new IntrinsicInfo(X86Instruction.Haddps, IntrinsicType.Binary));
|
||||||
Add(Intrinsic.X86Insertps, new IntrinsicInfo(X86Instruction.Insertps, IntrinsicType.TernaryImm));
|
Add(Intrinsic.X86Insertps, new IntrinsicInfo(X86Instruction.Insertps, IntrinsicType.TernaryImm));
|
||||||
|
@@ -54,6 +54,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Divps,
|
Divps,
|
||||||
Divsd,
|
Divsd,
|
||||||
Divss,
|
Divss,
|
||||||
|
Gf2p8affineqb,
|
||||||
Haddpd,
|
Haddpd,
|
||||||
Haddps,
|
Haddps,
|
||||||
Idiv,
|
Idiv,
|
||||||
|
@@ -7,5 +7,8 @@
|
|||||||
|
|
||||||
int Msb { get; }
|
int Msb { get; }
|
||||||
int Lsb { get; }
|
int Lsb { get; }
|
||||||
|
|
||||||
|
int SourceMask => (int)(0xFFFFFFFF >> (31 - Msb));
|
||||||
|
int DestMask => SourceMask & (int)(0xFFFFFFFF << Lsb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
7
ARMeilleure/Decoders/IOpCode32AluImm16.cs
Normal file
7
ARMeilleure/Decoders/IOpCode32AluImm16.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace ARMeilleure.Decoders
|
||||||
|
{
|
||||||
|
interface IOpCode32AluImm16 : IOpCode32Alu
|
||||||
|
{
|
||||||
|
int Immediate { get; }
|
||||||
|
}
|
||||||
|
}
|
11
ARMeilleure/Decoders/IOpCode32AluMla.cs
Normal file
11
ARMeilleure/Decoders/IOpCode32AluMla.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace ARMeilleure.Decoders
|
||||||
|
{
|
||||||
|
interface IOpCode32AluMla : IOpCode32AluReg
|
||||||
|
{
|
||||||
|
int Ra { get; }
|
||||||
|
|
||||||
|
bool NHigh { get; }
|
||||||
|
bool MHigh { get; }
|
||||||
|
bool R { get; }
|
||||||
|
}
|
||||||
|
}
|
13
ARMeilleure/Decoders/IOpCode32AluUmull.cs
Normal file
13
ARMeilleure/Decoders/IOpCode32AluUmull.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace ARMeilleure.Decoders
|
||||||
|
{
|
||||||
|
interface IOpCode32AluUmull : IOpCode32, IOpCode32HasSetFlags
|
||||||
|
{
|
||||||
|
int RdLo { get; }
|
||||||
|
int RdHi { get; }
|
||||||
|
int Rn { get; }
|
||||||
|
int Rm { get; }
|
||||||
|
|
||||||
|
bool NHigh { get; }
|
||||||
|
bool MHigh { get; }
|
||||||
|
}
|
||||||
|
}
|
@@ -13,16 +13,13 @@ namespace ARMeilleure.Decoders
|
|||||||
Cond = (Condition)((uint)opCode >> 28);
|
Cond = (Condition)((uint)opCode >> 28);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsThumb()
|
public bool IsThumb { get; protected init; } = false;
|
||||||
{
|
|
||||||
return this is OpCodeT16 || this is OpCodeT32;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint GetPc()
|
public uint GetPc()
|
||||||
{
|
{
|
||||||
// Due to backwards compatibility and legacy behavior of ARMv4 CPUs pipeline,
|
// Due to backwards compatibility and legacy behavior of ARMv4 CPUs pipeline,
|
||||||
// the PC actually points 2 instructions ahead.
|
// the PC actually points 2 instructions ahead.
|
||||||
if (IsThumb())
|
if (IsThumb)
|
||||||
{
|
{
|
||||||
// PC is ahead by 4 in thumb mode whether or not the current instruction
|
// PC is ahead by 4 in thumb mode whether or not the current instruction
|
||||||
// is 16 or 32 bit.
|
// is 16 or 32 bit.
|
||||||
|
@@ -6,12 +6,8 @@
|
|||||||
public int Rn { get; }
|
public int Rn { get; }
|
||||||
|
|
||||||
public int Msb { get; }
|
public int Msb { get; }
|
||||||
|
|
||||||
public int Lsb { get; }
|
public int Lsb { get; }
|
||||||
|
|
||||||
public int SourceMask => (int)(0xFFFFFFFF >> (31 - Msb));
|
|
||||||
public int DestMask => SourceMask & (int)(0xFFFFFFFF << Lsb);
|
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluBf(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluBf(inst, address, opCode);
|
||||||
|
|
||||||
public OpCode32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
namespace ARMeilleure.Decoders
|
namespace ARMeilleure.Decoders
|
||||||
{
|
{
|
||||||
class OpCode32AluImm16 : OpCode32Alu
|
class OpCode32AluImm16 : OpCode32Alu, IOpCode32AluImm16
|
||||||
{
|
{
|
||||||
public int Immediate { get; }
|
public int Immediate { get; }
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
namespace ARMeilleure.Decoders
|
namespace ARMeilleure.Decoders
|
||||||
{
|
{
|
||||||
class OpCode32AluMla : OpCode32, IOpCode32AluReg
|
class OpCode32AluMla : OpCode32, IOpCode32AluMla
|
||||||
{
|
{
|
||||||
public int Rn { get; }
|
public int Rn { get; }
|
||||||
public int Rm { get; }
|
public int Rm { get; }
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
namespace ARMeilleure.Decoders
|
namespace ARMeilleure.Decoders
|
||||||
{
|
{
|
||||||
class OpCode32AluUmull : OpCode32, IOpCode32HasSetFlags
|
class OpCode32AluUmull : OpCode32, IOpCode32AluUmull
|
||||||
{
|
{
|
||||||
public int RdLo { get; }
|
public int RdLo { get; }
|
||||||
public int RdHi { get; }
|
public int RdHi { get; }
|
||||||
@@ -11,7 +11,6 @@
|
|||||||
public bool MHigh { get; }
|
public bool MHigh { get; }
|
||||||
|
|
||||||
public bool? SetFlags { get; }
|
public bool? SetFlags { get; }
|
||||||
public DataOp DataOp { get; }
|
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluUmull(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32AluUmull(inst, address, opCode);
|
||||||
|
|
||||||
@@ -26,7 +25,6 @@
|
|||||||
MHigh = ((opCode >> 6) & 0x1) == 1;
|
MHigh = ((opCode >> 6) & 0x1) == 1;
|
||||||
|
|
||||||
SetFlags = ((opCode >> 20) & 0x1) != 0;
|
SetFlags = ((opCode >> 20) & 0x1) != 0;
|
||||||
DataOp = DataOp.Arithmetic;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -7,14 +7,15 @@
|
|||||||
public bool F { get; protected set; }
|
public bool F { get; protected set; }
|
||||||
public bool U { get; }
|
public bool U { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Simd(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Simd(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32Simd(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32Simd(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32Simd(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Size = (opCode >> 20) & 0x3;
|
Size = (opCode >> 20) & 0x3;
|
||||||
Q = ((opCode >> 6) & 0x1) != 0;
|
Q = ((opCode >> 6) & 0x1) != 0;
|
||||||
F = ((opCode >> 10) & 0x1) != 0;
|
F = ((opCode >> 10) & 0x1) != 0;
|
||||||
U = ((opCode >> 24) & 0x1) != 0;
|
U = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;
|
||||||
Opc = (opCode >> 7) & 0x3;
|
Opc = (opCode >> 7) & 0x3;
|
||||||
|
|
||||||
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
|
RegisterSize = Q ? RegisterSize.Simd128 : RegisterSize.Simd64;
|
||||||
|
@@ -47,6 +47,9 @@ namespace ARMeilleure.Decoders
|
|||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public OpCode32SimdBase(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { }
|
protected OpCode32SimdBase(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,9 +5,10 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class OpCode32SimdBinary : OpCode32SimdReg
|
class OpCode32SimdBinary : OpCode32SimdReg
|
||||||
{
|
{
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdBinary(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdBinary(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdBinary(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdBinary(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdBinary(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Size = 3;
|
Size = 3;
|
||||||
|
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
{
|
{
|
||||||
class OpCode32SimdCmpZ : OpCode32Simd
|
class OpCode32SimdCmpZ : OpCode32Simd
|
||||||
{
|
{
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCmpZ(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCmpZ(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCmpZ(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdCmpZ(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Size = (opCode >> 18) & 0x3;
|
Size = (opCode >> 18) & 0x3;
|
||||||
|
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
{
|
{
|
||||||
class OpCode32SimdCvtFI : OpCode32SimdS
|
class OpCode32SimdCvtFI : OpCode32SimdS
|
||||||
{
|
{
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFI(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFI(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFI(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdCvtFI(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdCvtFI(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Opc = (opCode >> 7) & 0x1;
|
Opc = (opCode >> 7) & 0x1;
|
||||||
|
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
{
|
{
|
||||||
public int Index { get; }
|
public int Index { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupElem(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupElem(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupElem(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdDupElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
var opc = (opCode >> 16) & 0xf;
|
var opc = (opCode >> 16) & 0xf;
|
||||||
|
|
||||||
|
@@ -7,10 +7,13 @@
|
|||||||
public int Rt { get; }
|
public int Rt { get; }
|
||||||
public bool Q { get; }
|
public bool Q { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupGP(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupGP(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdDupGP(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdDupGP(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdDupGP(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
|
||||||
Size = 2 - (((opCode >> 21) & 0x2) | ((opCode >> 5) & 0x1)); // B:E - 0 for 32, 16 then 8.
|
Size = 2 - (((opCode >> 21) & 0x2) | ((opCode >> 5) & 0x1)); // B:E - 0 for 32, 16 then 8.
|
||||||
if (Size == -1)
|
if (Size == -1)
|
||||||
{
|
{
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
{
|
{
|
||||||
public int Immediate { get; }
|
public int Immediate { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdExt(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdExt(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdExt(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdExt(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdExt(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Immediate = (opCode >> 8) & 0xf;
|
Immediate = (opCode >> 8) & 0xf;
|
||||||
Size = 0;
|
Size = 0;
|
||||||
|
@@ -6,9 +6,10 @@
|
|||||||
public long Immediate { get; }
|
public long Immediate { get; }
|
||||||
public int Elems => GetBytesCount() >> Size;
|
public int Elems => GetBytesCount() >> Size;
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdImm(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Vd = (opCode >> 12) & 0xf;
|
Vd = (opCode >> 12) & 0xf;
|
||||||
Vd |= (opCode >> 18) & 0x10;
|
Vd |= (opCode >> 18) & 0x10;
|
||||||
@@ -22,7 +23,7 @@
|
|||||||
|
|
||||||
imm = ((uint)opCode >> 0) & 0xf;
|
imm = ((uint)opCode >> 0) & 0xf;
|
||||||
imm |= ((uint)opCode >> 12) & 0x70;
|
imm |= ((uint)opCode >> 12) & 0x70;
|
||||||
imm |= ((uint)opCode >> 17) & 0x80;
|
imm |= ((uint)opCode >> (isThumb ? 21 : 17)) & 0x80;
|
||||||
|
|
||||||
(Immediate, Size) = OpCodeSimdHelper.GetSimdImmediateAndSize(cMode, op, imm);
|
(Immediate, Size) = OpCodeSimdHelper.GetSimdImmediateAndSize(cMode, op, imm);
|
||||||
|
|
||||||
|
@@ -7,10 +7,13 @@
|
|||||||
public int Size { get; }
|
public int Size { get; }
|
||||||
public int Elems { get; }
|
public int Elems { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm44(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm44(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdImm44(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdImm44(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdImm44(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
|
||||||
Size = (opCode >> 8) & 0x3;
|
Size = (opCode >> 8) & 0x3;
|
||||||
|
|
||||||
bool single = Size != 3;
|
bool single = Size != 3;
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
{
|
{
|
||||||
public bool U { get; }
|
public bool U { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdLong(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdLong(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdLong(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
int imm3h = (opCode >> 19) & 0x7;
|
int imm3h = (opCode >> 19) & 0x7;
|
||||||
|
|
||||||
@@ -18,7 +19,7 @@
|
|||||||
case 4: Size = 2; break;
|
case 4: Size = 2; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
U = ((opCode >> 24) & 0x1) != 0;
|
U = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;
|
||||||
|
|
||||||
RegisterSize = RegisterSize.Simd64;
|
RegisterSize = RegisterSize.Simd64;
|
||||||
|
|
||||||
|
@@ -8,10 +8,13 @@
|
|||||||
public bool Add { get; }
|
public bool Add { get; }
|
||||||
public int Immediate { get; }
|
public int Immediate { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemImm(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemImm(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemImm(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdMemImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdMemImm(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
|
||||||
Immediate = opCode & 0xff;
|
Immediate = opCode & 0xff;
|
||||||
|
|
||||||
Rn = (opCode >> 16) & 0xf;
|
Rn = (opCode >> 16) & 0xf;
|
||||||
|
@@ -12,10 +12,13 @@
|
|||||||
public bool DoubleWidth { get; }
|
public bool DoubleWidth { get; }
|
||||||
public bool Add { get; }
|
public bool Add { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemMult(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemMult(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemMult(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdMemMult(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdMemMult(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
|
||||||
Rn = (opCode >> 16) & 0xf;
|
Rn = (opCode >> 16) & 0xf;
|
||||||
|
|
||||||
bool isLoad = (opCode & (1 << 20)) != 0;
|
bool isLoad = (opCode & (1 << 20)) != 0;
|
||||||
|
@@ -1,11 +1,10 @@
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Decoders
|
namespace ARMeilleure.Decoders
|
||||||
{
|
{
|
||||||
class OpCode32SimdMemPair : OpCode32, IOpCode32Simd
|
class OpCode32SimdMemPair : OpCode32, IOpCode32Simd
|
||||||
{
|
{
|
||||||
private static int[] RegsMap =
|
private static int[] _regsMap =
|
||||||
{
|
{
|
||||||
1, 1, 4, 2,
|
1, 1, 4, 2,
|
||||||
1, 1, 3, 1,
|
1, 1, 3, 1,
|
||||||
@@ -24,10 +23,13 @@ namespace ARMeilleure.Decoders
|
|||||||
public int Regs { get; }
|
public int Regs { get; }
|
||||||
public int Increment { get; }
|
public int Increment { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemPair(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemPair(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemPair(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdMemPair(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdMemPair(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
|
||||||
Vd = (opCode >> 12) & 0xf;
|
Vd = (opCode >> 12) & 0xf;
|
||||||
Vd |= (opCode >> 18) & 0x10;
|
Vd |= (opCode >> 18) & 0x10;
|
||||||
|
|
||||||
@@ -40,9 +42,9 @@ namespace ARMeilleure.Decoders
|
|||||||
WBack = Rm != RegisterAlias.Aarch32Pc;
|
WBack = Rm != RegisterAlias.Aarch32Pc;
|
||||||
RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp;
|
RegisterIndex = Rm != RegisterAlias.Aarch32Pc && Rm != RegisterAlias.Aarch32Sp;
|
||||||
|
|
||||||
Regs = RegsMap[(opCode >> 8) & 0xf];
|
Regs = _regsMap[(opCode >> 8) & 0xf];
|
||||||
|
|
||||||
Increment = Math.Min(Regs, ((opCode >> 8) & 0x1) + 1);
|
Increment = ((opCode >> 8) & 0x1) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -15,10 +15,13 @@ namespace ARMeilleure.Decoders
|
|||||||
public bool Replicate { get; }
|
public bool Replicate { get; }
|
||||||
public int Increment { get; }
|
public int Increment { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemSingle(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemSingle(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMemSingle(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdMemSingle(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
|
||||||
Vd = (opCode >> 12) & 0xf;
|
Vd = (opCode >> 12) & 0xf;
|
||||||
Vd |= (opCode >> 18) & 0x10;
|
Vd |= (opCode >> 18) & 0x10;
|
||||||
|
|
||||||
|
@@ -11,10 +11,13 @@
|
|||||||
public int Opc1 { get; }
|
public int Opc1 { get; }
|
||||||
public int Opc2 { get; }
|
public int Opc2 { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGp(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGp(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGp(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdMovGp(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdMovGp(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
|
||||||
// Which one is used is instruction dependant.
|
// Which one is used is instruction dependant.
|
||||||
Op = (opCode >> 20) & 0x1;
|
Op = (opCode >> 20) & 0x1;
|
||||||
|
|
||||||
|
@@ -9,10 +9,13 @@
|
|||||||
public int Rt2 { get; }
|
public int Rt2 { get; }
|
||||||
public int Op { get; }
|
public int Op { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpDouble(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpDouble(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpDouble(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdMovGpDouble(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdMovGpDouble(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
|
||||||
// Which one is used is instruction dependant.
|
// Which one is used is instruction dependant.
|
||||||
Op = (opCode >> 20) & 0x1;
|
Op = (opCode >> 20) & 0x1;
|
||||||
|
|
||||||
|
@@ -11,10 +11,13 @@
|
|||||||
|
|
||||||
public int Index { get; }
|
public int Index { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpElem(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpElem(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovGpElem(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdMovGpElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdMovGpElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
|
||||||
Op = (opCode >> 20) & 0x1;
|
Op = (opCode >> 20) & 0x1;
|
||||||
U = ((opCode >> 23) & 1) != 0;
|
U = ((opCode >> 23) & 1) != 0;
|
||||||
|
|
||||||
|
@@ -2,9 +2,10 @@ namespace ARMeilleure.Decoders
|
|||||||
{
|
{
|
||||||
class OpCode32SimdMovn : OpCode32Simd
|
class OpCode32SimdMovn : OpCode32Simd
|
||||||
{
|
{
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovn(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovn(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdMovn(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdMovn(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdMovn(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Size = (opCode >> 18) & 0x3;
|
Size = (opCode >> 18) & 0x3;
|
||||||
}
|
}
|
||||||
|
@@ -8,9 +8,10 @@
|
|||||||
public int In => GetQuadwordSubindex(Vn) << (3 - Size);
|
public int In => GetQuadwordSubindex(Vn) << (3 - Size);
|
||||||
public int Fn => GetQuadwordSubindex(Vn) << (1 - (Size & 1));
|
public int Fn => GetQuadwordSubindex(Vn) << (1 - (Size & 1));
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdReg(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdReg(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdReg(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdReg(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Vn = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);
|
Vn = ((opCode >> 3) & 0x10) | ((opCode >> 16) & 0xf);
|
||||||
|
|
||||||
|
@@ -2,11 +2,12 @@
|
|||||||
{
|
{
|
||||||
class OpCode32SimdRegElem : OpCode32SimdReg
|
class OpCode32SimdRegElem : OpCode32SimdReg
|
||||||
{
|
{
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElem(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElem(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElem(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdRegElem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdRegElem(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Q = ((opCode >> 24) & 0x1) != 0;
|
Q = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;
|
||||||
F = ((opCode >> 8) & 0x1) != 0;
|
F = ((opCode >> 8) & 0x1) != 0;
|
||||||
Size = (opCode >> 20) & 0x3;
|
Size = (opCode >> 20) & 0x3;
|
||||||
|
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
{
|
{
|
||||||
class OpCode32SimdRegElemLong : OpCode32SimdRegElem
|
class OpCode32SimdRegElemLong : OpCode32SimdRegElem
|
||||||
{
|
{
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElemLong(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElemLong(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegElemLong(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdRegElemLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdRegElemLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Q = false;
|
Q = false;
|
||||||
F = false;
|
F = false;
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
{
|
{
|
||||||
public bool Polynomial { get; }
|
public bool Polynomial { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegLong(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegLong(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegLong(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdRegLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdRegLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Q = false;
|
Q = false;
|
||||||
RegisterSize = RegisterSize.Simd64;
|
RegisterSize = RegisterSize.Simd64;
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
{
|
{
|
||||||
public int Vn { get; }
|
public int Vn { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegS(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegS(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegS(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdRegS(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdRegS(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
bool single = Size != 3;
|
bool single = Size != 3;
|
||||||
if (single)
|
if (single)
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
{
|
{
|
||||||
class OpCode32SimdRegWide : OpCode32SimdReg
|
class OpCode32SimdRegWide : OpCode32SimdReg
|
||||||
{
|
{
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegWide(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegWide(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRegWide(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdRegWide(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdRegWide(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Q = false;
|
Q = false;
|
||||||
RegisterSize = RegisterSize.Simd64;
|
RegisterSize = RegisterSize.Simd64;
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
{
|
{
|
||||||
class OpCode32SimdRev : OpCode32SimdCmpZ
|
class OpCode32SimdRev : OpCode32SimdCmpZ
|
||||||
{
|
{
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRev(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRev(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdRev(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdRev(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdRev(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
if (Opc + Size >= 3)
|
if (Opc + Size >= 3)
|
||||||
{
|
{
|
||||||
|
@@ -8,10 +8,13 @@
|
|||||||
public int Opc2 { get; } // opc2 or RM (opc2<1:0>) [Vcvt, Vrint].
|
public int Opc2 { get; } // opc2 or RM (opc2<1:0>) [Vcvt, Vrint].
|
||||||
public int Size { get; protected set; }
|
public int Size { get; protected set; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdS(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdS(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdS(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdS(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdS(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
|
||||||
Opc = (opCode >> 15) & 0x3;
|
Opc = (opCode >> 15) & 0x3;
|
||||||
Opc2 = (opCode >> 16) & 0x7;
|
Opc2 = (opCode >> 16) & 0x7;
|
||||||
|
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
{
|
{
|
||||||
public OpCode32SimdSelMode Cc { get; }
|
public OpCode32SimdSelMode Cc { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSel(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSel(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSel(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdSel(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdSel(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Cc = (OpCode32SimdSelMode)((opCode >> 20) & 3);
|
Cc = (OpCode32SimdSelMode)((opCode >> 20) & 3);
|
||||||
}
|
}
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
{
|
{
|
||||||
public int Shift { get; }
|
public int Shift { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImm(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImm(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImm(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdShImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdShImm(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
int imm6 = (opCode >> 16) & 0x3f;
|
int imm6 = (opCode >> 16) & 0x3f;
|
||||||
int limm6 = ((opCode >> 1) & 0x40) | imm6;
|
int limm6 = ((opCode >> 1) & 0x40) | imm6;
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
{
|
{
|
||||||
public int Shift { get; }
|
public int Shift { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmLong(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmLong(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmLong(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdShImmLong(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdShImmLong(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Q = false;
|
Q = false;
|
||||||
RegisterSize = RegisterSize.Simd64;
|
RegisterSize = RegisterSize.Simd64;
|
||||||
|
@@ -2,8 +2,9 @@
|
|||||||
{
|
{
|
||||||
class OpCode32SimdShImmNarrow : OpCode32SimdShImm
|
class OpCode32SimdShImmNarrow : OpCode32SimdShImm
|
||||||
{
|
{
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmNarrow(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmNarrow(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdShImmNarrow(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdShImmNarrow(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) { }
|
public OpCode32SimdShImmNarrow(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,10 +5,13 @@
|
|||||||
public int Rt { get; }
|
public int Rt { get; }
|
||||||
public int Sreg { get; }
|
public int Sreg { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSpecial(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSpecial(inst, address, opCode, false);
|
||||||
|
public static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSpecial(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdSpecial(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdSpecial(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
IsThumb = isThumb;
|
||||||
|
|
||||||
Rt = (opCode >> 12) & 0xf;
|
Rt = (opCode >> 12) & 0xf;
|
||||||
Sreg = (opCode >> 16) & 0xf;
|
Sreg = (opCode >> 16) & 0xf;
|
||||||
}
|
}
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
{
|
{
|
||||||
class OpCode32SimdSqrte : OpCode32Simd
|
class OpCode32SimdSqrte : OpCode32Simd
|
||||||
{
|
{
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSqrte(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSqrte(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdSqrte(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdSqrte(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdSqrte(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Size = (opCode >> 18) & 0x1;
|
Size = (opCode >> 18) & 0x1;
|
||||||
F = ((opCode >> 8) & 0x1) != 0;
|
F = ((opCode >> 8) & 0x1) != 0;
|
||||||
|
@@ -4,9 +4,10 @@
|
|||||||
{
|
{
|
||||||
public int Length { get; }
|
public int Length { get; }
|
||||||
|
|
||||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdTbl(inst, address, opCode);
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdTbl(inst, address, opCode, false);
|
||||||
|
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdTbl(inst, address, opCode, true);
|
||||||
|
|
||||||
public OpCode32SimdTbl(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCode32SimdTbl(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||||
{
|
{
|
||||||
Length = (opCode >> 8) & 3;
|
Length = (opCode >> 8) & 3;
|
||||||
Size = 0;
|
Size = 0;
|
||||||
|
@@ -8,6 +8,7 @@ namespace ARMeilleure.Decoders
|
|||||||
{
|
{
|
||||||
Cond = Condition.Al;
|
Cond = Condition.Al;
|
||||||
|
|
||||||
|
IsThumb = true;
|
||||||
OpCodeSizeInBytes = 2;
|
OpCodeSizeInBytes = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
{
|
{
|
||||||
Cond = Condition.Al;
|
Cond = Condition.Al;
|
||||||
|
|
||||||
|
IsThumb = true;
|
||||||
OpCodeSizeInBytes = 4;
|
OpCodeSizeInBytes = 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
22
ARMeilleure/Decoders/OpCodeT32AluBf.cs
Normal file
22
ARMeilleure/Decoders/OpCodeT32AluBf.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
namespace ARMeilleure.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeT32AluBf : OpCodeT32, IOpCode32AluBf
|
||||||
|
{
|
||||||
|
public int Rd { get; }
|
||||||
|
public int Rn { get; }
|
||||||
|
|
||||||
|
public int Msb { get; }
|
||||||
|
public int Lsb { get; }
|
||||||
|
|
||||||
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluBf(inst, address, opCode);
|
||||||
|
|
||||||
|
public OpCodeT32AluBf(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||||
|
{
|
||||||
|
Rd = (opCode >> 8) & 0xf;
|
||||||
|
Rn = (opCode >> 16) & 0xf;
|
||||||
|
|
||||||
|
Msb = (opCode >> 0) & 0x1f;
|
||||||
|
Lsb = ((opCode >> 6) & 0x3) | ((opCode >> 10) & 0x1c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
ARMeilleure/Decoders/OpCodeT32AluMla.cs
Normal file
29
ARMeilleure/Decoders/OpCodeT32AluMla.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
namespace ARMeilleure.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeT32AluMla : OpCodeT32, IOpCode32AluMla
|
||||||
|
{
|
||||||
|
public int Rn { get; }
|
||||||
|
public int Rm { get; }
|
||||||
|
public int Ra { get; }
|
||||||
|
public int Rd { get; }
|
||||||
|
|
||||||
|
public bool NHigh { get; }
|
||||||
|
public bool MHigh { get; }
|
||||||
|
public bool R { get; }
|
||||||
|
public bool? SetFlags => false;
|
||||||
|
|
||||||
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluMla(inst, address, opCode);
|
||||||
|
|
||||||
|
public OpCodeT32AluMla(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||||
|
{
|
||||||
|
Rm = (opCode >> 0) & 0xf;
|
||||||
|
Rd = (opCode >> 8) & 0xf;
|
||||||
|
Ra = (opCode >> 12) & 0xf;
|
||||||
|
Rn = (opCode >> 16) & 0xf;
|
||||||
|
R = (opCode & (1 << 4)) != 0;
|
||||||
|
|
||||||
|
MHigh = ((opCode >> 4) & 0x1) == 1;
|
||||||
|
NHigh = ((opCode >> 5) & 0x1) == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
ARMeilleure/Decoders/OpCodeT32AluUmull.cs
Normal file
28
ARMeilleure/Decoders/OpCodeT32AluUmull.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
namespace ARMeilleure.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeT32AluUmull : OpCodeT32, IOpCode32AluUmull
|
||||||
|
{
|
||||||
|
public int RdLo { get; }
|
||||||
|
public int RdHi { get; }
|
||||||
|
public int Rn { get; }
|
||||||
|
public int Rm { get; }
|
||||||
|
|
||||||
|
public bool NHigh { get; }
|
||||||
|
public bool MHigh { get; }
|
||||||
|
|
||||||
|
public bool? SetFlags => false;
|
||||||
|
|
||||||
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluUmull(inst, address, opCode);
|
||||||
|
|
||||||
|
public OpCodeT32AluUmull(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||||
|
{
|
||||||
|
Rm = (opCode >> 0) & 0xf;
|
||||||
|
RdHi = (opCode >> 8) & 0xf;
|
||||||
|
RdLo = (opCode >> 12) & 0xf;
|
||||||
|
Rn = (opCode >> 16) & 0xf;
|
||||||
|
|
||||||
|
MHigh = ((opCode >> 4) & 0x1) == 1;
|
||||||
|
NHigh = ((opCode >> 5) & 0x1) == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
ARMeilleure/Decoders/OpCodeT32AluUx.cs
Normal file
18
ARMeilleure/Decoders/OpCodeT32AluUx.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using ARMeilleure.State;
|
||||||
|
|
||||||
|
namespace ARMeilleure.Decoders
|
||||||
|
{
|
||||||
|
class OpCodeT32AluUx : OpCodeT32AluReg, IOpCode32AluUx
|
||||||
|
{
|
||||||
|
public int Rotate { get; }
|
||||||
|
public int RotateBits => Rotate * 8;
|
||||||
|
public bool Add => Rn != RegisterAlias.Aarch32Pc;
|
||||||
|
|
||||||
|
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32AluUx(inst, address, opCode);
|
||||||
|
|
||||||
|
public OpCodeT32AluUx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||||
|
{
|
||||||
|
Rotate = (opCode >> 4) & 0x3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -27,7 +27,7 @@ namespace ARMeilleure.Decoders
|
|||||||
int i2 = j2 ^ s ^ 1;
|
int i2 = j2 ^ s ^ 1;
|
||||||
|
|
||||||
int imm32 = imm11 | (imm10 << 11) | (i2 << 21) | (i1 << 22) | (s << 23);
|
int imm32 = imm11 | (imm10 << 11) | (i2 << 21) | (i1 << 22) | (s << 23);
|
||||||
imm32 = (imm32 << 9) >> 8;
|
imm32 = (imm32 << 8) >> 7;
|
||||||
|
|
||||||
Immediate = pc + imm32;
|
Immediate = pc + imm32;
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ namespace ARMeilleure.Decoders
|
|||||||
{
|
{
|
||||||
public int Rd => 0;
|
public int Rd => 0;
|
||||||
public int Rt { get; }
|
public int Rt { get; }
|
||||||
|
public int Rt2 { get; }
|
||||||
public int Rn { get; }
|
public int Rn { get; }
|
||||||
|
|
||||||
public bool WBack => false;
|
public bool WBack => false;
|
||||||
@@ -17,6 +18,7 @@ namespace ARMeilleure.Decoders
|
|||||||
|
|
||||||
public OpCodeT32MemLdEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCodeT32MemLdEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
|
Rt2 = (opCode >> 8) & 0xf;
|
||||||
Rt = (opCode >> 12) & 0xf;
|
Rt = (opCode >> 12) & 0xf;
|
||||||
Rn = (opCode >> 16) & 0xf;
|
Rn = (opCode >> 16) & 0xf;
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ namespace ARMeilleure.Decoders
|
|||||||
{
|
{
|
||||||
public int Rd { get; }
|
public int Rd { get; }
|
||||||
public int Rt { get; }
|
public int Rt { get; }
|
||||||
|
public int Rt2 { get; }
|
||||||
public int Rn { get; }
|
public int Rn { get; }
|
||||||
|
|
||||||
public bool WBack => false;
|
public bool WBack => false;
|
||||||
@@ -18,6 +19,7 @@ namespace ARMeilleure.Decoders
|
|||||||
public OpCodeT32MemStEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCodeT32MemStEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||||
{
|
{
|
||||||
Rd = (opCode >> 0) & 0xf;
|
Rd = (opCode >> 0) & 0xf;
|
||||||
|
Rt2 = (opCode >> 8) & 0xf;
|
||||||
Rt = (opCode >> 12) & 0xf;
|
Rt = (opCode >> 12) & 0xf;
|
||||||
Rn = (opCode >> 16) & 0xf;
|
Rn = (opCode >> 16) & 0xf;
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,6 @@
|
|||||||
using ARMeilleure.Common;
|
|
||||||
using System.Runtime.Intrinsics;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Decoders
|
namespace ARMeilleure.Decoders
|
||||||
{
|
{
|
||||||
class OpCodeT32MovImm16 : OpCodeT32Alu, IOpCode32AluImm
|
class OpCodeT32MovImm16 : OpCodeT32Alu, IOpCode32AluImm16
|
||||||
{
|
{
|
||||||
public int Immediate { get; }
|
public int Immediate { get; }
|
||||||
|
|
||||||
|
@@ -93,6 +93,7 @@ namespace ARMeilleure.Decoders
|
|||||||
SetA64("00011010110xxxxx010101xxxxxxxxxx", InstName.Crc32ch, InstEmit.Crc32ch, OpCodeAluBinary.Create);
|
SetA64("00011010110xxxxx010101xxxxxxxxxx", InstName.Crc32ch, InstEmit.Crc32ch, OpCodeAluBinary.Create);
|
||||||
SetA64("00011010110xxxxx010110xxxxxxxxxx", InstName.Crc32cw, InstEmit.Crc32cw, OpCodeAluBinary.Create);
|
SetA64("00011010110xxxxx010110xxxxxxxxxx", InstName.Crc32cw, InstEmit.Crc32cw, OpCodeAluBinary.Create);
|
||||||
SetA64("10011010110xxxxx010111xxxxxxxxxx", InstName.Crc32cx, InstEmit.Crc32cx, OpCodeAluBinary.Create);
|
SetA64("10011010110xxxxx010111xxxxxxxxxx", InstName.Crc32cx, InstEmit.Crc32cx, OpCodeAluBinary.Create);
|
||||||
|
SetA64("11010101000000110010001010011111", InstName.Csdb, InstEmit.Csdb, OpCodeSystem.Create);
|
||||||
SetA64("x0011010100xxxxxxxxx00xxxxxxxxxx", InstName.Csel, InstEmit.Csel, OpCodeCsel.Create);
|
SetA64("x0011010100xxxxxxxxx00xxxxxxxxxx", InstName.Csel, InstEmit.Csel, OpCodeCsel.Create);
|
||||||
SetA64("x0011010100xxxxxxxxx01xxxxxxxxxx", InstName.Csinc, InstEmit.Csinc, OpCodeCsel.Create);
|
SetA64("x0011010100xxxxxxxxx01xxxxxxxxxx", InstName.Csinc, InstEmit.Csinc, OpCodeCsel.Create);
|
||||||
SetA64("x1011010100xxxxxxxxx00xxxxxxxxxx", InstName.Csinv, InstEmit.Csinv, OpCodeCsel.Create);
|
SetA64("x1011010100xxxxxxxxx00xxxxxxxxxx", InstName.Csinv, InstEmit.Csinv, OpCodeCsel.Create);
|
||||||
@@ -107,7 +108,6 @@ namespace ARMeilleure.Decoders
|
|||||||
SetA64("11001010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit.Eor, OpCodeAluRs.Create);
|
SetA64("11001010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit.Eor, OpCodeAluRs.Create);
|
||||||
SetA64("00010011100xxxxx0xxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, OpCodeAluRs.Create);
|
SetA64("00010011100xxxxx0xxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, OpCodeAluRs.Create);
|
||||||
SetA64("10010011110xxxxxxxxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, OpCodeAluRs.Create);
|
SetA64("10010011110xxxxxxxxxxxxxxxxxxxxx", InstName.Extr, InstEmit.Extr, OpCodeAluRs.Create);
|
||||||
SetA64("11010101000000110010xxxxxxx11111", InstName.Hint, InstEmit.Hint, OpCodeSystem.Create);
|
|
||||||
SetA64("11010101000000110011xxxx11011111", InstName.Isb, InstEmit.Isb, OpCodeSystem.Create);
|
SetA64("11010101000000110011xxxx11011111", InstName.Isb, InstEmit.Isb, OpCodeSystem.Create);
|
||||||
SetA64("xx001000110xxxxx1xxxxxxxxxxxxxxx", InstName.Ldar, InstEmit.Ldar, OpCodeMemEx.Create);
|
SetA64("xx001000110xxxxx1xxxxxxxxxxxxxxx", InstName.Ldar, InstEmit.Ldar, OpCodeMemEx.Create);
|
||||||
SetA64("1x001000011xxxxx1xxxxxxxxxxxxxxx", InstName.Ldaxp, InstEmit.Ldaxp, OpCodeMemEx.Create);
|
SetA64("1x001000011xxxxx1xxxxxxxxxxxxxxx", InstName.Ldaxp, InstEmit.Ldaxp, OpCodeMemEx.Create);
|
||||||
@@ -159,6 +159,8 @@ namespace ARMeilleure.Decoders
|
|||||||
SetA64("00010011000xxxxx0xxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, OpCodeBfm.Create);
|
SetA64("00010011000xxxxx0xxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, OpCodeBfm.Create);
|
||||||
SetA64("1001001101xxxxxxxxxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, OpCodeBfm.Create);
|
SetA64("1001001101xxxxxxxxxxxxxxxxxxxxxx", InstName.Sbfm, InstEmit.Sbfm, OpCodeBfm.Create);
|
||||||
SetA64("x0011010110xxxxx000011xxxxxxxxxx", InstName.Sdiv, InstEmit.Sdiv, OpCodeAluBinary.Create);
|
SetA64("x0011010110xxxxx000011xxxxxxxxxx", InstName.Sdiv, InstEmit.Sdiv, OpCodeAluBinary.Create);
|
||||||
|
SetA64("11010101000000110010000010011111", InstName.Sev, InstEmit.Nop, OpCodeSystem.Create);
|
||||||
|
SetA64("11010101000000110010000010111111", InstName.Sevl, InstEmit.Nop, OpCodeSystem.Create);
|
||||||
SetA64("10011011001xxxxx0xxxxxxxxxxxxxxx", InstName.Smaddl, InstEmit.Smaddl, OpCodeMul.Create);
|
SetA64("10011011001xxxxx0xxxxxxxxxxxxxxx", InstName.Smaddl, InstEmit.Smaddl, OpCodeMul.Create);
|
||||||
SetA64("10011011001xxxxx1xxxxxxxxxxxxxxx", InstName.Smsubl, InstEmit.Smsubl, OpCodeMul.Create);
|
SetA64("10011011001xxxxx1xxxxxxxxxxxxxxx", InstName.Smsubl, InstEmit.Smsubl, OpCodeMul.Create);
|
||||||
SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", InstName.Smulh, InstEmit.Smulh, OpCodeMul.Create);
|
SetA64("10011011010xxxxx0xxxxxxxxxxxxxxx", InstName.Smulh, InstEmit.Smulh, OpCodeMul.Create);
|
||||||
@@ -191,6 +193,9 @@ namespace ARMeilleure.Decoders
|
|||||||
SetA64("10011011101xxxxx0xxxxxxxxxxxxxxx", InstName.Umaddl, InstEmit.Umaddl, OpCodeMul.Create);
|
SetA64("10011011101xxxxx0xxxxxxxxxxxxxxx", InstName.Umaddl, InstEmit.Umaddl, OpCodeMul.Create);
|
||||||
SetA64("10011011101xxxxx1xxxxxxxxxxxxxxx", InstName.Umsubl, InstEmit.Umsubl, OpCodeMul.Create);
|
SetA64("10011011101xxxxx1xxxxxxxxxxxxxxx", InstName.Umsubl, InstEmit.Umsubl, OpCodeMul.Create);
|
||||||
SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstName.Umulh, InstEmit.Umulh, OpCodeMul.Create);
|
SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstName.Umulh, InstEmit.Umulh, OpCodeMul.Create);
|
||||||
|
SetA64("11010101000000110010000001011111", InstName.Wfe, InstEmit.Nop, OpCodeSystem.Create);
|
||||||
|
SetA64("11010101000000110010000001111111", InstName.Wfi, InstEmit.Nop, OpCodeSystem.Create);
|
||||||
|
SetA64("11010101000000110010000000111111", InstName.Yield, InstEmit.Nop, OpCodeSystem.Create);
|
||||||
|
|
||||||
// FP & SIMD
|
// FP & SIMD
|
||||||
SetA64("0101111011100000101110xxxxxxxxxx", InstName.Abs_S, InstEmit.Abs_S, OpCodeSimd.Create);
|
SetA64("0101111011100000101110xxxxxxxxxx", InstName.Abs_S, InstEmit.Abs_S, OpCodeSimd.Create);
|
||||||
@@ -669,6 +674,17 @@ namespace ARMeilleure.Decoders
|
|||||||
SetA32("<<<<0010001xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluImm.Create);
|
SetA32("<<<<0010001xxxxxxxxxxxxxxxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluImm.Create);
|
||||||
SetA32("<<<<0000001xxxxxxxxxxxxxxxx0xxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluRsImm.Create);
|
SetA32("<<<<0000001xxxxxxxxxxxxxxxx0xxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluRsImm.Create);
|
||||||
SetA32("<<<<0000001xxxxxxxxxxxxx0xx1xxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluRsReg.Create);
|
SetA32("<<<<0000001xxxxxxxxxxxxx0xx1xxxx", InstName.Eor, InstEmit32.Eor, OpCode32AluRsReg.Create);
|
||||||
|
SetA32("<<<<0011001000001111000000010000", InstName.Esb, InstEmit32.Nop, OpCode32.Create); // Error Synchronization Barrier (FEAT_RAS)
|
||||||
|
SetA32("<<<<001100100000111100000000011x", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
|
||||||
|
SetA32("<<<<0011001000001111000000001xxx", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
|
||||||
|
SetA32("<<<<0011001000001111000000010001", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
|
||||||
|
SetA32("<<<<0011001000001111000000010011", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
|
||||||
|
SetA32("<<<<0011001000001111000000010101", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
|
||||||
|
SetA32("<<<<001100100000111100000001011x", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
|
||||||
|
SetA32("<<<<0011001000001111000000011xxx", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
|
||||||
|
SetA32("<<<<00110010000011110000001xxxxx", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
|
||||||
|
SetA32("<<<<0011001000001111000001xxxxxx", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
|
||||||
|
SetA32("<<<<001100100000111100001xxxxxxx", InstName.Hint, InstEmit32.Nop, OpCode32.Create); // Reserved Hint
|
||||||
SetA32("1111010101111111111100000110xxxx", InstName.Isb, InstEmit32.Nop, OpCode32.Create);
|
SetA32("1111010101111111111100000110xxxx", InstName.Isb, InstEmit32.Nop, OpCode32.Create);
|
||||||
SetA32("<<<<00011001xxxxxxxx110010011111", InstName.Lda, InstEmit32.Lda, OpCode32MemLdEx.Create);
|
SetA32("<<<<00011001xxxxxxxx110010011111", InstName.Lda, InstEmit32.Lda, OpCode32MemLdEx.Create);
|
||||||
SetA32("<<<<00011101xxxxxxxx110010011111", InstName.Ldab, InstEmit32.Ldab, OpCode32MemLdEx.Create);
|
SetA32("<<<<00011101xxxxxxxx110010011111", InstName.Ldab, InstEmit32.Ldab, OpCode32MemLdEx.Create);
|
||||||
@@ -727,11 +743,15 @@ namespace ARMeilleure.Decoders
|
|||||||
SetA32("<<<<0010111xxxxxxxxxxxxxxxxxxxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluImm.Create);
|
SetA32("<<<<0010111xxxxxxxxxxxxxxxxxxxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluImm.Create);
|
||||||
SetA32("<<<<0000111xxxxxxxxxxxxxxxx0xxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluRsImm.Create);
|
SetA32("<<<<0000111xxxxxxxxxxxxxxxx0xxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluRsImm.Create);
|
||||||
SetA32("<<<<0000111xxxxxxxxxxxxx0xx1xxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluRsReg.Create);
|
SetA32("<<<<0000111xxxxxxxxxxxxx0xx1xxxx", InstName.Rsc, InstEmit32.Rsc, OpCode32AluRsReg.Create);
|
||||||
|
SetA32("<<<<01100001xxxxxxxx11111001xxxx", InstName.Sadd8, InstEmit32.Sadd8, OpCode32AluReg.Create);
|
||||||
SetA32("<<<<0010110xxxxxxxxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluImm.Create);
|
SetA32("<<<<0010110xxxxxxxxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluImm.Create);
|
||||||
SetA32("<<<<0000110xxxxxxxxxxxxxxxx0xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsImm.Create);
|
SetA32("<<<<0000110xxxxxxxxxxxxxxxx0xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsImm.Create);
|
||||||
SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsReg.Create);
|
SetA32("<<<<0000110xxxxxxxxxxxxx0xx1xxxx", InstName.Sbc, InstEmit32.Sbc, OpCode32AluRsReg.Create);
|
||||||
SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, OpCode32AluBf.Create);
|
SetA32("<<<<0111101xxxxxxxxxxxxxx101xxxx", InstName.Sbfx, InstEmit32.Sbfx, OpCode32AluBf.Create);
|
||||||
SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, OpCode32AluMla.Create);
|
SetA32("<<<<01110001xxxx1111xxxx0001xxxx", InstName.Sdiv, InstEmit32.Sdiv, OpCode32AluMla.Create);
|
||||||
|
SetA32("<<<<01101000xxxxxxxx11111011xxxx", InstName.Sel, InstEmit32.Sel, OpCode32AluReg.Create);
|
||||||
|
SetA32("<<<<0011001000001111000000000100", InstName.Sev, InstEmit32.Nop, OpCode32.Create);
|
||||||
|
SetA32("<<<<0011001000001111000000000101", InstName.Sevl, InstEmit32.Nop, OpCode32.Create);
|
||||||
SetA32("<<<<01100011xxxxxxxx11111001xxxx", InstName.Shadd8, InstEmit32.Shadd8, OpCode32AluReg.Create);
|
SetA32("<<<<01100011xxxxxxxx11111001xxxx", InstName.Shadd8, InstEmit32.Shadd8, OpCode32AluReg.Create);
|
||||||
SetA32("<<<<01100011xxxxxxxx11111111xxxx", InstName.Shsub8, InstEmit32.Shsub8, OpCode32AluReg.Create);
|
SetA32("<<<<01100011xxxxxxxx11111111xxxx", InstName.Shsub8, InstEmit32.Shsub8, OpCode32AluReg.Create);
|
||||||
SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smla__, InstEmit32.Smla__, OpCode32AluMla.Create);
|
SetA32("<<<<00010000xxxxxxxxxxxx1xx0xxxx", InstName.Smla__, InstEmit32.Smla__, OpCode32AluMla.Create);
|
||||||
@@ -745,6 +765,7 @@ namespace ARMeilleure.Decoders
|
|||||||
SetA32("<<<<00010010xxxx0000xxxx1x10xxxx", InstName.Smulw_, InstEmit32.Smulw_, OpCode32AluMla.Create);
|
SetA32("<<<<00010010xxxx0000xxxx1x10xxxx", InstName.Smulw_, InstEmit32.Smulw_, OpCode32AluMla.Create);
|
||||||
SetA32("<<<<0110101xxxxxxxxxxxxxxx01xxxx", InstName.Ssat, InstEmit32.Ssat, OpCode32Sat.Create);
|
SetA32("<<<<0110101xxxxxxxxxxxxxxx01xxxx", InstName.Ssat, InstEmit32.Ssat, OpCode32Sat.Create);
|
||||||
SetA32("<<<<01101010xxxxxxxx11110011xxxx", InstName.Ssat16, InstEmit32.Ssat16, OpCode32Sat16.Create);
|
SetA32("<<<<01101010xxxxxxxx11110011xxxx", InstName.Ssat16, InstEmit32.Ssat16, OpCode32Sat16.Create);
|
||||||
|
SetA32("<<<<01100001xxxxxxxx11111111xxxx", InstName.Ssub8, InstEmit32.Ssub8, OpCode32AluReg.Create);
|
||||||
SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, OpCode32MemStEx.Create);
|
SetA32("<<<<00011000xxxx111111001001xxxx", InstName.Stl, InstEmit32.Stl, OpCode32MemStEx.Create);
|
||||||
SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, OpCode32MemStEx.Create);
|
SetA32("<<<<00011100xxxx111111001001xxxx", InstName.Stlb, InstEmit32.Stlb, OpCode32MemStEx.Create);
|
||||||
SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, OpCode32MemStEx.Create);
|
SetA32("<<<<00011000xxxxxxxx11101001xxxx", InstName.Stlex, InstEmit32.Stlex, OpCode32MemStEx.Create);
|
||||||
@@ -776,9 +797,11 @@ namespace ARMeilleure.Decoders
|
|||||||
SetA32("<<<<00010011xxxx0000xxxxxxx0xxxx", InstName.Teq, InstEmit32.Teq, OpCode32AluRsImm.Create);
|
SetA32("<<<<00010011xxxx0000xxxxxxx0xxxx", InstName.Teq, InstEmit32.Teq, OpCode32AluRsImm.Create);
|
||||||
SetA32("<<<<00010011xxxx0000xxxx0xx1xxxx", InstName.Teq, InstEmit32.Teq, OpCode32AluRsReg.Create);
|
SetA32("<<<<00010011xxxx0000xxxx0xx1xxxx", InstName.Teq, InstEmit32.Teq, OpCode32AluRsReg.Create);
|
||||||
SetA32("<<<<0111111111111101111011111110", InstName.Trap, InstEmit32.Trap, OpCode32Exception.Create);
|
SetA32("<<<<0111111111111101111011111110", InstName.Trap, InstEmit32.Trap, OpCode32Exception.Create);
|
||||||
|
SetA32("<<<<0011001000001111000000010010", InstName.Tsb, InstEmit32.Nop, OpCode32.Create); // Trace Synchronization Barrier (FEAT_TRF)
|
||||||
SetA32("<<<<00110001xxxx0000xxxxxxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluImm.Create);
|
SetA32("<<<<00110001xxxx0000xxxxxxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluImm.Create);
|
||||||
SetA32("<<<<00010001xxxx0000xxxxxxx0xxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluRsImm.Create);
|
SetA32("<<<<00010001xxxx0000xxxxxxx0xxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluRsImm.Create);
|
||||||
SetA32("<<<<00010001xxxx0000xxxx0xx1xxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluRsReg.Create);
|
SetA32("<<<<00010001xxxx0000xxxx0xx1xxxx", InstName.Tst, InstEmit32.Tst, OpCode32AluRsReg.Create);
|
||||||
|
SetA32("<<<<01100101xxxxxxxx11111001xxxx", InstName.Uadd8, InstEmit32.Uadd8, OpCode32AluReg.Create);
|
||||||
SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, OpCode32AluBf.Create);
|
SetA32("<<<<0111111xxxxxxxxxxxxxx101xxxx", InstName.Ubfx, InstEmit32.Ubfx, OpCode32AluBf.Create);
|
||||||
SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, OpCode32AluMla.Create);
|
SetA32("<<<<01110011xxxx1111xxxx0001xxxx", InstName.Udiv, InstEmit32.Udiv, OpCode32AluMla.Create);
|
||||||
SetA32("<<<<01100111xxxxxxxx11111001xxxx", InstName.Uhadd8, InstEmit32.Uhadd8, OpCode32AluReg.Create);
|
SetA32("<<<<01100111xxxxxxxx11111001xxxx", InstName.Uhadd8, InstEmit32.Uhadd8, OpCode32AluReg.Create);
|
||||||
@@ -788,207 +811,237 @@ namespace ARMeilleure.Decoders
|
|||||||
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, OpCode32AluUmull.Create);
|
SetA32("<<<<0000100xxxxxxxxxxxxx1001xxxx", InstName.Umull, InstEmit32.Umull, OpCode32AluUmull.Create);
|
||||||
SetA32("<<<<0110111xxxxxxxxxxxxxxx01xxxx", InstName.Usat, InstEmit32.Usat, OpCode32Sat.Create);
|
SetA32("<<<<0110111xxxxxxxxxxxxxxx01xxxx", InstName.Usat, InstEmit32.Usat, OpCode32Sat.Create);
|
||||||
SetA32("<<<<01101110xxxxxxxx11110011xxxx", InstName.Usat16, InstEmit32.Usat16, OpCode32Sat16.Create);
|
SetA32("<<<<01101110xxxxxxxx11110011xxxx", InstName.Usat16, InstEmit32.Usat16, OpCode32Sat16.Create);
|
||||||
|
SetA32("<<<<01100101xxxxxxxx11111111xxxx", InstName.Usub8, InstEmit32.Usub8, OpCode32AluReg.Create);
|
||||||
SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, OpCode32AluUx.Create);
|
SetA32("<<<<01101110xxxxxxxxxx000111xxxx", InstName.Uxtb, InstEmit32.Uxtb, OpCode32AluUx.Create);
|
||||||
SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16, InstEmit32.Uxtb16, OpCode32AluUx.Create);
|
SetA32("<<<<01101100xxxxxxxxxx000111xxxx", InstName.Uxtb16, InstEmit32.Uxtb16, OpCode32AluUx.Create);
|
||||||
SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, OpCode32AluUx.Create);
|
SetA32("<<<<01101111xxxxxxxxxx000111xxxx", InstName.Uxth, InstEmit32.Uxth, OpCode32AluUx.Create);
|
||||||
|
SetA32("<<<<0011001000001111000000000010", InstName.Wfe, InstEmit32.Nop, OpCode32.Create);
|
||||||
|
SetA32("<<<<0011001000001111000000000011", InstName.Wfi, InstEmit32.Nop, OpCode32.Create);
|
||||||
|
SetA32("<<<<0011001000001111000000000001", InstName.Yield, InstEmit32.Nop, OpCode32.Create);
|
||||||
|
|
||||||
// FP & SIMD
|
// VFP
|
||||||
SetA32("111100111x110000xxx0001101x0xxx0", InstName.Aesd_V, InstEmit32.Aesd_V, OpCode32Simd.Create);
|
SetVfp("<<<<11101x110000xxxx101x11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||||
SetA32("111100111x110000xxx0001100x0xxx0", InstName.Aese_V, InstEmit32.Aese_V, OpCode32Simd.Create);
|
SetVfp("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("111100111x110000xxx0001111x0xxx0", InstName.Aesimc_V, InstEmit32.Aesimc_V, OpCode32Simd.Create);
|
SetVfp("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||||
SetA32("111100111x110000xxx0001110x0xxx0", InstName.Aesmc_V, InstEmit32.Aesmc_V, OpCode32Simd.Create);
|
SetVfp("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||||
SetA32("111100110x00xxx0xxx01100x1x0xxx0", InstName.Sha256h_V, InstEmit32.Sha256h_V, OpCode32SimdReg.Create);
|
SetVfp("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, OpCode32SimdS.Create, OpCode32SimdS.CreateT32); // FP 32 and 64, scalar.
|
||||||
SetA32("111100110x01xxx0xxx01100x1x0xxx0", InstName.Sha256h2_V, InstEmit32.Sha256h2_V, OpCode32SimdReg.Create);
|
SetVfp("<<<<11101x11110xxxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create, OpCode32SimdCvtFI.CreateT32); // FP32 to int.
|
||||||
SetA32("111100111x111010xxx0001111x0xxx0", InstName.Sha256su0_V, InstEmit32.Sha256su0_V, OpCode32Simd.Create);
|
SetVfp("<<<<11101x111000xxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create, OpCode32SimdCvtFI.CreateT32); // Int to FP32.
|
||||||
SetA32("111100110x10xxx0xxx01100x1x0xxx0", InstName.Sha256su1_V, InstEmit32.Sha256su1_V, OpCode32SimdReg.Create);
|
SetVfp("111111101x1111xxxxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_RM, OpCode32SimdCvtFI.Create, OpCode32SimdCvtFI.CreateT32); // The many FP32 to int encodings (fp).
|
||||||
SetA32("1111001x0x<<xxxxxxxx0111xxx0xxxx", InstName.Vabd, InstEmit32.Vabd_I, OpCode32SimdReg.Create);
|
SetVfp("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxxx0111x0x0xxxx", InstName.Vabdl, InstEmit32.Vabdl_I, OpCode32SimdRegLong.Create);
|
SetVfp("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, OpCode32SimdDupGP.Create, OpCode32SimdDupGP.CreateT32);
|
||||||
SetA32("<<<<11101x110000xxxx101x11x0xxxx", InstName.Vabs, InstEmit32.Vabs_S, OpCode32SimdS.Create);
|
SetVfp("<<<<11101x10xxxxxxxx101xx0x0xxxx", InstName.Vfma, InstEmit32.Vfma_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("111100111x11<<01xxxx00110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create);
|
SetVfp("<<<<11101x10xxxxxxxx101xx1x0xxxx", InstName.Vfms, InstEmit32.Vfms_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("111100111x111001xxxx01110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create);
|
SetVfp("<<<<11101x01xxxxxxxx101xx1x0xxxx", InstName.Vfnma, InstEmit32.Vfnma_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, OpCode32SimdReg.Create);
|
SetVfp("<<<<11101x01xxxxxxxx101xx0x0xxxx", InstName.Vfnms, InstEmit32.Vfnms_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("<<<<11100x11xxxxxxxx101xx0x0xxxx", InstName.Vadd, InstEmit32.Vadd_S, OpCode32SimdRegS.Create);
|
SetVfp("<<<<11001x01xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, OpCode32SimdReg.Create);
|
SetVfp("<<<<11001x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxx00000x0x0xxxx", InstName.Vaddl, InstEmit32.Vaddl_I, OpCode32SimdRegLong.Create);
|
SetVfp("<<<<11010x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxx00001x0x0xxxx", InstName.Vaddw, InstEmit32.Vaddw_I, OpCode32SimdRegWide.Create);
|
SetVfp("<<<<11001x01xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, OpCode32SimdBinary.Create);
|
SetVfp("<<<<11001x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("111100100x01xxxxxxxx0001xxx1xxxx", InstName.Vbic, InstEmit32.Vbic_I, OpCode32SimdBinary.Create);
|
SetVfp("<<<<11010x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("1111001x1x000xxxxxxx<<x10x11xxxx", InstName.Vbic, InstEmit32.Vbic_II, OpCode32SimdImm.Create);
|
SetVfp("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, OpCode32SimdMemImm.Create, OpCode32SimdMemImm.CreateT32);
|
||||||
SetA32("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, OpCode32SimdBinary.Create);
|
SetVfp("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, OpCode32SimdBinary.Create);
|
SetVfp("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.Vminnm, InstEmit32.Vminnm_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, OpCode32SimdBinary.Create);
|
SetVfp("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, OpCode32SimdReg.Create);
|
SetVfp("<<<<11100x00xxxxxxxx101xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, OpCode32SimdReg.Create);
|
SetVfp("<<<<11100xx0xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create, OpCode32SimdMovGpElem.CreateT32); // From gen purpose.
|
||||||
SetA32("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, OpCode32SimdCmpZ.Create);
|
SetVfp("<<<<1110xxx1xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create, OpCode32SimdMovGpElem.CreateT32); // To gen purpose.
|
||||||
SetA32("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, OpCode32SimdReg.Create);
|
SetVfp("<<<<1100010xxxxxxxxx101000x1xxxx", InstName.Vmov, InstEmit32.Vmov_G2, OpCode32SimdMovGpDouble.Create, OpCode32SimdMovGpDouble.CreateT32); // To/from gen purpose x2 and single precision x2.
|
||||||
SetA32("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, OpCode32SimdReg.Create);
|
SetVfp("<<<<1100010xxxxxxxxx101100x1xxxx", InstName.Vmov, InstEmit32.Vmov_GD, OpCode32SimdMovGpDouble.Create, OpCode32SimdMovGpDouble.CreateT32); // To/from gen purpose x2 and double precision.
|
||||||
SetA32("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, OpCode32SimdCmpZ.Create);
|
SetVfp("<<<<1110000xxxxxxxxx1010x0010000", InstName.Vmov, InstEmit32.Vmov_GS, OpCode32SimdMovGp.Create, OpCode32SimdMovGp.CreateT32); // To/from gen purpose and single precision.
|
||||||
SetA32("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, OpCode32SimdReg.Create);
|
SetVfp("<<<<11101x11xxxxxxxx101x0000xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm44.Create, OpCode32SimdImm44.CreateT32); // Scalar f16/32/64 based on size 01 10 11.
|
||||||
SetA32("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, OpCode32SimdReg.Create);
|
SetVfp("<<<<11101x110000xxxx101x01x0xxxx", InstName.Vmov, InstEmit32.Vmov_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||||
SetA32("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, OpCode32SimdCmpZ.Create);
|
SetVfp("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, OpCode32SimdSpecial.Create, OpCode32SimdSpecial.CreateT32);
|
||||||
SetA32("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, OpCode32SimdCmpZ.Create);
|
SetVfp("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, OpCode32SimdSpecial.Create, OpCode32SimdSpecial.CreateT32);
|
||||||
SetA32("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create);
|
SetVfp("<<<<11100x10xxxxxxxx101xx0x0xxxx", InstName.Vmul, InstEmit32.Vmul_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("<<<<11101x11010xxxxx101x01x0xxxx", InstName.Vcmp, InstEmit32.Vcmp, OpCode32SimdS.Create);
|
SetVfp("<<<<11101x110001xxxx101x01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||||
SetA32("<<<<11101x11010xxxxx101x11x0xxxx", InstName.Vcmpe, InstEmit32.Vcmpe, OpCode32SimdS.Create);
|
SetVfp("<<<<11100x01xxxxxxxx101xx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create);
|
SetVfp("<<<<11100x01xxxxxxxx101xx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("<<<<11101x110111xxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FD, OpCode32SimdS.Create); // FP 32 and 64, scalar.
|
SetVfp("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("<<<<11101x11110xxxxx101x11x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // FP32 to int.
|
SetVfp("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||||
SetA32("<<<<11101x111000xxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_FI, OpCode32SimdCvtFI.Create); // Int to FP32.
|
SetVfp("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||||
SetA32("111111101x1111xxxxxx101xx1x0xxxx", InstName.Vcvt, InstEmit32.Vcvt_RM, OpCode32SimdCvtFI.Create); // The many FP32 to int encodings (fp).
|
SetVfp("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||||
SetA32("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create); // FP and integer, vector.
|
SetVfp("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
|
||||||
SetA32("<<<<11101x00xxxxxxxx101xx0x0xxxx", InstName.Vdiv, InstEmit32.Vdiv_S, OpCode32SimdRegS.Create);
|
SetVfp("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create, OpCode32SimdSel.CreateT32);
|
||||||
SetA32("<<<<11101xx0xxxxxxxx1011x0x10000", InstName.Vdup, InstEmit32.Vdup, OpCode32SimdDupGP.Create);
|
SetVfp("<<<<11001x00xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create);
|
SetVfp("<<<<11001x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create);
|
SetVfp("<<<<11010x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create);
|
SetVfp("<<<<11001x00xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("<<<<11101x10xxxxxxxx101xx0x0xxxx", InstName.Vfma, InstEmit32.Vfma_S, OpCode32SimdRegS.Create);
|
SetVfp("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("111100100x00xxxxxxxx1100xxx1xxxx", InstName.Vfma, InstEmit32.Vfma_V, OpCode32SimdReg.Create);
|
SetVfp("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create, OpCode32SimdMemMult.CreateT32);
|
||||||
SetA32("<<<<11101x10xxxxxxxx101xx1x0xxxx", InstName.Vfms, InstEmit32.Vfms_S, OpCode32SimdRegS.Create);
|
SetVfp("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, OpCode32SimdMemImm.Create, OpCode32SimdMemImm.CreateT32);
|
||||||
SetA32("111100100x10xxxxxxxx1100xxx1xxxx", InstName.Vfms, InstEmit32.Vfms_V, OpCode32SimdReg.Create);
|
SetVfp("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
|
||||||
SetA32("<<<<11101x01xxxxxxxx101xx1x0xxxx", InstName.Vfnma, InstEmit32.Vfnma_S, OpCode32SimdRegS.Create);
|
|
||||||
SetA32("<<<<11101x01xxxxxxxx101xx0x0xxxx", InstName.Vfnms, InstEmit32.Vfnms_S, OpCode32SimdRegS.Create);
|
// ASIMD
|
||||||
SetA32("1111001x0x<<xxxxxxxx0000xxx0xxxx", InstName.Vhadd, InstEmit32.Vhadd, OpCode32SimdReg.Create);
|
SetAsimd("111100111x110000xxx0001101x0xxx0", InstName.Aesd_V, InstEmit32.Aesd_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
|
||||||
SetA32("111101001x10xxxxxxxxxx00xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create);
|
SetAsimd("111100111x110000xxx0001100x0xxx0", InstName.Aese_V, InstEmit32.Aese_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
|
||||||
SetA32("111101000x10xxxxxxxx0111xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 1.
|
SetAsimd("111100111x110000xxx0001111x0xxx0", InstName.Aesimc_V, InstEmit32.Aesimc_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
|
||||||
SetA32("111101000x10xxxxxxxx1010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 2.
|
SetAsimd("111100111x110000xxx0001110x0xxx0", InstName.Aesmc_V, InstEmit32.Aesmc_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
|
||||||
SetA32("111101000x10xxxxxxxx0110xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 3.
|
SetAsimd("111100110x00xxx0xxx01100x1x0xxx0", InstName.Sha256h_V, InstEmit32.Sha256h_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create); // Regs = 4.
|
SetAsimd("111100110x01xxx0xxx01100x1x0xxx0", InstName.Sha256h2_V, InstEmit32.Sha256h2_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111101001x10xxxxxxxxxx01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create);
|
SetAsimd("111100111x111010xxx0001111x0xxx0", InstName.Sha256su0_V, InstEmit32.Sha256su0_V, OpCode32Simd.Create, OpCode32Simd.CreateT32);
|
||||||
SetA32("111101000x10xxxxxxxx100xxxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype).
|
SetAsimd("111100110x10xxx0xxx01100x1x0xxx0", InstName.Sha256su1_V, InstEmit32.Sha256su1_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111101000x10xxxxxxxx0011xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2.
|
SetAsimd("1111001x0x<<xxxxxxxx0111xxx0xxxx", InstName.Vabd, InstEmit32.Vabd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111101001x10xxxxxxxxxx10xxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create);
|
SetAsimd("1111001x1x<<xxxxxxxx0111x0x0xxxx", InstName.Vabdl, InstEmit32.Vabdl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
|
||||||
SetA32("111101000x10xxxxxxxx010xxxxxxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
|
SetAsimd("111100111x11<<01xxxx00110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("111101001x10xxxxxxxxxx11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create);
|
SetAsimd("111100111x111001xxxx01110xx0xxxx", InstName.Vabs, InstEmit32.Vabs_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("111101000x10xxxxxxxx000xxxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
|
SetAsimd("111100100xxxxxxxxxxx1000xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<11001x01xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
|
SetAsimd("111100100x00xxxxxxxx1101xxx0xxxx", InstName.Vadd, InstEmit32.Vadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<11001x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
|
SetAsimd("1111001x1x<<xxxxxxx00000x0x0xxxx", InstName.Vaddl, InstEmit32.Vaddl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
|
||||||
SetA32("<<<<11010x11xxxxxxxx1011xxxxxxx0", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
|
SetAsimd("1111001x1x<<xxxxxxx00001x0x0xxxx", InstName.Vaddw, InstEmit32.Vaddw_I, OpCode32SimdRegWide.Create, OpCode32SimdRegWide.CreateT32);
|
||||||
SetA32("<<<<11001x01xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
|
SetAsimd("111100100x00xxxxxxxx0001xxx1xxxx", InstName.Vand, InstEmit32.Vand_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
||||||
SetA32("<<<<11001x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
|
SetAsimd("111100100x01xxxxxxxx0001xxx1xxxx", InstName.Vbic, InstEmit32.Vbic_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
||||||
SetA32("<<<<11010x11xxxxxxxx1010xxxxxxxx", InstName.Vldm, InstEmit32.Vldm, OpCode32SimdMemMult.Create);
|
SetAsimd("1111001x1x000xxxxxxx<<x10x11xxxx", InstName.Vbic, InstEmit32.Vbic_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
|
||||||
SetA32("<<<<1101xx01xxxxxxxx101xxxxxxxxx", InstName.Vldr, InstEmit32.Vldr, OpCode32SimdMemImm.Create);
|
SetAsimd("111100110x11xxxxxxxx0001xxx1xxxx", InstName.Vbif, InstEmit32.Vbif, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
||||||
SetA32("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, OpCode32SimdReg.Create);
|
SetAsimd("111100110x10xxxxxxxx0001xxx1xxxx", InstName.Vbit, InstEmit32.Vbit, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
||||||
SetA32("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, OpCode32SimdReg.Create);
|
SetAsimd("111100110x01xxxxxxxx0001xxx1xxxx", InstName.Vbsl, InstEmit32.Vbsl, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
||||||
SetA32("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, OpCode32SimdReg.Create);
|
SetAsimd("111100110x<<xxxxxxxx1000xxx1xxxx", InstName.Vceq, InstEmit32.Vceq_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, OpCode32SimdReg.Create);
|
SetAsimd("111100100x00xxxxxxxx1110xxx0xxxx", InstName.Vceq, InstEmit32.Vceq_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111111101x00xxxxxxxx10>>x0x0xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_S, OpCode32SimdRegS.Create);
|
SetAsimd("111100111x11xx01xxxx0x010xx0xxxx", InstName.Vceq, InstEmit32.Vceq_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_V, OpCode32SimdReg.Create);
|
SetAsimd("1111001x0x<<xxxxxxxx0011xxx1xxxx", InstName.Vcge, InstEmit32.Vcge_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111111101x00xxxxxxxx10>>x1x0xxxx", InstName.Vminnm, InstEmit32.Vminnm_S, OpCode32SimdRegS.Create);
|
SetAsimd("111100110x00xxxxxxxx1110xxx0xxxx", InstName.Vcge, InstEmit32.Vcge_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.Vminnm_V, OpCode32SimdReg.Create);
|
SetAsimd("111100111x11xx01xxxx0x001xx0xxxx", InstName.Vcge, InstEmit32.Vcge_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, OpCode32SimdRegElem.Create);
|
SetAsimd("1111001x0x<<xxxxxxxx0011xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, OpCode32SimdReg.Create);
|
SetAsimd("111100110x10xxxxxxxx1110xxx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<11100x00xxxxxxxx101xx0x0xxxx", InstName.Vmla, InstEmit32.Vmla_S, OpCode32SimdRegS.Create);
|
SetAsimd("111100111x11xx01xxxx0x000xx0xxxx", InstName.Vcgt, InstEmit32.Vcgt_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, OpCode32SimdReg.Create);
|
SetAsimd("111100111x11xx01xxxx0x011xx0xxxx", InstName.Vcle, InstEmit32.Vcle_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxx01000x0x0xxxx", InstName.Vmlal, InstEmit32.Vmlal_I, OpCode32SimdRegLong.Create);
|
SetAsimd("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, OpCode32SimdRegElem.Create);
|
SetAsimd("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("<<<<11100x00xxxxxxxx101xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_S, OpCode32SimdRegS.Create);
|
SetAsimd("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); // FP and integer, vector.
|
||||||
SetA32("111100100x10xxxxxxxx1101xxx1xxxx", InstName.Vmls, InstEmit32.Vmls_V, OpCode32SimdReg.Create);
|
SetAsimd("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create, OpCode32SimdDupElem.CreateT32);
|
||||||
SetA32("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, OpCode32SimdReg.Create);
|
SetAsimd("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxx01010x0x0xxxx", InstName.Vmlsl, InstEmit32.Vmlsl_I, OpCode32SimdRegLong.Create);
|
SetAsimd("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create, OpCode32SimdExt.CreateT32);
|
||||||
SetA32("<<<<11100xx0xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // From gen purpose.
|
SetAsimd("111100100x00xxxxxxxx1100xxx1xxxx", InstName.Vfma, InstEmit32.Vfma_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<1110xxx1xxxxxxxx1011xxx10000", InstName.Vmov, InstEmit32.Vmov_G1, OpCode32SimdMovGpElem.Create); // To gen purpose.
|
SetAsimd("111100100x10xxxxxxxx1100xxx1xxxx", InstName.Vfms, InstEmit32.Vfms_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<1100010xxxxxxxxx101000x1xxxx", InstName.Vmov, InstEmit32.Vmov_G2, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and single precision x2.
|
SetAsimd("1111001x0x<<xxxxxxxx0000xxx0xxxx", InstName.Vhadd, InstEmit32.Vhadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<1100010xxxxxxxxx101100x1xxxx", InstName.Vmov, InstEmit32.Vmov_GD, OpCode32SimdMovGpDouble.Create); // To/from gen purpose x2 and double precision.
|
SetAsimd("111101001x10xxxxxxxx0000xxx0xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("<<<<1110000xxxxxxxxx1010x0010000", InstName.Vmov, InstEmit32.Vmov_GS, OpCode32SimdMovGp.Create); // To/from gen purpose and single precision.
|
SetAsimd("111101001x10xxxxxxxx0100xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q vector I32.
|
SetAsimd("111101001x10xxxxxxxx1000x000xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("<<<<11101x11xxxxxxxx101x0000xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm44.Create); // Scalar f16/32/64 based on size 01 10 11.
|
SetAsimd("111101001x10xxxxxxxx1000x011xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I16.
|
SetAsimd("111101001x10xxxxxxxx110000x0xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q (dt - from cmode).
|
SetAsimd("111101001x10xxxxxxxx110001xxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create); // D/Q I64.
|
SetAsimd("111101001x10xxxxxxxx110010xxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("<<<<11101x110000xxxx101x01x0xxxx", InstName.Vmov, InstEmit32.Vmov_S, OpCode32SimdS.Create);
|
SetAsimd("111101000x10xxxxxxxx0111xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1.
|
||||||
SetA32("1111001x1x001000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
|
SetAsimd("111101000x10xxxxxxxx1010xx<<xxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2.
|
||||||
SetA32("1111001x1x010000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
|
SetAsimd("111101000x10xxxxxxxx0110xx0xxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 3.
|
||||||
SetA32("1111001x1x100000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create);
|
SetAsimd("111101000x10xxxxxxxx0010xxxxxxxx", InstName.Vld1, InstEmit32.Vld1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 4.
|
||||||
SetA32("111100111x11<<10xxxx001000x0xxx0", InstName.Vmovn, InstEmit32.Vmovn, OpCode32SimdMovn.Create);
|
SetAsimd("111101001x10xxxxxxxx0x01xxxxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("<<<<11101111xxxxxxxx101000010000", InstName.Vmrs, InstEmit32.Vmrs, OpCode32SimdSpecial.Create);
|
SetAsimd("111101001x10xxxxxxxx1001xx0xxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("<<<<11101110xxxxxxxx101000010000", InstName.Vmsr, InstEmit32.Vmsr, OpCode32SimdSpecial.Create);
|
SetAsimd("111101001x10xxxxxxxx1101<<xxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, OpCode32SimdRegElem.Create);
|
SetAsimd("111101000x10xxxxxxxx100x<<0xxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
|
||||||
SetA32("111100100x<<xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create);
|
SetAsimd("111101000x10xxxxxxxx100x<<10xxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
|
||||||
SetA32("111100110x00xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create);
|
SetAsimd("111101000x10xxxxxxxx0011<<xxxxxx", InstName.Vld2, InstEmit32.Vld2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2, inc = 2.
|
||||||
SetA32("<<<<11100x10xxxxxxxx101xx0x0xxxx", InstName.Vmul, InstEmit32.Vmul_S, OpCode32SimdRegS.Create);
|
SetAsimd("111101001x10xxxxxxxx0x10xxx0xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, OpCode32SimdReg.Create);
|
SetAsimd("111101001x10xxxxxxxx1010xx00xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxx01010x1x0xxxx", InstName.Vmull, InstEmit32.Vmull_1, OpCode32SimdRegElemLong.Create);
|
SetAsimd("111101001x10xxxxxxxx1110<<x0xxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxx01100x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create);
|
SetAsimd("111101000x10xxxxxxxx010x<<0xxxxx", InstName.Vld3, InstEmit32.Vld3, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
|
||||||
SetA32("111100101xx0xxxxxxx01110x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create); // P8/P64
|
SetAsimd("111101001x10xxxxxxxx0x11xxxxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("111100111x110000xxxx01011xx0xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, OpCode32SimdBinary.Create);
|
SetAsimd("111101001x10xxxxxxxx1011xx<<xxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create); // D/Q vector I32.
|
SetAsimd("111101001x10xxxxxxxx1111<<x>xxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create);
|
SetAsimd("111101000x10xxxxxxxx000x<<xxxxxx", InstName.Vld4, InstEmit32.Vld4, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
|
||||||
SetA32("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create);
|
SetAsimd("1111001x0x<<xxxxxxxx0110xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<11101x110001xxxx101x01x0xxxx", InstName.Vneg, InstEmit32.Vneg_S, OpCode32SimdS.Create);
|
SetAsimd("111100100x00xxxxxxxx1111xxx0xxxx", InstName.Vmax, InstEmit32.Vmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111100111x11<<01xxxx00111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create);
|
SetAsimd("1111001x0x<<xxxxxxxx0110xxx1xxxx", InstName.Vmin, InstEmit32.Vmin_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111100111x111001xxxx01111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create);
|
SetAsimd("111100100x10xxxxxxxx1111xxx0xxxx", InstName.Vmin, InstEmit32.Vmin_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<11100x01xxxxxxxx101xx1x0xxxx", InstName.Vnmla, InstEmit32.Vnmla_S, OpCode32SimdRegS.Create);
|
SetAsimd("111100110x0xxxxxxxxx1111xxx1xxxx", InstName.Vmaxnm, InstEmit32.Vmaxnm_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<11100x01xxxxxxxx101xx0x0xxxx", InstName.Vnmls, InstEmit32.Vnmls_S, OpCode32SimdRegS.Create);
|
SetAsimd("111100110x1xxxxxxxxx1111xxx1xxxx", InstName.Vminnm, InstEmit32.Vminnm_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create);
|
SetAsimd("1111001x1x<<xxxxxxxx000xx1x0xxxx", InstName.Vmla, InstEmit32.Vmla_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32);
|
||||||
SetA32("111100100x11xxxxxxxx0001xxx1xxxx", InstName.Vorn, InstEmit32.Vorn_I, OpCode32SimdBinary.Create);
|
SetAsimd("111100100xxxxxxxxxxx1001xxx0xxxx", InstName.Vmla, InstEmit32.Vmla_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, OpCode32SimdBinary.Create);
|
SetAsimd("111100100x00xxxxxxxx1101xxx1xxxx", InstName.Vmla, InstEmit32.Vmla_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create);
|
SetAsimd("1111001x1x<<xxxxxxx01000x0x0xxxx", InstName.Vmlal, InstEmit32.Vmlal_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
|
||||||
SetA32("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x<<xxxxxxxx010xx1x0xxxx", InstName.Vmls, InstEmit32.Vmls_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32);
|
||||||
SetA32("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create);
|
SetAsimd("111100100x10xxxxxxxx1101xxx1xxxx", InstName.Vmls, InstEmit32.Vmls_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111100111x11<<00xxxx0010xxx0xxxx", InstName.Vpaddl, InstEmit32.Vpaddl, OpCode32SimdCmpZ.Create);
|
SetAsimd("111100110xxxxxxxxxxx1001xxx0xxxx", InstName.Vmls, InstEmit32.Vmls_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x<<xxxxxxx01010x0x0xxxx", InstName.Vmlsl, InstEmit32.Vmlsl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
|
||||||
SetA32("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x000xxxxxxx0xx00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q vector I32.
|
||||||
SetA32("1111001x0x<<xxxxxxxx1010x0x1xxxx", InstName.Vpmin, InstEmit32.Vpmin_I, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x000xxxxxxx10x00x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q I16.
|
||||||
SetA32("111100110x10xxxxxxxx1111x0x0xxxx", InstName.Vpmin, InstEmit32.Vpmin_V, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x000xxxxxxx11xx0x01xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q (dt - from cmode).
|
||||||
SetA32("1111001x0xxxxxxxxxxx0000xxx1xxxx", InstName.Vqadd, InstEmit32.Vqadd, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x000xxxxxxx11100x11xxxx", InstName.Vmov, InstEmit32.Vmov_I, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q I64.
|
||||||
SetA32("111100100x01xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x001000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32);
|
||||||
SetA32("111100100x10xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x010000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32);
|
||||||
SetA32("111100111x11<<10xxxx00101xx0xxx0", InstName.Vqmovn, InstEmit32.Vqmovn, OpCode32SimdMovn.Create);
|
SetAsimd("1111001x1x100000xxx0101000x1xxxx", InstName.Vmovl, InstEmit32.Vmovl, OpCode32SimdLong.Create, OpCode32SimdLong.CreateT32);
|
||||||
SetA32("111100111x11<<10xxxx001001x0xxx0", InstName.Vqmovun, InstEmit32.Vqmovun, OpCode32SimdMovn.Create);
|
SetAsimd("111100111x11<<10xxxx001000x0xxx0", InstName.Vmovn, InstEmit32.Vmovn, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
|
||||||
SetA32("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create);
|
SetAsimd("1111001x1x<<xxxxxxxx100xx1x0xxxx", InstName.Vmul, InstEmit32.Vmul_1, OpCode32SimdRegElem.Create, OpCode32SimdRegElem.CreateT32);
|
||||||
SetA32("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create);
|
SetAsimd("111100100x<<xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create);
|
SetAsimd("111100110x00xxxxxxxx1001xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111100111x>>>xxxxxxx100000x1xxx0", InstName.Vqshrun, InstEmit32.Vqshrun, OpCode32SimdShImmNarrow.Create);
|
SetAsimd("111100110x00xxxxxxxx1101xxx1xxxx", InstName.Vmul, InstEmit32.Vmul_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("1111001x0xxxxxxxxxxx0010xxx1xxxx", InstName.Vqsub, InstEmit32.Vqsub, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x<<xxxxxxx01010x1x0xxxx", InstName.Vmull, InstEmit32.Vmull_1, OpCode32SimdRegElemLong.Create, OpCode32SimdRegElemLong.CreateT32);
|
||||||
SetA32("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, OpCode32SimdSqrte.Create);
|
SetAsimd("1111001x1x<<xxxxxxx01100x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
|
||||||
SetA32("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, OpCode32SimdReg.Create);
|
SetAsimd("111100101xx0xxxxxxx01110x0x0xxxx", InstName.Vmull, InstEmit32.Vmull_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32); // P8/P64
|
||||||
SetA32("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, OpCode32SimdRev.Create);
|
SetAsimd("111100111x110000xxxx01011xx0xxxx", InstName.Vmvn, InstEmit32.Vmvn_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
||||||
SetA32("1111001x0x<<xxxxxxxx0001xxx0xxxx", InstName.Vrhadd, InstEmit32.Vrhadd, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x000xxxxxxx0xx00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32); // D/Q vector I32.
|
||||||
SetA32("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create);
|
SetAsimd("1111001x1x000xxxxxxx10x00x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
|
||||||
SetA32("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create);
|
SetAsimd("1111001x1x000xxxxxxx110x0x11xxxx", InstName.Vmvn, InstEmit32.Vmvn_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
|
||||||
SetA32("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create);
|
SetAsimd("111100111x11<<01xxxx00111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("1111001x1x>>>xxxxxxx0010>xx1xxxx", InstName.Vrshr, InstEmit32.Vrshr, OpCode32SimdShImm.Create);
|
SetAsimd("111100111x111001xxxx01111xx0xxxx", InstName.Vneg, InstEmit32.Vneg_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("111100101x>>>xxxxxxx100001x1xxx0", InstName.Vrshrn, InstEmit32.Vrshrn, OpCode32SimdShImmNarrow.Create);
|
SetAsimd("111100100x11xxxxxxxx0001xxx1xxxx", InstName.Vorn, InstEmit32.Vorn_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
||||||
SetA32("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, OpCode32SimdSqrte.Create);
|
SetAsimd("111100100x10xxxxxxxx0001xxx1xxxx", InstName.Vorr, InstEmit32.Vorr_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
||||||
SetA32("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
|
||||||
SetA32("1111001x1x>>>xxxxxxx0011>xx1xxxx", InstName.Vrsra, InstEmit32.Vrsra, OpCode32SimdShImm.Create);
|
SetAsimd("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create);
|
SetAsimd("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create);
|
SetAsimd("111100111x11<<00xxxx0010xxx0xxxx", InstName.Vpaddl, InstEmit32.Vpaddl, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create);
|
SetAsimd("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create); // A1 encoding.
|
SetAsimd("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create);
|
SetAsimd("1111001x0x<<xxxxxxxx1010x0x1xxxx", InstName.Vpmin, InstEmit32.Vpmin_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create);
|
SetAsimd("111100110x10xxxxxxxx1111x0x0xxxx", InstName.Vpmin, InstEmit32.Vpmin_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create);
|
SetAsimd("1111001x0xxxxxxxxxxx0000xxx1xxxx", InstName.Vqadd, InstEmit32.Vqadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create);
|
SetAsimd("111100100x01xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111101001x00xxxxxxxx<<00xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create);
|
SetAsimd("111100100x10xxxxxxxx1011xxx0xxxx", InstName.Vqdmulh, InstEmit32.Vqdmulh, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111101000x00xxxxxxxx0111xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 1.
|
SetAsimd("111100111x11<<10xxxx00101xx0xxx0", InstName.Vqmovn, InstEmit32.Vqmovn, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
|
||||||
SetA32("111101000x00xxxxxxxx1010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 2.
|
SetAsimd("111100111x11<<10xxxx001001x0xxx0", InstName.Vqmovun, InstEmit32.Vqmovun, OpCode32SimdMovn.Create, OpCode32SimdMovn.CreateT32);
|
||||||
SetA32("111101000x00xxxxxxxx0110xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 3.
|
SetAsimd("1111001x1x>>>xxxxxxx100101x1xxx0", InstName.Vqrshrn, InstEmit32.Vqrshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
|
||||||
SetA32("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create); // Regs = 4.
|
SetAsimd("111100111x>>>xxxxxxx100001x1xxx0", InstName.Vqrshrun, InstEmit32.Vqrshrun, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
|
||||||
SetA32("111101001x00xxxxxxxx<<01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create);
|
SetAsimd("1111001x1x>>>xxxxxxx100100x1xxx0", InstName.Vqshrn, InstEmit32.Vqshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
|
||||||
SetA32("111101000x00xxxxxxxx100xxxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 1, inc = 1/2 (itype).
|
SetAsimd("111100111x>>>xxxxxxx100000x1xxx0", InstName.Vqshrun, InstEmit32.Vqshrun, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
|
||||||
SetA32("111101000x00xxxxxxxx0011xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create); // Regs = 2, inc = 2.
|
SetAsimd("1111001x0xxxxxxxxxxx0010xxx1xxxx", InstName.Vqsub, InstEmit32.Vqsub, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111101001x00xxxxxxxx<<10xxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create);
|
SetAsimd("111100111x111011xxxx010x0xx0xxxx", InstName.Vrecpe, InstEmit32.Vrecpe, OpCode32SimdSqrte.Create, OpCode32SimdSqrte.CreateT32);
|
||||||
SetA32("111101000x00xxxxxxxx010xxxxxxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
|
SetAsimd("111100100x00xxxxxxxx1111xxx1xxxx", InstName.Vrecps, InstEmit32.Vrecps, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("111101001x00xxxxxxxx<<11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create);
|
SetAsimd("111100111x11xx00xxxx000<<xx0xxxx", InstName.Vrev, InstEmit32.Vrev, OpCode32SimdRev.Create, OpCode32SimdRev.CreateT32);
|
||||||
SetA32("111101000x00xxxxxxxx000xxxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemPair.Create); // Inc = 1/2 (itype).
|
SetAsimd("1111001x0x<<xxxxxxxx0001xxx0xxxx", InstName.Vrhadd, InstEmit32.Vrhadd, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<11001x00xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
|
SetAsimd("111100111x111010xxxx01010xx0xxxx", InstName.Vrinta, InstEmit32.Vrinta_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("<<<<11001x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
|
SetAsimd("111100111x111010xxxx01101xx0xxxx", InstName.Vrintm, InstEmit32.Vrintm_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("<<<<11010x10xxxxxxxx1011xxxxxxx0", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
|
SetAsimd("111100111x111010xxxx01000xx0xxxx", InstName.Vrintn, InstEmit32.Vrintn_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("<<<<11001x00xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
|
SetAsimd("111100111x111010xxxx01111xx0xxxx", InstName.Vrintp, InstEmit32.Vrintp_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
SetA32("<<<<11001x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
|
SetAsimd("1111001x1x>>>xxxxxxx0010>xx1xxxx", InstName.Vrshr, InstEmit32.Vrshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
|
||||||
SetA32("<<<<11010x10xxxxxxxx1010xxxxxxxx", InstName.Vstm, InstEmit32.Vstm, OpCode32SimdMemMult.Create);
|
SetAsimd("111100101x>>>xxxxxxx100001x1xxx0", InstName.Vrshrn, InstEmit32.Vrshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
|
||||||
SetA32("<<<<1101xx00xxxxxxxx101xxxxxxxxx", InstName.Vstr, InstEmit32.Vstr, OpCode32SimdMemImm.Create);
|
SetAsimd("111100111x111011xxxx010x1xx0xxxx", InstName.Vrsqrte, InstEmit32.Vrsqrte, OpCode32SimdSqrte.Create, OpCode32SimdSqrte.CreateT32);
|
||||||
SetA32("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, OpCode32SimdReg.Create);
|
SetAsimd("111100100x10xxxxxxxx1111xxx1xxxx", InstName.Vrsqrts, InstEmit32.Vrsqrts, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("<<<<11100x11xxxxxxxx101xx1x0xxxx", InstName.Vsub, InstEmit32.Vsub_S, OpCode32SimdRegS.Create);
|
SetAsimd("1111001x1x>>>xxxxxxx0011>xx1xxxx", InstName.Vrsra, InstEmit32.Vrsra, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
|
||||||
SetA32("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create);
|
SetAsimd("111100101x>>>xxxxxxx0101>xx1xxxx", InstName.Vshl, InstEmit32.Vshl, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxx00010x0x0xxxx", InstName.Vsubl, InstEmit32.Vsubl_I, OpCode32SimdRegLong.Create);
|
SetAsimd("1111001x0xxxxxxxxxxx0100xxx0xxxx", InstName.Vshl, InstEmit32.Vshl_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
SetA32("1111001x1x<<xxxxxxx00011x0x0xxxx", InstName.Vsubw, InstEmit32.Vsubw_I, OpCode32SimdRegWide.Create);
|
SetAsimd("1111001x1x>>>xxxxxxx101000x1xxxx", InstName.Vshll, InstEmit32.Vshll, OpCode32SimdShImmLong.Create, OpCode32SimdShImmLong.CreateT32); // A1 encoding.
|
||||||
SetA32("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, OpCode32SimdTbl.Create);
|
SetAsimd("1111001x1x>>>xxxxxxx0000>xx1xxxx", InstName.Vshr, InstEmit32.Vshr, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
|
||||||
SetA32("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, OpCode32SimdCmpZ.Create);
|
SetAsimd("111100101x>>>xxxxxxx100000x1xxx0", InstName.Vshrn, InstEmit32.Vshrn, OpCode32SimdShImmNarrow.Create, OpCode32SimdShImmNarrow.CreateT32);
|
||||||
SetA32("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create);
|
SetAsimd("1111001x1x>>>xxxxxxx0001>xx1xxxx", InstName.Vsra, InstEmit32.Vsra, OpCode32SimdShImm.Create, OpCode32SimdShImm.CreateT32);
|
||||||
SetA32("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, OpCode32SimdCmpZ.Create);
|
SetAsimd("111101001x00xxxxxxxx0000xxx0xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
SetA32("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create);
|
SetAsimd("111101001x00xxxxxxxx0100xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
|
SetAsimd("111101001x00xxxxxxxx1000x000xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
|
SetAsimd("111101001x00xxxxxxxx1000x011xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
|
SetAsimd("111101000x00xxxxxxxx0111xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1.
|
||||||
|
SetAsimd("111101000x00xxxxxxxx1010xx<<xxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2.
|
||||||
|
SetAsimd("111101000x00xxxxxxxx0110xx0xxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 3.
|
||||||
|
SetAsimd("111101000x00xxxxxxxx0010xxxxxxxx", InstName.Vst1, InstEmit32.Vst1, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 4.
|
||||||
|
SetAsimd("111101001x00xxxxxxxx0x01xxxxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
|
SetAsimd("111101001x00xxxxxxxx1001xx0xxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
|
SetAsimd("111101000x00xxxxxxxx100x<<0xxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
|
||||||
|
SetAsimd("111101000x00xxxxxxxx100x<<10xxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 1, inc = 1/2 (itype).
|
||||||
|
SetAsimd("111101000x00xxxxxxxx0011<<xxxxxx", InstName.Vst2, InstEmit32.Vst2, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Regs = 2, inc = 2.
|
||||||
|
SetAsimd("111101001x00xxxxxxxx0x10xxx0xxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
|
SetAsimd("111101001x00xxxxxxxx1010xx00xxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
|
SetAsimd("111101000x00xxxxxxxx010x<<0xxxxx", InstName.Vst3, InstEmit32.Vst3, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
|
||||||
|
SetAsimd("111101001x00xxxxxxxx0x11xxxxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
|
SetAsimd("111101001x00xxxxxxxx1011xx<<xxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemSingle.Create, OpCode32SimdMemSingle.CreateT32);
|
||||||
|
SetAsimd("111101000x00xxxxxxxx000x<<xxxxxx", InstName.Vst4, InstEmit32.Vst4, OpCode32SimdMemPair.Create, OpCode32SimdMemPair.CreateT32); // Inc = 1/2 (itype).
|
||||||
|
SetAsimd("111100110xxxxxxxxxxx1000xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
|
SetAsimd("111100100x10xxxxxxxx1101xxx0xxxx", InstName.Vsub, InstEmit32.Vsub_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
|
SetAsimd("1111001x1x<<xxxxxxx00010x0x0xxxx", InstName.Vsubl, InstEmit32.Vsubl_I, OpCode32SimdRegLong.Create, OpCode32SimdRegLong.CreateT32);
|
||||||
|
SetAsimd("1111001x1x<<xxxxxxx00011x0x0xxxx", InstName.Vsubw, InstEmit32.Vsubw_I, OpCode32SimdRegWide.Create, OpCode32SimdRegWide.CreateT32);
|
||||||
|
SetAsimd("111100111x11xxxxxxxx10xxxxx0xxxx", InstName.Vtbl, InstEmit32.Vtbl, OpCode32SimdTbl.Create, OpCode32SimdTbl.CreateT32);
|
||||||
|
SetAsimd("111100111x11<<10xxxx00001xx0xxxx", InstName.Vtrn, InstEmit32.Vtrn, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
|
SetAsimd("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||||
|
SetAsimd("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
|
SetAsimd("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "OpCode Table (AArch32, T16)"
|
#region "OpCode Table (AArch32, T16)"
|
||||||
@@ -1054,7 +1107,14 @@ namespace ARMeilleure.Decoders
|
|||||||
SetT16("1011101011xxxxxx", InstName.Revsh, InstEmit32.Revsh, OpCodeT16AluRegLow.Create);
|
SetT16("1011101011xxxxxx", InstName.Revsh, InstEmit32.Revsh, OpCodeT16AluRegLow.Create);
|
||||||
SetT16("101110x1xxxxxxxx", InstName.Cbnz, InstEmit32.Cbnz, OpCodeT16BImmCmp.Create);
|
SetT16("101110x1xxxxxxxx", InstName.Cbnz, InstEmit32.Cbnz, OpCodeT16BImmCmp.Create);
|
||||||
SetT16("1011110xxxxxxxxx", InstName.Pop, InstEmit32.Ldm, OpCodeT16MemStack.Create);
|
SetT16("1011110xxxxxxxxx", InstName.Pop, InstEmit32.Ldm, OpCodeT16MemStack.Create);
|
||||||
SetT16("10111111xxxx0000", InstName.Nop, InstEmit32.Nop, OpCodeT16.Create);
|
SetT16("1011111100000000", InstName.Nop, InstEmit32.Nop, OpCodeT16.Create);
|
||||||
|
SetT16("1011111100010000", InstName.Yield, InstEmit32.Nop, OpCodeT16.Create);
|
||||||
|
SetT16("1011111100100000", InstName.Wfe, InstEmit32.Nop, OpCodeT16.Create);
|
||||||
|
SetT16("1011111100110000", InstName.Wfi, InstEmit32.Nop, OpCodeT16.Create);
|
||||||
|
SetT16("1011111101000000", InstName.Sev, InstEmit32.Nop, OpCodeT16.Create);
|
||||||
|
SetT16("1011111101010000", InstName.Sevl, InstEmit32.Nop, OpCodeT16.Create);
|
||||||
|
SetT16("10111111011x0000", InstName.Hint, InstEmit32.Nop, OpCodeT16.Create); // Hint instruction
|
||||||
|
SetT16("101111111xxx0000", InstName.Hint, InstEmit32.Nop, OpCodeT16.Create); // Hint instruction
|
||||||
SetT16("10111111xxxx>>>>", InstName.It, InstEmit32.It, OpCodeT16IfThen.Create);
|
SetT16("10111111xxxx>>>>", InstName.It, InstEmit32.It, OpCodeT16IfThen.Create);
|
||||||
SetT16("11000xxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT16MemMult.Create);
|
SetT16("11000xxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT16MemMult.Create);
|
||||||
SetT16("11001xxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT16MemMult.Create);
|
SetT16("11001xxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT16MemMult.Create);
|
||||||
@@ -1074,6 +1134,8 @@ namespace ARMeilleure.Decoders
|
|||||||
SetT32("11110x00000<xxxx0xxx<<<<xxxxxxxx", InstName.And, InstEmit32.And, OpCodeT32AluImm.Create);
|
SetT32("11110x00000<xxxx0xxx<<<<xxxxxxxx", InstName.And, InstEmit32.And, OpCodeT32AluImm.Create);
|
||||||
SetT32("11110x<<<xxxxxxx10x0xxxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT32BImm20.Create);
|
SetT32("11110x<<<xxxxxxx10x0xxxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT32BImm20.Create);
|
||||||
SetT32("11110xxxxxxxxxxx10x1xxxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT32BImm24.Create);
|
SetT32("11110xxxxxxxxxxx10x1xxxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT32BImm24.Create);
|
||||||
|
SetT32("11110011011011110xxxxxxxxx0xxxxx", InstName.Bfc, InstEmit32.Bfc, OpCodeT32AluBf.Create);
|
||||||
|
SetT32("111100110110<<<<0xxxxxxxxx0xxxxx", InstName.Bfi, InstEmit32.Bfi, OpCodeT32AluBf.Create);
|
||||||
SetT32("11101010001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT32AluRsImm.Create);
|
SetT32("11101010001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT32AluRsImm.Create);
|
||||||
SetT32("11110x00001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT32AluImm.Create);
|
SetT32("11110x00001xxxxx0xxxxxxxxxxxxxxx", InstName.Bic, InstEmit32.Bic, OpCodeT32AluImm.Create);
|
||||||
SetT32("11110xxxxxxxxxxx11x1xxxxxxxxxxxx", InstName.Bl, InstEmit32.Bl, OpCodeT32BImm24.Create);
|
SetT32("11110xxxxxxxxxxx11x1xxxxxxxxxxxx", InstName.Bl, InstEmit32.Bl, OpCodeT32BImm24.Create);
|
||||||
@@ -1083,39 +1145,64 @@ namespace ARMeilleure.Decoders
|
|||||||
SetT32("11110x010001xxxx0xxx1111xxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCodeT32AluImm.Create);
|
SetT32("11110x010001xxxx0xxx1111xxxxxxxx", InstName.Cmn, InstEmit32.Cmn, OpCodeT32AluImm.Create);
|
||||||
SetT32("111010111011xxxx0xxx1111xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT32AluRsImm.Create);
|
SetT32("111010111011xxxx0xxx1111xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT32AluRsImm.Create);
|
||||||
SetT32("11110x011011xxxx0xxx1111xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT32AluImm.Create);
|
SetT32("11110x011011xxxx0xxx1111xxxxxxxx", InstName.Cmp, InstEmit32.Cmp, OpCodeT32AluImm.Create);
|
||||||
|
SetT32("11110011101011111000000000010100", InstName.Csdb, InstEmit32.Csdb, OpCodeT32.Create);
|
||||||
SetT32("11101010100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluRsImm.Create);
|
SetT32("11101010100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluRsImm.Create);
|
||||||
SetT32("11110x00100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluImm.Create);
|
SetT32("11110x00100<xxxx0xxx<<<<xxxxxxxx", InstName.Eor, InstEmit32.Eor, OpCodeT32AluImm.Create);
|
||||||
|
SetT32("11110011101011111000000000010000", InstName.Esb, InstEmit32.Nop, OpCodeT32.Create); // Error Synchronization Barrier (FEAT_RAS)
|
||||||
|
SetT32("1111001110101111100000000000011x", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
|
||||||
|
SetT32("11110011101011111000000000001xxx", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
|
||||||
|
SetT32("11110011101011111000000000010001", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
|
||||||
|
SetT32("11110011101011111000000000010011", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
|
||||||
|
SetT32("11110011101011111000000000010101", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
|
||||||
|
SetT32("1111001110101111100000000001011x", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
|
||||||
|
SetT32("11110011101011111000000000011xxx", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
|
||||||
|
SetT32("111100111010111110000000001xxxxx", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
|
||||||
|
SetT32("11110011101011111000000001xxxxxx", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
|
||||||
|
SetT32("1111001110101111100000001xxxxxxx", InstName.Hint, InstEmit32.Nop, OpCodeT32.Create); // Reserved Hint
|
||||||
SetT32("111010001101xxxxxxxx111110101111", InstName.Lda, InstEmit32.Lda, OpCodeT32MemLdEx.Create);
|
SetT32("111010001101xxxxxxxx111110101111", InstName.Lda, InstEmit32.Lda, OpCodeT32MemLdEx.Create);
|
||||||
|
SetT32("111010001101xxxxxxxx111110001111", InstName.Ldab, InstEmit32.Ldab, OpCodeT32MemLdEx.Create);
|
||||||
SetT32("111010001101xxxxxxxx111111101111", InstName.Ldaex, InstEmit32.Ldaex, OpCodeT32MemLdEx.Create);
|
SetT32("111010001101xxxxxxxx111111101111", InstName.Ldaex, InstEmit32.Ldaex, OpCodeT32MemLdEx.Create);
|
||||||
|
SetT32("111010001101xxxxxxxx111111001111", InstName.Ldaexb, InstEmit32.Ldaexb, OpCodeT32MemLdEx.Create);
|
||||||
|
SetT32("111010001101xxxxxxxxxxxx11111111", InstName.Ldaexd, InstEmit32.Ldaexd, OpCodeT32MemLdEx.Create);
|
||||||
|
SetT32("111010001101xxxxxxxx111111011111", InstName.Ldaexh, InstEmit32.Ldaexh, OpCodeT32MemLdEx.Create);
|
||||||
|
SetT32("111010001101xxxxxxxx111110011111", InstName.Ldah, InstEmit32.Ldah, OpCodeT32MemLdEx.Create);
|
||||||
SetT32("1110100010x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT32MemMult.Create);
|
SetT32("1110100010x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT32MemMult.Create);
|
||||||
SetT32("1110100100x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT32MemMult.Create);
|
SetT32("1110100100x1xxxxxxxxxxxxxxxxxxxx", InstName.Ldm, InstEmit32.Ldm, OpCodeT32MemMult.Create);
|
||||||
SetT32("111110000101xxxx<<<<10x1xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
|
SetT32("111110000101xxxxxxxx10x1xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110000101xxxx<<<<1100xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
|
SetT32("111110000101xxxxxxxx1100xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110000101xxxx<<<<11x1xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
|
SetT32("111110000101xxxxxxxx11x1xxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110001101xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm12.Create);
|
SetT32("111110001101xxxxxxxxxxxxxxxxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemImm12.Create);
|
||||||
SetT32("111110000101<<<<xxxx000000xxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemRsImm.Create);
|
SetT32("111110000101<<<<xxxx000000xxxxxx", InstName.Ldr, InstEmit32.Ldr, OpCodeT32MemRsImm.Create);
|
||||||
SetT32("111110000001xxxx<<<<10x1xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
|
SetT32("111110000001xxxxxxxx10x1xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110000001xxxx<<<<1100xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
|
SetT32("111110000001xxxx<<<<1100xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110000001xxxx<<<<11x1xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
|
SetT32("111110000001xxxxxxxx11x1xxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110001001xxxxxxxxxxxxxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm12.Create);
|
SetT32("111110001001xxxx<<<<xxxxxxxxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemImm12.Create);
|
||||||
|
SetT32("111110000001xxxx<<<<000000xxxxxx", InstName.Ldrb, InstEmit32.Ldrb, OpCodeT32MemRsImm.Create);
|
||||||
SetT32("11101000x111<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd, InstEmit32.Ldrd, OpCodeT32MemImm8D.Create);
|
SetT32("11101000x111<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd, InstEmit32.Ldrd, OpCodeT32MemImm8D.Create);
|
||||||
SetT32("11101001x1x1<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd, InstEmit32.Ldrd, OpCodeT32MemImm8D.Create);
|
SetT32("11101001x1x1<<<<xxxxxxxxxxxxxxxx", InstName.Ldrd, InstEmit32.Ldrd, OpCodeT32MemImm8D.Create);
|
||||||
SetT32("111110000011xxxx<<<<10x1xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
|
SetT32("111110000011xxxxxxxx10x1xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110000011xxxx<<<<1100xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
|
SetT32("111110000011xxxx<<<<1100xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110000011xxxx<<<<11x1xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
|
SetT32("111110000011xxxxxxxx11x1xxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110001011xxxxxxxxxxxxxxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm12.Create);
|
SetT32("111110001011xxxx<<<<xxxxxxxxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemImm12.Create);
|
||||||
SetT32("111110010001xxxx<<<<10x1xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create);
|
SetT32("111110000011xxxx<<<<000000xxxxxx", InstName.Ldrh, InstEmit32.Ldrh, OpCodeT32MemRsImm.Create);
|
||||||
|
SetT32("111110010001xxxxxxxx10x1xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110010001xxxx<<<<1100xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create);
|
SetT32("111110010001xxxx<<<<1100xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110010001xxxx<<<<11x1xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create);
|
SetT32("111110010001xxxxxxxx11x1xxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110011001xxxxxxxxxxxxxxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm12.Create);
|
SetT32("111110011001xxxx<<<<xxxxxxxxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemImm12.Create);
|
||||||
SetT32("111110010011xxxx<<<<10x1xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create);
|
SetT32("111110010001xxxx<<<<000000xxxxxx", InstName.Ldrsb, InstEmit32.Ldrsb, OpCodeT32MemRsImm.Create);
|
||||||
|
SetT32("111110010011xxxxxxxx10x1xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110010011xxxx<<<<1100xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create);
|
SetT32("111110010011xxxx<<<<1100xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110010011xxxx<<<<11x1xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create);
|
SetT32("111110010011xxxxxxxx11x1xxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110011011xxxxxxxxxxxxxxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm12.Create);
|
SetT32("111110011011xxxx<<<<xxxxxxxxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemImm12.Create);
|
||||||
|
SetT32("111110010011xxxx<<<<000000xxxxxx", InstName.Ldrsh, InstEmit32.Ldrsh, OpCodeT32MemRsImm.Create);
|
||||||
|
SetT32("111110110000xxxx<<<<xxxx0000xxxx", InstName.Mla, InstEmit32.Mla, OpCodeT32AluMla.Create);
|
||||||
|
SetT32("111110110000xxxxxxxxxxxx0001xxxx", InstName.Mls, InstEmit32.Mls, OpCodeT32AluMla.Create);
|
||||||
SetT32("11101010010x11110xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32AluRsImm.Create);
|
SetT32("11101010010x11110xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32AluRsImm.Create);
|
||||||
SetT32("111110100xxxxxxx1111xxxx0000xxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32ShiftReg.Create);
|
SetT32("111110100xxxxxxx1111xxxx0000xxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32ShiftReg.Create);
|
||||||
SetT32("11110x00010x11110xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32AluImm.Create);
|
SetT32("11110x00010x11110xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32AluImm.Create);
|
||||||
SetT32("11110x100100xxxx0xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32MovImm16.Create);
|
SetT32("11110x100100xxxx0xxxxxxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT32MovImm16.Create);
|
||||||
|
SetT32("11110x101100xxxx0xxxxxxxxxxxxxxx", InstName.Movt, InstEmit32.Movt, OpCodeT32MovImm16.Create);
|
||||||
|
SetT32("111110110000xxxx1111xxxx0000xxxx", InstName.Mul, InstEmit32.Mul, OpCodeT32AluMla.Create);
|
||||||
SetT32("11101010011x11110xxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT32AluRsImm.Create);
|
SetT32("11101010011x11110xxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT32AluRsImm.Create);
|
||||||
SetT32("11110x00011x11110xxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT32AluImm.Create);
|
SetT32("11110x00011x11110xxxxxxxxxxxxxxx", InstName.Mvn, InstEmit32.Mvn, OpCodeT32AluImm.Create);
|
||||||
SetT32("11110011101011111000000000000000", InstName.Nop, InstEmit32.Nop, OpCodeT32.Create);
|
SetT32("11110011101011111000000000000000", InstName.Nop, InstEmit32.Nop, OpCodeT32.Create);
|
||||||
@@ -1123,30 +1210,85 @@ namespace ARMeilleure.Decoders
|
|||||||
SetT32("11110x00011x<<<<0xxxxxxxxxxxxxxx", InstName.Orn, InstEmit32.Orn, OpCodeT32AluImm.Create);
|
SetT32("11110x00011x<<<<0xxxxxxxxxxxxxxx", InstName.Orn, InstEmit32.Orn, OpCodeT32AluImm.Create);
|
||||||
SetT32("11101010010x<<<<0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT32AluRsImm.Create);
|
SetT32("11101010010x<<<<0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT32AluRsImm.Create);
|
||||||
SetT32("11110x00010x<<<<0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT32AluImm.Create);
|
SetT32("11110x00010x<<<<0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit32.Orr, OpCodeT32AluImm.Create);
|
||||||
|
SetT32("1111100010x1xxxx1111xxxxxxxxxxxx", InstName.Pld, InstEmit32.Nop, OpCodeT32.Create);
|
||||||
|
SetT32("1111100000x1xxxx11111100xxxxxxxx", InstName.Pld, InstEmit32.Nop, OpCodeT32.Create);
|
||||||
|
SetT32("1111100000x1xxxx1111000000xxxxxx", InstName.Pld, InstEmit32.Nop, OpCodeT32.Create);
|
||||||
SetT32("11101011110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT32AluRsImm.Create);
|
SetT32("11101011110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT32AluRsImm.Create);
|
||||||
SetT32("11110x01110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT32AluImm.Create);
|
SetT32("11110x01110xxxxx0xxxxxxxxxxxxxxx", InstName.Rsb, InstEmit32.Rsb, OpCodeT32AluImm.Create);
|
||||||
|
SetT32("111110101000xxxx1111xxxx0000xxxx", InstName.Sadd8, InstEmit32.Sadd8, OpCodeT32AluReg.Create);
|
||||||
SetT32("11101011011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluRsImm.Create);
|
SetT32("11101011011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluRsImm.Create);
|
||||||
SetT32("11110x01011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluImm.Create);
|
SetT32("11110x01011xxxxx0xxxxxxxxxxxxxxx", InstName.Sbc, InstEmit32.Sbc, OpCodeT32AluImm.Create);
|
||||||
|
SetT32("111100110100xxxx0xxxxxxxxx0xxxxx", InstName.Sbfx, InstEmit32.Sbfx, OpCodeT32AluBf.Create);
|
||||||
|
SetT32("111110111001xxxx1111xxxx1111xxxx", InstName.Sdiv, InstEmit32.Sdiv, OpCodeT32AluMla.Create);
|
||||||
|
SetT32("111110101010xxxx1111xxxx1000xxxx", InstName.Sel, InstEmit32.Sel, OpCodeT32AluReg.Create);
|
||||||
|
SetT32("111110101000xxxx1111xxxx0010xxxx", InstName.Shadd8, InstEmit32.Shadd8, OpCodeT32AluReg.Create);
|
||||||
|
SetT32("111110101100xxxx1111xxxx0010xxxx", InstName.Shsub8, InstEmit32.Shsub8, OpCodeT32AluReg.Create);
|
||||||
|
SetT32("11110011101011111000000000000100", InstName.Sev, InstEmit32.Nop, OpCodeT32.Create);
|
||||||
|
SetT32("11110011101011111000000000000101", InstName.Sevl, InstEmit32.Nop, OpCodeT32.Create);
|
||||||
|
SetT32("111110110001xxxx<<<<xxxx00xxxxxx", InstName.Smla__, InstEmit32.Smla__, OpCodeT32AluMla.Create);
|
||||||
|
SetT32("111110111100xxxxxxxxxxxx0000xxxx", InstName.Smlal, InstEmit32.Smlal, OpCodeT32AluUmull.Create);
|
||||||
|
SetT32("111110111100xxxxxxxxxxxx10xxxxxx", InstName.Smlal__, InstEmit32.Smlal__, OpCodeT32AluUmull.Create);
|
||||||
|
SetT32("111110110011xxxx<<<<xxxx000xxxxx", InstName.Smlaw_, InstEmit32.Smlaw_, OpCodeT32AluMla.Create);
|
||||||
|
SetT32("111110110101xxxx<<<<xxxx000xxxxx", InstName.Smmla, InstEmit32.Smmla, OpCodeT32AluMla.Create);
|
||||||
|
SetT32("111110110110xxxxxxxxxxxx000xxxxx", InstName.Smmls, InstEmit32.Smmls, OpCodeT32AluMla.Create);
|
||||||
|
SetT32("111110110001xxxx1111xxxx00xxxxxx", InstName.Smul__, InstEmit32.Smul__, OpCodeT32AluMla.Create);
|
||||||
|
SetT32("111110111000xxxxxxxxxxxx0000xxxx", InstName.Smull, InstEmit32.Smull, OpCodeT32AluUmull.Create);
|
||||||
|
SetT32("111110110011xxxx1111xxxx000xxxxx", InstName.Smulw_, InstEmit32.Smulw_, OpCodeT32AluMla.Create);
|
||||||
|
SetT32("111110101100xxxx1111xxxx0000xxxx", InstName.Ssub8, InstEmit32.Ssub8, OpCodeT32AluReg.Create);
|
||||||
|
SetT32("111010001100xxxxxxxx111110101111", InstName.Stl, InstEmit32.Stl, OpCodeT32MemStEx.Create);
|
||||||
|
SetT32("111010001100xxxxxxxx111110001111", InstName.Stlb, InstEmit32.Stlb, OpCodeT32MemStEx.Create);
|
||||||
SetT32("111010001100xxxxxxxx11111110xxxx", InstName.Stlex, InstEmit32.Stlex, OpCodeT32MemStEx.Create);
|
SetT32("111010001100xxxxxxxx11111110xxxx", InstName.Stlex, InstEmit32.Stlex, OpCodeT32MemStEx.Create);
|
||||||
|
SetT32("111010001100xxxxxxxx11111100xxxx", InstName.Stlexb, InstEmit32.Stlexb, OpCodeT32MemStEx.Create);
|
||||||
|
SetT32("111010001100xxxxxxxxxxxx1111xxxx", InstName.Stlexd, InstEmit32.Stlexd, OpCodeT32MemStEx.Create);
|
||||||
|
SetT32("111010001100xxxxxxxx11111101xxxx", InstName.Stlexh, InstEmit32.Stlexh, OpCodeT32MemStEx.Create);
|
||||||
|
SetT32("111010001100xxxxxxxx111110011111", InstName.Stlh, InstEmit32.Stlh, OpCodeT32MemStEx.Create);
|
||||||
SetT32("1110100010x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT32MemMult.Create);
|
SetT32("1110100010x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT32MemMult.Create);
|
||||||
SetT32("1110100100x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT32MemMult.Create);
|
SetT32("1110100100x0xxxx0xxxxxxxxxxxxxxx", InstName.Stm, InstEmit32.Stm, OpCodeT32MemMult.Create);
|
||||||
SetT32("111110000100xxxxxxxx1<<>xxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm8.Create);
|
SetT32("111110000100<<<<xxxx10x1xxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110001100xxxxxxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm12.Create);
|
SetT32("111110000100<<<<xxxx1100xxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm8.Create);
|
||||||
|
SetT32("111110000100<<<<xxxx11x1xxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm8.Create);
|
||||||
|
SetT32("111110001100<<<<xxxxxxxxxxxxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemImm12.Create);
|
||||||
SetT32("111110000100<<<<xxxx000000xxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemRsImm.Create);
|
SetT32("111110000100<<<<xxxx000000xxxxxx", InstName.Str, InstEmit32.Str, OpCodeT32MemRsImm.Create);
|
||||||
SetT32("111110000000xxxxxxxx1<<>xxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm8.Create);
|
SetT32("111110000000<<<<xxxx10x1xxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110001000xxxxxxxxxxxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm12.Create);
|
SetT32("111110000000<<<<xxxx1100xxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm8.Create);
|
||||||
|
SetT32("111110000000<<<<xxxx11x1xxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm8.Create);
|
||||||
|
SetT32("111110001000<<<<xxxxxxxxxxxxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemImm12.Create);
|
||||||
|
SetT32("111110000000<<<<xxxx000000xxxxxx", InstName.Strb, InstEmit32.Strb, OpCodeT32MemRsImm.Create);
|
||||||
SetT32("11101000x110<<<<xxxxxxxxxxxxxxxx", InstName.Strd, InstEmit32.Strd, OpCodeT32MemImm8D.Create);
|
SetT32("11101000x110<<<<xxxxxxxxxxxxxxxx", InstName.Strd, InstEmit32.Strd, OpCodeT32MemImm8D.Create);
|
||||||
SetT32("11101001x1x0<<<<xxxxxxxxxxxxxxxx", InstName.Strd, InstEmit32.Strd, OpCodeT32MemImm8D.Create);
|
SetT32("11101001x1x0<<<<xxxxxxxxxxxxxxxx", InstName.Strd, InstEmit32.Strd, OpCodeT32MemImm8D.Create);
|
||||||
SetT32("111110000010xxxxxxxx1<<>xxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm8.Create);
|
SetT32("111110000010<<<<xxxx10x1xxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm8.Create);
|
||||||
SetT32("111110001010xxxxxxxxxxxxxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm12.Create);
|
SetT32("111110000010<<<<xxxx1100xxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm8.Create);
|
||||||
|
SetT32("111110000010<<<<xxxx11x1xxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm8.Create);
|
||||||
|
SetT32("111110001010<<<<xxxxxxxxxxxxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemImm12.Create);
|
||||||
|
SetT32("111110000010<<<<xxxx000000xxxxxx", InstName.Strh, InstEmit32.Strh, OpCodeT32MemRsImm.Create);
|
||||||
SetT32("11101011101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluRsImm.Create);
|
SetT32("11101011101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluRsImm.Create);
|
||||||
SetT32("11110x01101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluImm.Create);
|
SetT32("11110x01101<xxxx0xxx<<<<xxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluImm.Create);
|
||||||
|
SetT32("11110x101010xxxx0xxxxxxxxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT32AluImm12.Create);
|
||||||
|
SetT32("111110100100xxxx1111xxxx10xxxxxx", InstName.Sxtb, InstEmit32.Sxtb, OpCodeT32AluUx.Create);
|
||||||
|
SetT32("111110100010xxxx1111xxxx10xxxxxx", InstName.Sxtb16, InstEmit32.Sxtb16, OpCodeT32AluUx.Create);
|
||||||
|
SetT32("111110100000xxxx1111xxxx10xxxxxx", InstName.Sxth, InstEmit32.Sxth, OpCodeT32AluUx.Create);
|
||||||
SetT32("111010001101xxxx111100000000xxxx", InstName.Tbb, InstEmit32.Tbb, OpCodeT32Tb.Create);
|
SetT32("111010001101xxxx111100000000xxxx", InstName.Tbb, InstEmit32.Tbb, OpCodeT32Tb.Create);
|
||||||
SetT32("111010001101xxxx111100000001xxxx", InstName.Tbh, InstEmit32.Tbh, OpCodeT32Tb.Create);
|
SetT32("111010001101xxxx111100000001xxxx", InstName.Tbh, InstEmit32.Tbh, OpCodeT32Tb.Create);
|
||||||
SetT32("111010101001xxxx0xxx1111xxxxxxxx", InstName.Teq, InstEmit32.Teq, OpCodeT32AluRsImm.Create);
|
SetT32("111010101001xxxx0xxx1111xxxxxxxx", InstName.Teq, InstEmit32.Teq, OpCodeT32AluRsImm.Create);
|
||||||
SetT32("11110x001001xxxx0xxx1111xxxxxxxx", InstName.Teq, InstEmit32.Teq, OpCodeT32AluImm.Create);
|
SetT32("11110x001001xxxx0xxx1111xxxxxxxx", InstName.Teq, InstEmit32.Teq, OpCodeT32AluImm.Create);
|
||||||
|
SetT32("11110011101011111000000000010010", InstName.Tsb, InstEmit32.Nop, OpCodeT32.Create); // Trace Synchronization Barrier (FEAT_TRF)
|
||||||
SetT32("111010100001xxxx0xxx1111xxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT32AluRsImm.Create);
|
SetT32("111010100001xxxx0xxx1111xxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT32AluRsImm.Create);
|
||||||
SetT32("11110x000001xxxx0xxx1111xxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT32AluImm.Create);
|
SetT32("11110x000001xxxx0xxx1111xxxxxxxx", InstName.Tst, InstEmit32.Tst, OpCodeT32AluImm.Create);
|
||||||
|
SetT32("111110101000xxxx1111xxxx0100xxxx", InstName.Uadd8, InstEmit32.Uadd8, OpCodeT32AluReg.Create);
|
||||||
|
SetT32("111100111100xxxx0xxxxxxxxx0xxxxx", InstName.Ubfx, InstEmit32.Ubfx, OpCodeT32AluBf.Create);
|
||||||
|
SetT32("111110111011xxxx1111xxxx1111xxxx", InstName.Udiv, InstEmit32.Udiv, OpCodeT32AluMla.Create);
|
||||||
|
SetT32("111110101000xxxx1111xxxx0110xxxx", InstName.Uhadd8, InstEmit32.Uhadd8, OpCodeT32AluReg.Create);
|
||||||
|
SetT32("111110101100xxxx1111xxxx0110xxxx", InstName.Uhsub8, InstEmit32.Uhsub8, OpCodeT32AluReg.Create);
|
||||||
|
SetT32("111110111110xxxxxxxxxxxx0110xxxx", InstName.Umaal, InstEmit32.Umaal, OpCodeT32AluUmull.Create);
|
||||||
|
SetT32("111110111110xxxxxxxxxxxx0000xxxx", InstName.Umlal, InstEmit32.Umlal, OpCodeT32AluUmull.Create);
|
||||||
|
SetT32("111110111010xxxxxxxxxxxx0000xxxx", InstName.Umull, InstEmit32.Umull, OpCodeT32AluUmull.Create);
|
||||||
|
SetT32("111110101100xxxx1111xxxx0100xxxx", InstName.Usub8, InstEmit32.Usub8, OpCodeT32AluReg.Create);
|
||||||
|
SetT32("111110100101xxxx1111xxxx10xxxxxx", InstName.Uxtb, InstEmit32.Uxtb, OpCodeT32AluUx.Create);
|
||||||
|
SetT32("111110100011xxxx1111xxxx10xxxxxx", InstName.Uxtb16, InstEmit32.Uxtb16, OpCodeT32AluUx.Create);
|
||||||
|
SetT32("111110100001xxxx1111xxxx10xxxxxx", InstName.Uxth, InstEmit32.Uxth, OpCodeT32AluUx.Create);
|
||||||
|
SetT32("11110011101011111000000000000010", InstName.Wfe, InstEmit32.Nop, OpCodeT32.Create);
|
||||||
|
SetT32("11110011101011111000000000000011", InstName.Wfi, InstEmit32.Nop, OpCodeT32.Create);
|
||||||
|
SetT32("11110011101011111000000000000001", InstName.Yield, InstEmit32.Nop, OpCodeT32.Create);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA);
|
FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA);
|
||||||
@@ -1203,6 +1345,46 @@ namespace ARMeilleure.Decoders
|
|||||||
Set(reversedEncoding, AllInstT32, new InstDescriptor(name, emitter), reversedMakeOp);
|
Set(reversedEncoding, AllInstT32, new InstDescriptor(name, emitter), reversedMakeOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void SetVfp(string encoding, InstName name, InstEmitter emitter, MakeOp makeOpA32, MakeOp makeOpT32)
|
||||||
|
{
|
||||||
|
SetA32(encoding, name, emitter, makeOpA32);
|
||||||
|
|
||||||
|
string thumbEncoding = encoding;
|
||||||
|
if (thumbEncoding.StartsWith("<<<<"))
|
||||||
|
{
|
||||||
|
thumbEncoding = "1110" + thumbEncoding.Substring(4);
|
||||||
|
}
|
||||||
|
SetT32(thumbEncoding, name, emitter, makeOpT32);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetAsimd(string encoding, InstName name, InstEmitter emitter, MakeOp makeOpA32, MakeOp makeOpT32)
|
||||||
|
{
|
||||||
|
SetA32(encoding, name, emitter, makeOpA32);
|
||||||
|
|
||||||
|
string thumbEncoding = encoding;
|
||||||
|
if (thumbEncoding.StartsWith("11110100"))
|
||||||
|
{
|
||||||
|
thumbEncoding = "11111001" + encoding.Substring(8);
|
||||||
|
}
|
||||||
|
else if (thumbEncoding.StartsWith("1111001x"))
|
||||||
|
{
|
||||||
|
thumbEncoding = "111x1111" + encoding.Substring(8);
|
||||||
|
}
|
||||||
|
else if (thumbEncoding.StartsWith("11110010"))
|
||||||
|
{
|
||||||
|
thumbEncoding = "11101111" + encoding.Substring(8);
|
||||||
|
}
|
||||||
|
else if (thumbEncoding.StartsWith("11110011"))
|
||||||
|
{
|
||||||
|
thumbEncoding = "11111111" + encoding.Substring(8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Invalid ASIMD instruction encoding");
|
||||||
|
}
|
||||||
|
SetT32(thumbEncoding, name, emitter, makeOpT32);
|
||||||
|
}
|
||||||
|
|
||||||
private static void SetA64(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
|
private static void SetA64(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
|
||||||
{
|
{
|
||||||
Set(encoding, AllInstA64, new InstDescriptor(name, emitter), makeOp);
|
Set(encoding, AllInstA64, new InstDescriptor(name, emitter), makeOp);
|
||||||
|
@@ -74,7 +74,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Bfc(ArmEmitterContext context)
|
public static void Bfc(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp;
|
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
|
||||||
|
|
||||||
Operand d = GetIntA32(context, op.Rd);
|
Operand d = GetIntA32(context, op.Rd);
|
||||||
Operand res = context.BitwiseAnd(d, Const(~op.DestMask));
|
Operand res = context.BitwiseAnd(d, Const(~op.DestMask));
|
||||||
@@ -84,7 +84,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Bfi(ArmEmitterContext context)
|
public static void Bfi(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp;
|
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
|
||||||
|
|
||||||
Operand n = GetIntA32(context, op.Rn);
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
Operand d = GetIntA32(context, op.Rd);
|
Operand d = GetIntA32(context, op.Rd);
|
||||||
@@ -185,7 +185,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Movt(ArmEmitterContext context)
|
public static void Movt(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluImm16 op = (OpCode32AluImm16)context.CurrOp;
|
IOpCode32AluImm16 op = (IOpCode32AluImm16)context.CurrOp;
|
||||||
|
|
||||||
Operand d = GetIntA32(context, op.Rd);
|
Operand d = GetIntA32(context, op.Rd);
|
||||||
Operand imm = Const(op.Immediate << 16); // Immeditate value as top halfword.
|
Operand imm = Const(op.Immediate << 16); // Immeditate value as top halfword.
|
||||||
@@ -363,6 +363,11 @@ namespace ARMeilleure.Instructions
|
|||||||
EmitAluStore(context, res);
|
EmitAluStore(context, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Sadd8(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
EmitAddSub8(context, add: true, unsigned: false);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Sbc(ArmEmitterContext context)
|
public static void Sbc(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
|
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
|
||||||
@@ -389,7 +394,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Sbfx(ArmEmitterContext context)
|
public static void Sbfx(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp;
|
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
|
||||||
|
|
||||||
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
|
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
|
||||||
|
|
||||||
@@ -401,17 +406,38 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Sdiv(ArmEmitterContext context)
|
public static void Sdiv(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
EmitDiv(context, false);
|
EmitDiv(context, unsigned: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Sel(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
IOpCode32AluReg op = (IOpCode32AluReg)context.CurrOp;
|
||||||
|
|
||||||
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
|
Operand m = GetIntA32(context, op.Rm);
|
||||||
|
|
||||||
|
Operand ge0 = context.ZeroExtend8(OperandType.I32, context.Negate(GetFlag(PState.GE0Flag)));
|
||||||
|
Operand ge1 = context.ZeroExtend8(OperandType.I32, context.Negate(GetFlag(PState.GE1Flag)));
|
||||||
|
Operand ge2 = context.ZeroExtend8(OperandType.I32, context.Negate(GetFlag(PState.GE2Flag)));
|
||||||
|
Operand ge3 = context.Negate(GetFlag(PState.GE3Flag));
|
||||||
|
|
||||||
|
Operand mask = context.BitwiseOr(ge0, context.ShiftLeft(ge1, Const(8)));
|
||||||
|
mask = context.BitwiseOr(mask, context.ShiftLeft(ge2, Const(16)));
|
||||||
|
mask = context.BitwiseOr(mask, context.ShiftLeft(ge3, Const(24)));
|
||||||
|
|
||||||
|
Operand res = context.BitwiseOr(context.BitwiseAnd(n, mask), context.BitwiseAnd(m, context.BitwiseNot(mask)));
|
||||||
|
|
||||||
|
SetIntA32(context, op.Rd, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Shadd8(ArmEmitterContext context)
|
public static void Shadd8(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
EmitHadd8(context, false);
|
EmitHadd8(context, unsigned: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Shsub8(ArmEmitterContext context)
|
public static void Shsub8(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
EmitHsub8(context, false);
|
EmitHsub8(context, unsigned: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ssat(ArmEmitterContext context)
|
public static void Ssat(ArmEmitterContext context)
|
||||||
@@ -428,6 +454,11 @@ namespace ARMeilleure.Instructions
|
|||||||
EmitSat16(context, -(1 << op.SatImm), (1 << op.SatImm) - 1);
|
EmitSat16(context, -(1 << op.SatImm), (1 << op.SatImm) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Ssub8(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
EmitAddSub8(context, add: false, unsigned: false);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Sub(ArmEmitterContext context)
|
public static void Sub(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
|
IOpCode32Alu op = (IOpCode32Alu)context.CurrOp;
|
||||||
@@ -482,9 +513,14 @@ namespace ARMeilleure.Instructions
|
|||||||
EmitNZFlagsCheck(context, res);
|
EmitNZFlagsCheck(context, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Uadd8(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
EmitAddSub8(context, add: true, unsigned: true);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Ubfx(ArmEmitterContext context)
|
public static void Ubfx(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluBf op = (OpCode32AluBf)context.CurrOp;
|
IOpCode32AluBf op = (IOpCode32AluBf)context.CurrOp;
|
||||||
|
|
||||||
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
|
var msb = op.Lsb + op.Msb; // For this instruction, the msb is actually a width.
|
||||||
|
|
||||||
@@ -496,17 +532,17 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Udiv(ArmEmitterContext context)
|
public static void Udiv(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
EmitDiv(context, true);
|
EmitDiv(context, unsigned: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Uhadd8(ArmEmitterContext context)
|
public static void Uhadd8(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
EmitHadd8(context, true);
|
EmitHadd8(context, unsigned: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Uhsub8(ArmEmitterContext context)
|
public static void Uhsub8(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
EmitHsub8(context, true);
|
EmitHsub8(context, unsigned: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Usat(ArmEmitterContext context)
|
public static void Usat(ArmEmitterContext context)
|
||||||
@@ -523,6 +559,11 @@ namespace ARMeilleure.Instructions
|
|||||||
EmitSat16(context, 0, (1 << op.SatImm) - 1);
|
EmitSat16(context, 0, (1 << op.SatImm) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Usub8(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
EmitAddSub8(context, add: false, unsigned: true);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Uxtb(ArmEmitterContext context)
|
public static void Uxtb(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
EmitSignExtend(context, false, 8);
|
EmitSignExtend(context, false, 8);
|
||||||
@@ -678,9 +719,40 @@ namespace ARMeilleure.Instructions
|
|||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void EmitAddSub8(ArmEmitterContext context, bool add, bool unsigned)
|
||||||
|
{
|
||||||
|
IOpCode32AluReg op = (IOpCode32AluReg)context.CurrOp;
|
||||||
|
|
||||||
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
|
Operand m = GetIntA32(context, op.Rm);
|
||||||
|
|
||||||
|
Operand res = Const(0);
|
||||||
|
|
||||||
|
for (int byteSel = 0; byteSel < 4; byteSel++)
|
||||||
|
{
|
||||||
|
Operand shift = Const(byteSel * 8);
|
||||||
|
|
||||||
|
Operand nByte = context.ShiftRightUI(n, shift);
|
||||||
|
Operand mByte = context.ShiftRightUI(m, shift);
|
||||||
|
|
||||||
|
nByte = unsigned ? context.ZeroExtend8(OperandType.I32, nByte) : context.SignExtend8(OperandType.I32, nByte);
|
||||||
|
mByte = unsigned ? context.ZeroExtend8(OperandType.I32, mByte) : context.SignExtend8(OperandType.I32, mByte);
|
||||||
|
|
||||||
|
Operand resByte = add ? context.Add(nByte, mByte) : context.Subtract(nByte, mByte);
|
||||||
|
|
||||||
|
res = context.BitwiseOr(res, context.ShiftLeft(context.ZeroExtend8(OperandType.I32, resByte), shift));
|
||||||
|
|
||||||
|
SetFlag(context, PState.GE0Flag + byteSel, unsigned && add
|
||||||
|
? context.ShiftRightUI(resByte, Const(8))
|
||||||
|
: context.ShiftRightUI(context.BitwiseNot(resByte), Const(31)));
|
||||||
|
}
|
||||||
|
|
||||||
|
SetIntA32(context, op.Rd, res);
|
||||||
|
}
|
||||||
|
|
||||||
private static void EmitHadd8(ArmEmitterContext context, bool unsigned)
|
private static void EmitHadd8(ArmEmitterContext context, bool unsigned)
|
||||||
{
|
{
|
||||||
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
|
IOpCode32AluReg op = (IOpCode32AluReg)context.CurrOp;
|
||||||
|
|
||||||
Operand m = GetIntA32(context, op.Rm);
|
Operand m = GetIntA32(context, op.Rm);
|
||||||
Operand n = GetIntA32(context, op.Rn);
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
@@ -710,7 +782,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static void EmitHsub8(ArmEmitterContext context, bool unsigned)
|
private static void EmitHsub8(ArmEmitterContext context, bool unsigned)
|
||||||
{
|
{
|
||||||
OpCode32AluReg op = (OpCode32AluReg)context.CurrOp;
|
IOpCode32AluReg op = (IOpCode32AluReg)context.CurrOp;
|
||||||
|
|
||||||
Operand m = GetIntA32(context, op.Rm);
|
Operand m = GetIntA32(context, op.Rm);
|
||||||
Operand n = GetIntA32(context, op.Rn);
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
|
@@ -128,7 +128,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Debug.Assert(value.Type == OperandType.I32);
|
Debug.Assert(value.Type == OperandType.I32);
|
||||||
|
|
||||||
if (((OpCode32)context.CurrOp).IsThumb())
|
if (((OpCode32)context.CurrOp).IsThumb)
|
||||||
{
|
{
|
||||||
bool isReturn = IsA32Return(context);
|
bool isReturn = IsA32Return(context);
|
||||||
if (!isReturn)
|
if (!isReturn)
|
||||||
@@ -205,7 +205,7 @@ namespace ARMeilleure.Instructions
|
|||||||
return Const(op.Immediate);
|
return Const(op.Immediate);
|
||||||
}
|
}
|
||||||
|
|
||||||
case OpCode32AluImm16 op: return Const(op.Immediate);
|
case IOpCode32AluImm16 op: return Const(op.Immediate);
|
||||||
|
|
||||||
case IOpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
|
case IOpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
|
||||||
case IOpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry);
|
case IOpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry);
|
||||||
|
@@ -34,7 +34,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
uint pc = op.GetPc();
|
uint pc = op.GetPc();
|
||||||
|
|
||||||
bool isThumb = ((OpCode32)context.CurrOp).IsThumb();
|
bool isThumb = ((OpCode32)context.CurrOp).IsThumb;
|
||||||
|
|
||||||
uint currentPc = isThumb
|
uint currentPc = isThumb
|
||||||
? pc | 1
|
? pc | 1
|
||||||
@@ -61,7 +61,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Operand addr = context.Copy(GetIntA32(context, op.Rm));
|
Operand addr = context.Copy(GetIntA32(context, op.Rm));
|
||||||
Operand bitOne = context.BitwiseAnd(addr, Const(1));
|
Operand bitOne = context.BitwiseAnd(addr, Const(1));
|
||||||
|
|
||||||
bool isThumb = ((OpCode32)context.CurrOp).IsThumb();
|
bool isThumb = ((OpCode32)context.CurrOp).IsThumb;
|
||||||
|
|
||||||
uint currentPc = isThumb
|
uint currentPc = isThumb
|
||||||
? (pc - 2) | 1
|
? (pc - 2) | 1
|
||||||
|
@@ -26,6 +26,11 @@ namespace ARMeilleure.Instructions
|
|||||||
EmitClearExclusive(context);
|
EmitClearExclusive(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Csdb(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
// Execute as no-op.
|
||||||
|
}
|
||||||
|
|
||||||
public static void Dmb(ArmEmitterContext context) => EmitBarrier(context);
|
public static void Dmb(ArmEmitterContext context) => EmitBarrier(context);
|
||||||
public static void Dsb(ArmEmitterContext context) => EmitBarrier(context);
|
public static void Dsb(ArmEmitterContext context) => EmitBarrier(context);
|
||||||
|
|
||||||
|
@@ -172,13 +172,13 @@ namespace ARMeilleure.Instructions
|
|||||||
context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
|
context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
|
||||||
|
|
||||||
SetIntA32(context, op.Rt, valueLow);
|
SetIntA32(context, op.Rt, valueLow);
|
||||||
SetIntA32(context, op.Rt | 1, valueHigh);
|
SetIntA32(context, op.Rt2, valueHigh);
|
||||||
|
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblBigEndian);
|
context.MarkLabel(lblBigEndian);
|
||||||
|
|
||||||
SetIntA32(context, op.Rt | 1, valueLow);
|
SetIntA32(context, op.Rt2, valueLow);
|
||||||
SetIntA32(context, op.Rt, valueHigh);
|
SetIntA32(context, op.Rt, valueHigh);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -195,7 +195,7 @@ namespace ARMeilleure.Instructions
|
|||||||
// Split the result into 2 words (based on endianness)
|
// Split the result into 2 words (based on endianness)
|
||||||
|
|
||||||
Operand lo = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt));
|
Operand lo = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt));
|
||||||
Operand hi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt | 1));
|
Operand hi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt2));
|
||||||
|
|
||||||
Operand lblBigEndian = Label();
|
Operand lblBigEndian = Label();
|
||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
|
@@ -25,7 +25,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Mla(ArmEmitterContext context)
|
public static void Mla(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
|
IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
|
||||||
|
|
||||||
Operand n = GetAluN(context);
|
Operand n = GetAluN(context);
|
||||||
Operand m = GetAluM(context);
|
Operand m = GetAluM(context);
|
||||||
@@ -43,7 +43,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Mls(ArmEmitterContext context)
|
public static void Mls(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
|
IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
|
||||||
|
|
||||||
Operand n = GetAluN(context);
|
Operand n = GetAluN(context);
|
||||||
Operand m = GetAluM(context);
|
Operand m = GetAluM(context);
|
||||||
@@ -71,7 +71,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static void EmitSmmul(ArmEmitterContext context, MullFlags flags)
|
private static void EmitSmmul(ArmEmitterContext context, MullFlags flags)
|
||||||
{
|
{
|
||||||
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
|
IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
|
||||||
|
|
||||||
Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn));
|
Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn));
|
||||||
Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm));
|
Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm));
|
||||||
@@ -99,7 +99,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Smla__(ArmEmitterContext context)
|
public static void Smla__(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
|
IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
|
||||||
|
|
||||||
Operand n = GetIntA32(context, op.Rn);
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
Operand m = GetIntA32(context, op.Rm);
|
Operand m = GetIntA32(context, op.Rm);
|
||||||
@@ -142,7 +142,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Smlal__(ArmEmitterContext context)
|
public static void Smlal__(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
|
IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
|
||||||
|
|
||||||
Operand n = GetIntA32(context, op.Rn);
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
Operand m = GetIntA32(context, op.Rm);
|
Operand m = GetIntA32(context, op.Rm);
|
||||||
@@ -180,7 +180,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Smlaw_(ArmEmitterContext context)
|
public static void Smlaw_(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
|
IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
|
||||||
|
|
||||||
Operand n = GetIntA32(context, op.Rn);
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
Operand m = GetIntA32(context, op.Rm);
|
Operand m = GetIntA32(context, op.Rm);
|
||||||
@@ -210,7 +210,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Smul__(ArmEmitterContext context)
|
public static void Smul__(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
|
IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
|
||||||
|
|
||||||
Operand n = GetIntA32(context, op.Rn);
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
Operand m = GetIntA32(context, op.Rm);
|
Operand m = GetIntA32(context, op.Rm);
|
||||||
@@ -240,7 +240,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Smull(ArmEmitterContext context)
|
public static void Smull(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
|
IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
|
||||||
|
|
||||||
Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn));
|
Operand n = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rn));
|
||||||
Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm));
|
Operand m = context.SignExtend32(OperandType.I64, GetIntA32(context, op.Rm));
|
||||||
@@ -261,7 +261,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Smulw_(ArmEmitterContext context)
|
public static void Smulw_(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluMla op = (OpCode32AluMla)context.CurrOp;
|
IOpCode32AluMla op = (IOpCode32AluMla)context.CurrOp;
|
||||||
|
|
||||||
Operand n = GetIntA32(context, op.Rn);
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
Operand m = GetIntA32(context, op.Rm);
|
Operand m = GetIntA32(context, op.Rm);
|
||||||
@@ -285,7 +285,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Umaal(ArmEmitterContext context)
|
public static void Umaal(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
|
IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
|
||||||
|
|
||||||
Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn));
|
Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn));
|
||||||
Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm));
|
Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm));
|
||||||
@@ -310,7 +310,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Umull(ArmEmitterContext context)
|
public static void Umull(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
|
IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
|
||||||
|
|
||||||
Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn));
|
Operand n = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rn));
|
||||||
Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm));
|
Operand m = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rm));
|
||||||
@@ -331,7 +331,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static void EmitMlal(ArmEmitterContext context, bool signed)
|
private static void EmitMlal(ArmEmitterContext context, bool signed)
|
||||||
{
|
{
|
||||||
OpCode32AluUmull op = (OpCode32AluUmull)context.CurrOp;
|
IOpCode32AluUmull op = (IOpCode32AluUmull)context.CurrOp;
|
||||||
|
|
||||||
Operand n = GetIntA32(context, op.Rn);
|
Operand n = GetIntA32(context, op.Rn);
|
||||||
Operand m = GetIntA32(context, op.Rm);
|
Operand m = GetIntA32(context, op.Rm);
|
||||||
|
@@ -726,7 +726,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||||
{
|
{
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)), op1, op2);
|
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum), op1, op2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -774,7 +774,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||||
{
|
{
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMax)), op1, op2);
|
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax), op1, op2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -900,7 +900,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||||
{
|
{
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)), op1, op2);
|
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum), op1, op2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -948,7 +948,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||||
{
|
{
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMin)), op1, op2);
|
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin), op1, op2);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1633,37 +1633,17 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Frinti_S(ArmEmitterContext context)
|
public static void Frinti_S(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
|
||||||
|
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
if (op.Size == 0)
|
return EmitRoundByRMode(context, op1);
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
|
||||||
}
|
|
||||||
else /* if (op.Size == 1) */
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Frinti_V(ArmEmitterContext context)
|
public static void Frinti_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
|
||||||
|
|
||||||
int sizeF = op.Size & 1;
|
|
||||||
|
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
if (sizeF == 0)
|
return EmitRoundByRMode(context, op1);
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
|
||||||
}
|
|
||||||
else /* if (sizeF == 1) */
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1759,37 +1739,17 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Frintx_S(ArmEmitterContext context)
|
public static void Frintx_S(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
|
||||||
|
|
||||||
EmitScalarUnaryOpF(context, (op1) =>
|
EmitScalarUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
if (op.Size == 0)
|
return EmitRoundByRMode(context, op1);
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
|
||||||
}
|
|
||||||
else /* if (op.Size == 1) */
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Frintx_V(ArmEmitterContext context)
|
public static void Frintx_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
|
||||||
|
|
||||||
int sizeF = op.Size & 1;
|
|
||||||
|
|
||||||
EmitVectorUnaryOpF(context, (op1) =>
|
EmitVectorUnaryOpF(context, (op1) =>
|
||||||
{
|
{
|
||||||
if (sizeF == 0)
|
return EmitRoundByRMode(context, op1);
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
|
||||||
}
|
|
||||||
else /* if (sizeF == 1) */
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||||
@@ -178,37 +177,20 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static void EmitCmpOpF32(ArmEmitterContext context, string name, bool zero)
|
private static void EmitCmpOpF32(ArmEmitterContext context, string name, bool zero)
|
||||||
{
|
{
|
||||||
Operand one = Const(1);
|
|
||||||
if (zero)
|
if (zero)
|
||||||
{
|
{
|
||||||
EmitVectorUnaryOpF32(context, (m) =>
|
EmitVectorUnaryOpF32(context, (m) =>
|
||||||
{
|
{
|
||||||
OperandType type = m.Type;
|
Operand zeroOp = m.Type == OperandType.FP64 ? ConstF(0.0d) : ConstF(0.0f);
|
||||||
|
|
||||||
if (type == OperandType.FP64)
|
return EmitSoftFloatCallDefaultFpscr(context, name, m, zeroOp);
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFloat64).GetMethod(name), m, ConstF(0.0d), one);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(name), m, ConstF(0.0f), one);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EmitVectorBinaryOpF32(context, (n, m) =>
|
EmitVectorBinaryOpF32(context, (n, m) =>
|
||||||
{
|
{
|
||||||
OperandType type = n.Type;
|
return EmitSoftFloatCallDefaultFpscr(context, name, n, m);
|
||||||
|
|
||||||
if (type == OperandType.FP64)
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFloat64).GetMethod(name), n, m, one);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return context.Call(typeof(SoftFloat32).GetMethod(name), n, m, one);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,11 +339,7 @@ namespace ARMeilleure.Instructions
|
|||||||
me = ExtractScalar(context, type, op.Vm);
|
me = ExtractScalar(context, type, op.Vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodInfo info = sizeF != 0
|
Operand nzcv = EmitSoftFloatCall(context, nameof(SoftFloat32.FPCompare), ne, me, Const(signalNaNs));
|
||||||
? typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare))
|
|
||||||
: typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare));
|
|
||||||
|
|
||||||
Operand nzcv = context.Call(info, ne, me, Const(signalNaNs));
|
|
||||||
|
|
||||||
EmitSetFpscrNzcv(context, nzcv);
|
EmitSetFpscrNzcv(context, nzcv);
|
||||||
}
|
}
|
||||||
|
@@ -76,7 +76,9 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0);
|
Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0);
|
||||||
|
|
||||||
|
context.StoreToContext();
|
||||||
Operand res = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
Operand res = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
res = context.ZeroExtend16(OperandType.I64, res);
|
res = context.ZeroExtend16(OperandType.I64, res);
|
||||||
|
|
||||||
@@ -98,7 +100,9 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
|
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
|
||||||
|
|
||||||
|
context.StoreToContext();
|
||||||
Operand res = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
Operand res = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||||
}
|
}
|
||||||
@@ -120,7 +124,9 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand ne = context.VectorExtract(OperandType.FP64, GetVec(op.Rn), 0);
|
Operand ne = context.VectorExtract(OperandType.FP64, GetVec(op.Rn), 0);
|
||||||
|
|
||||||
|
context.StoreToContext();
|
||||||
Operand res = context.Call(typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert)), ne);
|
Operand res = context.Call(typeof(SoftFloat64_16).GetMethod(nameof(SoftFloat64_16.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
res = context.ZeroExtend16(OperandType.I64, res);
|
res = context.ZeroExtend16(OperandType.I64, res);
|
||||||
|
|
||||||
@@ -143,7 +149,9 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
|
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
|
||||||
|
|
||||||
|
context.StoreToContext();
|
||||||
Operand res = context.Call(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)), ne);
|
Operand res = context.Call(typeof(SoftFloat16_64).GetMethod(nameof(SoftFloat16_64.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||||
}
|
}
|
||||||
@@ -224,7 +232,9 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand ne = EmitVectorExtractZx(context, op.Rn, part + index, 1);
|
Operand ne = EmitVectorExtractZx(context, op.Rn, part + index, 1);
|
||||||
|
|
||||||
|
context.StoreToContext();
|
||||||
Operand e = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
Operand e = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
res = context.VectorInsert(res, e, index);
|
res = context.VectorInsert(res, e, index);
|
||||||
}
|
}
|
||||||
@@ -333,7 +343,9 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
if (sizeF == 0)
|
if (sizeF == 0)
|
||||||
{
|
{
|
||||||
|
context.StoreToContext();
|
||||||
Operand e = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
Operand e = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
e = context.ZeroExtend16(OperandType.I64, e);
|
e = context.ZeroExtend16(OperandType.I64, e);
|
||||||
|
|
||||||
|
@@ -161,33 +161,14 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
Operand toConvert = ExtractScalar(context, floatSize, op.Vm);
|
Operand toConvert = ExtractScalar(context, floatSize, op.Vm);
|
||||||
|
|
||||||
Operand asInteger;
|
|
||||||
|
|
||||||
// TODO: Fast Path.
|
// TODO: Fast Path.
|
||||||
if (roundWithFpscr)
|
if (roundWithFpscr)
|
||||||
{
|
{
|
||||||
MethodInfo info;
|
toConvert = EmitRoundByRMode(context, toConvert);
|
||||||
|
|
||||||
if (floatSize == OperandType.FP64)
|
|
||||||
{
|
|
||||||
info = unsigned
|
|
||||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToUInt32))
|
|
||||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToInt32));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info = unsigned
|
|
||||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToUInt32))
|
|
||||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToInt32));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asInteger = context.Call(info, toConvert);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Round towards zero.
|
// Round towards zero.
|
||||||
asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
Operand asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
||||||
}
|
|
||||||
|
|
||||||
InsertScalar(context, op.Vd, asInteger);
|
InsertScalar(context, op.Vd, asInteger);
|
||||||
}
|
}
|
||||||
@@ -271,9 +252,7 @@ namespace ARMeilleure.Instructions
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand asInteger;
|
Operand asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
||||||
|
|
||||||
asInteger = EmitSaturateFloatToInt(context, toConvert, unsigned);
|
|
||||||
|
|
||||||
InsertScalar(context, op.Vd, asInteger);
|
InsertScalar(context, op.Vd, asInteger);
|
||||||
}
|
}
|
||||||
@@ -323,6 +302,60 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VRINTA (vector).
|
||||||
|
public static void Vrinta_V(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
EmitVectorUnaryOpF32(context, (m) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, m));
|
||||||
|
}
|
||||||
|
|
||||||
|
// VRINTM (vector).
|
||||||
|
public static void Vrintm_V(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
if (Optimizations.UseSse2)
|
||||||
|
{
|
||||||
|
EmitVectorUnaryOpSimd32(context, (m) =>
|
||||||
|
{
|
||||||
|
return context.AddIntrinsic(Intrinsic.X86Roundps, m, Const(X86GetRoundControl(FPRoundingMode.TowardsMinusInfinity)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Floor), m));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VRINTN (vector).
|
||||||
|
public static void Vrintn_V(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
if (Optimizations.UseSse2)
|
||||||
|
{
|
||||||
|
EmitVectorUnaryOpSimd32(context, (m) =>
|
||||||
|
{
|
||||||
|
return context.AddIntrinsic(Intrinsic.X86Roundps, m, Const(X86GetRoundControl(FPRoundingMode.ToNearest)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EmitVectorUnaryOpF32(context, (m) => EmitRoundMathCall(context, MidpointRounding.ToEven, m));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// VRINTP (vector).
|
||||||
|
public static void Vrintp_V(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
if (Optimizations.UseSse2)
|
||||||
|
{
|
||||||
|
EmitVectorUnaryOpSimd32(context, (m) =>
|
||||||
|
{
|
||||||
|
return context.AddIntrinsic(Intrinsic.X86Roundps, m, Const(X86GetRoundControl(FPRoundingMode.TowardsPlusInfinity)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EmitVectorUnaryOpF32(context, (m) => EmitUnaryMathCall(context, nameof(Math.Ceiling), m));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// VRINTZ (floating-point).
|
// VRINTZ (floating-point).
|
||||||
public static void Vrint_Z(ArmEmitterContext context)
|
public static void Vrint_Z(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
@@ -345,15 +378,9 @@ namespace ARMeilleure.Instructions
|
|||||||
// VRINTX (floating-point).
|
// VRINTX (floating-point).
|
||||||
public static void Vrintx_S(ArmEmitterContext context)
|
public static void Vrintx_S(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
|
||||||
|
|
||||||
bool doubleSize = (op.Size & 1) == 1;
|
|
||||||
string methodName = doubleSize ? nameof(SoftFallback.Round) : nameof(SoftFallback.RoundF);
|
|
||||||
|
|
||||||
EmitScalarUnaryOpF32(context, (op1) =>
|
EmitScalarUnaryOpF32(context, (op1) =>
|
||||||
{
|
{
|
||||||
MethodInfo info = typeof(SoftFallback).GetMethod(methodName);
|
return EmitRoundByRMode(context, op1);
|
||||||
return context.Call(info, op1);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -243,6 +243,21 @@ namespace ARMeilleure.Instructions
|
|||||||
throw new ArgumentException($"Invalid rounding mode \"{roundMode}\".");
|
throw new ArgumentException($"Invalid rounding mode \"{roundMode}\".");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ulong X86GetGf2p8LogicalShiftLeft(int shift)
|
||||||
|
{
|
||||||
|
ulong identity =
|
||||||
|
(0b00000001UL << 56) |
|
||||||
|
(0b00000010UL << 48) |
|
||||||
|
(0b00000100UL << 40) |
|
||||||
|
(0b00001000UL << 32) |
|
||||||
|
(0b00010000UL << 24) |
|
||||||
|
(0b00100000UL << 16) |
|
||||||
|
(0b01000000UL << 8) |
|
||||||
|
(0b10000000UL << 0);
|
||||||
|
|
||||||
|
return shift >= 0 ? identity >> (shift * 8) : identity << (-shift * 8);
|
||||||
|
}
|
||||||
|
|
||||||
public static Operand EmitCountSetBits8(ArmEmitterContext context, Operand op) // "size" is 8 (SIMD&FP Inst.).
|
public static Operand EmitCountSetBits8(ArmEmitterContext context, Operand op) // "size" is 8 (SIMD&FP Inst.).
|
||||||
{
|
{
|
||||||
Debug.Assert(op.Type == OperandType.I32 || op.Type == OperandType.I64);
|
Debug.Assert(op.Type == OperandType.I32 || op.Type == OperandType.I64);
|
||||||
@@ -361,6 +376,54 @@ namespace ARMeilleure.Instructions
|
|||||||
return context.Call(info, n, Const((int)roundMode));
|
return context.Call(info, n, Const((int)roundMode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Operand EmitGetRoundingMode(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
Operand rMode = context.ShiftLeft(GetFpFlag(FPState.RMode1Flag), Const(1));
|
||||||
|
rMode = context.BitwiseOr(rMode, GetFpFlag(FPState.RMode0Flag));
|
||||||
|
|
||||||
|
return rMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand EmitRoundByRMode(ArmEmitterContext context, Operand op)
|
||||||
|
{
|
||||||
|
Debug.Assert(op.Type == OperandType.FP32 || op.Type == OperandType.FP64);
|
||||||
|
|
||||||
|
Operand lbl1 = Label();
|
||||||
|
Operand lbl2 = Label();
|
||||||
|
Operand lbl3 = Label();
|
||||||
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
|
Operand rN = Const((int)FPRoundingMode.ToNearest);
|
||||||
|
Operand rP = Const((int)FPRoundingMode.TowardsPlusInfinity);
|
||||||
|
Operand rM = Const((int)FPRoundingMode.TowardsMinusInfinity);
|
||||||
|
|
||||||
|
Operand res = context.AllocateLocal(op.Type);
|
||||||
|
|
||||||
|
Operand rMode = EmitGetRoundingMode(context);
|
||||||
|
|
||||||
|
context.BranchIf(lbl1, rMode, rN, Comparison.NotEqual);
|
||||||
|
context.Copy(res, EmitRoundMathCall(context, MidpointRounding.ToEven, op));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lbl1);
|
||||||
|
context.BranchIf(lbl2, rMode, rP, Comparison.NotEqual);
|
||||||
|
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Ceiling), op));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lbl2);
|
||||||
|
context.BranchIf(lbl3, rMode, rM, Comparison.NotEqual);
|
||||||
|
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Floor), op));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lbl3);
|
||||||
|
context.Copy(res, EmitUnaryMathCall(context, nameof(Math.Truncate), op));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lblEnd);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
public static Operand EmitSoftFloatCall(ArmEmitterContext context, string name, params Operand[] callArgs)
|
public static Operand EmitSoftFloatCall(ArmEmitterContext context, string name, params Operand[] callArgs)
|
||||||
{
|
{
|
||||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||||
@@ -369,7 +432,11 @@ namespace ARMeilleure.Instructions
|
|||||||
? typeof(SoftFloat32).GetMethod(name)
|
? typeof(SoftFloat32).GetMethod(name)
|
||||||
: typeof(SoftFloat64).GetMethod(name);
|
: typeof(SoftFloat64).GetMethod(name);
|
||||||
|
|
||||||
return context.Call(info, callArgs);
|
context.StoreToContext();
|
||||||
|
Operand res = context.Call(info, callArgs);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void EmitScalarBinaryOpByElemF(ArmEmitterContext context, Func2I emit)
|
public static void EmitScalarBinaryOpByElemF(ArmEmitterContext context, Func2I emit)
|
||||||
@@ -1269,7 +1336,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void EmitSseOrAvxEnterFtzAndDazModesOpF(ArmEmitterContext context, out Operand isTrue)
|
public static void EmitSseOrAvxEnterFtzAndDazModesOpF(ArmEmitterContext context, out Operand isTrue)
|
||||||
{
|
{
|
||||||
isTrue = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)));
|
isTrue = GetFpFlag(FPState.FzFlag);
|
||||||
|
|
||||||
Operand lblTrue = Label();
|
Operand lblTrue = Label();
|
||||||
context.BranchIfFalse(lblTrue, isTrue);
|
context.BranchIfFalse(lblTrue, isTrue);
|
||||||
@@ -1281,9 +1348,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void EmitSseOrAvxExitFtzAndDazModesOpF(ArmEmitterContext context, Operand isTrue = default)
|
public static void EmitSseOrAvxExitFtzAndDazModesOpF(ArmEmitterContext context, Operand isTrue = default)
|
||||||
{
|
{
|
||||||
isTrue = isTrue == default
|
isTrue = isTrue == default ? GetFpFlag(FPState.FzFlag) : isTrue;
|
||||||
? context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)))
|
|
||||||
: isTrue;
|
|
||||||
|
|
||||||
Operand lblTrue = Label();
|
Operand lblTrue = Label();
|
||||||
context.BranchIfFalse(lblTrue, isTrue);
|
context.BranchIfFalse(lblTrue, isTrue);
|
||||||
@@ -1533,31 +1598,90 @@ namespace ARMeilleure.Instructions
|
|||||||
context.Copy(d, res);
|
context.Copy(d, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TSrc (16bit, 32bit, 64bit; signed) > TDst (8bit, 16bit, 32bit; signed, unsigned).
|
// long SignedSignSatQ(long op, int size);
|
||||||
// long SignedSrcSignedDstSatQ(long op, int size); ulong SignedSrcUnsignedDstSatQ(long op, int size);
|
public static Operand EmitSignedSignSatQ(ArmEmitterContext context, Operand op, int size)
|
||||||
public static Operand EmitSignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
|
|
||||||
{
|
{
|
||||||
Debug.Assert(op.Type == OperandType.I64 && (uint)sizeDst <= 2u);
|
int eSize = 8 << size;
|
||||||
|
|
||||||
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
|
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||||
|
|
||||||
Operand lbl1 = Label();
|
Operand lbl1 = Label();
|
||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
int eSize = 8 << sizeDst;
|
Operand zeroL = Const(0L);
|
||||||
|
Operand maxT = Const((1L << (eSize - 1)) - 1L);
|
||||||
|
Operand minT = Const(-(1L << (eSize - 1)));
|
||||||
|
|
||||||
Operand maxT = signedDst ? Const((1L << (eSize - 1)) - 1L) : Const((1UL << eSize) - 1UL);
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroL);
|
||||||
Operand minT = signedDst ? Const(-(1L << (eSize - 1))) : Const(0UL);
|
|
||||||
|
|
||||||
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
|
context.BranchIf(lbl1, op, zeroL, Comparison.LessOrEqual);
|
||||||
|
|
||||||
context.BranchIf(lbl1, res, maxT, Comparison.LessOrEqual);
|
|
||||||
context.Copy(res, maxT);
|
context.Copy(res, maxT);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl1);
|
context.MarkLabel(lbl1);
|
||||||
context.BranchIf(lblEnd, res, minT, Comparison.GreaterOrEqual);
|
context.BranchIf(lblEnd, op, zeroL, Comparison.GreaterOrEqual);
|
||||||
context.Copy(res, minT);
|
context.Copy(res, minT);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lblEnd);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// private static ulong UnsignedSignSatQ(ulong op, int size);
|
||||||
|
public static Operand EmitUnsignedSignSatQ(ArmEmitterContext context, Operand op, int size)
|
||||||
|
{
|
||||||
|
int eSize = 8 << size;
|
||||||
|
|
||||||
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
|
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||||
|
|
||||||
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
|
Operand zeroUL = Const(0UL);
|
||||||
|
Operand maxT = Const(ulong.MaxValue >> (64 - eSize));
|
||||||
|
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroUL);
|
||||||
|
|
||||||
|
context.BranchIf(lblEnd, op, zeroUL, Comparison.LessOrEqualUI);
|
||||||
|
context.Copy(res, maxT);
|
||||||
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lblEnd);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TSrc (16bit, 32bit, 64bit; signed) > TDst (8bit, 16bit, 32bit; signed, unsigned).
|
||||||
|
// long SignedSrcSignedDstSatQ(long op, int size); ulong SignedSrcUnsignedDstSatQ(long op, int size);
|
||||||
|
public static Operand EmitSignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
|
||||||
|
{
|
||||||
|
int eSizeDst = 8 << sizeDst;
|
||||||
|
|
||||||
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
|
Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
|
||||||
|
|
||||||
|
Operand lbl1 = Label();
|
||||||
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
|
Operand maxT = signedDst ? Const((1L << (eSizeDst - 1)) - 1L) : Const((1UL << eSizeDst) - 1UL);
|
||||||
|
Operand minT = signedDst ? Const(-(1L << (eSizeDst - 1))) : Const(0UL);
|
||||||
|
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
|
||||||
|
|
||||||
|
context.BranchIf(lbl1, op, maxT, Comparison.LessOrEqual);
|
||||||
|
context.Copy(res, maxT);
|
||||||
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lbl1);
|
||||||
|
context.BranchIf(lblEnd, op, minT, Comparison.GreaterOrEqual);
|
||||||
|
context.Copy(res, minT);
|
||||||
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1569,19 +1693,20 @@ namespace ARMeilleure.Instructions
|
|||||||
// long UnsignedSrcSignedDstSatQ(ulong op, int size); ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size);
|
// long UnsignedSrcSignedDstSatQ(ulong op, int size); ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size);
|
||||||
public static Operand EmitUnsignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
|
public static Operand EmitUnsignedSrcSatQ(ArmEmitterContext context, Operand op, int sizeDst, bool signedDst)
|
||||||
{
|
{
|
||||||
Debug.Assert(op.Type == OperandType.I64 && (uint)sizeDst <= 2u);
|
int eSizeDst = 8 << sizeDst;
|
||||||
|
|
||||||
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
|
Debug.Assert(eSizeDst == 8 || eSizeDst == 16 || eSizeDst == 32);
|
||||||
|
|
||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
int eSize = 8 << sizeDst;
|
Operand maxT = signedDst ? Const((1L << (eSizeDst - 1)) - 1L) : Const((1UL << eSizeDst) - 1UL);
|
||||||
|
|
||||||
Operand maxL = signedDst ? Const((1L << (eSize - 1)) - 1L) : Const((1UL << eSize) - 1UL);
|
|
||||||
|
|
||||||
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
|
||||||
|
|
||||||
context.BranchIf(lblEnd, res, maxL, Comparison.LessOrEqualUI);
|
context.BranchIf(lblEnd, op, maxT, Comparison.LessOrEqualUI);
|
||||||
context.Copy(res, maxL);
|
context.Copy(res, maxT);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1601,9 +1726,9 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
|
||||||
|
|
||||||
context.BranchIf(lblEnd, res, minL, Comparison.NotEqual);
|
context.BranchIf(lblEnd, op, minL, Comparison.NotEqual);
|
||||||
context.Copy(res, maxL);
|
context.Copy(res, maxL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1620,17 +1745,18 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Operand minL = Const(long.MinValue);
|
Operand minL = Const(long.MinValue);
|
||||||
Operand maxL = Const(long.MaxValue);
|
Operand maxL = Const(long.MaxValue);
|
||||||
Operand zero = Const(0L);
|
Operand zeroL = Const(0L);
|
||||||
|
|
||||||
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
|
Operand add = context.Add(op1, op2);
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
|
||||||
|
|
||||||
Operand left = context.BitwiseNot(context.BitwiseExclusiveOr(op1, op2));
|
Operand left = context.BitwiseNot(context.BitwiseExclusiveOr(op1, op2));
|
||||||
Operand right = context.BitwiseExclusiveOr(op1, res);
|
Operand right = context.BitwiseExclusiveOr(op1, add);
|
||||||
context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zero, Comparison.GreaterOrEqual);
|
context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zeroL, Comparison.GreaterOrEqual);
|
||||||
|
|
||||||
Operand isPositive = context.ICompareGreaterOrEqual(op1, zero);
|
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
|
||||||
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
|
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1647,11 +1773,12 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Operand maxUL = Const(ulong.MaxValue);
|
Operand maxUL = Const(ulong.MaxValue);
|
||||||
|
|
||||||
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
|
Operand add = context.Add(op1, op2);
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
|
||||||
|
|
||||||
context.BranchIf(lblEnd, res, op1, Comparison.GreaterOrEqualUI);
|
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
|
||||||
context.Copy(res, maxUL);
|
context.Copy(res, maxUL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1668,17 +1795,18 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Operand minL = Const(long.MinValue);
|
Operand minL = Const(long.MinValue);
|
||||||
Operand maxL = Const(long.MaxValue);
|
Operand maxL = Const(long.MaxValue);
|
||||||
Operand zero = Const(0L);
|
Operand zeroL = Const(0L);
|
||||||
|
|
||||||
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Subtract(op1, op2));
|
Operand sub = context.Subtract(op1, op2);
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sub);
|
||||||
|
|
||||||
Operand left = context.BitwiseExclusiveOr(op1, op2);
|
Operand left = context.BitwiseExclusiveOr(op1, op2);
|
||||||
Operand right = context.BitwiseExclusiveOr(op1, res);
|
Operand right = context.BitwiseExclusiveOr(op1, sub);
|
||||||
context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zero, Comparison.GreaterOrEqual);
|
context.BranchIf(lblEnd, context.BitwiseAnd(left, right), zeroL, Comparison.GreaterOrEqual);
|
||||||
|
|
||||||
Operand isPositive = context.ICompareGreaterOrEqual(op1, zero);
|
Operand isPositive = context.ICompareGreaterOrEqual(op1, zeroL);
|
||||||
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
|
context.Copy(res, context.ConditionalSelect(isPositive, maxL, minL));
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1693,13 +1821,14 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
Operand zero = Const(0L);
|
Operand zeroL = Const(0L);
|
||||||
|
|
||||||
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Subtract(op1, op2));
|
Operand sub = context.Subtract(op1, op2);
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sub);
|
||||||
|
|
||||||
context.BranchIf(lblEnd, op1, op2, Comparison.GreaterOrEqualUI);
|
context.BranchIf(lblEnd, op1, op2, Comparison.GreaterOrEqualUI);
|
||||||
context.Copy(res, zero);
|
context.Copy(res, zeroL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1717,27 +1846,28 @@ namespace ARMeilleure.Instructions
|
|||||||
Operand lblEnd = Label();
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
Operand maxL = Const(long.MaxValue);
|
Operand maxL = Const(long.MaxValue);
|
||||||
Operand zero = Const(0L);
|
Operand zeroL = Const(0L);
|
||||||
|
|
||||||
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
|
Operand add = context.Add(op1, op2);
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
|
||||||
|
|
||||||
context.BranchIf(lbl1, op1, maxL, Comparison.GreaterUI);
|
context.BranchIf(lbl1, op1, maxL, Comparison.GreaterUI);
|
||||||
Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), res);
|
Operand notOp2AndRes = context.BitwiseAnd(context.BitwiseNot(op2), add);
|
||||||
context.BranchIf(lblEnd, notOp2AndRes, zero, Comparison.GreaterOrEqual);
|
context.BranchIf(lblEnd, notOp2AndRes, zeroL, Comparison.GreaterOrEqual);
|
||||||
context.Copy(res, maxL);
|
context.Copy(res, maxL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl1);
|
context.MarkLabel(lbl1);
|
||||||
context.BranchIf(lbl2, op2, zero, Comparison.Less);
|
context.BranchIf(lbl2, op2, zeroL, Comparison.Less);
|
||||||
context.Copy(res, maxL);
|
context.Copy(res, maxL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl2);
|
context.MarkLabel(lbl2);
|
||||||
context.BranchIf(lblEnd, res, maxL, Comparison.LessOrEqualUI);
|
context.BranchIf(lblEnd, add, maxL, Comparison.LessOrEqualUI);
|
||||||
context.Copy(res, maxL);
|
context.Copy(res, maxL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
@@ -1755,21 +1885,22 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
Operand maxUL = Const(ulong.MaxValue);
|
Operand maxUL = Const(ulong.MaxValue);
|
||||||
Operand maxL = Const(long.MaxValue);
|
Operand maxL = Const(long.MaxValue);
|
||||||
Operand zero = Const(0L);
|
Operand zeroL = Const(0L);
|
||||||
|
|
||||||
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), context.Add(op1, op2));
|
Operand add = context.Add(op1, op2);
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), add);
|
||||||
|
|
||||||
context.BranchIf(lbl1, op1, zero, Comparison.Less);
|
context.BranchIf(lbl1, op1, zeroL, Comparison.Less);
|
||||||
context.BranchIf(lblEnd, res, op1, Comparison.GreaterOrEqualUI);
|
context.BranchIf(lblEnd, add, op1, Comparison.GreaterOrEqualUI);
|
||||||
context.Copy(res, maxUL);
|
context.Copy(res, maxUL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lbl1);
|
context.MarkLabel(lbl1);
|
||||||
context.BranchIf(lblEnd, op2, maxL, Comparison.GreaterUI);
|
context.BranchIf(lblEnd, op2, maxL, Comparison.GreaterUI);
|
||||||
context.BranchIf(lblEnd, res, zero, Comparison.GreaterOrEqual);
|
context.BranchIf(lblEnd, add, zeroL, Comparison.GreaterOrEqual);
|
||||||
context.Copy(res, zero);
|
context.Copy(res, zeroL);
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
context.Branch(lblEnd);
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
context.MarkLabel(lblEnd);
|
context.MarkLabel(lblEnd);
|
||||||
|
@@ -1181,7 +1181,11 @@ namespace ARMeilleure.Instructions
|
|||||||
Array.Resize(ref callArgs, callArgs.Length + 1);
|
Array.Resize(ref callArgs, callArgs.Length + 1);
|
||||||
callArgs[callArgs.Length - 1] = Const(1);
|
callArgs[callArgs.Length - 1] = Const(1);
|
||||||
|
|
||||||
return context.Call(info, callArgs);
|
context.StoreToContext();
|
||||||
|
Operand res = context.Call(info, callArgs);
|
||||||
|
context.LoadFromContext();
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand EmitVectorExtractSx32(ArmEmitterContext context, int reg, int index, int size)
|
public static Operand EmitVectorExtractSx32(ArmEmitterContext context, int reg, int index, int size)
|
||||||
|
@@ -336,8 +336,32 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||||
|
|
||||||
Operand res = context.VectorZero();
|
if (Optimizations.UseGfni)
|
||||||
|
{
|
||||||
|
const long bitMatrix =
|
||||||
|
(0b10000000L << 56) |
|
||||||
|
(0b01000000L << 48) |
|
||||||
|
(0b00100000L << 40) |
|
||||||
|
(0b00010000L << 32) |
|
||||||
|
(0b00001000L << 24) |
|
||||||
|
(0b00000100L << 16) |
|
||||||
|
(0b00000010L << 8) |
|
||||||
|
(0b00000001L << 0);
|
||||||
|
|
||||||
|
Operand vBitMatrix = X86GetAllElements(context, bitMatrix);
|
||||||
|
|
||||||
|
Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, GetVec(op.Rn), vBitMatrix, Const(0));
|
||||||
|
|
||||||
|
if (op.RegisterSize == RegisterSize.Simd64)
|
||||||
|
{
|
||||||
|
res = context.VectorZeroUpper64(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Copy(GetVec(op.Rd), res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Operand res = context.VectorZero();
|
||||||
int elems = op.RegisterSize == RegisterSize.Simd128 ? 16 : 8;
|
int elems = op.RegisterSize == RegisterSize.Simd128 ? 16 : 8;
|
||||||
|
|
||||||
for (int index = 0; index < elems; index++)
|
for (int index = 0; index < elems; index++)
|
||||||
@@ -351,6 +375,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.Copy(GetVec(op.Rd), res);
|
context.Copy(GetVec(op.Rd), res);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Operand EmitReverseBits8Op(ArmEmitterContext context, Operand op)
|
private static Operand EmitReverseBits8Op(ArmEmitterContext context, Operand op)
|
||||||
{
|
{
|
||||||
|
@@ -67,7 +67,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
// Write an element from a double simd register.
|
// Accesses an element from a double simd register.
|
||||||
Operand address = context.Add(n, Const(offset));
|
Operand address = context.Add(n, Const(offset));
|
||||||
if (eBytes == 8)
|
if (eBytes == 8)
|
||||||
{
|
{
|
||||||
@@ -131,6 +131,7 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
OpCode32SimdMemPair op = (OpCode32SimdMemPair)context.CurrOp;
|
OpCode32SimdMemPair op = (OpCode32SimdMemPair)context.CurrOp;
|
||||||
|
|
||||||
|
int increment = count > 1 ? op.Increment : 1;
|
||||||
int eBytes = 1 << op.Size;
|
int eBytes = 1 << op.Size;
|
||||||
|
|
||||||
Operand n = context.Copy(GetIntA32(context, op.Rn));
|
Operand n = context.Copy(GetIntA32(context, op.Rn));
|
||||||
@@ -144,7 +145,7 @@ namespace ARMeilleure.Instructions
|
|||||||
int elemD = d + reg;
|
int elemD = d + reg;
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
// Write an element from a double simd register
|
// Accesses an element from a double simd register,
|
||||||
// add ebytes for each element.
|
// add ebytes for each element.
|
||||||
Operand address = context.Add(n, Const(offset));
|
Operand address = context.Add(n, Const(offset));
|
||||||
int index = ((elemD & 1) << (3 - op.Size)) + elem;
|
int index = ((elemD & 1) << (3 - op.Size)) + elem;
|
||||||
@@ -161,7 +162,6 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
if (load)
|
if (load)
|
||||||
{
|
{
|
||||||
EmitLoadSimd(context, address, GetVecA32(elemD >> 1), elemD >> 1, index, op.Size);
|
EmitLoadSimd(context, address, GetVecA32(elemD >> 1), elemD >> 1, index, op.Size);
|
||||||
@@ -173,7 +173,7 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
|
|
||||||
offset += eBytes;
|
offset += eBytes;
|
||||||
elemD += op.Increment;
|
elemD += increment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -88,8 +88,35 @@ namespace ARMeilleure.Instructions
|
|||||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||||
|
|
||||||
int shift = GetImmShl(op);
|
int shift = GetImmShl(op);
|
||||||
|
int eSize = 8 << op.Size;
|
||||||
|
|
||||||
if (Optimizations.UseSse2 && op.Size > 0)
|
if (shift >= eSize)
|
||||||
|
{
|
||||||
|
if ((op.RegisterSize == RegisterSize.Simd64))
|
||||||
|
{
|
||||||
|
Operand res = context.VectorZeroUpper64(GetVec(op.Rd));
|
||||||
|
|
||||||
|
context.Copy(GetVec(op.Rd), res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Optimizations.UseGfni && op.Size == 0)
|
||||||
|
{
|
||||||
|
Operand n = GetVec(op.Rn);
|
||||||
|
|
||||||
|
ulong bitMatrix = X86GetGf2p8LogicalShiftLeft(shift);
|
||||||
|
|
||||||
|
Operand vBitMatrix = X86GetElements(context, bitMatrix, bitMatrix);
|
||||||
|
|
||||||
|
Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, n, vBitMatrix, Const(0));
|
||||||
|
|
||||||
|
if (op.RegisterSize == RegisterSize.Simd64)
|
||||||
|
{
|
||||||
|
res = context.VectorZeroUpper64(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Copy(GetVec(op.Rd), res);
|
||||||
|
}
|
||||||
|
else if (Optimizations.UseSse2 && op.Size > 0)
|
||||||
{
|
{
|
||||||
Operand n = GetVec(op.Rn);
|
Operand n = GetVec(op.Rn);
|
||||||
|
|
||||||
@@ -188,23 +215,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Sqrshl_V(ArmEmitterContext context)
|
public static void Sqrshl_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round | ShlRegFlags.Saturating);
|
||||||
|
|
||||||
Operand res = context.VectorZero();
|
|
||||||
|
|
||||||
int elems = op.GetBytesCount() >> op.Size;
|
|
||||||
|
|
||||||
for (int index = 0; index < elems; index++)
|
|
||||||
{
|
|
||||||
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
|
|
||||||
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
|
|
||||||
|
|
||||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)), ne, me, Const(1), Const(op.Size));
|
|
||||||
|
|
||||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sqrshrn_S(ArmEmitterContext context)
|
public static void Sqrshrn_S(ArmEmitterContext context)
|
||||||
@@ -229,23 +240,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Sqshl_V(ArmEmitterContext context)
|
public static void Sqshl_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Saturating);
|
||||||
|
|
||||||
Operand res = context.VectorZero();
|
|
||||||
|
|
||||||
int elems = op.GetBytesCount() >> op.Size;
|
|
||||||
|
|
||||||
for (int index = 0; index < elems; index++)
|
|
||||||
{
|
|
||||||
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
|
|
||||||
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
|
|
||||||
|
|
||||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)), ne, me, Const(0), Const(op.Size));
|
|
||||||
|
|
||||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sqshrn_S(ArmEmitterContext context)
|
public static void Sqshrn_S(ArmEmitterContext context)
|
||||||
@@ -280,23 +275,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Srshl_V(ArmEmitterContext context)
|
public static void Srshl_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
EmitShlRegOp(context, ShlRegFlags.Signed | ShlRegFlags.Round);
|
||||||
|
|
||||||
Operand res = context.VectorZero();
|
|
||||||
|
|
||||||
int elems = op.GetBytesCount() >> op.Size;
|
|
||||||
|
|
||||||
for (int index = 0; index < elems; index++)
|
|
||||||
{
|
|
||||||
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
|
|
||||||
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
|
|
||||||
|
|
||||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)), ne, me, Const(1), Const(op.Size));
|
|
||||||
|
|
||||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Srshr_S(ArmEmitterContext context)
|
public static void Srshr_S(ArmEmitterContext context)
|
||||||
@@ -393,12 +372,12 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Sshl_S(ArmEmitterContext context)
|
public static void Sshl_S(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
EmitSshlOrUshl(context, signed: true, scalar: true);
|
EmitShlRegOp(context, ShlRegFlags.Scalar | ShlRegFlags.Signed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sshl_V(ArmEmitterContext context)
|
public static void Sshl_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
EmitSshlOrUshl(context, signed: true, scalar: false);
|
EmitShlRegOp(context, ShlRegFlags.Signed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sshll_V(ArmEmitterContext context)
|
public static void Sshll_V(ArmEmitterContext context)
|
||||||
@@ -444,10 +423,40 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||||
|
|
||||||
if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3)
|
|
||||||
{
|
|
||||||
int shift = GetImmShr(op);
|
int shift = GetImmShr(op);
|
||||||
|
|
||||||
|
if (Optimizations.UseGfni && op.Size == 0)
|
||||||
|
{
|
||||||
|
Operand n = GetVec(op.Rn);
|
||||||
|
|
||||||
|
ulong bitMatrix;
|
||||||
|
|
||||||
|
if (shift < 8)
|
||||||
|
{
|
||||||
|
bitMatrix = X86GetGf2p8LogicalShiftLeft(-shift);
|
||||||
|
|
||||||
|
// Extend sign-bit
|
||||||
|
bitMatrix |= 0x8080808080808080UL >> (64 - shift * 8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Replicate sign-bit into all bits
|
||||||
|
bitMatrix = 0x8080808080808080UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand vBitMatrix = X86GetElements(context, bitMatrix, bitMatrix);
|
||||||
|
|
||||||
|
Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, n, vBitMatrix, Const(0));
|
||||||
|
|
||||||
|
if (op.RegisterSize == RegisterSize.Simd64)
|
||||||
|
{
|
||||||
|
res = context.VectorZeroUpper64(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Copy(GetVec(op.Rd), res);
|
||||||
|
}
|
||||||
|
else if (Optimizations.UseSse2 && op.Size > 0 && op.Size < 3)
|
||||||
|
{
|
||||||
Operand n = GetVec(op.Rn);
|
Operand n = GetVec(op.Rn);
|
||||||
|
|
||||||
Intrinsic sraInst = X86PsraInstruction[op.Size];
|
Intrinsic sraInst = X86PsraInstruction[op.Size];
|
||||||
@@ -506,23 +515,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Uqrshl_V(ArmEmitterContext context)
|
public static void Uqrshl_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
EmitShlRegOp(context, ShlRegFlags.Round | ShlRegFlags.Saturating);
|
||||||
|
|
||||||
Operand res = context.VectorZero();
|
|
||||||
|
|
||||||
int elems = op.GetBytesCount() >> op.Size;
|
|
||||||
|
|
||||||
for (int index = 0; index < elems; index++)
|
|
||||||
{
|
|
||||||
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
|
|
||||||
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
|
|
||||||
|
|
||||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)), ne, me, Const(1), Const(op.Size));
|
|
||||||
|
|
||||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Uqrshrn_S(ArmEmitterContext context)
|
public static void Uqrshrn_S(ArmEmitterContext context)
|
||||||
@@ -537,23 +530,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Uqshl_V(ArmEmitterContext context)
|
public static void Uqshl_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
EmitShlRegOp(context, ShlRegFlags.Saturating);
|
||||||
|
|
||||||
Operand res = context.VectorZero();
|
|
||||||
|
|
||||||
int elems = op.GetBytesCount() >> op.Size;
|
|
||||||
|
|
||||||
for (int index = 0; index < elems; index++)
|
|
||||||
{
|
|
||||||
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
|
|
||||||
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
|
|
||||||
|
|
||||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)), ne, me, Const(0), Const(op.Size));
|
|
||||||
|
|
||||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Uqshrn_S(ArmEmitterContext context)
|
public static void Uqshrn_S(ArmEmitterContext context)
|
||||||
@@ -568,23 +545,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Urshl_V(ArmEmitterContext context)
|
public static void Urshl_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
EmitShlRegOp(context, ShlRegFlags.Round);
|
||||||
|
|
||||||
Operand res = context.VectorZero();
|
|
||||||
|
|
||||||
int elems = op.GetBytesCount() >> op.Size;
|
|
||||||
|
|
||||||
for (int index = 0; index < elems; index++)
|
|
||||||
{
|
|
||||||
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
|
|
||||||
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
|
|
||||||
|
|
||||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)), ne, me, Const(1), Const(op.Size));
|
|
||||||
|
|
||||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Urshr_S(ArmEmitterContext context)
|
public static void Urshr_S(ArmEmitterContext context)
|
||||||
@@ -677,12 +638,12 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Ushl_S(ArmEmitterContext context)
|
public static void Ushl_S(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
EmitSshlOrUshl(context, signed: false, scalar: true);
|
EmitShlRegOp(context, ShlRegFlags.Scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ushl_V(ArmEmitterContext context)
|
public static void Ushl_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
EmitSshlOrUshl(context, signed: false, scalar: false);
|
EmitShlRegOp(context, ShlRegFlags.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ushll_V(ArmEmitterContext context)
|
public static void Ushll_V(ArmEmitterContext context)
|
||||||
@@ -872,43 +833,6 @@ namespace ARMeilleure.Instructions
|
|||||||
context.Copy(GetVec(op.Rd), res);
|
context.Copy(GetVec(op.Rd), res);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Operand EmitShlRegOp(ArmEmitterContext context, Operand op, Operand shiftLsB, int size, bool signed)
|
|
||||||
{
|
|
||||||
Debug.Assert(op.Type == OperandType.I64);
|
|
||||||
Debug.Assert(shiftLsB.Type == OperandType.I32);
|
|
||||||
Debug.Assert((uint)size < 4u);
|
|
||||||
|
|
||||||
Operand negShiftLsB = context.Negate(shiftLsB);
|
|
||||||
|
|
||||||
Operand isInRange = context.BitwiseAnd(
|
|
||||||
context.ICompareLess(shiftLsB, Const(8 << size)),
|
|
||||||
context.ICompareLess(negShiftLsB, Const(8 << size)));
|
|
||||||
|
|
||||||
Operand isPositive = context.ICompareGreaterOrEqual(shiftLsB, Const(0));
|
|
||||||
|
|
||||||
Operand shl = context.ShiftLeft(op, shiftLsB);
|
|
||||||
|
|
||||||
Operand sarOrShr = signed
|
|
||||||
? context.ShiftRightSI(op, negShiftLsB)
|
|
||||||
: context.ShiftRightUI(op, negShiftLsB);
|
|
||||||
|
|
||||||
Operand res = context.ConditionalSelect(isPositive, shl, sarOrShr);
|
|
||||||
|
|
||||||
if (signed)
|
|
||||||
{
|
|
||||||
Operand isPositive2 = context.ICompareGreaterOrEqual(op, Const(0L));
|
|
||||||
|
|
||||||
Operand res2 = context.ConditionalSelect(isPositive2, Const(0L), Const(-1L));
|
|
||||||
res2 = context.ConditionalSelect(isPositive, Const(0L), res2);
|
|
||||||
|
|
||||||
return context.ConditionalSelect(isInRange, res, res2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return context.ConditionalSelect(isInRange, res, Const(0UL));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void EmitVectorShrImmNarrowOpZx(ArmEmitterContext context, bool round)
|
private static void EmitVectorShrImmNarrowOpZx(ArmEmitterContext context, bool round)
|
||||||
{
|
{
|
||||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||||
@@ -1062,10 +986,44 @@ namespace ARMeilleure.Instructions
|
|||||||
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
|
||||||
|
|
||||||
int shift = GetImmShl(op);
|
int shift = GetImmShl(op);
|
||||||
|
int eSize = 8 << op.Size;
|
||||||
|
|
||||||
ulong mask = shift != 0 ? ulong.MaxValue >> (64 - shift) : 0UL;
|
ulong mask = shift != 0 ? ulong.MaxValue >> (64 - shift) : 0UL;
|
||||||
|
|
||||||
if (Optimizations.UseSse2 && op.Size > 0)
|
if (shift >= eSize)
|
||||||
|
{
|
||||||
|
if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
|
||||||
|
{
|
||||||
|
Operand res = context.VectorZeroUpper64(GetVec(op.Rd));
|
||||||
|
|
||||||
|
context.Copy(GetVec(op.Rd), res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Optimizations.UseGfni && op.Size == 0)
|
||||||
|
{
|
||||||
|
Operand d = GetVec(op.Rd);
|
||||||
|
Operand n = GetVec(op.Rn);
|
||||||
|
|
||||||
|
ulong bitMatrix = X86GetGf2p8LogicalShiftLeft(shift);
|
||||||
|
|
||||||
|
Operand vBitMatrix = X86GetElements(context, bitMatrix, bitMatrix);
|
||||||
|
|
||||||
|
Operand nShifted = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, n, vBitMatrix, Const(0));
|
||||||
|
|
||||||
|
Operand dMask = X86GetAllElements(context, (long)mask * _masks_SliSri[op.Size]);
|
||||||
|
|
||||||
|
Operand dMasked = context.AddIntrinsic(Intrinsic.X86Pand, d, dMask);
|
||||||
|
|
||||||
|
Operand res = context.AddIntrinsic(Intrinsic.X86Por, nShifted, dMasked);
|
||||||
|
|
||||||
|
if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
|
||||||
|
{
|
||||||
|
res = context.VectorZeroUpper64(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Copy(d, res);
|
||||||
|
}
|
||||||
|
else if (Optimizations.UseSse2 && op.Size > 0)
|
||||||
{
|
{
|
||||||
Operand d = GetVec(op.Rd);
|
Operand d = GetVec(op.Rd);
|
||||||
Operand n = GetVec(op.Rn);
|
Operand n = GetVec(op.Rn);
|
||||||
@@ -1121,7 +1079,40 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
ulong mask = (ulong.MaxValue << (eSize - shift)) & (ulong.MaxValue >> (64 - eSize));
|
ulong mask = (ulong.MaxValue << (eSize - shift)) & (ulong.MaxValue >> (64 - eSize));
|
||||||
|
|
||||||
if (Optimizations.UseSse2 && op.Size > 0)
|
if (shift >= eSize)
|
||||||
|
{
|
||||||
|
if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
|
||||||
|
{
|
||||||
|
Operand res = context.VectorZeroUpper64(GetVec(op.Rd));
|
||||||
|
|
||||||
|
context.Copy(GetVec(op.Rd), res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Optimizations.UseGfni && op.Size == 0)
|
||||||
|
{
|
||||||
|
Operand d = GetVec(op.Rd);
|
||||||
|
Operand n = GetVec(op.Rn);
|
||||||
|
|
||||||
|
ulong bitMatrix = X86GetGf2p8LogicalShiftLeft(-shift);
|
||||||
|
|
||||||
|
Operand vBitMatrix = X86GetElements(context, bitMatrix, bitMatrix);
|
||||||
|
|
||||||
|
Operand nShifted = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, n, vBitMatrix, Const(0));
|
||||||
|
|
||||||
|
Operand dMask = X86GetAllElements(context, (long)mask * _masks_SliSri[op.Size]);
|
||||||
|
|
||||||
|
Operand dMasked = context.AddIntrinsic(Intrinsic.X86Pand, d, dMask);
|
||||||
|
|
||||||
|
Operand res = context.AddIntrinsic(Intrinsic.X86Por, nShifted, dMasked);
|
||||||
|
|
||||||
|
if ((op.RegisterSize == RegisterSize.Simd64) || scalar)
|
||||||
|
{
|
||||||
|
res = context.VectorZeroUpper64(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
context.Copy(d, res);
|
||||||
|
}
|
||||||
|
else if (Optimizations.UseSse2 && op.Size > 0)
|
||||||
{
|
{
|
||||||
Operand d = GetVec(op.Rd);
|
Operand d = GetVec(op.Rd);
|
||||||
Operand n = GetVec(op.Rn);
|
Operand n = GetVec(op.Rn);
|
||||||
@@ -1168,8 +1159,23 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitSshlOrUshl(ArmEmitterContext context, bool signed, bool scalar)
|
[Flags]
|
||||||
|
private enum ShlRegFlags
|
||||||
{
|
{
|
||||||
|
None = 0,
|
||||||
|
Scalar = 1 << 0,
|
||||||
|
Signed = 1 << 1,
|
||||||
|
Round = 1 << 2,
|
||||||
|
Saturating = 1 << 3
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitShlRegOp(ArmEmitterContext context, ShlRegFlags flags = ShlRegFlags.None)
|
||||||
|
{
|
||||||
|
bool scalar = flags.HasFlag(ShlRegFlags.Scalar);
|
||||||
|
bool signed = flags.HasFlag(ShlRegFlags.Signed);
|
||||||
|
bool round = flags.HasFlag(ShlRegFlags.Round);
|
||||||
|
bool saturating = flags.HasFlag(ShlRegFlags.Saturating);
|
||||||
|
|
||||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||||
|
|
||||||
Operand res = context.VectorZero();
|
Operand res = context.VectorZero();
|
||||||
@@ -1178,15 +1184,225 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
for (int index = 0; index < elems; index++)
|
for (int index = 0; index < elems; index++)
|
||||||
{
|
{
|
||||||
Operand ne = EmitVectorExtract (context, op.Rn, index, op.Size, signed);
|
Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size, signed);
|
||||||
Operand me = EmitVectorExtractSx(context, op.Rm, index << op.Size, 0);
|
Operand me = EmitVectorExtractSx(context, op.Rm, index << op.Size, size: 0);
|
||||||
|
|
||||||
Operand e = EmitShlRegOp(context, ne, context.ConvertI64ToI32(me), op.Size, signed);
|
Operand e = !saturating
|
||||||
|
? EmitShlReg(context, ne, context.ConvertI64ToI32(me), round, op.Size, signed)
|
||||||
|
: EmitShlRegSatQ(context, ne, context.ConvertI64ToI32(me), round, op.Size, signed);
|
||||||
|
|
||||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), res);
|
context.Copy(GetVec(op.Rd), res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// long SignedShlReg(long op, int shiftLsB, bool round, int size);
|
||||||
|
// ulong UnsignedShlReg(ulong op, int shiftLsB, bool round, int size);
|
||||||
|
private static Operand EmitShlReg(ArmEmitterContext context, Operand op, Operand shiftLsB, bool round, int size, bool signed)
|
||||||
|
{
|
||||||
|
int eSize = 8 << size;
|
||||||
|
|
||||||
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
|
Debug.Assert(shiftLsB.Type == OperandType.I32);
|
||||||
|
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||||
|
|
||||||
|
Operand lbl1 = Label();
|
||||||
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
|
Operand eSizeOp = Const(eSize);
|
||||||
|
Operand zero = Const(0);
|
||||||
|
Operand zeroL = Const(0L);
|
||||||
|
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
|
||||||
|
|
||||||
|
context.BranchIf(lbl1, shiftLsB, zero, Comparison.GreaterOrEqual);
|
||||||
|
context.Copy(res, signed
|
||||||
|
? EmitSignedShrReg(context, op, context.Negate(shiftLsB), round, eSize)
|
||||||
|
: EmitUnsignedShrReg(context, op, context.Negate(shiftLsB), round, eSize));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lbl1);
|
||||||
|
context.BranchIf(lblEnd, shiftLsB, zero, Comparison.LessOrEqual);
|
||||||
|
Operand shl = context.ShiftLeft(op, shiftLsB);
|
||||||
|
Operand isGreaterOrEqual = context.ICompareGreaterOrEqual(shiftLsB, eSizeOp);
|
||||||
|
context.Copy(res, context.ConditionalSelect(isGreaterOrEqual, zeroL, shl));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lblEnd);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// long SignedShlRegSatQ(long op, int shiftLsB, bool round, int size);
|
||||||
|
// ulong UnsignedShlRegSatQ(ulong op, int shiftLsB, bool round, int size);
|
||||||
|
private static Operand EmitShlRegSatQ(ArmEmitterContext context, Operand op, Operand shiftLsB, bool round, int size, bool signed)
|
||||||
|
{
|
||||||
|
int eSize = 8 << size;
|
||||||
|
|
||||||
|
Debug.Assert(op.Type == OperandType.I64);
|
||||||
|
Debug.Assert(shiftLsB.Type == OperandType.I32);
|
||||||
|
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
|
||||||
|
|
||||||
|
Operand lbl1 = Label();
|
||||||
|
Operand lbl2 = Label();
|
||||||
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
|
Operand eSizeOp = Const(eSize);
|
||||||
|
Operand zero = Const(0);
|
||||||
|
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
|
||||||
|
|
||||||
|
context.BranchIf(lbl1, shiftLsB, zero, Comparison.GreaterOrEqual);
|
||||||
|
context.Copy(res, signed
|
||||||
|
? EmitSignedShrReg(context, op, context.Negate(shiftLsB), round, eSize)
|
||||||
|
: EmitUnsignedShrReg(context, op, context.Negate(shiftLsB), round, eSize));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lbl1);
|
||||||
|
context.BranchIf(lblEnd, shiftLsB, zero, Comparison.LessOrEqual);
|
||||||
|
context.BranchIf(lbl2, shiftLsB, eSizeOp, Comparison.Less);
|
||||||
|
context.Copy(res, signed
|
||||||
|
? EmitSignedSignSatQ(context, op, size)
|
||||||
|
: EmitUnsignedSignSatQ(context, op, size));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lbl2);
|
||||||
|
Operand shl = context.ShiftLeft(op, shiftLsB);
|
||||||
|
if (eSize == 64)
|
||||||
|
{
|
||||||
|
Operand sarOrShr = signed
|
||||||
|
? context.ShiftRightSI(shl, shiftLsB)
|
||||||
|
: context.ShiftRightUI(shl, shiftLsB);
|
||||||
|
context.Copy(res, shl);
|
||||||
|
context.BranchIf(lblEnd, sarOrShr, op, Comparison.Equal);
|
||||||
|
context.Copy(res, signed
|
||||||
|
? EmitSignedSignSatQ(context, op, size)
|
||||||
|
: EmitUnsignedSignSatQ(context, op, size));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Copy(res, signed
|
||||||
|
? EmitSignedSrcSatQ(context, shl, size, signedDst: true)
|
||||||
|
: EmitUnsignedSrcSatQ(context, shl, size, signedDst: false));
|
||||||
|
}
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lblEnd);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
// shift := [1, 128]; eSize := {8, 16, 32, 64}.
|
||||||
|
// long SignedShrReg(long op, int shift, bool round, int eSize);
|
||||||
|
private static Operand EmitSignedShrReg(ArmEmitterContext context, Operand op, Operand shift, bool round, int eSize)
|
||||||
|
{
|
||||||
|
if (round)
|
||||||
|
{
|
||||||
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
|
Operand eSizeOp = Const(eSize);
|
||||||
|
Operand zeroL = Const(0L);
|
||||||
|
Operand one = Const(1);
|
||||||
|
Operand oneL = Const(1L);
|
||||||
|
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroL);
|
||||||
|
|
||||||
|
context.BranchIf(lblEnd, shift, eSizeOp, Comparison.GreaterOrEqual);
|
||||||
|
Operand roundConst = context.ShiftLeft(oneL, context.Subtract(shift, one));
|
||||||
|
Operand add = context.Add(op, roundConst);
|
||||||
|
Operand sar = context.ShiftRightSI(add, shift);
|
||||||
|
if (eSize == 64)
|
||||||
|
{
|
||||||
|
Operand shr = context.ShiftRightUI(add, shift);
|
||||||
|
Operand left = context.BitwiseAnd(context.Negate(op), context.BitwiseExclusiveOr(op, add));
|
||||||
|
Operand isLess = context.ICompareLess(left, zeroL);
|
||||||
|
context.Copy(res, context.ConditionalSelect(isLess, shr, sar));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Copy(res, sar);
|
||||||
|
}
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lblEnd);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
|
Operand eSizeOp = Const(eSize);
|
||||||
|
Operand zeroL = Const(0L);
|
||||||
|
Operand negOneL = Const(-1L);
|
||||||
|
|
||||||
|
Operand sar = context.ShiftRightSI(op, shift);
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), sar);
|
||||||
|
|
||||||
|
context.BranchIf(lblEnd, shift, eSizeOp, Comparison.Less);
|
||||||
|
Operand isLess = context.ICompareLess(op, zeroL);
|
||||||
|
context.Copy(res, context.ConditionalSelect(isLess, negOneL, zeroL));
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lblEnd);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// shift := [1, 128]; eSize := {8, 16, 32, 64}.
|
||||||
|
// ulong UnsignedShrReg(ulong op, int shift, bool round, int eSize);
|
||||||
|
private static Operand EmitUnsignedShrReg(ArmEmitterContext context, Operand op, Operand shift, bool round, int eSize)
|
||||||
|
{
|
||||||
|
if (round)
|
||||||
|
{
|
||||||
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
|
Operand zeroUL = Const(0UL);
|
||||||
|
Operand one = Const(1);
|
||||||
|
Operand oneUL = Const(1UL);
|
||||||
|
Operand eSizeMaxOp = Const(64);
|
||||||
|
Operand oneShl63UL = Const(1UL << 63);
|
||||||
|
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), zeroUL);
|
||||||
|
|
||||||
|
context.BranchIf(lblEnd, shift, eSizeMaxOp, Comparison.Greater);
|
||||||
|
Operand roundConst = context.ShiftLeft(oneUL, context.Subtract(shift, one));
|
||||||
|
Operand add = context.Add(op, roundConst);
|
||||||
|
Operand shr = context.ShiftRightUI(add, shift);
|
||||||
|
Operand isEqual = context.ICompareEqual(shift, eSizeMaxOp);
|
||||||
|
context.Copy(res, context.ConditionalSelect(isEqual, zeroUL, shr));
|
||||||
|
if (eSize == 64)
|
||||||
|
{
|
||||||
|
context.BranchIf(lblEnd, add, op, Comparison.GreaterOrEqualUI);
|
||||||
|
Operand right = context.BitwiseOr(shr, context.ShiftRightUI(oneShl63UL, context.Subtract(shift, one)));
|
||||||
|
context.Copy(res, context.ConditionalSelect(isEqual, oneUL, right));
|
||||||
|
}
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lblEnd);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Operand lblEnd = Label();
|
||||||
|
|
||||||
|
Operand eSizeOp = Const(eSize);
|
||||||
|
Operand zeroUL = Const(0UL);
|
||||||
|
|
||||||
|
Operand shr = context.ShiftRightUI(op, shift);
|
||||||
|
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), shr);
|
||||||
|
|
||||||
|
context.BranchIf(lblEnd, shift, eSizeOp, Comparison.Less);
|
||||||
|
context.Copy(res, zeroUL);
|
||||||
|
context.Branch(lblEnd);
|
||||||
|
|
||||||
|
context.MarkLabel(lblEnd);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using ARMeilleure.Decoders;
|
using ARMeilleure.Decoders;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@@ -378,7 +379,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt));
|
context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt));
|
||||||
|
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
SetFpFlag(context, FPState.QcFlag, Const(1));
|
||||||
|
|
||||||
context.MarkLabel(lblNoSat);
|
context.MarkLabel(lblNoSat);
|
||||||
|
|
||||||
|
@@ -15,11 +15,6 @@ namespace ARMeilleure.Instructions
|
|||||||
private const int DczSizeLog2 = 4; // Log2 size in words
|
private const int DczSizeLog2 = 4; // Log2 size in words
|
||||||
public const int DczSizeInBytes = 4 << DczSizeLog2;
|
public const int DczSizeInBytes = 4 << DczSizeLog2;
|
||||||
|
|
||||||
public static void Hint(ArmEmitterContext context)
|
|
||||||
{
|
|
||||||
// Execute as no-op.
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Isb(ArmEmitterContext context)
|
public static void Isb(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
// Execute as no-op.
|
// Execute as no-op.
|
||||||
@@ -36,8 +31,8 @@ namespace ARMeilleure.Instructions
|
|||||||
case 0b11_011_0000_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)); break;
|
case 0b11_011_0000_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)); break;
|
||||||
case 0b11_011_0000_0000_111: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)); break;
|
case 0b11_011_0000_0000_111: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)); break;
|
||||||
case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
|
case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
|
||||||
case 0b11_011_0100_0100_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcr)); break;
|
case 0b11_011_0100_0100_000: EmitGetFpcr(context); return;
|
||||||
case 0b11_011_0100_0100_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpsr)); break;
|
case 0b11_011_0100_0100_001: EmitGetFpsr(context); return;
|
||||||
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)); break;
|
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)); break;
|
||||||
case 0b11_011_1101_0000_011: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)); break;
|
case 0b11_011_1101_0000_011: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)); break;
|
||||||
case 0b11_011_1110_0000_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)); break;
|
case 0b11_011_1110_0000_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)); break;
|
||||||
@@ -59,8 +54,8 @@ namespace ARMeilleure.Instructions
|
|||||||
switch (GetPackedId(op))
|
switch (GetPackedId(op))
|
||||||
{
|
{
|
||||||
case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
|
case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
|
||||||
case 0b11_011_0100_0100_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)); break;
|
case 0b11_011_0100_0100_000: EmitSetFpcr(context); return;
|
||||||
case 0b11_011_0100_0100_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)); break;
|
case 0b11_011_0100_0100_001: EmitSetFpsr(context); return;
|
||||||
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)); break;
|
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)); break;
|
||||||
|
|
||||||
default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||||
@@ -126,39 +121,91 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
|
|
||||||
Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
Operand nzcv = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
||||||
Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
|
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
|
||||||
Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
|
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
|
||||||
Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));
|
nzcv = context.BitwiseOr(nzcv, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
|
||||||
|
|
||||||
Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
|
SetIntOrZR(context, op.Rt, nzcv);
|
||||||
|
}
|
||||||
|
|
||||||
SetIntOrZR(context, op.Rt, nzcvSh);
|
private static void EmitGetFpcr(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
|
|
||||||
|
Operand fpcr = Const(0);
|
||||||
|
|
||||||
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
|
||||||
|
{
|
||||||
|
fpcr = context.BitwiseOr(fpcr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetIntOrZR(context, op.Rt, fpcr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitGetFpsr(ArmEmitterContext context)
|
||||||
|
{
|
||||||
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
|
|
||||||
|
Operand fpsr = Const(0);
|
||||||
|
|
||||||
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
|
||||||
|
{
|
||||||
|
fpsr = context.BitwiseOr(fpsr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SetIntOrZR(context, op.Rt, fpsr);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitSetNzcv(ArmEmitterContext context)
|
private static void EmitSetNzcv(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
|
|
||||||
Operand t = GetIntOrZR(context, op.Rt);
|
Operand nzcv = GetIntOrZR(context, op.Rt);
|
||||||
t = context.ConvertI64ToI32(t);
|
nzcv = context.ConvertI64ToI32(nzcv);
|
||||||
|
|
||||||
Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag));
|
SetFlag(context, PState.VFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.VFlag)), Const(1)));
|
||||||
v = context.BitwiseAnd (v, Const(1));
|
SetFlag(context, PState.CFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.CFlag)), Const(1)));
|
||||||
|
SetFlag(context, PState.ZFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.ZFlag)), Const(1)));
|
||||||
|
SetFlag(context, PState.NFlag, context.BitwiseAnd(context.ShiftRightUI(nzcv, Const((int)PState.NFlag)), Const(1)));
|
||||||
|
}
|
||||||
|
|
||||||
Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag));
|
private static void EmitSetFpcr(ArmEmitterContext context)
|
||||||
c = context.BitwiseAnd (c, Const(1));
|
{
|
||||||
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
|
|
||||||
Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag));
|
Operand fpcr = GetIntOrZR(context, op.Rt);
|
||||||
z = context.BitwiseAnd (z, Const(1));
|
fpcr = context.ConvertI64ToI32(fpcr);
|
||||||
|
|
||||||
Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag));
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
n = context.BitwiseAnd (n, Const(1));
|
{
|
||||||
|
if (FPCR.Mask.HasFlag((FPCR)(1u << flag)))
|
||||||
|
{
|
||||||
|
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpcr, Const(flag)), Const(1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SetFlag(context, PState.VFlag, v);
|
private static void EmitSetFpsr(ArmEmitterContext context)
|
||||||
SetFlag(context, PState.CFlag, c);
|
{
|
||||||
SetFlag(context, PState.ZFlag, z);
|
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||||
SetFlag(context, PState.NFlag, n);
|
|
||||||
|
Operand fpsr = GetIntOrZR(context, op.Rt);
|
||||||
|
fpsr = context.ConvertI64ToI32(fpsr);
|
||||||
|
|
||||||
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
if (FPSR.Mask.HasFlag((FPSR)(1u << flag)))
|
||||||
|
{
|
||||||
|
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpsr, Const(flag)), Const(1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -169,14 +169,11 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
Operand spsr = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag));
|
||||||
Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag));
|
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)));
|
||||||
Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag));
|
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)));
|
||||||
Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag));
|
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)));
|
||||||
Operand qSh = context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag));
|
spsr = context.BitwiseOr(spsr, context.ShiftLeft(GetFlag(PState.QFlag), Const((int)PState.QFlag)));
|
||||||
|
|
||||||
Operand spsr = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
|
|
||||||
spsr = context.BitwiseOr(spsr, qSh);
|
|
||||||
|
|
||||||
// TODO: Remaining flags.
|
// TODO: Remaining flags.
|
||||||
|
|
||||||
@@ -200,8 +197,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
EmitSetNzcv(context, value);
|
EmitSetNzcv(context, value);
|
||||||
|
|
||||||
Operand q = context.ShiftRightUI(value, Const((int)PState.QFlag));
|
Operand q = context.BitwiseAnd(context.ShiftRightUI(value, Const((int)PState.QFlag)), Const(1));
|
||||||
q = context.BitwiseAnd(q, Const(1));
|
|
||||||
|
|
||||||
SetFlag(context, PState.QFlag, q);
|
SetFlag(context, PState.QFlag, q);
|
||||||
}
|
}
|
||||||
@@ -284,17 +280,10 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
|
private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
|
||||||
{
|
{
|
||||||
Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag));
|
Operand v = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.VFlag)), Const(1));
|
||||||
v = context.BitwiseAnd(v, Const(1));
|
Operand c = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.CFlag)), Const(1));
|
||||||
|
Operand z = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.ZFlag)), Const(1));
|
||||||
Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag));
|
Operand n = context.BitwiseAnd(context.ShiftRightUI(t, Const((int)PState.NFlag)), Const(1));
|
||||||
c = context.BitwiseAnd(c, Const(1));
|
|
||||||
|
|
||||||
Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag));
|
|
||||||
z = context.BitwiseAnd(z, Const(1));
|
|
||||||
|
|
||||||
Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag));
|
|
||||||
n = context.BitwiseAnd(n, Const(1));
|
|
||||||
|
|
||||||
SetFlag(context, PState.VFlag, v);
|
SetFlag(context, PState.VFlag, v);
|
||||||
SetFlag(context, PState.CFlag, c);
|
SetFlag(context, PState.CFlag, c);
|
||||||
@@ -306,42 +295,32 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
||||||
|
|
||||||
Operand vSh = context.ShiftLeft(GetFpFlag(FPState.VFlag), Const((int)FPState.VFlag));
|
Operand fpscr = Const(0);
|
||||||
Operand cSh = context.ShiftLeft(GetFpFlag(FPState.CFlag), Const((int)FPState.CFlag));
|
|
||||||
Operand zSh = context.ShiftLeft(GetFpFlag(FPState.ZFlag), Const((int)FPState.ZFlag));
|
|
||||||
Operand nSh = context.ShiftLeft(GetFpFlag(FPState.NFlag), Const((int)FPState.NFlag));
|
|
||||||
|
|
||||||
Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh));
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
|
||||||
|
{
|
||||||
|
fpscr = context.BitwiseOr(fpscr, context.ShiftLeft(GetFpFlag((FPState)flag), Const(flag)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Operand fpscr = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr)));
|
SetIntA32(context, op.Rt, fpscr);
|
||||||
|
|
||||||
SetIntA32(context, op.Rt, context.BitwiseOr(nzcvSh, fpscr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitSetFpscr(ArmEmitterContext context)
|
private static void EmitSetFpscr(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
||||||
|
|
||||||
Operand t = GetIntA32(context, op.Rt);
|
Operand fpscr = GetIntA32(context, op.Rt);
|
||||||
|
|
||||||
Operand v = context.ShiftRightUI(t, Const((int)FPState.VFlag));
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
v = context.BitwiseAnd(v, Const(1));
|
{
|
||||||
|
if (FPSCR.Mask.HasFlag((FPSCR)(1u << flag)))
|
||||||
Operand c = context.ShiftRightUI(t, Const((int)FPState.CFlag));
|
{
|
||||||
c = context.BitwiseAnd(c, Const(1));
|
SetFpFlag(context, (FPState)flag, context.BitwiseAnd(context.ShiftRightUI(fpscr, Const(flag)), Const(1)));
|
||||||
|
}
|
||||||
Operand z = context.ShiftRightUI(t, Const((int)FPState.ZFlag));
|
}
|
||||||
z = context.BitwiseAnd(z, Const(1));
|
|
||||||
|
|
||||||
Operand n = context.ShiftRightUI(t, Const((int)FPState.NFlag));
|
|
||||||
n = context.BitwiseAnd(n, Const(1));
|
|
||||||
|
|
||||||
SetFpFlag(context, FPState.VFlag, v);
|
|
||||||
SetFpFlag(context, FPState.CFlag, c);
|
|
||||||
SetFpFlag(context, FPState.ZFlag, z);
|
|
||||||
SetFpFlag(context, FPState.NFlag, n);
|
|
||||||
|
|
||||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr)), t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -45,6 +45,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Dsb,
|
Dsb,
|
||||||
Eon,
|
Eon,
|
||||||
Eor,
|
Eor,
|
||||||
|
Esb,
|
||||||
Extr,
|
Extr,
|
||||||
Hint,
|
Hint,
|
||||||
Isb,
|
Isb,
|
||||||
@@ -81,6 +82,9 @@ namespace ARMeilleure.Instructions
|
|||||||
Sbcs,
|
Sbcs,
|
||||||
Sbfm,
|
Sbfm,
|
||||||
Sdiv,
|
Sdiv,
|
||||||
|
Sel,
|
||||||
|
Sev,
|
||||||
|
Sevl,
|
||||||
Shsub8,
|
Shsub8,
|
||||||
Smaddl,
|
Smaddl,
|
||||||
Smsubl,
|
Smsubl,
|
||||||
@@ -104,12 +108,16 @@ namespace ARMeilleure.Instructions
|
|||||||
Sys,
|
Sys,
|
||||||
Tbnz,
|
Tbnz,
|
||||||
Tbz,
|
Tbz,
|
||||||
|
Tsb,
|
||||||
Ubfm,
|
Ubfm,
|
||||||
Udiv,
|
Udiv,
|
||||||
Umaddl,
|
Umaddl,
|
||||||
Umsubl,
|
Umsubl,
|
||||||
Umulh,
|
Umulh,
|
||||||
Und,
|
Und,
|
||||||
|
Wfe,
|
||||||
|
Wfi,
|
||||||
|
Yield,
|
||||||
|
|
||||||
// FP & SIMD (AArch64)
|
// FP & SIMD (AArch64)
|
||||||
Abs_S,
|
Abs_S,
|
||||||
@@ -519,6 +527,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Revsh,
|
Revsh,
|
||||||
Rsb,
|
Rsb,
|
||||||
Rsc,
|
Rsc,
|
||||||
|
Sadd8,
|
||||||
Sbfx,
|
Sbfx,
|
||||||
Shadd8,
|
Shadd8,
|
||||||
Smla__,
|
Smla__,
|
||||||
@@ -529,6 +538,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Smmls,
|
Smmls,
|
||||||
Smul__,
|
Smul__,
|
||||||
Smmul,
|
Smmul,
|
||||||
|
Ssub8,
|
||||||
Stl,
|
Stl,
|
||||||
Stlb,
|
Stlb,
|
||||||
Stlex,
|
Stlex,
|
||||||
@@ -550,6 +560,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Teq,
|
Teq,
|
||||||
Trap,
|
Trap,
|
||||||
Tst,
|
Tst,
|
||||||
|
Uadd8,
|
||||||
Ubfx,
|
Ubfx,
|
||||||
Uhadd8,
|
Uhadd8,
|
||||||
Uhsub8,
|
Uhsub8,
|
||||||
@@ -558,6 +569,7 @@ namespace ARMeilleure.Instructions
|
|||||||
Umull,
|
Umull,
|
||||||
Usat,
|
Usat,
|
||||||
Usat16,
|
Usat16,
|
||||||
|
Usub8,
|
||||||
Uxtb,
|
Uxtb,
|
||||||
Uxtb16,
|
Uxtb16,
|
||||||
Uxth,
|
Uxth,
|
||||||
@@ -636,6 +648,10 @@ namespace ARMeilleure.Instructions
|
|||||||
Vrev,
|
Vrev,
|
||||||
Vrhadd,
|
Vrhadd,
|
||||||
Vrint,
|
Vrint,
|
||||||
|
Vrinta,
|
||||||
|
Vrintm,
|
||||||
|
Vrintn,
|
||||||
|
Vrintp,
|
||||||
Vrintx,
|
Vrintx,
|
||||||
Vrshr,
|
Vrshr,
|
||||||
Vrshrn,
|
Vrshrn,
|
||||||
|
@@ -72,29 +72,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return (ulong)GetContext().DczidEl0;
|
return (ulong)GetContext().DczidEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ulong GetFpcr()
|
|
||||||
{
|
|
||||||
return (ulong)GetContext().Fpcr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool GetFpcrFz()
|
|
||||||
{
|
|
||||||
return (GetContext().Fpcr & FPCR.Fz) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong GetFpsr()
|
|
||||||
{
|
|
||||||
return (ulong)GetContext().Fpsr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static uint GetFpscr()
|
|
||||||
{
|
|
||||||
ExecutionContext context = GetContext();
|
|
||||||
|
|
||||||
return (uint)(context.Fpsr & FPSR.A32Mask & ~FPSR.Nzcv) |
|
|
||||||
(uint)(context.Fpcr & FPCR.A32Mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong GetTpidrEl0()
|
public static ulong GetTpidrEl0()
|
||||||
{
|
{
|
||||||
return (ulong)GetContext().TpidrEl0;
|
return (ulong)GetContext().TpidrEl0;
|
||||||
@@ -130,29 +107,6 @@ namespace ARMeilleure.Instructions
|
|||||||
return GetContext().CntvctEl0;
|
return GetContext().CntvctEl0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SetFpcr(ulong value)
|
|
||||||
{
|
|
||||||
GetContext().Fpcr = (FPCR)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetFpsr(ulong value)
|
|
||||||
{
|
|
||||||
GetContext().Fpsr = (FPSR)value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetFpsrQc()
|
|
||||||
{
|
|
||||||
GetContext().Fpsr |= FPSR.Qc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetFpscr(uint fpscr)
|
|
||||||
{
|
|
||||||
ExecutionContext context = GetContext();
|
|
||||||
|
|
||||||
context.Fpsr = FPSR.A32Mask & (FPSR)fpscr;
|
|
||||||
context.Fpcr = FPCR.A32Mask & (FPCR)fpscr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetTpidrEl0(ulong value)
|
public static void SetTpidrEl0(ulong value)
|
||||||
{
|
{
|
||||||
GetContext().TpidrEl0 = (long)value;
|
GetContext().TpidrEl0 = (long)value;
|
||||||
|
@@ -5,287 +5,6 @@ namespace ARMeilleure.Instructions
|
|||||||
{
|
{
|
||||||
static class SoftFallback
|
static class SoftFallback
|
||||||
{
|
{
|
||||||
#region "ShlReg"
|
|
||||||
public static long SignedShlReg(long value, long shift, bool round, int size)
|
|
||||||
{
|
|
||||||
int eSize = 8 << size;
|
|
||||||
|
|
||||||
int shiftLsB = (sbyte)shift;
|
|
||||||
|
|
||||||
if (shiftLsB < 0)
|
|
||||||
{
|
|
||||||
return SignedShrReg(value, -shiftLsB, round, eSize);
|
|
||||||
}
|
|
||||||
else if (shiftLsB > 0)
|
|
||||||
{
|
|
||||||
if (shiftLsB >= eSize)
|
|
||||||
{
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value << shiftLsB;
|
|
||||||
}
|
|
||||||
else /* if (shiftLsB == 0) */
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong UnsignedShlReg(ulong value, ulong shift, bool round, int size)
|
|
||||||
{
|
|
||||||
int eSize = 8 << size;
|
|
||||||
|
|
||||||
int shiftLsB = (sbyte)shift;
|
|
||||||
|
|
||||||
if (shiftLsB < 0)
|
|
||||||
{
|
|
||||||
return UnsignedShrReg(value, -shiftLsB, round, eSize);
|
|
||||||
}
|
|
||||||
else if (shiftLsB > 0)
|
|
||||||
{
|
|
||||||
if (shiftLsB >= eSize)
|
|
||||||
{
|
|
||||||
return 0UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value << shiftLsB;
|
|
||||||
}
|
|
||||||
else /* if (shiftLsB == 0) */
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static long SignedShlRegSatQ(long value, long shift, bool round, int size)
|
|
||||||
{
|
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
|
||||||
|
|
||||||
int eSize = 8 << size;
|
|
||||||
|
|
||||||
int shiftLsB = (sbyte)shift;
|
|
||||||
|
|
||||||
if (shiftLsB < 0)
|
|
||||||
{
|
|
||||||
return SignedShrReg(value, -shiftLsB, round, eSize);
|
|
||||||
}
|
|
||||||
else if (shiftLsB > 0)
|
|
||||||
{
|
|
||||||
if (shiftLsB >= eSize)
|
|
||||||
{
|
|
||||||
return SignedSignSatQ(value, eSize, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eSize == 64)
|
|
||||||
{
|
|
||||||
long shl = value << shiftLsB;
|
|
||||||
long shr = shl >> shiftLsB;
|
|
||||||
|
|
||||||
if (shr != value)
|
|
||||||
{
|
|
||||||
return SignedSignSatQ(value, eSize, context);
|
|
||||||
}
|
|
||||||
else /* if (shr == value) */
|
|
||||||
{
|
|
||||||
return shl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* if (eSize != 64) */
|
|
||||||
{
|
|
||||||
return SignedSrcSignedDstSatQ(value << shiftLsB, size); // InstEmitSimdHelper.EmitSignedSrcSatQ(signedDst: true).
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* if (shiftLsB == 0) */
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong UnsignedShlRegSatQ(ulong value, ulong shift, bool round, int size)
|
|
||||||
{
|
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
|
||||||
|
|
||||||
int eSize = 8 << size;
|
|
||||||
|
|
||||||
int shiftLsB = (sbyte)shift;
|
|
||||||
|
|
||||||
if (shiftLsB < 0)
|
|
||||||
{
|
|
||||||
return UnsignedShrReg(value, -shiftLsB, round, eSize);
|
|
||||||
}
|
|
||||||
else if (shiftLsB > 0)
|
|
||||||
{
|
|
||||||
if (shiftLsB >= eSize)
|
|
||||||
{
|
|
||||||
return UnsignedSignSatQ(value, eSize, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eSize == 64)
|
|
||||||
{
|
|
||||||
ulong shl = value << shiftLsB;
|
|
||||||
ulong shr = shl >> shiftLsB;
|
|
||||||
|
|
||||||
if (shr != value)
|
|
||||||
{
|
|
||||||
return UnsignedSignSatQ(value, eSize, context);
|
|
||||||
}
|
|
||||||
else /* if (shr == value) */
|
|
||||||
{
|
|
||||||
return shl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* if (eSize != 64) */
|
|
||||||
{
|
|
||||||
return UnsignedSrcUnsignedDstSatQ(value << shiftLsB, size); // InstEmitSimdHelper.EmitUnsignedSrcSatQ(signedDst: false).
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* if (shiftLsB == 0) */
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long SignedShrReg(long value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
|
|
||||||
{
|
|
||||||
if (round)
|
|
||||||
{
|
|
||||||
if (shift >= eSize)
|
|
||||||
{
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
long roundConst = 1L << (shift - 1);
|
|
||||||
|
|
||||||
long add = value + roundConst;
|
|
||||||
|
|
||||||
if (eSize == 64)
|
|
||||||
{
|
|
||||||
if ((~value & (value ^ add)) < 0L)
|
|
||||||
{
|
|
||||||
return (long)((ulong)add >> shift);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return add >> shift;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* if (eSize != 64) */
|
|
||||||
{
|
|
||||||
return add >> shift;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* if (!round) */
|
|
||||||
{
|
|
||||||
if (shift >= eSize)
|
|
||||||
{
|
|
||||||
if (value < 0L)
|
|
||||||
{
|
|
||||||
return -1L;
|
|
||||||
}
|
|
||||||
else /* if (value >= 0L) */
|
|
||||||
{
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return value >> shift;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ulong UnsignedShrReg(ulong value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
|
|
||||||
{
|
|
||||||
if (round)
|
|
||||||
{
|
|
||||||
if (shift > 64)
|
|
||||||
{
|
|
||||||
return 0UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong roundConst = 1UL << (shift - 1);
|
|
||||||
|
|
||||||
ulong add = value + roundConst;
|
|
||||||
|
|
||||||
if (eSize == 64)
|
|
||||||
{
|
|
||||||
if ((add < value) && (add < roundConst))
|
|
||||||
{
|
|
||||||
if (shift == 64)
|
|
||||||
{
|
|
||||||
return 1UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (shift == 64)
|
|
||||||
{
|
|
||||||
return 0UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return add >> shift;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* if (eSize != 64) */
|
|
||||||
{
|
|
||||||
if (shift == 64)
|
|
||||||
{
|
|
||||||
return 0UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return add >> shift;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else /* if (!round) */
|
|
||||||
{
|
|
||||||
if (shift >= eSize)
|
|
||||||
{
|
|
||||||
return 0UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value >> shift;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long SignedSignSatQ(long op, int eSize, ExecutionContext context) // eSize := {8, 16, 32, 64}.
|
|
||||||
{
|
|
||||||
long tMaxValue = (1L << (eSize - 1)) - 1L;
|
|
||||||
long tMinValue = -(1L << (eSize - 1));
|
|
||||||
|
|
||||||
if (op > 0L)
|
|
||||||
{
|
|
||||||
context.Fpsr |= FPSR.Qc;
|
|
||||||
|
|
||||||
return tMaxValue;
|
|
||||||
}
|
|
||||||
else if (op < 0L)
|
|
||||||
{
|
|
||||||
context.Fpsr |= FPSR.Qc;
|
|
||||||
|
|
||||||
return tMinValue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0L;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ulong UnsignedSignSatQ(ulong op, int eSize, ExecutionContext context) // eSize := {8, 16, 32, 64}.
|
|
||||||
{
|
|
||||||
ulong tMaxValue = ulong.MaxValue >> (64 - eSize);
|
|
||||||
|
|
||||||
if (op > 0UL)
|
|
||||||
{
|
|
||||||
context.Fpsr |= FPSR.Qc;
|
|
||||||
|
|
||||||
return tMaxValue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0UL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region "ShrImm64"
|
#region "ShrImm64"
|
||||||
public static long SignedShrImm64(long value, long roundConst, int shift)
|
public static long SignedShrImm64(long value, long roundConst, int shift)
|
||||||
{
|
{
|
||||||
@@ -372,76 +91,6 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Rounding"
|
|
||||||
public static double Round(double value)
|
|
||||||
{
|
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
|
||||||
|
|
||||||
FPRoundingMode roundMode = context.Fpcr.GetRoundingMode();
|
|
||||||
|
|
||||||
if (roundMode == FPRoundingMode.ToNearest)
|
|
||||||
{
|
|
||||||
return Math.Round(value); // even
|
|
||||||
}
|
|
||||||
else if (roundMode == FPRoundingMode.TowardsPlusInfinity)
|
|
||||||
{
|
|
||||||
return Math.Ceiling(value);
|
|
||||||
}
|
|
||||||
else if (roundMode == FPRoundingMode.TowardsMinusInfinity)
|
|
||||||
{
|
|
||||||
return Math.Floor(value);
|
|
||||||
}
|
|
||||||
else /* if (roundMode == FPRoundingMode.TowardsZero) */
|
|
||||||
{
|
|
||||||
return Math.Truncate(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float RoundF(float value)
|
|
||||||
{
|
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
|
||||||
|
|
||||||
FPRoundingMode roundMode = context.Fpcr.GetRoundingMode();
|
|
||||||
|
|
||||||
if (roundMode == FPRoundingMode.ToNearest)
|
|
||||||
{
|
|
||||||
return MathF.Round(value); // even
|
|
||||||
}
|
|
||||||
else if (roundMode == FPRoundingMode.TowardsPlusInfinity)
|
|
||||||
{
|
|
||||||
return MathF.Ceiling(value);
|
|
||||||
}
|
|
||||||
else if (roundMode == FPRoundingMode.TowardsMinusInfinity)
|
|
||||||
{
|
|
||||||
return MathF.Floor(value);
|
|
||||||
}
|
|
||||||
else /* if (roundMode == FPRoundingMode.TowardsZero) */
|
|
||||||
{
|
|
||||||
return MathF.Truncate(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int FloatToInt32(float value)
|
|
||||||
{
|
|
||||||
return SatF32ToS32(RoundF(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int DoubleToInt32(double value)
|
|
||||||
{
|
|
||||||
return SatF64ToS32(Round(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static uint FloatToUInt32(float value)
|
|
||||||
{
|
|
||||||
return SatF32ToU32(RoundF(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static uint DoubleToUInt32(double value)
|
|
||||||
{
|
|
||||||
return SatF64ToU32(Round(value));
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region "Saturation"
|
#region "Saturation"
|
||||||
public static int SatF32ToS32(float value)
|
public static int SatF32ToS32(float value)
|
||||||
{
|
{
|
||||||
@@ -508,55 +157,6 @@ namespace ARMeilleure.Instructions
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Saturating"
|
|
||||||
private static long SignedSrcSignedDstSatQ(long op, int size)
|
|
||||||
{
|
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
|
||||||
|
|
||||||
int eSize = 8 << size;
|
|
||||||
|
|
||||||
long tMaxValue = (1L << (eSize - 1)) - 1L;
|
|
||||||
long tMinValue = -(1L << (eSize - 1));
|
|
||||||
|
|
||||||
if (op > tMaxValue)
|
|
||||||
{
|
|
||||||
context.Fpsr |= FPSR.Qc;
|
|
||||||
|
|
||||||
return tMaxValue;
|
|
||||||
}
|
|
||||||
else if (op < tMinValue)
|
|
||||||
{
|
|
||||||
context.Fpsr |= FPSR.Qc;
|
|
||||||
|
|
||||||
return tMinValue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size)
|
|
||||||
{
|
|
||||||
ExecutionContext context = NativeInterface.GetContext();
|
|
||||||
|
|
||||||
int eSize = 8 << size;
|
|
||||||
|
|
||||||
ulong tMaxValue = (1UL << eSize) - 1UL;
|
|
||||||
|
|
||||||
if (op > tMaxValue)
|
|
||||||
{
|
|
||||||
context.Fpsr |= FPSR.Qc;
|
|
||||||
|
|
||||||
return tMaxValue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region "Count"
|
#region "Count"
|
||||||
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
|
||||||
{
|
{
|
||||||
|
@@ -12,8 +12,8 @@ namespace ARMeilleure.Instructions
|
|||||||
RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable();
|
RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static readonly byte[] RecipEstimateTable;
|
public static readonly byte[] RecipEstimateTable;
|
||||||
internal static readonly byte[] RecipSqrtEstimateTable;
|
public static readonly byte[] RecipSqrtEstimateTable;
|
||||||
|
|
||||||
private static byte[] BuildRecipEstimateTable()
|
private static byte[] BuildRecipEstimateTable()
|
||||||
{
|
{
|
||||||
@@ -94,6 +94,13 @@ namespace ARMeilleure.Instructions
|
|||||||
context.Fpsr |= (FPSR)(1 << (int)exc);
|
context.Fpsr |= (FPSR)(1 << (int)exc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FPRoundingMode GetRoundingMode(this FPCR fpcr)
|
||||||
|
{
|
||||||
|
const int RModeShift = 22;
|
||||||
|
|
||||||
|
return (FPRoundingMode)(((uint)fpcr >> RModeShift) & 3u);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class SoftFloat16
|
static class SoftFloat16
|
||||||
|
@@ -47,6 +47,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
X86Divps,
|
X86Divps,
|
||||||
X86Divsd,
|
X86Divsd,
|
||||||
X86Divss,
|
X86Divss,
|
||||||
|
X86Gf2p8affineqb,
|
||||||
X86Haddpd,
|
X86Haddpd,
|
||||||
X86Haddps,
|
X86Haddps,
|
||||||
X86Insertps,
|
X86Insertps,
|
||||||
|
@@ -22,6 +22,7 @@ namespace ARMeilleure
|
|||||||
public static bool UseAesniIfAvailable { get; set; } = true;
|
public static bool UseAesniIfAvailable { get; set; } = true;
|
||||||
public static bool UsePclmulqdqIfAvailable { get; set; } = true;
|
public static bool UsePclmulqdqIfAvailable { get; set; } = true;
|
||||||
public static bool UseShaIfAvailable { get; set; } = true;
|
public static bool UseShaIfAvailable { get; set; } = true;
|
||||||
|
public static bool UseGfniIfAvailable { get; set; } = true;
|
||||||
|
|
||||||
public static bool ForceLegacySse
|
public static bool ForceLegacySse
|
||||||
{
|
{
|
||||||
@@ -42,5 +43,6 @@ namespace ARMeilleure
|
|||||||
internal static bool UseAesni => UseAesniIfAvailable && HardwareCapabilities.SupportsAesni;
|
internal static bool UseAesni => UseAesniIfAvailable && HardwareCapabilities.SupportsAesni;
|
||||||
internal static bool UsePclmulqdq => UsePclmulqdqIfAvailable && HardwareCapabilities.SupportsPclmulqdq;
|
internal static bool UsePclmulqdq => UsePclmulqdqIfAvailable && HardwareCapabilities.SupportsPclmulqdq;
|
||||||
internal static bool UseSha => UseShaIfAvailable && HardwareCapabilities.SupportsSha;
|
internal static bool UseSha => UseShaIfAvailable && HardwareCapabilities.SupportsSha;
|
||||||
|
internal static bool UseGfni => UseGfniIfAvailable && HardwareCapabilities.SupportsGfni;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -36,10 +36,25 @@ namespace ARMeilleure.State
|
|||||||
set => _nativeContext.SetPstate(value);
|
set => _nativeContext.SetPstate(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FPCR Fpcr { get; set; }
|
public FPSR Fpsr
|
||||||
public FPSR Fpsr { get; set; }
|
{
|
||||||
|
get => (FPSR)_nativeContext.GetFPState((uint)FPSR.Mask);
|
||||||
|
set => _nativeContext.SetFPState((uint)value, (uint)FPSR.Mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FPCR Fpcr
|
||||||
|
{
|
||||||
|
get => (FPCR)_nativeContext.GetFPState((uint)FPCR.Mask);
|
||||||
|
set => _nativeContext.SetFPState((uint)value, (uint)FPCR.Mask);
|
||||||
|
}
|
||||||
public FPCR StandardFpcrValue => (Fpcr & (FPCR.Ahp)) | FPCR.Dn | FPCR.Fz;
|
public FPCR StandardFpcrValue => (Fpcr & (FPCR.Ahp)) | FPCR.Dn | FPCR.Fz;
|
||||||
|
|
||||||
|
public FPSCR Fpscr
|
||||||
|
{
|
||||||
|
get => (FPSCR)_nativeContext.GetFPState((uint)FPSCR.Mask);
|
||||||
|
set => _nativeContext.SetFPState((uint)value, (uint)FPSCR.Mask);
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsAarch32 { get; set; }
|
public bool IsAarch32 { get; set; }
|
||||||
|
|
||||||
internal ExecutionMode ExecutionMode
|
internal ExecutionMode ExecutionMode
|
||||||
|
@@ -5,21 +5,18 @@ namespace ARMeilleure.State
|
|||||||
[Flags]
|
[Flags]
|
||||||
public enum FPCR : uint
|
public enum FPCR : uint
|
||||||
{
|
{
|
||||||
|
Ioe = 1u << 8,
|
||||||
|
Dze = 1u << 9,
|
||||||
|
Ofe = 1u << 10,
|
||||||
Ufe = 1u << 11,
|
Ufe = 1u << 11,
|
||||||
|
Ixe = 1u << 12,
|
||||||
|
Ide = 1u << 15,
|
||||||
|
RMode0 = 1u << 22,
|
||||||
|
RMode1 = 1u << 23,
|
||||||
Fz = 1u << 24,
|
Fz = 1u << 24,
|
||||||
Dn = 1u << 25,
|
Dn = 1u << 25,
|
||||||
Ahp = 1u << 26,
|
Ahp = 1u << 26,
|
||||||
|
|
||||||
A32Mask = 0x07FF9F00u
|
Mask = Ahp | Dn | Fz | RMode1 | RMode0 | Ide | Ixe | Ufe | Ofe | Dze | Ioe // 0x07C09F00u
|
||||||
}
|
|
||||||
|
|
||||||
public static class FPCRExtensions
|
|
||||||
{
|
|
||||||
private const int RModeShift = 22;
|
|
||||||
|
|
||||||
public static FPRoundingMode GetRoundingMode(this FPCR fpcr)
|
|
||||||
{
|
|
||||||
return (FPRoundingMode)(((int)fpcr >> RModeShift) & 3);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
ARMeilleure/State/FPSCR.cs
Normal file
15
ARMeilleure/State/FPSCR.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ARMeilleure.State
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum FPSCR : uint
|
||||||
|
{
|
||||||
|
V = 1u << 28,
|
||||||
|
C = 1u << 29,
|
||||||
|
Z = 1u << 30,
|
||||||
|
N = 1u << 31,
|
||||||
|
|
||||||
|
Mask = N | Z | C | V | FPSR.Mask | FPCR.Mask // 0xFFC09F9Fu
|
||||||
|
}
|
||||||
|
}
|
@@ -5,11 +5,14 @@ namespace ARMeilleure.State
|
|||||||
[Flags]
|
[Flags]
|
||||||
public enum FPSR : uint
|
public enum FPSR : uint
|
||||||
{
|
{
|
||||||
|
Ioc = 1u << 0,
|
||||||
|
Dzc = 1u << 1,
|
||||||
|
Ofc = 1u << 2,
|
||||||
Ufc = 1u << 3,
|
Ufc = 1u << 3,
|
||||||
|
Ixc = 1u << 4,
|
||||||
|
Idc = 1u << 7,
|
||||||
Qc = 1u << 27,
|
Qc = 1u << 27,
|
||||||
|
|
||||||
Nzcv = (1u << 31) | (1u << 30) | (1u << 29) | (1u << 28),
|
Mask = Qc | Idc | Ixc | Ufc | Ofc | Dzc | Ioc // 0x0800009Fu
|
||||||
|
|
||||||
A32Mask = 0xF800009Fu
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,9 +2,30 @@
|
|||||||
{
|
{
|
||||||
public enum FPState
|
public enum FPState
|
||||||
{
|
{
|
||||||
|
// FPSR Flags.
|
||||||
|
IocFlag = 0,
|
||||||
|
DzcFlag = 1,
|
||||||
|
OfcFlag = 2,
|
||||||
|
UfcFlag = 3,
|
||||||
|
IxcFlag = 4,
|
||||||
|
IdcFlag = 7,
|
||||||
|
QcFlag = 27,
|
||||||
VFlag = 28,
|
VFlag = 28,
|
||||||
CFlag = 29,
|
CFlag = 29,
|
||||||
ZFlag = 30,
|
ZFlag = 30,
|
||||||
NFlag = 31
|
NFlag = 31,
|
||||||
|
|
||||||
|
// FPCR Flags.
|
||||||
|
IoeFlag = 8,
|
||||||
|
DzeFlag = 9,
|
||||||
|
OfeFlag = 10,
|
||||||
|
UfeFlag = 11,
|
||||||
|
IxeFlag = 12,
|
||||||
|
IdeFlag = 15,
|
||||||
|
RMode0Flag = 22,
|
||||||
|
RMode1Flag = 23,
|
||||||
|
FzFlag = 24,
|
||||||
|
DnFlag = 25,
|
||||||
|
AhpFlag = 26
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -140,6 +140,34 @@ namespace ARMeilleure.State
|
|||||||
GetStorage().FpFlags[(int)flag] = value ? 1u : 0u;
|
GetStorage().FpFlags[(int)flag] = value ? 1u : 0u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe uint GetFPState(uint mask = uint.MaxValue)
|
||||||
|
{
|
||||||
|
uint value = 0;
|
||||||
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
uint bit = 1u << flag;
|
||||||
|
|
||||||
|
if ((mask & bit) == bit)
|
||||||
|
{
|
||||||
|
value |= GetStorage().FpFlags[flag] != 0 ? bit : 0u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe void SetFPState(uint value, uint mask = uint.MaxValue)
|
||||||
|
{
|
||||||
|
for (int flag = 0; flag < RegisterConsts.FpFlagsCount; flag++)
|
||||||
|
{
|
||||||
|
uint bit = 1u << flag;
|
||||||
|
|
||||||
|
if ((mask & bit) == bit)
|
||||||
|
{
|
||||||
|
GetStorage().FpFlags[flag] = (value & bit) == bit ? 1u : 0u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int GetCounter() => GetStorage().Counter;
|
public int GetCounter() => GetStorage().Counter;
|
||||||
public void SetCounter(int value) => GetStorage().Counter = value;
|
public void SetCounter(int value) => GetStorage().Counter = value;
|
||||||
|
|
||||||
|
@@ -4,6 +4,10 @@ namespace ARMeilleure.State
|
|||||||
{
|
{
|
||||||
TFlag = 5,
|
TFlag = 5,
|
||||||
EFlag = 9,
|
EFlag = 9,
|
||||||
|
GE0Flag = 16,
|
||||||
|
GE1Flag = 17,
|
||||||
|
GE2Flag = 18,
|
||||||
|
GE3Flag = 19,
|
||||||
QFlag = 27,
|
QFlag = 27,
|
||||||
VFlag = 28,
|
VFlag = 28,
|
||||||
CFlag = 29,
|
CFlag = 29,
|
||||||
|
@@ -109,10 +109,6 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcr)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpsr)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.InvalidateCacheLine)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrroEl0)));
|
||||||
@@ -124,10 +120,6 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
|
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
|
||||||
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
|
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SignalMemoryTracking)));
|
||||||
@@ -151,12 +143,8 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32w)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32w)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32x)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Crc32x)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToInt32))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToUInt32))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToInt32))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToUInt32))); // A32 only.
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)));
|
||||||
@@ -165,8 +153,6 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.PolynomialMult64_128)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.PolynomialMult64_128)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)));
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)));
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)));
|
||||||
@@ -179,8 +165,6 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)));
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)));
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)));
|
||||||
@@ -190,8 +174,6 @@ namespace ARMeilleure.Translation
|
|||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)));
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)));
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)));
|
|
||||||
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64)));
|
SetDelegateInfo(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64)));
|
||||||
|
|
||||||
SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)));
|
SetDelegateInfo(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)));
|
||||||
|
@@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||||
|
|
||||||
private const uint InternalVersion = 3683; //! To be incremented manually for each change to the ARMeilleure project.
|
private const uint InternalVersion = 3710; //! To be incremented manually for each change to the ARMeilleure project.
|
||||||
|
|
||||||
private const string ActualDir = "0";
|
private const string ActualDir = "0";
|
||||||
private const string BackupDir = "1";
|
private const string BackupDir = "1";
|
||||||
@@ -951,7 +951,8 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
return new FeatureInfo(
|
return new FeatureInfo(
|
||||||
(uint)HardwareCapabilities.FeatureInfo1Ecx,
|
(uint)HardwareCapabilities.FeatureInfo1Ecx,
|
||||||
(uint)HardwareCapabilities.FeatureInfo1Edx,
|
(uint)HardwareCapabilities.FeatureInfo1Edx,
|
||||||
(uint)HardwareCapabilities.FeatureInfo7Ebx);
|
(uint)HardwareCapabilities.FeatureInfo7Ebx,
|
||||||
|
(uint)HardwareCapabilities.FeatureInfo7Ecx);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte GetMemoryManagerMode()
|
private static byte GetMemoryManagerMode()
|
||||||
@@ -971,7 +972,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
return osPlatform;
|
return osPlatform;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 54*/)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 58*/)]
|
||||||
private struct OuterHeader
|
private struct OuterHeader
|
||||||
{
|
{
|
||||||
public ulong Magic;
|
public ulong Magic;
|
||||||
@@ -1002,8 +1003,8 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 12*/)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 16*/)]
|
||||||
private record struct FeatureInfo(uint FeatureInfo0, uint FeatureInfo1, uint FeatureInfo2);
|
private record struct FeatureInfo(uint FeatureInfo0, uint FeatureInfo1, uint FeatureInfo2, uint FeatureInfo3);
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 128*/)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 128*/)]
|
||||||
private struct InnerHeader
|
private struct InnerHeader
|
||||||
|
12
README.md
12
README.md
@@ -27,7 +27,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
<img src="https://raw.githubusercontent.com/Ryujinx/Ryujinx-Website/master/static/public/shell_fullsize.png">
|
<img src="https://raw.githubusercontent.com/Ryujinx/Ryujinx-Website/master/public/assets/images/shell.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h5 align="center">
|
<h5 align="center">
|
||||||
@@ -36,8 +36,8 @@
|
|||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
As of January 2022, Ryujinx has been tested on approximately 3,500 titles; over 3,200 boot past menus and into gameplay, with roughly 2,500 of those being considered playable.
|
As of September 2022, Ryujinx has been tested on approximately 3,600 titles; over 3,400 boot past menus and into gameplay, with roughly 2,700 of those being considered playable. You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues).
|
||||||
You can check out the compatibility list [here](https://github.com/Ryujinx/Ryujinx-Games-List/issues). Anyone is free to submit an updated test on an existing game entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
|
Anyone is free to submit a new game test or update an existing game test entry; simply follow the new issue template and testing guidelines, or post as a reply to the applicable game issue. Use the search function to see if a game has been tested already!
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
@@ -118,11 +118,11 @@ If you'd like to support the project financially, Ryujinx has an active Patreon
|
|||||||
<img src="https://images.squarespace-cdn.com/content/v1/560c1d39e4b0b4fae0c9cf2a/1567548955044-WVD994WZP76EWF15T0L3/Patreon+Button.png?format=500w" width="150">
|
<img src="https://images.squarespace-cdn.com/content/v1/560c1d39e4b0b4fae0c9cf2a/1567548955044-WVD994WZP76EWF15T0L3/Patreon+Button.png?format=500w" width="150">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
All the developers working on the project do so on their free time, but the project has several expenses:
|
All developers working on the project do so in their free time, but the project has several expenses:
|
||||||
* Hackable Nintendo Switch consoles to reverse-engineer the hardware
|
* Hackable Nintendo Switch consoles to reverse-engineer the hardware
|
||||||
* Additional computer hardware for testing purposes (e.g. GPUs to diagnose graphical bugs, etc.)
|
* Additional computer hardware for testing purposes (e.g. GPUs to diagnose graphical bugs, etc.)
|
||||||
* Licenses for various software development tools (e.g. Jetbrains, LDN servers, IDA)
|
* Licenses for various software development tools (e.g. Jetbrains, IDA)
|
||||||
* Web hosting and infrastructure maintenance
|
* Web hosting and infrastructure maintenance (e.g. LDN servers)
|
||||||
|
|
||||||
All funds received through Patreon are considered a donation to support the project. Patrons receive early access to progress reports and exclusive access to developer interviews.
|
All funds received through Patreon are considered a donation to support the project. Patrons receive early access to progress reports and exclusive access to developer interviews.
|
||||||
|
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using ARMeilleure.Translation.PTC;
|
using ARMeilleure.Translation.PTC;
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using LibHac.Tools.FsSystem;
|
using LibHac.Tools.FsSystem;
|
||||||
@@ -12,10 +11,8 @@ using Ryujinx.Audio.Integration;
|
|||||||
using Ryujinx.Ava.Common;
|
using Ryujinx.Ava.Common;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.Input;
|
using Ryujinx.Ava.Input;
|
||||||
using Ryujinx.Ava.Ui.Backend.Vulkan;
|
|
||||||
using Ryujinx.Ava.Ui.Controls;
|
using Ryujinx.Ava.Ui.Controls;
|
||||||
using Ryujinx.Ava.Ui.Models;
|
using Ryujinx.Ava.Ui.Models;
|
||||||
using Ryujinx.Ava.Ui.Vulkan;
|
|
||||||
using Ryujinx.Ava.Ui.Windows;
|
using Ryujinx.Ava.Ui.Windows;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
@@ -39,6 +36,7 @@ using SixLabors.ImageSharp;
|
|||||||
using SixLabors.ImageSharp.Formats.Png;
|
using SixLabors.ImageSharp.Formats.Png;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
using SixLabors.ImageSharp.Processing;
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using SPB.Graphics.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@@ -58,24 +56,27 @@ namespace Ryujinx.Ava
|
|||||||
{
|
{
|
||||||
private const int CursorHideIdleTime = 8; // Hide Cursor seconds
|
private const int CursorHideIdleTime = 8; // Hide Cursor seconds
|
||||||
private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
|
private const float MaxResolutionScale = 4.0f; // Max resolution hotkeys can scale to before wrapping.
|
||||||
|
private const int TargetFps = 60;
|
||||||
|
|
||||||
|
private const float VolumeDelta = 0.05f;
|
||||||
|
|
||||||
private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None);
|
private static readonly Cursor InvisibleCursor = new Cursor(StandardCursorType.None);
|
||||||
|
|
||||||
|
private readonly long _ticksPerFrame;
|
||||||
|
private readonly Stopwatch _chrono;
|
||||||
private readonly AccountManager _accountManager;
|
private readonly AccountManager _accountManager;
|
||||||
private readonly UserChannelPersistence _userChannelPersistence;
|
private readonly UserChannelPersistence _userChannelPersistence;
|
||||||
|
|
||||||
private readonly InputManager _inputManager;
|
private readonly InputManager _inputManager;
|
||||||
|
|
||||||
private readonly IKeyboard _keyboardInterface;
|
|
||||||
|
|
||||||
private readonly MainWindow _parent;
|
private readonly MainWindow _parent;
|
||||||
|
private readonly IKeyboard _keyboardInterface;
|
||||||
private readonly GraphicsDebugLevel _glLogLevel;
|
private readonly GraphicsDebugLevel _glLogLevel;
|
||||||
|
|
||||||
private bool _hideCursorOnIdle;
|
private bool _hideCursorOnIdle;
|
||||||
private bool _isStopped;
|
private bool _isStopped;
|
||||||
private bool _isActive;
|
private bool _isActive;
|
||||||
private long _lastCursorMoveTime;
|
private long _lastCursorMoveTime;
|
||||||
|
private float _newVolume;
|
||||||
|
private long _ticks = 0;
|
||||||
|
|
||||||
private KeyboardHotkeyState _prevHotkeyState;
|
private KeyboardHotkeyState _prevHotkeyState;
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ namespace Ryujinx.Ava
|
|||||||
public event EventHandler AppExit;
|
public event EventHandler AppExit;
|
||||||
public event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
|
public event EventHandler<StatusUpdatedEventArgs> StatusUpdatedEvent;
|
||||||
|
|
||||||
public RendererControl Renderer { get; }
|
public RendererHost Renderer { get; }
|
||||||
public VirtualFileSystem VirtualFileSystem { get; }
|
public VirtualFileSystem VirtualFileSystem { get; }
|
||||||
public ContentManager ContentManager { get; }
|
public ContentManager ContentManager { get; }
|
||||||
public Switch Device { get; set; }
|
public Switch Device { get; set; }
|
||||||
@@ -111,7 +112,7 @@ namespace Ryujinx.Ava
|
|||||||
private object _lockObject = new();
|
private object _lockObject = new();
|
||||||
|
|
||||||
public AppHost(
|
public AppHost(
|
||||||
RendererControl renderer,
|
RendererHost renderer,
|
||||||
InputManager inputManager,
|
InputManager inputManager,
|
||||||
string applicationPath,
|
string applicationPath,
|
||||||
VirtualFileSystem virtualFileSystem,
|
VirtualFileSystem virtualFileSystem,
|
||||||
@@ -128,7 +129,7 @@ namespace Ryujinx.Ava
|
|||||||
_hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle;
|
_hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle;
|
||||||
_lastCursorMoveTime = Stopwatch.GetTimestamp();
|
_lastCursorMoveTime = Stopwatch.GetTimestamp();
|
||||||
_glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
|
_glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
|
||||||
_inputManager.SetMouseDriver(new AvaloniaMouseDriver(renderer));
|
_inputManager.SetMouseDriver(new AvaloniaMouseDriver(_parent, renderer));
|
||||||
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
|
_keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
|
||||||
|
|
||||||
NpadManager = _inputManager.CreateNpadManager();
|
NpadManager = _inputManager.CreateNpadManager();
|
||||||
@@ -138,6 +139,9 @@ namespace Ryujinx.Ava
|
|||||||
VirtualFileSystem = virtualFileSystem;
|
VirtualFileSystem = virtualFileSystem;
|
||||||
ContentManager = contentManager;
|
ContentManager = contentManager;
|
||||||
|
|
||||||
|
_chrono = new Stopwatch();
|
||||||
|
_ticksPerFrame = Stopwatch.Frequency / TargetFps;
|
||||||
|
|
||||||
if (ApplicationPath.StartsWith("@SystemContent"))
|
if (ApplicationPath.StartsWith("@SystemContent"))
|
||||||
{
|
{
|
||||||
ApplicationPath = _parent.VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath);
|
ApplicationPath = _parent.VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath);
|
||||||
@@ -177,7 +181,7 @@ namespace Ryujinx.Ava
|
|||||||
if (_renderer != null)
|
if (_renderer != null)
|
||||||
{
|
{
|
||||||
double scale = _parent.PlatformImpl.RenderScaling;
|
double scale = _parent.PlatformImpl.RenderScaling;
|
||||||
_renderer.Window.SetSize((int)(size.Width * scale), (int)(size.Height * scale));
|
_renderer.Window?.SetSize((int)(size.Width * scale), (int)(size.Height * scale));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,8 +339,6 @@ namespace Ryujinx.Ava
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface.Display.ChangeVSyncMode(true);
|
|
||||||
|
|
||||||
_isStopped = true;
|
_isStopped = true;
|
||||||
_isActive = false;
|
_isActive = false;
|
||||||
}
|
}
|
||||||
@@ -376,6 +378,8 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
_gpuCancellationTokenSource.Cancel();
|
_gpuCancellationTokenSource.Cancel();
|
||||||
_gpuCancellationTokenSource.Dispose();
|
_gpuCancellationTokenSource.Dispose();
|
||||||
|
|
||||||
|
_chrono.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DisposeGpu()
|
public void DisposeGpu()
|
||||||
@@ -390,7 +394,6 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
Device.DisposeGpu();
|
Device.DisposeGpu();
|
||||||
|
|
||||||
Renderer?.DestroyBackgroundContext();
|
|
||||||
Renderer?.MakeCurrent(null);
|
Renderer?.MakeCurrent(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,16 +599,11 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
IRenderer renderer;
|
IRenderer renderer;
|
||||||
|
|
||||||
if (Program.UseVulkan)
|
if (Renderer.IsVulkan)
|
||||||
{
|
{
|
||||||
var vulkan = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
|
string preferredGpu = ConfigurationState.Instance.Graphics.PreferredGpu.Value;
|
||||||
|
|
||||||
renderer = new VulkanRenderer(vulkan.Instance.InternalHandle,
|
renderer = new VulkanRenderer(Renderer.CreateVulkanSurface, VulkanHelper.GetRequiredInstanceExtensions, preferredGpu);
|
||||||
vulkan.MainSurface.Device.InternalHandle,
|
|
||||||
vulkan.PhysicalDevice.InternalHandle,
|
|
||||||
vulkan.MainSurface.Device.Queue.InternalHandle,
|
|
||||||
vulkan.PhysicalDevice.QueueFamilyIndex,
|
|
||||||
vulkan.MainSurface.Device.Lock);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -778,12 +776,8 @@ namespace Ryujinx.Ava
|
|||||||
{
|
{
|
||||||
Width = (int)e.Width;
|
Width = (int)e.Width;
|
||||||
Height = (int)e.Height;
|
Height = (int)e.Height;
|
||||||
|
|
||||||
if (!Program.UseVulkan)
|
|
||||||
{
|
|
||||||
SetRendererWindowSize(e);
|
SetRendererWindowSize(e);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void MainLoop()
|
private void MainLoop()
|
||||||
{
|
{
|
||||||
@@ -822,12 +816,10 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
_renderer.ScreenCaptured += Renderer_ScreenCaptured;
|
_renderer.ScreenCaptured += Renderer_ScreenCaptured;
|
||||||
|
|
||||||
(_renderer as OpenGLRenderer)?.InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext((Renderer as OpenGLRendererControl).GameContext));
|
(_renderer as OpenGLRenderer)?.InitializeBackgroundContext(SPBOpenGLContext.CreateBackgroundContext(Renderer.GetContext()));
|
||||||
|
|
||||||
Renderer.MakeCurrent();
|
Renderer.MakeCurrent();
|
||||||
|
|
||||||
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
|
|
||||||
|
|
||||||
Device.Gpu.Renderer.Initialize(_glLogLevel);
|
Device.Gpu.Renderer.Initialize(_glLogLevel);
|
||||||
|
|
||||||
Width = (int)Renderer.Bounds.Width;
|
Width = (int)Renderer.Bounds.Width;
|
||||||
@@ -835,16 +827,20 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
_renderer.Window.SetSize((int)(Width * _parent.PlatformImpl.RenderScaling), (int)(Height * _parent.PlatformImpl.RenderScaling));
|
_renderer.Window.SetSize((int)(Width * _parent.PlatformImpl.RenderScaling), (int)(Height * _parent.PlatformImpl.RenderScaling));
|
||||||
|
|
||||||
|
_chrono.Start();
|
||||||
|
|
||||||
Device.Gpu.Renderer.RunLoop(() =>
|
Device.Gpu.Renderer.RunLoop(() =>
|
||||||
{
|
{
|
||||||
Device.Gpu.SetGpuThread();
|
Device.Gpu.SetGpuThread();
|
||||||
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
|
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
|
||||||
Translator.IsReadyForTranslation.Set();
|
Translator.IsReadyForTranslation.Set();
|
||||||
|
|
||||||
Renderer.Start();
|
|
||||||
|
|
||||||
while (_isActive)
|
while (_isActive)
|
||||||
{
|
{
|
||||||
|
_ticks += _chrono.ElapsedTicks;
|
||||||
|
|
||||||
|
_chrono.Restart();
|
||||||
|
|
||||||
if (Device.WaitFifo())
|
if (Device.WaitFifo())
|
||||||
{
|
{
|
||||||
Device.Statistics.RecordFifoStart();
|
Device.Statistics.RecordFifoStart();
|
||||||
@@ -860,19 +856,20 @@ namespace Ryujinx.Ava
|
|||||||
_parent.SwitchToGameControl();
|
_parent.SwitchToGameControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
Device.PresentFrame(Present);
|
Device.PresentFrame(() => Renderer?.SwapBuffers());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer.Stop();
|
if (_ticks >= _ticksPerFrame)
|
||||||
|
{
|
||||||
|
UpdateStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Renderer?.MakeCurrent(null);
|
Renderer?.MakeCurrent(null);
|
||||||
|
|
||||||
Renderer.SizeChanged -= Window_SizeChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Present(object image)
|
public void UpdateStatus()
|
||||||
{
|
{
|
||||||
// Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued
|
// Run a status update only when a frame is to be drawn. This prevents from updating the ui and wasting a render when no frame is queued
|
||||||
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance["Docked"] : LocaleManager.Instance["Handheld"];
|
string dockedMode = ConfigurationState.Instance.System.EnableDockedMode ? LocaleManager.Instance["Docked"] : LocaleManager.Instance["Handheld"];
|
||||||
@@ -885,25 +882,13 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
|
StatusUpdatedEvent?.Invoke(this, new StatusUpdatedEventArgs(
|
||||||
Device.EnableDeviceVsync,
|
Device.EnableDeviceVsync,
|
||||||
Device.GetVolume(),
|
LocaleManager.Instance["VolumeShort"] + $": {(int)(Device.GetVolume() * 100)}%",
|
||||||
Program.UseVulkan ? "Vulkan" : "OpenGL",
|
Renderer.IsVulkan ? "Vulkan" : "OpenGL",
|
||||||
dockedMode,
|
dockedMode,
|
||||||
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
|
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
|
||||||
LocaleManager.Instance["Game"] + $": {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
|
LocaleManager.Instance["Game"] + $": {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
|
||||||
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
|
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
|
||||||
$"GPU: {_renderer.GetHardwareInfo().GpuVendor}"));
|
$"GPU: {_renderer.GetHardwareInfo().GpuVendor}"));
|
||||||
|
|
||||||
if (Program.UseVulkan)
|
|
||||||
{
|
|
||||||
var platformInterface = AvaloniaLocator.Current.GetService<VulkanPlatformInterface>();
|
|
||||||
if (platformInterface.MainSurface.Display.IsSurfaceChanged())
|
|
||||||
{
|
|
||||||
SetRendererWindowSize(new Size(Width, Height));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Renderer.Present(image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ShowExitPrompt()
|
public async Task ShowExitPrompt()
|
||||||
@@ -985,8 +970,6 @@ namespace Ryujinx.Ava
|
|||||||
case KeyboardHotkeyState.ToggleVSync:
|
case KeyboardHotkeyState.ToggleVSync:
|
||||||
Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
|
Device.EnableDeviceVsync = !Device.EnableDeviceVsync;
|
||||||
|
|
||||||
AvaloniaLocator.Current.GetService<VulkanPlatformInterface>()?.MainSurface?.Display?.ChangeVSyncMode(Device.EnableDeviceVsync);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case KeyboardHotkeyState.Screenshot:
|
case KeyboardHotkeyState.Screenshot:
|
||||||
ScreenshotRequested = true;
|
ScreenshotRequested = true;
|
||||||
@@ -1023,6 +1006,18 @@ namespace Ryujinx.Ava
|
|||||||
GraphicsConfig.ResScale =
|
GraphicsConfig.ResScale =
|
||||||
(MaxResolutionScale + GraphicsConfig.ResScale - 2) % MaxResolutionScale + 1;
|
(MaxResolutionScale + GraphicsConfig.ResScale - 2) % MaxResolutionScale + 1;
|
||||||
break;
|
break;
|
||||||
|
case KeyboardHotkeyState.VolumeUp:
|
||||||
|
_newVolume = MathF.Round((Device.GetVolume() + VolumeDelta), 2);
|
||||||
|
Device.SetVolume(_newVolume);
|
||||||
|
|
||||||
|
_parent.ViewModel.Volume = Device.GetVolume();
|
||||||
|
break;
|
||||||
|
case KeyboardHotkeyState.VolumeDown:
|
||||||
|
_newVolume = MathF.Round((Device.GetVolume() - VolumeDelta), 2);
|
||||||
|
Device.SetVolume(_newVolume);
|
||||||
|
|
||||||
|
_parent.ViewModel.Volume = Device.GetVolume();
|
||||||
|
break;
|
||||||
case KeyboardHotkeyState.None:
|
case KeyboardHotkeyState.None:
|
||||||
(_keyboardInterface as AvaloniaKeyboard).Clear();
|
(_keyboardInterface as AvaloniaKeyboard).Clear();
|
||||||
break;
|
break;
|
||||||
@@ -1088,6 +1083,14 @@ namespace Ryujinx.Ava
|
|||||||
{
|
{
|
||||||
state = KeyboardHotkeyState.ResScaleDown;
|
state = KeyboardHotkeyState.ResScaleDown;
|
||||||
}
|
}
|
||||||
|
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeUp))
|
||||||
|
{
|
||||||
|
state = KeyboardHotkeyState.VolumeUp;
|
||||||
|
}
|
||||||
|
else if (_keyboardInterface.IsPressed((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.VolumeDown))
|
||||||
|
{
|
||||||
|
state = KeyboardHotkeyState.VolumeDown;
|
||||||
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@@ -579,7 +579,7 @@
|
|||||||
"SettingsTabHotkeysResScaleUpHotkey": "Increase resolution:",
|
"SettingsTabHotkeysResScaleUpHotkey": "Increase resolution:",
|
||||||
"SettingsTabHotkeysResScaleDownHotkey": "Decrease resolution:",
|
"SettingsTabHotkeysResScaleDownHotkey": "Decrease resolution:",
|
||||||
"UserProfilesName": "Name:",
|
"UserProfilesName": "Name:",
|
||||||
"UserProfilesUserId" : "User Id:",
|
"UserProfilesUserId": "User Id:",
|
||||||
"SettingsTabGraphicsBackend": "Graphics Backend",
|
"SettingsTabGraphicsBackend": "Graphics Backend",
|
||||||
"SettingsTabGraphicsBackendTooltip": "Graphics Backend to use",
|
"SettingsTabGraphicsBackendTooltip": "Graphics Backend to use",
|
||||||
"SettingsEnableTextureRecompression": "Enable Texture Recompression",
|
"SettingsEnableTextureRecompression": "Enable Texture Recompression",
|
||||||
@@ -588,5 +588,9 @@
|
|||||||
"SettingsTabGraphicsPreferredGpuTooltip": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
|
"SettingsTabGraphicsPreferredGpuTooltip": "Select the graphics card that will be used with the Vulkan graphics backend.\n\nDoes not affect the GPU that OpenGL will use.\n\nSet to the GPU flagged as \"dGPU\" if unsure. If there isn't one, leave untouched.",
|
||||||
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
|
"SettingsAppRequiredRestartMessage": "Ryujinx Restart Required",
|
||||||
"SettingsGpuBackendRestartMessage": "Graphics Backend or Gpu settings have been modified. This will require a restart to be applied",
|
"SettingsGpuBackendRestartMessage": "Graphics Backend or Gpu settings have been modified. This will require a restart to be applied",
|
||||||
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?"
|
"SettingsGpuBackendRestartSubMessage": "Do you want to restart now?",
|
||||||
|
"RyujinxUpdaterMessage": "Do you want to update Ryujinx to the latest version?",
|
||||||
|
"SettingsTabHotkeysVolumeUpHotkey": "Increase Volume:",
|
||||||
|
"SettingsTabHotkeysVolumeDownHotkey": "Decrease Volume:",
|
||||||
|
"VolumeShort": "Vol"
|
||||||
}
|
}
|
||||||
|
@@ -54,6 +54,12 @@
|
|||||||
<Style Selector="Border.huge">
|
<Style Selector="Border.huge">
|
||||||
<Setter Property="Width" Value="200" />
|
<Setter Property="Width" Value="200" />
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style Selector="Border.settings">
|
||||||
|
<Setter Property="Background" Value="{DynamicResource ThemeDarkColor}" />
|
||||||
|
<Setter Property="BorderBrush" Value="{DynamicResource MenuFlyoutPresenterBorderColor}" />
|
||||||
|
<Setter Property="BorderThickness" Value="2" />
|
||||||
|
<Setter Property="CornerRadius" Value="3" />
|
||||||
|
</Style>
|
||||||
<Style Selector="Image.small">
|
<Style Selector="Image.small">
|
||||||
<Setter Property="Width" Value="50" />
|
<Setter Property="Width" Value="50" />
|
||||||
</Style>
|
</Style>
|
||||||
@@ -193,6 +199,14 @@
|
|||||||
<Setter Property="Margin" Value="{DynamicResource TextMargin}" />
|
<Setter Property="Margin" Value="{DynamicResource TextMargin}" />
|
||||||
<Setter Property="FontSize" Value="{DynamicResource FontSize}" />
|
<Setter Property="FontSize" Value="{DynamicResource FontSize}" />
|
||||||
<Setter Property="VerticalAlignment" Value="Center" />
|
<Setter Property="VerticalAlignment" Value="Center" />
|
||||||
|
<Setter Property="TextWrapping" Value="WrapWithOverflow" />
|
||||||
|
</Style>
|
||||||
|
<Style Selector="TextBlock.h1">
|
||||||
|
<Setter Property="Margin" Value="{DynamicResource TextMargin}" />
|
||||||
|
<Setter Property="VerticalAlignment" Value="Center" />
|
||||||
|
<Setter Property="FontWeight" Value="Bold" />
|
||||||
|
<Setter Property="FontSize" Value="16" />
|
||||||
|
<Setter Property="TextWrapping" Value="WrapWithOverflow" />
|
||||||
</Style>
|
</Style>
|
||||||
<Style Selector="Separator">
|
<Style Selector="Separator">
|
||||||
<Setter Property="Background" Value="{DynamicResource ThemeControlBorderColor}" />
|
<Setter Property="Background" Value="{DynamicResource ThemeControlBorderColor}" />
|
||||||
|
@@ -9,6 +9,8 @@
|
|||||||
Pause,
|
Pause,
|
||||||
ToggleMute,
|
ToggleMute,
|
||||||
ResScaleUp,
|
ResScaleUp,
|
||||||
ResScaleDown
|
ResScaleDown,
|
||||||
|
VolumeUp,
|
||||||
|
VolumeDown
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -14,21 +14,28 @@ namespace Ryujinx.Ava.Input
|
|||||||
private Control _widget;
|
private Control _widget;
|
||||||
private bool _isDisposed;
|
private bool _isDisposed;
|
||||||
private Size _size;
|
private Size _size;
|
||||||
|
private readonly Window _window;
|
||||||
|
|
||||||
public bool[] PressedButtons { get; }
|
public bool[] PressedButtons { get; }
|
||||||
|
|
||||||
public Vector2 CurrentPosition { get; private set; }
|
public Vector2 CurrentPosition { get; private set; }
|
||||||
public Vector2 Scroll { get; private set; }
|
public Vector2 Scroll { get; private set; }
|
||||||
|
|
||||||
public AvaloniaMouseDriver(Control parent)
|
public AvaloniaMouseDriver(Window window, Control parent)
|
||||||
{
|
{
|
||||||
_widget = parent;
|
_widget = parent;
|
||||||
|
_window = window;
|
||||||
|
|
||||||
_widget.PointerMoved += Parent_PointerMovedEvent;
|
_widget.PointerMoved += Parent_PointerMovedEvent;
|
||||||
_widget.PointerPressed += Parent_PointerPressEvent;
|
_widget.PointerPressed += Parent_PointerPressEvent;
|
||||||
_widget.PointerReleased += Parent_PointerReleaseEvent;
|
_widget.PointerReleased += Parent_PointerReleaseEvent;
|
||||||
_widget.PointerWheelChanged += Parent_ScrollEvent;
|
_widget.PointerWheelChanged += Parent_ScrollEvent;
|
||||||
|
|
||||||
|
_window.PointerMoved += Parent_PointerMovedEvent;
|
||||||
|
_window.PointerPressed += Parent_PointerPressEvent;
|
||||||
|
_window.PointerReleased += Parent_PointerReleaseEvent;
|
||||||
|
_window.PointerWheelChanged += Parent_ScrollEvent;
|
||||||
|
|
||||||
PressedButtons = new bool[(int)MouseButton.Count];
|
PressedButtons = new bool[(int)MouseButton.Count];
|
||||||
|
|
||||||
_size = new Size((int)parent.Bounds.Width, (int)parent.Bounds.Height);
|
_size = new Size((int)parent.Bounds.Width, (int)parent.Bounds.Height);
|
||||||
@@ -47,7 +54,6 @@ namespace Ryujinx.Ava.Input
|
|||||||
|
|
||||||
private void Parent_PointerReleaseEvent(object o, PointerReleasedEventArgs args)
|
private void Parent_PointerReleaseEvent(object o, PointerReleasedEventArgs args)
|
||||||
{
|
{
|
||||||
var pointerProperties = args.GetCurrentPoint(_widget).Properties;
|
|
||||||
PressedButtons[(int)args.InitialPressMouseButton - 1] = false;
|
PressedButtons[(int)args.InitialPressMouseButton - 1] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +131,11 @@ namespace Ryujinx.Ava.Input
|
|||||||
_widget.PointerReleased -= Parent_PointerReleaseEvent;
|
_widget.PointerReleased -= Parent_PointerReleaseEvent;
|
||||||
_widget.PointerWheelChanged -= Parent_ScrollEvent;
|
_widget.PointerWheelChanged -= Parent_ScrollEvent;
|
||||||
|
|
||||||
|
_window.PointerMoved -= Parent_PointerMovedEvent;
|
||||||
|
_window.PointerPressed -= Parent_PointerPressEvent;
|
||||||
|
_window.PointerReleased -= Parent_PointerReleaseEvent;
|
||||||
|
_window.PointerWheelChanged -= Parent_ScrollEvent;
|
||||||
|
|
||||||
_widget = null;
|
_widget = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
|
using Avalonia.Controls;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
using FluentAvalonia.UI.Controls;
|
||||||
using ICSharpCode.SharpZipLib.GZip;
|
using ICSharpCode.SharpZipLib.GZip;
|
||||||
using ICSharpCode.SharpZipLib.Tar;
|
using ICSharpCode.SharpZipLib.Tar;
|
||||||
using ICSharpCode.SharpZipLib.Zip;
|
using ICSharpCode.SharpZipLib.Zip;
|
||||||
@@ -11,11 +13,13 @@ using Ryujinx.Common;
|
|||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.NetworkInformation;
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
@@ -40,6 +44,8 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
private static readonly string[] WindowsDependencyDirs = Array.Empty<string>();
|
private static readonly string[] WindowsDependencyDirs = Array.Empty<string>();
|
||||||
|
|
||||||
|
public static bool UpdateSuccessful { get; private set; }
|
||||||
|
|
||||||
public static async Task BeginParse(MainWindow mainWindow, bool showVersionUpToDate)
|
public static async Task BeginParse(MainWindow mainWindow, bool showVersionUpToDate)
|
||||||
{
|
{
|
||||||
if (Running)
|
if (Running)
|
||||||
@@ -198,11 +204,18 @@ namespace Ryujinx.Modules
|
|||||||
_buildSize = -1;
|
_buildSize = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(async () =>
|
Dispatcher.UIThread.Post(async () =>
|
||||||
{
|
{
|
||||||
// Show a message asking the user if they want to update
|
// Show a message asking the user if they want to update
|
||||||
UpdaterWindow updateDialog = new(mainWindow, newVersion, _buildUrl);
|
var shouldUpdate = await ContentDialogHelper.CreateChoiceDialog(LocaleManager.Instance["RyujinxUpdater"],
|
||||||
await updateDialog.ShowDialog(mainWindow);
|
LocaleManager.Instance["RyujinxUpdaterMessage"],
|
||||||
|
$"{Program.Version} -> {newVersion}");
|
||||||
|
|
||||||
|
if (shouldUpdate)
|
||||||
|
{
|
||||||
|
UpdateRyujinx(mainWindow, _buildUrl);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,8 +229,10 @@ namespace Ryujinx.Modules
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UpdateRyujinx(UpdaterWindow updateDialog, string downloadUrl)
|
public static async void UpdateRyujinx(Window parent, string downloadUrl)
|
||||||
{
|
{
|
||||||
|
UpdateSuccessful = false;
|
||||||
|
|
||||||
// Empty update dir, although it shouldn't ever have anything inside it
|
// Empty update dir, although it shouldn't ever have anything inside it
|
||||||
if (Directory.Exists(UpdateDir))
|
if (Directory.Exists(UpdateDir))
|
||||||
{
|
{
|
||||||
@@ -228,25 +243,56 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
string updateFile = Path.Combine(UpdateDir, "update.bin");
|
string updateFile = Path.Combine(UpdateDir, "update.bin");
|
||||||
|
|
||||||
// Download the update .zip
|
var taskDialog = new TaskDialog()
|
||||||
updateDialog.MainText.Text = LocaleManager.Instance["UpdaterDownloading"];
|
{
|
||||||
updateDialog.ProgressBar.Value = 0;
|
Header = LocaleManager.Instance["RyujinxUpdater"],
|
||||||
updateDialog.ProgressBar.Maximum = 100;
|
SubHeader = LocaleManager.Instance["UpdaterDownloading"],
|
||||||
|
IconSource = new SymbolIconSource { Symbol = Symbol.Download },
|
||||||
|
Buttons = { },
|
||||||
|
ShowProgressBar = true
|
||||||
|
};
|
||||||
|
|
||||||
Task.Run(() =>
|
taskDialog.XamlRoot = parent;
|
||||||
|
|
||||||
|
taskDialog.Opened += (s, e) =>
|
||||||
{
|
{
|
||||||
if (_buildSize >= 0)
|
if (_buildSize >= 0)
|
||||||
{
|
{
|
||||||
DoUpdateWithMultipleThreads(updateDialog, downloadUrl, updateFile);
|
DoUpdateWithMultipleThreads(taskDialog, downloadUrl, updateFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DoUpdateWithSingleThread(updateDialog, downloadUrl, updateFile);
|
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
|
||||||
|
await taskDialog.ShowAsync(true);
|
||||||
|
|
||||||
|
if (UpdateSuccessful)
|
||||||
|
{
|
||||||
|
var shouldRestart = await ContentDialogHelper.CreateChoiceDialog(LocaleManager.Instance["RyujinxUpdater"],
|
||||||
|
LocaleManager.Instance["DialogUpdaterCompleteMessage"],
|
||||||
|
LocaleManager.Instance["DialogUpdaterRestartMessage"]);
|
||||||
|
|
||||||
|
if (shouldRestart)
|
||||||
|
{
|
||||||
|
string ryuName = Path.GetFileName(Environment.ProcessPath);
|
||||||
|
string ryuExe = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, ryuName);
|
||||||
|
string ryuArg = string.Join(" ", Environment.GetCommandLineArgs().Skip(1).ToArray());
|
||||||
|
|
||||||
|
if (!OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
chmod(ryuExe, Convert.ToUInt32("0777", 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DoUpdateWithMultipleThreads(UpdaterWindow updateDialog, string downloadUrl, string updateFile)
|
Process.Start(ryuExe, ryuArg);
|
||||||
|
|
||||||
|
Environment.Exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DoUpdateWithMultipleThreads(TaskDialog taskDialog, string downloadUrl, string updateFile)
|
||||||
{
|
{
|
||||||
// Multi-Threaded Updater
|
// Multi-Threaded Updater
|
||||||
long chunkSize = _buildSize / ConnectionCount;
|
long chunkSize = _buildSize / ConnectionCount;
|
||||||
@@ -290,7 +336,7 @@ namespace Ryujinx.Modules
|
|||||||
Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage);
|
Interlocked.Exchange(ref progressPercentage[index], args.ProgressPercentage);
|
||||||
Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage);
|
Interlocked.Add(ref totalProgressPercentage, args.ProgressPercentage);
|
||||||
|
|
||||||
updateDialog.ProgressBar.Value = totalProgressPercentage / ConnectionCount;
|
taskDialog.SetProgressBarState(totalProgressPercentage / ConnectionCount, TaskDialogProgressState.Normal);
|
||||||
};
|
};
|
||||||
|
|
||||||
client.DownloadDataCompleted += (_, args) =>
|
client.DownloadDataCompleted += (_, args) =>
|
||||||
@@ -301,6 +347,8 @@ namespace Ryujinx.Modules
|
|||||||
{
|
{
|
||||||
webClients[index].Dispose();
|
webClients[index].Dispose();
|
||||||
|
|
||||||
|
taskDialog.Hide();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,14 +368,14 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
InstallUpdate(updateDialog, updateFile);
|
InstallUpdate(taskDialog, updateFile);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.Warning?.Print(LogClass.Application, e.Message);
|
Logger.Warning?.Print(LogClass.Application, e.Message);
|
||||||
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
|
Logger.Warning?.Print(LogClass.Application, "Multi-Threaded update failed, falling back to single-threaded updater.");
|
||||||
|
|
||||||
DoUpdateWithSingleThread(updateDialog, downloadUrl, updateFile);
|
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -348,7 +396,7 @@ namespace Ryujinx.Modules
|
|||||||
webClients[j].CancelAsync();
|
webClients[j].CancelAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
DoUpdateWithSingleThread(updateDialog, downloadUrl, updateFile);
|
DoUpdateWithSingleThread(taskDialog, downloadUrl, updateFile);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -356,7 +404,7 @@ namespace Ryujinx.Modules
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DoUpdateWithSingleThreadWorker(UpdaterWindow updateDialog, string downloadUrl, string updateFile)
|
private static void DoUpdateWithSingleThreadWorker(TaskDialog taskDialog, string downloadUrl, string updateFile)
|
||||||
{
|
{
|
||||||
using (HttpClient client = new HttpClient())
|
using (HttpClient client = new HttpClient())
|
||||||
{
|
{
|
||||||
@@ -384,19 +432,26 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
byteWritten += readSize;
|
byteWritten += readSize;
|
||||||
|
|
||||||
updateDialog.ProgressBar.Value = ((double)byteWritten / totalBytes) * 100;
|
taskDialog.SetProgressBarState(GetPercentage(byteWritten, totalBytes), TaskDialogProgressState.Normal);
|
||||||
|
|
||||||
updateFileStream.Write(buffer, 0, readSize);
|
updateFileStream.Write(buffer, 0, readSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
InstallUpdate(updateDialog, updateFile);
|
InstallUpdate(taskDialog, updateFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DoUpdateWithSingleThread(UpdaterWindow updateDialog, string downloadUrl, string updateFile)
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static double GetPercentage(double value, double max)
|
||||||
{
|
{
|
||||||
Thread worker = new Thread(() => DoUpdateWithSingleThreadWorker(updateDialog, downloadUrl, updateFile));
|
return max == 0 ? 0 : value / max * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DoUpdateWithSingleThread(TaskDialog taskDialog, string downloadUrl, string updateFile)
|
||||||
|
{
|
||||||
|
Thread worker = new Thread(() => DoUpdateWithSingleThreadWorker(taskDialog, downloadUrl, updateFile));
|
||||||
worker.Name = "Updater.SingleThreadWorker";
|
worker.Name = "Updater.SingleThreadWorker";
|
||||||
worker.Start();
|
worker.Start();
|
||||||
}
|
}
|
||||||
@@ -414,11 +469,11 @@ namespace Ryujinx.Modules
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async void InstallUpdate(UpdaterWindow updateDialog, string updateFile)
|
private static async void InstallUpdate(TaskDialog taskDialog, string updateFile)
|
||||||
{
|
{
|
||||||
// Extract Update
|
// Extract Update
|
||||||
updateDialog.MainText.Text = LocaleManager.Instance["UpdaterExtracting"];
|
taskDialog.SubHeader = LocaleManager.Instance["UpdaterExtracting"];
|
||||||
updateDialog.ProgressBar.Value = 0;
|
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
||||||
|
|
||||||
if (OperatingSystem.IsLinux())
|
if (OperatingSystem.IsLinux())
|
||||||
{
|
{
|
||||||
@@ -426,8 +481,6 @@ namespace Ryujinx.Modules
|
|||||||
using (Stream gzipStream = new GZipInputStream(inStream))
|
using (Stream gzipStream = new GZipInputStream(inStream))
|
||||||
using (TarInputStream tarStream = new TarInputStream(gzipStream, Encoding.ASCII))
|
using (TarInputStream tarStream = new TarInputStream(gzipStream, Encoding.ASCII))
|
||||||
{
|
{
|
||||||
updateDialog.ProgressBar.Maximum = inStream.Length;
|
|
||||||
|
|
||||||
await Task.Run(() =>
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
TarEntry tarEntry;
|
TarEntry tarEntry;
|
||||||
@@ -450,12 +503,12 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
updateDialog.ProgressBar.Value += entry.Size;
|
taskDialog.SetProgressBarState(GetPercentage(entry.Size, inStream.Length), TaskDialogProgressState.Normal);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
updateDialog.ProgressBar.Value = inStream.Length;
|
taskDialog.SetProgressBarState(100, TaskDialogProgressState.Normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -463,12 +516,12 @@ namespace Ryujinx.Modules
|
|||||||
using (Stream inStream = File.OpenRead(updateFile))
|
using (Stream inStream = File.OpenRead(updateFile))
|
||||||
using (ZipFile zipFile = new ZipFile(inStream))
|
using (ZipFile zipFile = new ZipFile(inStream))
|
||||||
{
|
{
|
||||||
updateDialog.ProgressBar.Maximum = zipFile.Count;
|
|
||||||
|
|
||||||
await Task.Run(() =>
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
|
double count = 0;
|
||||||
foreach (ZipEntry zipEntry in zipFile)
|
foreach (ZipEntry zipEntry in zipFile)
|
||||||
{
|
{
|
||||||
|
count++;
|
||||||
if (zipEntry.IsDirectory) continue;
|
if (zipEntry.IsDirectory) continue;
|
||||||
|
|
||||||
string outPath = Path.Combine(UpdateDir, zipEntry.Name);
|
string outPath = Path.Combine(UpdateDir, zipEntry.Name);
|
||||||
@@ -485,7 +538,7 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
updateDialog.ProgressBar.Value++;
|
taskDialog.SetProgressBarState(GetPercentage(count, zipFile.Count), TaskDialogProgressState.Normal);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -497,22 +550,23 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
List<string> allFiles = EnumerateFilesToDelete().ToList();
|
List<string> allFiles = EnumerateFilesToDelete().ToList();
|
||||||
|
|
||||||
updateDialog.MainText.Text = LocaleManager.Instance["UpdaterRenaming"];
|
taskDialog.SubHeader = LocaleManager.Instance["UpdaterRenaming"];
|
||||||
updateDialog.ProgressBar.Value = 0;
|
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
||||||
updateDialog.ProgressBar.Maximum = allFiles.Count;
|
|
||||||
|
|
||||||
// Replace old files
|
// Replace old files
|
||||||
await Task.Run(() =>
|
await Task.Run(() =>
|
||||||
{
|
{
|
||||||
|
double count = 0;
|
||||||
foreach (string file in allFiles)
|
foreach (string file in allFiles)
|
||||||
{
|
{
|
||||||
|
count++;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File.Move(file, file + ".ryuold");
|
File.Move(file, file + ".ryuold");
|
||||||
|
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
updateDialog.ProgressBar.Value++;
|
taskDialog.SetProgressBarState(GetPercentage(count, allFiles.Count), TaskDialogProgressState.Normal);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -523,23 +577,20 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
updateDialog.MainText.Text = LocaleManager.Instance["UpdaterAddingFiles"];
|
taskDialog.SubHeader = LocaleManager.Instance["UpdaterAddingFiles"];
|
||||||
updateDialog.ProgressBar.Value = 0;
|
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
|
||||||
updateDialog.ProgressBar.Maximum = Directory.GetFiles(UpdatePublishDir, "*", SearchOption.AllDirectories).Length;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
MoveAllFilesOver(UpdatePublishDir, HomeDir, updateDialog);
|
MoveAllFilesOver(UpdatePublishDir, HomeDir, taskDialog);
|
||||||
});
|
});
|
||||||
|
|
||||||
Directory.Delete(UpdateDir, true);
|
Directory.Delete(UpdateDir, true);
|
||||||
|
|
||||||
SetUnixPermissions();
|
SetUnixPermissions();
|
||||||
|
|
||||||
updateDialog.MainText.Text = LocaleManager.Instance["DialogUpdaterCompleteMessage"];
|
UpdateSuccessful = true;
|
||||||
updateDialog.SecondaryText.Text = LocaleManager.Instance["DialogUpdaterRestartMessage"];
|
|
||||||
|
|
||||||
updateDialog.ProgressBar.IsVisible = false;
|
taskDialog.Hide();
|
||||||
updateDialog.ButtonBox.IsVisible = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||||
@@ -618,8 +669,9 @@ namespace Ryujinx.Modules
|
|||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void MoveAllFilesOver(string root, string dest, UpdaterWindow dialog)
|
private static void MoveAllFilesOver(string root, string dest, TaskDialog taskDialog)
|
||||||
{
|
{
|
||||||
|
var total = Directory.GetFiles(root, "*", SearchOption.AllDirectories).Length;
|
||||||
foreach (string directory in Directory.GetDirectories(root))
|
foreach (string directory in Directory.GetDirectories(root))
|
||||||
{
|
{
|
||||||
string dirName = Path.GetFileName(directory);
|
string dirName = Path.GetFileName(directory);
|
||||||
@@ -629,16 +681,18 @@ namespace Ryujinx.Modules
|
|||||||
Directory.CreateDirectory(Path.Combine(dest, dirName));
|
Directory.CreateDirectory(Path.Combine(dest, dirName));
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveAllFilesOver(directory, Path.Combine(dest, dirName), dialog);
|
MoveAllFilesOver(directory, Path.Combine(dest, dirName), taskDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double count = 0;
|
||||||
foreach (string file in Directory.GetFiles(root))
|
foreach (string file in Directory.GetFiles(root))
|
||||||
{
|
{
|
||||||
|
count++;
|
||||||
File.Move(file, Path.Combine(dest, Path.GetFileName(file)), true);
|
File.Move(file, Path.Combine(dest, Path.GetFileName(file)), true);
|
||||||
|
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
dialog.ProgressBar.Value++;
|
taskDialog.SetProgressBarState(GetPercentage(count, total), TaskDialogProgressState.Normal);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,7 @@
|
|||||||
using ARMeilleure.Translation.PTC;
|
using ARMeilleure.Translation.PTC;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.OpenGL;
|
|
||||||
using Avalonia.Rendering;
|
using Avalonia.Rendering;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using Ryujinx.Ava.Ui.Backend;
|
|
||||||
using Ryujinx.Ava.Ui.Controls;
|
using Ryujinx.Ava.Ui.Controls;
|
||||||
using Ryujinx.Ava.Ui.Windows;
|
using Ryujinx.Ava.Ui.Windows;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
@@ -12,12 +10,10 @@ using Ryujinx.Common.GraphicsDriver;
|
|||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.System;
|
using Ryujinx.Common.System;
|
||||||
using Ryujinx.Common.SystemInfo;
|
using Ryujinx.Common.SystemInfo;
|
||||||
using Ryujinx.Graphics.Vulkan;
|
|
||||||
using Ryujinx.Modules;
|
using Ryujinx.Modules;
|
||||||
using Ryujinx.Ui.Common;
|
using Ryujinx.Ui.Common;
|
||||||
using Ryujinx.Ui.Common.Configuration;
|
using Ryujinx.Ui.Common.Configuration;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -34,7 +30,6 @@ namespace Ryujinx.Ava
|
|||||||
public static bool PreviewerDetached { get; private set; }
|
public static bool PreviewerDetached { get; private set; }
|
||||||
|
|
||||||
public static RenderTimer RenderTimer { get; private set; }
|
public static RenderTimer RenderTimer { get; private set; }
|
||||||
public static bool UseVulkan { get; private set; }
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
public static extern int MessageBoxA(IntPtr hWnd, string text, string caption, uint type);
|
public static extern int MessageBoxA(IntPtr hWnd, string text, string caption, uint type);
|
||||||
@@ -71,36 +66,16 @@ namespace Ryujinx.Ava
|
|||||||
EnableMultiTouch = true,
|
EnableMultiTouch = true,
|
||||||
EnableIme = true,
|
EnableIme = true,
|
||||||
UseEGL = false,
|
UseEGL = false,
|
||||||
UseGpu = !UseVulkan,
|
UseGpu = false
|
||||||
GlProfiles = new List<GlVersion>()
|
|
||||||
{
|
|
||||||
new GlVersion(GlProfileType.OpenGL, 4, 3)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.With(new Win32PlatformOptions
|
.With(new Win32PlatformOptions
|
||||||
{
|
{
|
||||||
EnableMultitouch = true,
|
EnableMultitouch = true,
|
||||||
UseWgl = !UseVulkan,
|
UseWgl = false,
|
||||||
WglProfiles = new List<GlVersion>()
|
|
||||||
{
|
|
||||||
new GlVersion(GlProfileType.OpenGL, 4, 3)
|
|
||||||
},
|
|
||||||
AllowEglInitialization = false,
|
AllowEglInitialization = false,
|
||||||
CompositionBackdropCornerRadius = 8f,
|
CompositionBackdropCornerRadius = 8f,
|
||||||
})
|
})
|
||||||
.UseSkia()
|
.UseSkia()
|
||||||
.With(new Ui.Vulkan.VulkanOptions()
|
|
||||||
{
|
|
||||||
ApplicationName = "Ryujinx.Graphics.Vulkan",
|
|
||||||
MaxQueueCount = 2,
|
|
||||||
PreferDiscreteGpu = true,
|
|
||||||
PreferredDevice = !PreviewerDetached ? "" : ConfigurationState.Instance.Graphics.PreferredGpu.Value,
|
|
||||||
UseDebug = !PreviewerDetached ? false : ConfigurationState.Instance.Logger.GraphicsDebugLevel.Value != GraphicsDebugLevel.None,
|
|
||||||
})
|
|
||||||
.With(new SkiaOptions()
|
|
||||||
{
|
|
||||||
CustomGpuFactory = UseVulkan ? SkiaGpuFactory.CreateVulkanGpu : null
|
|
||||||
})
|
|
||||||
.AfterSetup(_ =>
|
.AfterSetup(_ =>
|
||||||
{
|
{
|
||||||
AvaloniaLocator.CurrentMutable
|
AvaloniaLocator.CurrentMutable
|
||||||
@@ -176,26 +151,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
ReloadConfig();
|
ReloadConfig();
|
||||||
|
|
||||||
UseVulkan = PreviewerDetached ? ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan : false;
|
|
||||||
|
|
||||||
if (UseVulkan)
|
|
||||||
{
|
|
||||||
if (VulkanRenderer.GetPhysicalDevices().Length == 0)
|
|
||||||
{
|
|
||||||
UseVulkan = false;
|
|
||||||
|
|
||||||
ConfigurationState.Instance.Graphics.GraphicsBackend.Value = GraphicsBackend.OpenGl;
|
|
||||||
|
|
||||||
Logger.Warning?.PrintMsg(LogClass.Application, "A suitable Vulkan physical device is not available. Falling back to OpenGL");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UseVulkan)
|
|
||||||
{
|
|
||||||
// With a custom gpu backend, avalonia doesn't enable dpi awareness, so the backend must handle it. This isn't so for the opengl backed,
|
|
||||||
// as that uses avalonia's gpu backend and it's enabled there.
|
|
||||||
ForceDpiAware.Windows();
|
ForceDpiAware.Windows();
|
||||||
}
|
|
||||||
|
|
||||||
WindowScaleFactor = ForceDpiAware.GetWindowScaleFactor();
|
WindowScaleFactor = ForceDpiAware.GetWindowScaleFactor();
|
||||||
ActualScaleFactor = ForceDpiAware.GetActualScaleFactor() / BaseDpi;
|
ActualScaleFactor = ForceDpiAware.GetActualScaleFactor() / BaseDpi;
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
@@ -59,10 +60,26 @@ namespace Ryujinx.Ava.Ui.Controls
|
|||||||
|
|
||||||
string input = string.Empty;
|
string input = string.Empty;
|
||||||
|
|
||||||
|
var overlay = new ContentDialogOverlayWindow()
|
||||||
|
{
|
||||||
|
Height = window.Bounds.Height,
|
||||||
|
Width = window.Bounds.Width,
|
||||||
|
Position = window.PointToScreen(new Point())
|
||||||
|
};
|
||||||
|
|
||||||
|
window.PositionChanged += OverlayOnPositionChanged;
|
||||||
|
|
||||||
|
void OverlayOnPositionChanged(object sender, PixelPointEventArgs e)
|
||||||
|
{
|
||||||
|
overlay.Position = window.PointToScreen(new Point());
|
||||||
|
}
|
||||||
|
|
||||||
|
contentDialog = overlay.ContentDialog;
|
||||||
|
|
||||||
|
bool opened = false;
|
||||||
|
|
||||||
content.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
|
content.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax);
|
||||||
|
|
||||||
if (contentDialog != null)
|
|
||||||
{
|
|
||||||
content._host = contentDialog;
|
content._host = contentDialog;
|
||||||
contentDialog.Title = title;
|
contentDialog.Title = title;
|
||||||
contentDialog.PrimaryButtonText = args.SubmitText;
|
contentDialog.PrimaryButtonText = args.SubmitText;
|
||||||
@@ -70,6 +87,7 @@ namespace Ryujinx.Ava.Ui.Controls
|
|||||||
contentDialog.SecondaryButtonText = "";
|
contentDialog.SecondaryButtonText = "";
|
||||||
contentDialog.CloseButtonText = LocaleManager.Instance["InputDialogCancel"];
|
contentDialog.CloseButtonText = LocaleManager.Instance["InputDialogCancel"];
|
||||||
contentDialog.Content = content;
|
contentDialog.Content = content;
|
||||||
|
|
||||||
TypedEventHandler<ContentDialog, ContentDialogClosedEventArgs> handler = (sender, eventArgs) =>
|
TypedEventHandler<ContentDialog, ContentDialogClosedEventArgs> handler = (sender, eventArgs) =>
|
||||||
{
|
{
|
||||||
if (eventArgs.Result == ContentDialogResult.Primary)
|
if (eventArgs.Result == ContentDialogResult.Primary)
|
||||||
@@ -79,9 +97,26 @@ namespace Ryujinx.Ava.Ui.Controls
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
contentDialog.Closed += handler;
|
contentDialog.Closed += handler;
|
||||||
|
|
||||||
|
overlay.Opened += OverlayOnActivated;
|
||||||
|
|
||||||
|
async void OverlayOnActivated(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (opened)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
opened = true;
|
||||||
|
|
||||||
|
overlay.Position = window.PointToScreen(new Point());
|
||||||
|
|
||||||
await contentDialog.ShowAsync();
|
await contentDialog.ShowAsync();
|
||||||
contentDialog.Closed -= handler;
|
contentDialog.Closed -= handler;
|
||||||
}
|
overlay.Close();
|
||||||
|
};
|
||||||
|
|
||||||
|
await overlay.ShowDialog(window);
|
||||||
|
|
||||||
return (result, input);
|
return (result, input);
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user