Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
cb70e7bb30 | ||
|
c200a7b7c6 | ||
|
6268170a10 | ||
|
ee0f9b03a4 | ||
|
f93c5f006a |
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
<ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" />
|
||||||
<ProjectReference Include="..\Ryujinx.Memory\Ryujinx.Memory.csproj" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@@ -1033,13 +1033,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Debug.Assert(opCode != BadOp, "Invalid opcode value.");
|
Debug.Assert(opCode != BadOp, "Invalid opcode value.");
|
||||||
|
|
||||||
if ((flags & InstructionFlags.Evex) != 0 && HardwareCapabilities.SupportsEvexEncoding)
|
if ((flags & InstructionFlags.Vex) != 0 && HardwareCapabilities.SupportsVexEncoding)
|
||||||
{
|
|
||||||
WriteEvexInst(dest, src1, src2, type, flags, opCode);
|
|
||||||
|
|
||||||
opCode &= 0xff;
|
|
||||||
}
|
|
||||||
else if ((flags & InstructionFlags.Vex) != 0 && HardwareCapabilities.SupportsVexEncoding)
|
|
||||||
{
|
{
|
||||||
// In a vex encoding, only one prefix can be active at a time. The active prefix is encoded in the second byte using two bits.
|
// In a vex encoding, only one prefix can be active at a time. The active prefix is encoded in the second byte using two bits.
|
||||||
|
|
||||||
@@ -1158,103 +1152,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteEvexInst(
|
|
||||||
Operand dest,
|
|
||||||
Operand src1,
|
|
||||||
Operand src2,
|
|
||||||
OperandType type,
|
|
||||||
InstructionFlags flags,
|
|
||||||
int opCode,
|
|
||||||
bool broadcast = false,
|
|
||||||
int registerWidth = 128,
|
|
||||||
int maskRegisterIdx = 0,
|
|
||||||
bool zeroElements = false)
|
|
||||||
{
|
|
||||||
int destIdx = dest.GetRegister().Index;
|
|
||||||
int src1Idx = src1.GetRegister().Index;
|
|
||||||
int src2Idx = src2.GetRegister().Index;
|
|
||||||
|
|
||||||
WriteByte(0x62);
|
|
||||||
|
|
||||||
// P0
|
|
||||||
// Extend dest register
|
|
||||||
bool r = (destIdx & 8) == 0;
|
|
||||||
// Extend src register
|
|
||||||
bool x = (src1Idx & 16) == 0;
|
|
||||||
// Extend src register
|
|
||||||
bool b = (src1Idx & 8) == 0;
|
|
||||||
// Extend dest register
|
|
||||||
bool rp = (destIdx & 16) == 0;
|
|
||||||
// Escape code index
|
|
||||||
byte mm = 0b00;
|
|
||||||
|
|
||||||
switch ((ushort)(opCode >> 8))
|
|
||||||
{
|
|
||||||
case 0xf00: mm = 0b01; break;
|
|
||||||
case 0xf38: mm = 0b10; break;
|
|
||||||
case 0xf3a: mm = 0b11; break;
|
|
||||||
|
|
||||||
default: Debug.Assert(false, $"Failed to EVEX encode opcode 0x{opCode:X}."); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteByte(
|
|
||||||
(byte)(
|
|
||||||
(r ? 0x80 : 0) |
|
|
||||||
(x ? 0x40 : 0) |
|
|
||||||
(b ? 0x20 : 0) |
|
|
||||||
(rp ? 0x10 : 0) |
|
|
||||||
mm));
|
|
||||||
|
|
||||||
// P1
|
|
||||||
// Specify 64-bit lane mode
|
|
||||||
bool w = Is64Bits(type);
|
|
||||||
// Src2 register index
|
|
||||||
byte vvvv = (byte)(src2Idx & 0b1111);
|
|
||||||
// Opcode prefix
|
|
||||||
byte pp = (flags & InstructionFlags.PrefixMask) switch
|
|
||||||
{
|
|
||||||
InstructionFlags.Prefix66 => 0b01,
|
|
||||||
InstructionFlags.PrefixF3 => 0b10,
|
|
||||||
InstructionFlags.PrefixF2 => 0b11,
|
|
||||||
_ => 0
|
|
||||||
};
|
|
||||||
WriteByte(
|
|
||||||
(byte)(
|
|
||||||
(w ? 0x80 : 0) |
|
|
||||||
(vvvv << 3) |
|
|
||||||
0b100 |
|
|
||||||
pp));
|
|
||||||
|
|
||||||
// P2
|
|
||||||
// Mask register determines what elements to zero, rather than what elements to merge
|
|
||||||
bool z = zeroElements;
|
|
||||||
// Specifies register-width
|
|
||||||
byte ll = 0b00;
|
|
||||||
switch (registerWidth)
|
|
||||||
{
|
|
||||||
case 128: ll = 0b00; break;
|
|
||||||
case 256: ll = 0b01; break;
|
|
||||||
case 512: ll = 0b10; break;
|
|
||||||
|
|
||||||
default: Debug.Assert(false, $"Invalid EVEX vector register width {registerWidth}."); break;
|
|
||||||
}
|
|
||||||
// Embedded broadcast in the case of a memory operand
|
|
||||||
bool bcast = broadcast;
|
|
||||||
// Extend src2 register
|
|
||||||
bool vp = (src2Idx & 16) == 0;
|
|
||||||
// Mask register index
|
|
||||||
Debug.Assert(maskRegisterIdx < 8, $"Invalid mask register index {maskRegisterIdx}.");
|
|
||||||
byte aaa = (byte)(maskRegisterIdx & 0b111);
|
|
||||||
|
|
||||||
WriteByte(
|
|
||||||
(byte)(
|
|
||||||
(z ? 0x80 : 0) |
|
|
||||||
(ll << 5) |
|
|
||||||
(bcast ? 0x10 : 0) |
|
|
||||||
(vp ? 8 : 0) |
|
|
||||||
aaa));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteCompactInst(Operand operand, int opCode)
|
private void WriteCompactInst(Operand operand, int opCode)
|
||||||
{
|
{
|
||||||
int regIndex = operand.GetRegister().Index;
|
int regIndex = operand.GetRegister().Index;
|
||||||
|
@@ -20,7 +20,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Reg8Dest = 1 << 2,
|
Reg8Dest = 1 << 2,
|
||||||
RexW = 1 << 3,
|
RexW = 1 << 3,
|
||||||
Vex = 1 << 4,
|
Vex = 1 << 4,
|
||||||
Evex = 1 << 5,
|
|
||||||
|
|
||||||
PrefixBit = 16,
|
PrefixBit = 16,
|
||||||
PrefixMask = 7 << PrefixBit,
|
PrefixMask = 7 << PrefixBit,
|
||||||
@@ -279,7 +278,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Add(X86Instruction.Vfnmsub231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bf, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
|
Add(X86Instruction.Vfnmsub231sd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bf, InstructionFlags.Vex | InstructionFlags.Prefix66 | InstructionFlags.RexW));
|
||||||
Add(X86Instruction.Vfnmsub231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bf, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
Add(X86Instruction.Vfnmsub231ss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f38bf, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||||
Add(X86Instruction.Vpblendvb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
Add(X86Instruction.Vpblendvb, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4c, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||||
Add(X86Instruction.Vpternlogd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a25, InstructionFlags.Evex | InstructionFlags.Prefix66));
|
|
||||||
Add(X86Instruction.Xor, new InstructionInfo(0x00000031, 0x06000083, 0x06000081, BadOp, 0x00000033, InstructionFlags.None));
|
Add(X86Instruction.Xor, new InstructionInfo(0x00000031, 0x06000083, 0x06000081, BadOp, 0x00000033, InstructionFlags.None));
|
||||||
Add(X86Instruction.Xorpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
Add(X86Instruction.Xorpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||||
Add(X86Instruction.Xorps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex));
|
Add(X86Instruction.Xorps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex));
|
||||||
|
@@ -1587,6 +1587,12 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
|
||||||
|
|
||||||
|
// We can eliminate the move if source is already 32-bit and the registers are the same.
|
||||||
|
if (dest.Value == source.Value && source.Type == OperandType.I32)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
context.Assembler.Mov(dest, source, OperandType.I32);
|
context.Assembler.Mov(dest, source, OperandType.I32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,14 +1,10 @@
|
|||||||
using Ryujinx.Memory;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.X86
|
namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
static class HardwareCapabilities
|
static class HardwareCapabilities
|
||||||
{
|
{
|
||||||
private delegate uint GetXcr0();
|
|
||||||
|
|
||||||
static HardwareCapabilities()
|
static HardwareCapabilities()
|
||||||
{
|
{
|
||||||
if (!X86Base.IsSupported)
|
if (!X86Base.IsSupported)
|
||||||
@@ -28,28 +24,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
FeatureInfo7Ebx = (FeatureFlags7Ebx)ebx7;
|
FeatureInfo7Ebx = (FeatureFlags7Ebx)ebx7;
|
||||||
FeatureInfo7Ecx = (FeatureFlags7Ecx)ecx7;
|
FeatureInfo7Ecx = (FeatureFlags7Ecx)ecx7;
|
||||||
}
|
}
|
||||||
|
|
||||||
Xcr0InfoEax = (Xcr0FlagsEax)GetXcr0Eax();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static uint GetXcr0Eax()
|
|
||||||
{
|
|
||||||
ReadOnlySpan<byte> asmGetXcr0 = new byte[]
|
|
||||||
{
|
|
||||||
0x31, 0xc9, // xor ecx, ecx
|
|
||||||
0xf, 0x01, 0xd0, // xgetbv
|
|
||||||
0xc3, // ret
|
|
||||||
};
|
|
||||||
|
|
||||||
using MemoryBlock memGetXcr0 = new MemoryBlock((ulong)asmGetXcr0.Length);
|
|
||||||
|
|
||||||
memGetXcr0.Write(0, asmGetXcr0);
|
|
||||||
|
|
||||||
memGetXcr0.Reprotect(0, (ulong)asmGetXcr0.Length, MemoryPermission.ReadAndExecute);
|
|
||||||
|
|
||||||
var fGetXcr0 = Marshal.GetDelegateForFunctionPointer<GetXcr0>(memGetXcr0.Pointer);
|
|
||||||
|
|
||||||
return fGetXcr0();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@@ -70,7 +44,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Sse42 = 1 << 20,
|
Sse42 = 1 << 20,
|
||||||
Popcnt = 1 << 23,
|
Popcnt = 1 << 23,
|
||||||
Aes = 1 << 25,
|
Aes = 1 << 25,
|
||||||
Osxsave = 1 << 27,
|
|
||||||
Avx = 1 << 28,
|
Avx = 1 << 28,
|
||||||
F16c = 1 << 29
|
F16c = 1 << 29
|
||||||
}
|
}
|
||||||
@@ -79,11 +52,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
public enum FeatureFlags7Ebx
|
public enum FeatureFlags7Ebx
|
||||||
{
|
{
|
||||||
Avx2 = 1 << 5,
|
Avx2 = 1 << 5,
|
||||||
Avx512f = 1 << 16,
|
Sha = 1 << 29
|
||||||
Avx512dq = 1 << 17,
|
|
||||||
Sha = 1 << 29,
|
|
||||||
Avx512bw = 1 << 30,
|
|
||||||
Avx512vl = 1 << 31
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@@ -92,21 +61,10 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Gfni = 1 << 8,
|
Gfni = 1 << 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
|
||||||
public enum Xcr0FlagsEax
|
|
||||||
{
|
|
||||||
Sse = 1 << 1,
|
|
||||||
YmmHi128 = 1 << 2,
|
|
||||||
Opmask = 1 << 5,
|
|
||||||
ZmmHi256 = 1 << 6,
|
|
||||||
Hi16Zmm = 1 << 7
|
|
||||||
}
|
|
||||||
|
|
||||||
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 FeatureFlags7Ecx FeatureInfo7Ecx { get; } = 0;
|
||||||
public static Xcr0FlagsEax Xcr0InfoEax { 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);
|
||||||
@@ -118,13 +76,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
public static bool SupportsSse42 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse42);
|
public static bool SupportsSse42 => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Sse42);
|
||||||
public static bool SupportsPopcnt => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Popcnt);
|
public static bool SupportsPopcnt => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Popcnt);
|
||||||
public static bool SupportsAesni => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Aes);
|
public static bool SupportsAesni => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Aes);
|
||||||
public static bool SupportsAvx => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Avx | FeatureFlags1Ecx.Osxsave) && Xcr0InfoEax.HasFlag(Xcr0FlagsEax.Sse | Xcr0FlagsEax.YmmHi128);
|
public static bool SupportsAvx => FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Avx);
|
||||||
public static bool SupportsAvx2 => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx2) && SupportsAvx;
|
public static bool SupportsAvx2 => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx2) && SupportsAvx;
|
||||||
public static bool SupportsAvx512F => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx512f) && FeatureInfo1Ecx.HasFlag(FeatureFlags1Ecx.Osxsave)
|
|
||||||
&& Xcr0InfoEax.HasFlag(Xcr0FlagsEax.Sse | Xcr0FlagsEax.YmmHi128 | Xcr0FlagsEax.Opmask | Xcr0FlagsEax.ZmmHi256 | Xcr0FlagsEax.Hi16Zmm);
|
|
||||||
public static bool SupportsAvx512Vl => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx512vl) && SupportsAvx512F;
|
|
||||||
public static bool SupportsAvx512Bw => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx512bw) && SupportsAvx512F;
|
|
||||||
public static bool SupportsAvx512Dq => FeatureInfo7Ebx.HasFlag(FeatureFlags7Ebx.Avx512dq) && SupportsAvx512F;
|
|
||||||
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 SupportsGfni => FeatureInfo7Ecx.HasFlag(FeatureFlags7Ecx.Gfni);
|
||||||
@@ -132,6 +85,5 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
public static bool ForceLegacySse { get; set; }
|
public static bool ForceLegacySse { get; set; }
|
||||||
|
|
||||||
public static bool SupportsVexEncoding => SupportsAvx && !ForceLegacySse;
|
public static bool SupportsVexEncoding => SupportsAvx && !ForceLegacySse;
|
||||||
public static bool SupportsEvexEncoding => SupportsAvx512F && !ForceLegacySse;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -182,7 +182,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Add(Intrinsic.X86Vfnmadd231ss, new IntrinsicInfo(X86Instruction.Vfnmadd231ss, IntrinsicType.Fma));
|
Add(Intrinsic.X86Vfnmadd231ss, new IntrinsicInfo(X86Instruction.Vfnmadd231ss, IntrinsicType.Fma));
|
||||||
Add(Intrinsic.X86Vfnmsub231sd, new IntrinsicInfo(X86Instruction.Vfnmsub231sd, IntrinsicType.Fma));
|
Add(Intrinsic.X86Vfnmsub231sd, new IntrinsicInfo(X86Instruction.Vfnmsub231sd, IntrinsicType.Fma));
|
||||||
Add(Intrinsic.X86Vfnmsub231ss, new IntrinsicInfo(X86Instruction.Vfnmsub231ss, IntrinsicType.Fma));
|
Add(Intrinsic.X86Vfnmsub231ss, new IntrinsicInfo(X86Instruction.Vfnmsub231ss, IntrinsicType.Fma));
|
||||||
Add(Intrinsic.X86Vpternlogd, new IntrinsicInfo(X86Instruction.Vpternlogd, IntrinsicType.TernaryImm));
|
|
||||||
Add(Intrinsic.X86Xorpd, new IntrinsicInfo(X86Instruction.Xorpd, IntrinsicType.Binary));
|
Add(Intrinsic.X86Xorpd, new IntrinsicInfo(X86Instruction.Xorpd, IntrinsicType.Binary));
|
||||||
Add(Intrinsic.X86Xorps, new IntrinsicInfo(X86Instruction.Xorps, IntrinsicType.Binary));
|
Add(Intrinsic.X86Xorps, new IntrinsicInfo(X86Instruction.Xorps, IntrinsicType.Binary));
|
||||||
}
|
}
|
||||||
|
@@ -219,7 +219,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Vfnmsub231sd,
|
Vfnmsub231sd,
|
||||||
Vfnmsub231ss,
|
Vfnmsub231ss,
|
||||||
Vpblendvb,
|
Vpblendvb,
|
||||||
Vpternlogd,
|
|
||||||
Xor,
|
Xor,
|
||||||
Xorpd,
|
Xorpd,
|
||||||
Xorps,
|
Xorps,
|
||||||
|
@@ -224,22 +224,7 @@ namespace ARMeilleure.Instructions
|
|||||||
|
|
||||||
public static void Not_V(ArmEmitterContext context)
|
public static void Not_V(ArmEmitterContext context)
|
||||||
{
|
{
|
||||||
if (Optimizations.UseAvx512Ortho)
|
if (Optimizations.UseSse2)
|
||||||
{
|
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
|
||||||
|
|
||||||
Operand n = GetVec(op.Rn);
|
|
||||||
|
|
||||||
Operand res = context.AddIntrinsic(Intrinsic.X86Vpternlogd, n, n, Const(0b01010101));
|
|
||||||
|
|
||||||
if (op.RegisterSize == RegisterSize.Simd64)
|
|
||||||
{
|
|
||||||
res = context.VectorZeroUpper64(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Copy(GetVec(op.Rd), res);
|
|
||||||
}
|
|
||||||
else if (Optimizations.UseSse2)
|
|
||||||
{
|
{
|
||||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||||
|
|
||||||
|
@@ -171,7 +171,6 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
X86Vfnmadd231ss,
|
X86Vfnmadd231ss,
|
||||||
X86Vfnmsub231sd,
|
X86Vfnmsub231sd,
|
||||||
X86Vfnmsub231ss,
|
X86Vfnmsub231ss,
|
||||||
X86Vpternlogd,
|
|
||||||
X86Xorpd,
|
X86Xorpd,
|
||||||
X86Xorps
|
X86Xorps
|
||||||
}
|
}
|
||||||
|
@@ -378,14 +378,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
if (Kind == OperandKind.LocalVariable)
|
return ((ulong)_data).GetHashCode();
|
||||||
{
|
|
||||||
return base.GetHashCode();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (int)Value ^ ((int)Kind << 16) ^ ((int)Type << 20);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(Operand operand)
|
public bool Equals(Operand operand)
|
||||||
|
@@ -17,10 +17,6 @@ namespace ARMeilleure
|
|||||||
public static bool UseSse42IfAvailable { get; set; } = true;
|
public static bool UseSse42IfAvailable { get; set; } = true;
|
||||||
public static bool UsePopCntIfAvailable { get; set; } = true;
|
public static bool UsePopCntIfAvailable { get; set; } = true;
|
||||||
public static bool UseAvxIfAvailable { get; set; } = true;
|
public static bool UseAvxIfAvailable { get; set; } = true;
|
||||||
public static bool UseAvx512FIfAvailable { get; set; } = true;
|
|
||||||
public static bool UseAvx512VlIfAvailable { get; set; } = true;
|
|
||||||
public static bool UseAvx512BwIfAvailable { get; set; } = true;
|
|
||||||
public static bool UseAvx512DqIfAvailable { get; set; } = true;
|
|
||||||
public static bool UseF16cIfAvailable { get; set; } = true;
|
public static bool UseF16cIfAvailable { get; set; } = true;
|
||||||
public static bool UseFmaIfAvailable { get; set; } = true;
|
public static bool UseFmaIfAvailable { get; set; } = true;
|
||||||
public static bool UseAesniIfAvailable { get; set; } = true;
|
public static bool UseAesniIfAvailable { get; set; } = true;
|
||||||
@@ -42,18 +38,11 @@ namespace ARMeilleure
|
|||||||
internal static bool UseSse42 => UseSse42IfAvailable && HardwareCapabilities.SupportsSse42;
|
internal static bool UseSse42 => UseSse42IfAvailable && HardwareCapabilities.SupportsSse42;
|
||||||
internal static bool UsePopCnt => UsePopCntIfAvailable && HardwareCapabilities.SupportsPopcnt;
|
internal static bool UsePopCnt => UsePopCntIfAvailable && HardwareCapabilities.SupportsPopcnt;
|
||||||
internal static bool UseAvx => UseAvxIfAvailable && HardwareCapabilities.SupportsAvx && !ForceLegacySse;
|
internal static bool UseAvx => UseAvxIfAvailable && HardwareCapabilities.SupportsAvx && !ForceLegacySse;
|
||||||
internal static bool UseAvx512F => UseAvx512FIfAvailable && HardwareCapabilities.SupportsAvx512F && !ForceLegacySse;
|
|
||||||
internal static bool UseAvx512Vl => UseAvx512VlIfAvailable && HardwareCapabilities.SupportsAvx512Vl && !ForceLegacySse;
|
|
||||||
internal static bool UseAvx512Bw => UseAvx512BwIfAvailable && HardwareCapabilities.SupportsAvx512Bw && !ForceLegacySse;
|
|
||||||
internal static bool UseAvx512Dq => UseAvx512DqIfAvailable && HardwareCapabilities.SupportsAvx512Dq && !ForceLegacySse;
|
|
||||||
internal static bool UseF16c => UseF16cIfAvailable && HardwareCapabilities.SupportsF16c;
|
internal static bool UseF16c => UseF16cIfAvailable && HardwareCapabilities.SupportsF16c;
|
||||||
internal static bool UseFma => UseFmaIfAvailable && HardwareCapabilities.SupportsFma;
|
internal static bool UseFma => UseFmaIfAvailable && HardwareCapabilities.SupportsFma;
|
||||||
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;
|
internal static bool UseGfni => UseGfniIfAvailable && HardwareCapabilities.SupportsGfni;
|
||||||
|
|
||||||
internal static bool UseAvx512Ortho => UseAvx512F && UseAvx512Vl;
|
|
||||||
internal static bool UseAvx512OrthoFloat => UseAvx512Ortho && UseAvx512Dq;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -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 = 3714; //! To be incremented manually for each change to the ARMeilleure project.
|
private const uint InternalVersion = 4140; //! 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";
|
||||||
@@ -952,8 +952,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
(uint)HardwareCapabilities.FeatureInfo1Ecx,
|
(uint)HardwareCapabilities.FeatureInfo1Ecx,
|
||||||
(uint)HardwareCapabilities.FeatureInfo1Edx,
|
(uint)HardwareCapabilities.FeatureInfo1Edx,
|
||||||
(uint)HardwareCapabilities.FeatureInfo7Ebx,
|
(uint)HardwareCapabilities.FeatureInfo7Ebx,
|
||||||
(uint)HardwareCapabilities.FeatureInfo7Ecx,
|
(uint)HardwareCapabilities.FeatureInfo7Ecx);
|
||||||
(uint)HardwareCapabilities.Xcr0InfoEax);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte GetMemoryManagerMode()
|
private static byte GetMemoryManagerMode()
|
||||||
@@ -973,7 +972,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
return osPlatform;
|
return osPlatform;
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 62*/)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 58*/)]
|
||||||
private struct OuterHeader
|
private struct OuterHeader
|
||||||
{
|
{
|
||||||
public ulong Magic;
|
public ulong Magic;
|
||||||
@@ -1004,8 +1003,8 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 20*/)]
|
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 16*/)]
|
||||||
private record struct FeatureInfo(uint FeatureInfo0, uint FeatureInfo1, uint FeatureInfo2, uint FeatureInfo3, uint FeatureInfo4);
|
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
|
||||||
|
@@ -45,7 +45,7 @@
|
|||||||
TextWrapping="Wrap" />
|
TextWrapping="Wrap" />
|
||||||
<TextBox
|
<TextBox
|
||||||
Name="Input"
|
Name="Input"
|
||||||
Grid.Row="2"
|
Grid.Row="3"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
|
@@ -142,6 +142,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
_drawState.FirstIndex = firstIndex;
|
_drawState.FirstIndex = firstIndex;
|
||||||
_drawState.IndexCount = indexCount;
|
_drawState.IndexCount = indexCount;
|
||||||
|
_drawState.DrawFirstVertex = drawFirstVertex;
|
||||||
|
_drawState.DrawVertexCount = drawVertexCount;
|
||||||
_currentSpecState.SetHasConstantBufferDrawParameters(false);
|
_currentSpecState.SetHasConstantBufferDrawParameters(false);
|
||||||
|
|
||||||
engine.UpdateState();
|
engine.UpdateState();
|
||||||
@@ -163,10 +165,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
_instancedIndexCount = ibCount != 0 ? ibCount : indexCount;
|
_instancedIndexCount = ibCount != 0 ? ibCount : indexCount;
|
||||||
|
|
||||||
var drawState = _state.State.VertexBufferDrawState;
|
_instancedDrawStateFirst = drawFirstVertex;
|
||||||
|
_instancedDrawStateCount = drawVertexCount;
|
||||||
_instancedDrawStateFirst = drawState.First;
|
|
||||||
_instancedDrawStateCount = drawState.Count;
|
|
||||||
|
|
||||||
_drawState.DrawIndexed = false;
|
_drawState.DrawIndexed = false;
|
||||||
|
|
||||||
@@ -415,6 +415,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
bool oldDrawIndexed = _drawState.DrawIndexed;
|
bool oldDrawIndexed = _drawState.DrawIndexed;
|
||||||
|
|
||||||
_drawState.DrawIndexed = false;
|
_drawState.DrawIndexed = false;
|
||||||
|
engine.ForceStateDirty(VertexBufferFirstMethodOffset * 4);
|
||||||
|
|
||||||
DrawEnd(engine, 0, 0, firstVertex, vertexCount);
|
DrawEnd(engine, 0, 0, firstVertex, vertexCount);
|
||||||
|
|
||||||
@@ -526,8 +527,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_state.State.VertexBufferDrawState.First = firstVertex;
|
_drawState.DrawFirstVertex = firstVertex;
|
||||||
_state.State.VertexBufferDrawState.Count = count;
|
_drawState.DrawVertexCount = count;
|
||||||
engine.ForceStateDirty(VertexBufferFirstMethodOffset * 4);
|
engine.ForceStateDirty(VertexBufferFirstMethodOffset * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,6 +17,16 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int IndexCount;
|
public int IndexCount;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// First vertex used on non-indexed draws. This value is stored somewhere else on indexed draws.
|
||||||
|
/// </summary>
|
||||||
|
public int DrawFirstVertex;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vertex count used on non-indexed draws. Indexed draws have a index count instead.
|
||||||
|
/// </summary>
|
||||||
|
public int DrawVertexCount;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if the next draw will be a indexed draw.
|
/// Indicates if the next draw will be a indexed draw.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -989,6 +989,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
bool drawIndexed = _drawState.DrawIndexed;
|
bool drawIndexed = _drawState.DrawIndexed;
|
||||||
bool drawIndirect = _drawState.DrawIndirect;
|
bool drawIndirect = _drawState.DrawIndirect;
|
||||||
|
int drawFirstVertex = _drawState.DrawFirstVertex;
|
||||||
|
int drawVertexCount = _drawState.DrawVertexCount;
|
||||||
uint vbEnableMask = 0;
|
uint vbEnableMask = 0;
|
||||||
|
|
||||||
for (int index = 0; index < Constants.TotalVertexBuffers; index++)
|
for (int index = 0; index < Constants.TotalVertexBuffers; index++)
|
||||||
@@ -1050,9 +1052,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
int firstInstance = (int)_state.State.FirstInstance;
|
int firstInstance = (int)_state.State.FirstInstance;
|
||||||
|
|
||||||
var drawState = _state.State.VertexBufferDrawState;
|
size = Math.Min(vbSize, (ulong)((firstInstance + drawFirstVertex + drawVertexCount) * stride));
|
||||||
|
|
||||||
size = Math.Min(vbSize, (ulong)((firstInstance + drawState.First + drawState.Count) * stride));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_pipeline.VertexBuffers[index] = new BufferPipelineDescriptor(_channel.MemoryManager.IsMapped(address), stride, divisor);
|
_pipeline.VertexBuffers[index] = new BufferPipelineDescriptor(_channel.MemoryManager.IsMapped(address), stride, divisor);
|
||||||
|
Reference in New Issue
Block a user