See merge request ryubing/ryujinx!214
This commit is contained in:
GreemDev 2025-11-11 12:55:36 -06:00
parent 49c70efdd5
commit 6b814fb973
171 changed files with 6011 additions and 6335 deletions

View file

@ -5,7 +5,7 @@ If you wish to build the emulator yourself, follow these steps:
### Step 1 ### Step 1
Install the [.NET 9.0 (or higher) SDK](https://dotnet.microsoft.com/download/dotnet/9.0). Install the [.NET 10.0 (or higher) SDK](https://dotnet.microsoft.com/en-us/download/dotnet/10.0).
Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json). Make sure your SDK version is higher or equal to the required version specified in [global.json](global.json).
### Step 2 ### Step 2

View file

@ -1,6 +1,6 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<LangVersion>latest</LangVersion> <LangVersion>preview</LangVersion>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

View file

@ -85,6 +85,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.github\workflows\build.yml = .github\workflows\build.yml .github\workflows\build.yml = .github\workflows\build.yml
.github\workflows\canary.yml = .github\workflows\canary.yml .github\workflows\canary.yml = .github\workflows\canary.yml
Directory.Packages.props = Directory.Packages.props Directory.Packages.props = Directory.Packages.props
Directory.Build.props = Directory.Build.props
.github\workflows\release.yml = .github\workflows\release.yml .github\workflows\release.yml = .github\workflows\release.yml
nuget.config = nuget.config nuget.config = nuget.config
EndProjectSection EndProjectSection

View file

@ -1,6 +1,6 @@
{ {
"sdk": { "sdk": {
"version": "9.0.100", "version": "10.0.100",
"rollForward": "latestFeature" "rollForward": "latestFeature"
} }
} }

View file

@ -25,9 +25,9 @@ namespace ARMeilleure.CodeGen.Arm64
static class ComparisonArm64Extensions static class ComparisonArm64Extensions
{ {
public static ArmCondition ToArmCondition(this Comparison comp) extension(Comparison comparison)
{ {
return comp switch public ArmCondition Arm => comparison switch
{ {
#pragma warning disable IDE0055 // Disable formatting #pragma warning disable IDE0055 // Disable formatting
Comparison.Equal => ArmCondition.Eq, Comparison.Equal => ArmCondition.Eq,
@ -42,7 +42,7 @@ namespace ARMeilleure.CodeGen.Arm64
Comparison.LessUI => ArmCondition.LtUn, Comparison.LessUI => ArmCondition.LtUn,
#pragma warning restore IDE0055 #pragma warning restore IDE0055
_ => throw new ArgumentException(null, nameof(comp)), _ => throw new ArgumentException(null, nameof(comparison))
}; };
} }
} }

View file

@ -181,10 +181,10 @@ namespace ARMeilleure.CodeGen.Arm64
public void Fmov(Operand rd, Operand rn, bool topHalf) public void Fmov(Operand rd, Operand rn, bool topHalf)
{ {
Debug.Assert(rd.Type.IsInteger() != rn.Type.IsInteger()); Debug.Assert(rd.Type.IsInteger != rn.Type.IsInteger);
Debug.Assert(rd.Type == OperandType.I64 || rn.Type == OperandType.I64 || !topHalf); Debug.Assert(rd.Type == OperandType.I64 || rn.Type == OperandType.I64 || !topHalf);
uint opcode = rd.Type.IsInteger() ? 0b110u : 0b111u; uint opcode = rd.Type.IsInteger ? 0b110u : 0b111u;
uint rmode = topHalf ? 1u << 19 : 0u; uint rmode = topHalf ? 1u << 19 : 0u;
uint ftype = rd.Type == OperandType.FP64 || rn.Type == OperandType.FP64 ? 1u << 22 : 0u; uint ftype = rd.Type == OperandType.FP64 || rn.Type == OperandType.FP64 ? 1u << 22 : 0u;
@ -411,7 +411,7 @@ namespace ARMeilleure.CodeGen.Arm64
public void Mov(Operand rd, Operand rn) public void Mov(Operand rd, Operand rn)
{ {
if (rd.Type.IsInteger()) if (rd.Type.IsInteger)
{ {
Orr(rd, Factory.Register(ZrRegister, RegisterType.Integer, rd.Type), rn); Orr(rd, Factory.Register(ZrRegister, RegisterType.Integer, rd.Type), rn);
} }
@ -973,7 +973,7 @@ namespace ARMeilleure.CodeGen.Arm64
uint instruction; uint instruction;
int scale; int scale;
if (type.IsInteger()) if (type.IsInteger)
{ {
instruction = intInst; instruction = intInst;
@ -1009,7 +1009,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
uint instruction; uint instruction;
if (type.IsInteger()) if (type.IsInteger)
{ {
instruction = intInst; instruction = intInst;

View file

@ -250,7 +250,7 @@ namespace ARMeilleure.CodeGen.Arm64
// ValidateBinOp(dest, src1, src2); // ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Add(dest, src1, src2); context.Assembler.Add(dest, src1, src2);
} }
@ -268,7 +268,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.And(dest, src1, src2); context.Assembler.And(dest, src1, src2);
} }
@ -281,7 +281,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Eor(dest, src1, src2); context.Assembler.Eor(dest, src1, src2);
} }
@ -298,7 +298,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Mvn(dest, source); context.Assembler.Mvn(dest, source);
} }
@ -311,7 +311,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Orr(dest, src1, src2); context.Assembler.Orr(dest, src1, src2);
} }
@ -322,7 +322,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition(); ArmCondition cond = ((Comparison)comp.AsInt32()).Arm;
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@ -336,7 +336,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Rev(dest, source); context.Assembler.Rev(dest, source);
} }
@ -354,7 +354,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(dest.Type == OperandType.I32); Debug.Assert(dest.Type == OperandType.I32);
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
ArmCondition cond = ((Comparison)comp.AsInt32()).ToArmCondition(); ArmCondition cond = ((Comparison)comp.AsInt32()).Arm;
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@ -428,7 +428,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(src1, src2); EnsureSameType(src1, src2);
Debug.Assert(src1.Type.IsInteger()); Debug.Assert(src1.Type.IsInteger);
context.Assembler.Cmp(src1, src2); context.Assembler.Cmp(src1, src2);
} }
@ -442,7 +442,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, src2, src3); EnsureSameType(dest, src2, src3);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
Debug.Assert(src1.Type == OperandType.I32); Debug.Assert(src1.Type == OperandType.I32);
context.Assembler.Cmp(src1, Const(src1.Type, 0)); context.Assembler.Cmp(src1, Const(src1.Type, 0));
@ -468,7 +468,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(dest.Type != source.Type); Debug.Assert(dest.Type != source.Type);
Debug.Assert(source.Type != OperandType.V128); Debug.Assert(source.Type != OperandType.V128);
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
context.Assembler.ScvtfScalar(dest, source); context.Assembler.ScvtfScalar(dest, source);
} }
@ -485,7 +485,7 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64); Debug.Assert(dest.Type is OperandType.FP32 or OperandType.FP64);
Debug.Assert(dest.Type != source.Type); Debug.Assert(dest.Type != source.Type);
Debug.Assert(source.Type.IsInteger()); Debug.Assert(source.Type.IsInteger);
context.Assembler.UcvtfScalar(dest, source); context.Assembler.UcvtfScalar(dest, source);
} }
@ -497,7 +497,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger() || source.Kind != OperandKind.Constant); Debug.Assert(dest.Type.IsInteger || source.Kind != OperandKind.Constant);
// Moves to the same register are useless. // Moves to the same register are useless.
if (dest.Kind == source.Kind && dest.Value == source.Value) if (dest.Kind == source.Kind && dest.Value == source.Value)
@ -529,7 +529,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Clz(dest, source); context.Assembler.Clz(dest, source);
} }
@ -542,7 +542,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateBinOp(dest, dividend, divisor); ValidateBinOp(dest, dividend, divisor);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Sdiv(dest, dividend, divisor); context.Assembler.Sdiv(dest, dividend, divisor);
} }
@ -576,7 +576,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.LdrhRiUn(value, address, 0); context.Assembler.LdrhRiUn(value, address, 0);
} }
@ -586,7 +586,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.LdrbRiUn(value, address, 0); context.Assembler.LdrbRiUn(value, address, 0);
} }
@ -604,7 +604,7 @@ namespace ARMeilleure.CodeGen.Arm64
EnsureSameType(dest, src1, src2); EnsureSameType(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Mul(dest, src1, src2); context.Assembler.Mul(dest, src1, src2);
} }
@ -647,7 +647,7 @@ namespace ARMeilleure.CodeGen.Arm64
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Neg(dest, source); context.Assembler.Neg(dest, source);
} }
@ -732,7 +732,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Sxth(dest, source); context.Assembler.Sxth(dest, source);
} }
@ -742,7 +742,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Sxtw(dest, source); context.Assembler.Sxtw(dest, source);
} }
@ -752,7 +752,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Sxtb(dest, source); context.Assembler.Sxtb(dest, source);
} }
@ -823,7 +823,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.StrhRiUn(value, address, 0); context.Assembler.StrhRiUn(value, address, 0);
} }
@ -833,7 +833,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.StrbRiUn(value, address, 0); context.Assembler.StrbRiUn(value, address, 0);
} }
@ -858,7 +858,7 @@ namespace ARMeilleure.CodeGen.Arm64
// ValidateBinOp(dest, src1, src2); // ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Sub(dest, src1, src2); context.Assembler.Sub(dest, src1, src2);
} }
@ -882,7 +882,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (dest != default) if (dest != default)
{ {
Debug.Assert(!dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger && source.Type.IsInteger);
OperandType destType = source.Type == OperandType.I64 ? OperandType.FP64 : OperandType.FP32; OperandType destType = source.Type == OperandType.I64 ? OperandType.FP64 : OperandType.FP32;
@ -901,9 +901,9 @@ namespace ARMeilleure.CodeGen.Arm64
byte index = src2.AsByte(); byte index = src2.AsByte();
Debug.Assert(index < OperandType.V128.GetSizeInBytes() / dest.Type.GetSizeInBytes()); Debug.Assert(index < OperandType.V128.ByteSize / dest.Type.ByteSize);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Umov(dest, src1, index, dest.Type == OperandType.I64 ? 3 : 2); context.Assembler.Umov(dest, src1, index, dest.Type == OperandType.I64 ? 3 : 2);
} }
@ -959,7 +959,7 @@ namespace ARMeilleure.CodeGen.Arm64
byte index = src3.AsByte(); byte index = src3.AsByte();
if (src2.Type.IsInteger()) if (src2.Type.IsInteger)
{ {
context.Assembler.Ins(dest, src2, index, src2.Type == OperandType.I64 ? 3 : 2); context.Assembler.Ins(dest, src2, index, src2.Type == OperandType.I64 ? 3 : 2);
} }
@ -1007,7 +1007,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
context.Assembler.CmeqVector(dest, dest, dest, 2); context.Assembler.CmeqVector(dest, dest, dest, 2);
} }
@ -1016,7 +1016,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
context.Assembler.EorVector(dest, dest, dest); context.Assembler.EorVector(dest, dest, dest);
} }
@ -1046,7 +1046,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Uxth(dest, source); context.Assembler.Uxth(dest, source);
} }
@ -1056,7 +1056,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
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. // 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) if (dest.Value == source.Value && source.Type == OperandType.I32)
@ -1072,7 +1072,7 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Uxtb(dest, source); context.Assembler.Uxtb(dest, source);
} }
@ -1169,7 +1169,7 @@ namespace ARMeilleure.CodeGen.Arm64
context.Assembler.StrRiPre(Register(reg, type), Register(SpRegister), -calleeSaveRegionSize); context.Assembler.StrRiPre(Register(reg, type), Register(SpRegister), -calleeSaveRegionSize);
} }
offset += type.GetSizeInBytes(); offset += type.ByteSize;
} }
while (mask != 0) while (mask != 0)
@ -1195,7 +1195,7 @@ namespace ARMeilleure.CodeGen.Arm64
context.Assembler.StpRiPre(Register(reg, type), Register(reg2, type), Register(SpRegister), -calleeSaveRegionSize); context.Assembler.StpRiPre(Register(reg, type), Register(reg2, type), Register(SpRegister), -calleeSaveRegionSize);
} }
offset += type.GetSizeInBytes() * 2; offset += type.ByteSize * 2;
} }
} }
@ -1273,7 +1273,7 @@ namespace ARMeilleure.CodeGen.Arm64
mask &= ~(1 << reg2); mask &= ~(1 << reg2);
offset -= type.GetSizeInBytes() * 2; offset -= type.ByteSize * 2;
if (offset != 0) if (offset != 0)
{ {
@ -1286,7 +1286,7 @@ namespace ARMeilleure.CodeGen.Arm64
} }
else else
{ {
offset -= type.GetSizeInBytes(); offset -= type.ByteSize;
if (offset != 0) if (offset != 0)
{ {
@ -1435,12 +1435,12 @@ namespace ARMeilleure.CodeGen.Arm64
OperandType valueType = GetMemOpValueType(currentOp); OperandType valueType = GetMemOpValueType(currentOp);
if (valueType != GetMemOpValueType(nextOp) || op1Offset + valueType.GetSizeInBytes() != op2Offset) if (valueType != GetMemOpValueType(nextOp) || op1Offset + valueType.ByteSize != op2Offset)
{ {
return false; return false;
} }
if (!CodeGenCommon.ConstFitsOnSImm7(op1Offset, valueType.GetSizeInBytesLog2())) if (!CodeGenCommon.ConstFitsOnSImm7(op1Offset, valueType.ByteSizeLog2))
{ {
return false; return false;
} }
@ -1549,7 +1549,7 @@ namespace ARMeilleure.CodeGen.Arm64
// EnsureSameReg (dest, src1); // EnsureSameReg (dest, src1);
EnsureSameType(dest, src1); EnsureSameType(dest, src1);
Debug.Assert(dest.Type.IsInteger() && src2.Type == OperandType.I32); Debug.Assert(dest.Type.IsInteger && src2.Type == OperandType.I32);
} }
private static void EnsureSameReg(Operand op1, Operand op2) private static void EnsureSameReg(Operand op1, Operand op2)

View file

@ -462,7 +462,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
instruction |= (sz << 22); instruction |= (sz << 22);
if (rd.Type.IsInteger()) if (rd.Type.IsInteger)
{ {
context.Assembler.WriteInstructionAuto(instruction, rd, rn); context.Assembler.WriteInstructionAuto(instruction, rd, rn);
} }
@ -490,7 +490,7 @@ namespace ARMeilleure.CodeGen.Arm64
instruction |= (sz << 22); instruction |= (sz << 22);
instruction |= (64 - fBits) << 10; instruction |= (64 - fBits) << 10;
if (rd.Type.IsInteger()) if (rd.Type.IsInteger)
{ {
Debug.Assert(rd.Type != OperandType.I32 || fBits <= 32); Debug.Assert(rd.Type != OperandType.I32 || fBits <= 32);

View file

@ -112,7 +112,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (src1.Kind == OperandKind.Constant) if (src1.Kind == OperandKind.Constant)
{ {
if (!src1.Type.IsInteger()) if (!src1.Type.IsInteger)
{ {
// Handle non-integer types (FP32, FP64 and V128). // Handle non-integer types (FP32, FP64 and V128).
// For instructions without an immediate operand, we do the following: // For instructions without an immediate operand, we do the following:
@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (src2.Kind == OperandKind.Constant) if (src2.Kind == OperandKind.Constant)
{ {
if (!src2.Type.IsInteger()) if (!src2.Type.IsInteger)
{ {
src2 = AddFloatConstantCopy(constants, nodes, node, src2); src2 = AddFloatConstantCopy(constants, nodes, node, src2);
@ -191,7 +191,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (src.Kind == OperandKind.Constant) if (src.Kind == OperandKind.Constant)
{ {
if (!src.Type.IsInteger()) if (!src.Type.IsInteger)
{ {
src = AddFloatConstantCopy(constants, nodes, node, src); src = AddFloatConstantCopy(constants, nodes, node, src);
@ -282,7 +282,7 @@ namespace ARMeilleure.CodeGen.Arm64
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount < intMax; passOnReg = intCount < intMax;
} }
@ -309,7 +309,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (passOnReg) if (passOnReg)
{ {
Operand argReg = source.Type.IsInteger() Operand argReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@ -327,7 +327,7 @@ namespace ARMeilleure.CodeGen.Arm64
InsertConstantRegCopies(constants, nodes, nodes.AddBefore(node, spillOp)); InsertConstantRegCopies(constants, nodes, nodes.AddBefore(node, spillOp));
stackOffset += source.Type.GetSizeInBytes(); stackOffset += source.Type.ByteSize;
} }
} }
@ -345,7 +345,7 @@ namespace ARMeilleure.CodeGen.Arm64
} }
else else
{ {
Operand retReg = dest.Type.IsInteger() Operand retReg = dest.Type.IsInteger
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type); : Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.Arm64
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount + 1 < intMax; passOnReg = intCount + 1 < intMax;
} }
@ -408,7 +408,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (passOnReg) if (passOnReg)
{ {
Operand argReg = source.Type.IsInteger() Operand argReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@ -521,7 +521,7 @@ namespace ARMeilleure.CodeGen.Arm64
} }
else else
{ {
Operand retReg = source.Type.IsInteger() Operand retReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type); : Xmm(CallingConvention.GetVecReturnRegister(), source.Type);
@ -551,7 +551,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
OperandType argType = cctx.FuncArgTypes[cIndex]; OperandType argType = cctx.FuncArgTypes[cIndex];
if (argType.IsInteger()) if (argType.IsInteger)
{ {
intCount++; intCount++;
} }
@ -567,7 +567,7 @@ namespace ARMeilleure.CodeGen.Arm64
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount < CallingConvention.GetArgumentsOnRegsCount(); passOnReg = intCount < CallingConvention.GetArgumentsOnRegsCount();
} }
@ -606,7 +606,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
Operand pArg = Local(dest.Type); Operand pArg = Local(dest.Type);
Operand argReg = dest.Type.IsInteger() Operand argReg = dest.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);

View file

@ -51,7 +51,7 @@ namespace ARMeilleure.CodeGen.Optimizations
if (trueSucc == block.ListNext) if (trueSucc == block.ListNext)
{ {
Comparison comp = (Comparison)branchOp.GetSource(2).AsInt32(); Comparison comp = (Comparison)branchOp.GetSource(2).AsInt32();
Comparison compInv = comp.Invert(); Comparison compInv = comp.Inverse;
branchOp.SetSource(2, Const((int)compInv)); branchOp.SetSource(2, Const((int)compInv));

View file

@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Optimizations
} }
else if (otherCompType == Comparison.Equal) else if (otherCompType == Comparison.Equal)
{ {
propCompType = compType.Invert(); propCompType = compType.Inverse;
} }
else else
{ {

View file

@ -105,7 +105,7 @@ namespace ARMeilleure.CodeGen.Optimizations
Operand x = operation.GetSource(0); Operand x = operation.GetSource(0);
Operand y = operation.GetSource(1); Operand y = operation.GetSource(1);
if (x == y && x.Type.IsInteger()) if (x == y && x.Type.IsInteger)
{ {
operation.TurnIntoCopy(Const(x.Type, 0)); operation.TurnIntoCopy(Const(x.Type, 0));
} }
@ -161,7 +161,7 @@ namespace ARMeilleure.CodeGen.Optimizations
private static bool IsConstEqual(Operand operand, ulong comparand) private static bool IsConstEqual(Operand operand, ulong comparand)
{ {
if (operand.Kind != OperandKind.Constant || !operand.Type.IsInteger()) if (operand.Kind != OperandKind.Constant || !operand.Type.IsInteger)
{ {
return false; return false;
} }

View file

@ -98,7 +98,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
OperandType type = types[copyDest]; OperandType type = types[copyDest];
type = type.IsInteger() ? OperandType.I64 : OperandType.V128; type = type.IsInteger ? OperandType.I64 : OperandType.V128;
EmitXorSwap(sequence, GetRegister(copyDest, type), GetRegister(copySource, type)); EmitXorSwap(sequence, GetRegister(copyDest, type), GetRegister(copySource, type));

View file

@ -178,7 +178,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
} }
else if (dest.Kind == OperandKind.Register) else if (dest.Kind == OperandKind.Register)
{ {
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
intFixedRegisters |= 1 << dest.GetRegister().Index; intFixedRegisters |= 1 << dest.GetRegister().Index;
} }
@ -236,7 +236,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
Register reg = info.Register.GetRegister(); Register reg = info.Register.GetRegister();
if (local.Type.IsInteger()) if (local.Type.IsInteger)
{ {
intLocalFreeRegisters |= 1 << reg.Index; intLocalFreeRegisters |= 1 << reg.Index;
} }
@ -254,7 +254,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (temp == default || info.Sequence != sequence) if (temp == default || info.Sequence != sequence)
{ {
temp = local.Type.IsInteger() temp = local.Type.IsInteger
? GetSpillTemp(local, intSpillTempRegisters, ref intLocalUse) ? GetSpillTemp(local, intSpillTempRegisters, ref intLocalUse)
: GetSpillTemp(local, vecSpillTempRegisters, ref vecLocalUse); : GetSpillTemp(local, vecSpillTempRegisters, ref vecLocalUse);
@ -335,7 +335,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (info.UsesAllocated == 0) if (info.UsesAllocated == 0)
{ {
int mask = dest.Type.IsInteger() int mask = dest.Type.IsInteger
? intLocalFreeRegisters ? intLocalFreeRegisters
: vecLocalFreeRegisters; : vecLocalFreeRegisters;
@ -343,9 +343,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
int selectedReg = BitOperations.TrailingZeroCount(mask); int selectedReg = BitOperations.TrailingZeroCount(mask);
info.Register = Register(selectedReg, info.Type.ToRegisterType(), info.Type); info.Register = Register(selectedReg, info.Type.Register, info.Type);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
intLocalFreeRegisters &= ~(1 << selectedReg); intLocalFreeRegisters &= ~(1 << selectedReg);
intUsedRegisters |= 1 << selectedReg; intUsedRegisters |= 1 << selectedReg;
@ -359,7 +359,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
else else
{ {
info.Register = default; info.Register = default;
info.SpillOffset = Const(stackAlloc.Allocate(dest.Type.GetSizeInBytes())); info.SpillOffset = Const(stackAlloc.Allocate(dest.Type.ByteSize));
} }
} }
@ -377,7 +377,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (temp == default || info.Sequence != sequence) if (temp == default || info.Sequence != sequence)
{ {
temp = dest.Type.IsInteger() temp = dest.Type.IsInteger
? GetSpillTemp(dest, intSpillTempRegisters, ref intLocalAsg) ? GetSpillTemp(dest, intSpillTempRegisters, ref intLocalAsg)
: GetSpillTemp(dest, vecSpillTempRegisters, ref vecLocalAsg); : GetSpillTemp(dest, vecSpillTempRegisters, ref vecLocalAsg);
@ -443,7 +443,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
useMask |= 1 << selectedReg; useMask |= 1 << selectedReg;
return Register(selectedReg, local.Type.ToRegisterType(), local.Type); return Register(selectedReg, local.Type.Register, local.Type);
} }
private static int UsesCount(Operand local) private static int UsesCount(Operand local)

View file

@ -208,7 +208,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount) private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
{ {
RegisterType regType = current.Local.Type.ToRegisterType(); RegisterType regType = current.Local.Type.Register;
Span<int> freePositions = stackalloc int[registersCount]; Span<int> freePositions = stackalloc int[registersCount];
@ -318,7 +318,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount) private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex, int registersCount)
{ {
RegisterType regType = current.Local.Type.ToRegisterType(); RegisterType regType = current.Local.Type.Register;
Span<int> usePositions = stackalloc int[registersCount]; Span<int> usePositions = stackalloc int[registersCount];
Span<int> blockedPositions = stackalloc int[registersCount]; Span<int> blockedPositions = stackalloc int[registersCount];

View file

@ -10,7 +10,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public int Allocate(OperandType type) public int Allocate(OperandType type)
{ {
return Allocate(type.GetSizeInBytes()); return Allocate(type.ByteSize);
} }
public int Allocate(int sizeInBytes) public int Allocate(int sizeInBytes)

View file

@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
ref readonly InstructionInfo info = ref _instTable[(int)X86Instruction.Movd]; ref readonly InstructionInfo info = ref _instTable[(int)X86Instruction.Movd];
if (source.Type.IsInteger() || source.Kind == OperandKind.Memory) if (source.Type.IsInteger || source.Kind == OperandKind.Memory)
{ {
WriteOpCode(dest, default, source, OperandType.None, info.Flags, info.OpRRM, rrm: true); WriteOpCode(dest, default, source, OperandType.None, info.Flags, info.OpRRM, rrm: true);
} }
@ -416,11 +416,11 @@ namespace ARMeilleure.CodeGen.X86
InstructionFlags flags = info.Flags | InstructionFlags.RexW; InstructionFlags flags = info.Flags | InstructionFlags.RexW;
if (source.Type.IsInteger() || source.Kind == OperandKind.Memory) if (source.Type.IsInteger || source.Kind == OperandKind.Memory)
{ {
WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRRM, rrm: true); WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRRM, rrm: true);
} }
else if (dest.Type.IsInteger() || dest.Kind == OperandKind.Memory) else if (dest.Type.IsInteger || dest.Kind == OperandKind.Memory)
{ {
WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRMR); WriteOpCode(dest, default, source, OperandType.None, flags, info.OpRMR);
} }

View file

@ -289,7 +289,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Popcnt(dest, source, dest.Type); context.Assembler.Popcnt(dest, source, dest.Type);
@ -303,7 +303,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
context.Assembler.WriteInstruction(info.Inst, dest, source); context.Assembler.WriteInstruction(info.Inst, dest, source);
@ -315,7 +315,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && !source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && !source.Type.IsInteger);
if (operation.Intrinsic == Intrinsic.X86Cvtsi2si) if (operation.Intrinsic == Intrinsic.X86Cvtsi2si)
{ {
@ -349,8 +349,8 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
} }
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
Debug.Assert(!src2.Type.IsInteger() || src2.Kind == OperandKind.Constant); Debug.Assert(!src2.Type.IsInteger || src2.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2); context.Assembler.WriteInstruction(info.Inst, dest, src1, src2);
@ -370,7 +370,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
} }
Debug.Assert(!dest.Type.IsInteger() && src2.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger && src2.Type.IsInteger);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src2.Type); context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src2.Type);
@ -385,7 +385,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
Debug.Assert(dest.Type.IsInteger() && src1.Type.IsInteger() && src2.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && src1.Type.IsInteger && src2.Type.IsInteger);
context.Assembler.WriteInstruction(info.Inst, dest, src2, dest.Type); context.Assembler.WriteInstruction(info.Inst, dest, src2, dest.Type);
@ -405,7 +405,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
} }
Debug.Assert(!dest.Type.IsInteger() && src2.Kind == OperandKind.Constant); Debug.Assert(!dest.Type.IsInteger && src2.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2.AsByte()); context.Assembler.WriteInstruction(info.Inst, dest, src1, src2.AsByte());
@ -421,7 +421,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, src1, src2, src3); EnsureSameType(dest, src1, src2, src3);
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
if (info.Inst == X86Instruction.Blendvpd && HardwareCapabilities.SupportsVexEncoding) if (info.Inst == X86Instruction.Blendvpd && HardwareCapabilities.SupportsVexEncoding)
{ {
@ -461,7 +461,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
} }
Debug.Assert(!dest.Type.IsInteger() && src3.Kind == OperandKind.Constant); Debug.Assert(!dest.Type.IsInteger && src3.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src3.AsByte()); context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src3.AsByte());
@ -512,7 +512,7 @@ namespace ARMeilleure.CodeGen.X86
Operand src1 = operation.GetSource(0); Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1); Operand src2 = operation.GetSource(1);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
// If Destination and Source 1 Operands are the same, perform a standard add as there are no benefits to using LEA. // If Destination and Source 1 Operands are the same, perform a standard add as there are no benefits to using LEA.
if (dest.Kind == src1.Kind && dest.Value == src1.Value) if (dest.Kind == src1.Kind && dest.Value == src1.Value)
@ -567,7 +567,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
// Note: GenerateCompareCommon makes the assumption that BitwiseAnd will emit only a single `and` // Note: GenerateCompareCommon makes the assumption that BitwiseAnd will emit only a single `and`
// instruction. // instruction.
@ -582,7 +582,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Xor(dest, src2, dest.Type); context.Assembler.Xor(dest, src2, dest.Type);
} }
@ -599,7 +599,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Not(dest); context.Assembler.Not(dest);
} }
@ -612,7 +612,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Or(dest, src2, dest.Type); context.Assembler.Or(dest, src2, dest.Type);
} }
@ -623,7 +623,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition(); X86Condition cond = ((Comparison)comp.AsInt32()).X86;
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@ -637,7 +637,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Bswap(dest); context.Assembler.Bswap(dest);
} }
@ -661,7 +661,7 @@ namespace ARMeilleure.CodeGen.X86
Debug.Assert(dest.Type == OperandType.I32); Debug.Assert(dest.Type == OperandType.I32);
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
X86Condition cond = ((Comparison)comp.AsInt32()).ToX86Condition(); X86Condition cond = ((Comparison)comp.AsInt32()).X86;
GenerateCompareCommon(context, operation); GenerateCompareCommon(context, operation);
@ -676,7 +676,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(src1, src2); EnsureSameType(src1, src2);
Debug.Assert(src1.Type.IsInteger()); Debug.Assert(src1.Type.IsInteger);
if (src2.Kind == OperandKind.Constant && src2.Value == 0) if (src2.Kind == OperandKind.Constant && src2.Value == 0)
{ {
@ -766,7 +766,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src3); EnsureSameReg(dest, src3);
EnsureSameType(dest, src2, src3); EnsureSameType(dest, src2, src3);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
Debug.Assert(src1.Type == OperandType.I32); Debug.Assert(src1.Type == OperandType.I32);
context.Assembler.Test(src1, src1, src1.Type); context.Assembler.Test(src1, src1, src1.Type);
@ -792,9 +792,9 @@ namespace ARMeilleure.CodeGen.X86
if (dest.Type == OperandType.FP32) if (dest.Type == OperandType.FP32)
{ {
Debug.Assert(source.Type.IsInteger() || source.Type == OperandType.FP64); Debug.Assert(source.Type.IsInteger || source.Type == OperandType.FP64);
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
context.Assembler.Xorps(dest, dest, dest); context.Assembler.Xorps(dest, dest, dest);
context.Assembler.Cvtsi2ss(dest, dest, source, source.Type); context.Assembler.Cvtsi2ss(dest, dest, source, source.Type);
@ -808,9 +808,9 @@ namespace ARMeilleure.CodeGen.X86
} }
else /* if (dest.Type == OperandType.FP64) */ else /* if (dest.Type == OperandType.FP64) */
{ {
Debug.Assert(source.Type.IsInteger() || source.Type == OperandType.FP32); Debug.Assert(source.Type.IsInteger || source.Type == OperandType.FP32);
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
context.Assembler.Xorps(dest, dest, dest); context.Assembler.Xorps(dest, dest, dest);
context.Assembler.Cvtsi2sd(dest, dest, source, source.Type); context.Assembler.Cvtsi2sd(dest, dest, source, source.Type);
@ -831,7 +831,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger() || source.Kind != OperandKind.Constant); Debug.Assert(dest.Type.IsInteger || source.Kind != OperandKind.Constant);
// Moves to the same register are useless. // Moves to the same register are useless.
if (dest.Kind == source.Kind && dest.Value == source.Value) if (dest.Kind == source.Kind && dest.Value == source.Value)
@ -845,7 +845,7 @@ namespace ARMeilleure.CodeGen.X86
// Assemble "mov reg, 0" as "xor reg, reg" as the later is more efficient. // Assemble "mov reg, 0" as "xor reg, reg" as the later is more efficient.
context.Assembler.Xor(dest, dest, OperandType.I32); context.Assembler.Xor(dest, dest, OperandType.I32);
} }
else if (dest.Type.IsInteger()) else if (dest.Type.IsInteger)
{ {
context.Assembler.Mov(dest, source, dest.Type); context.Assembler.Mov(dest, source, dest.Type);
} }
@ -862,7 +862,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Bsr(dest, source, dest.Type); context.Assembler.Bsr(dest, source, dest.Type);
@ -894,12 +894,12 @@ namespace ARMeilleure.CodeGen.X86
Operand dividend = operation.GetSource(0); Operand dividend = operation.GetSource(0);
Operand divisor = operation.GetSource(1); Operand divisor = operation.GetSource(1);
if (!dest.Type.IsInteger()) if (!dest.Type.IsInteger)
{ {
ValidateBinOp(dest, dividend, divisor); ValidateBinOp(dest, dividend, divisor);
} }
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
divisor = operation.GetSource(2); divisor = operation.GetSource(2);
@ -932,7 +932,7 @@ namespace ARMeilleure.CodeGen.X86
Operand rdx = Register(X86Register.Rdx); Operand rdx = Register(X86Register.Rdx);
Debug.Assert(divisor.Type.IsInteger()); Debug.Assert(divisor.Type.IsInteger);
context.Assembler.Xor(rdx, rdx, OperandType.I32); context.Assembler.Xor(rdx, rdx, OperandType.I32);
context.Assembler.Div(divisor); context.Assembler.Div(divisor);
@ -967,7 +967,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.Movzx16(value, address, value.Type); context.Assembler.Movzx16(value, address, value.Type);
} }
@ -977,7 +977,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.Movzx8(value, address, value.Type); context.Assembler.Movzx8(value, address, value.Type);
} }
@ -1000,7 +1000,7 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameType(dest, src1, src2); EnsureSameType(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
if (src2.Kind == OperandKind.Constant) if (src2.Kind == OperandKind.Constant)
{ {
@ -1046,7 +1046,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger);
context.Assembler.Neg(dest); context.Assembler.Neg(dest);
} }
@ -1107,7 +1107,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Movsx16(dest, source, dest.Type); context.Assembler.Movsx16(dest, source, dest.Type);
} }
@ -1117,7 +1117,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Movsx32(dest, source, dest.Type); context.Assembler.Movsx32(dest, source, dest.Type);
} }
@ -1127,7 +1127,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Movsx8(dest, source, dest.Type); context.Assembler.Movsx8(dest, source, dest.Type);
} }
@ -1187,7 +1187,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.Mov16(address, value); context.Assembler.Mov16(address, value);
} }
@ -1197,7 +1197,7 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger);
context.Assembler.Mov8(address, value); context.Assembler.Mov8(address, value);
} }
@ -1210,7 +1210,7 @@ namespace ARMeilleure.CodeGen.X86
ValidateBinOp(dest, src1, src2); ValidateBinOp(dest, src1, src2);
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
context.Assembler.Sub(dest, src2, dest.Type); context.Assembler.Sub(dest, src2, dest.Type);
} }
@ -1236,7 +1236,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(!dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger && source.Type.IsInteger);
if (source.Type == OperandType.I32) if (source.Type == OperandType.I32)
{ {
@ -1259,7 +1259,7 @@ namespace ARMeilleure.CodeGen.X86
byte index = src2.AsByte(); byte index = src2.AsByte();
Debug.Assert(index < OperandType.V128.GetSizeInBytes() / dest.Type.GetSizeInBytes()); Debug.Assert(index < OperandType.V128.ByteSize / dest.Type.ByteSize);
if (dest.Type == OperandType.I32) if (dest.Type == OperandType.I32)
{ {
@ -1541,7 +1541,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
context.Assembler.Pcmpeqw(dest, dest, dest); context.Assembler.Pcmpeqw(dest, dest, dest);
} }
@ -1550,7 +1550,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger);
context.Assembler.Xorps(dest, dest, dest); context.Assembler.Xorps(dest, dest, dest);
} }
@ -1580,7 +1580,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Movzx16(dest, source, OperandType.I32); context.Assembler.Movzx16(dest, source, OperandType.I32);
} }
@ -1590,7 +1590,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
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. // 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) if (dest.Value == source.Value && source.Type == OperandType.I32)
@ -1606,7 +1606,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger && source.Type.IsInteger);
context.Assembler.Movzx8(dest, source, OperandType.I32); context.Assembler.Movzx8(dest, source, OperandType.I32);
} }
@ -1713,12 +1713,12 @@ namespace ARMeilleure.CodeGen.X86
EnsureSameReg(dest, src1); EnsureSameReg(dest, src1);
EnsureSameType(dest, src1); EnsureSameType(dest, src1);
Debug.Assert(dest.Type.IsInteger() && src2.Type == OperandType.I32); Debug.Assert(dest.Type.IsInteger && src2.Type == OperandType.I32);
} }
private static void EnsureSameReg(Operand op1, Operand op2) private static void EnsureSameReg(Operand op1, Operand op2)
{ {
if (!op1.Type.IsInteger() && HardwareCapabilities.SupportsVexEncoding) if (!op1.Type.IsInteger && HardwareCapabilities.SupportsVexEncoding)
{ {
return; return;
} }

View file

@ -86,7 +86,7 @@ namespace ARMeilleure.CodeGen.X86
break; break;
case Instruction.Negate: case Instruction.Negate:
if (!node.GetSource(0).Type.IsInteger()) if (!node.GetSource(0).Type.IsInteger)
{ {
GenerateNegate(block.Operations, node); GenerateNegate(block.Operations, node);
} }
@ -159,7 +159,7 @@ namespace ARMeilleure.CodeGen.X86
if (src1.Kind == OperandKind.Constant) if (src1.Kind == OperandKind.Constant)
{ {
if (!src1.Type.IsInteger()) if (!src1.Type.IsInteger)
{ {
// Handle non-integer types (FP32, FP64 and V128). // Handle non-integer types (FP32, FP64 and V128).
// For instructions without an immediate operand, we do the following: // For instructions without an immediate operand, we do the following:
@ -208,7 +208,7 @@ namespace ARMeilleure.CodeGen.X86
if (src2.Kind == OperandKind.Constant) if (src2.Kind == OperandKind.Constant)
{ {
if (!src2.Type.IsInteger()) if (!src2.Type.IsInteger)
{ {
src2 = AddXmmCopy(nodes, node, src2); src2 = AddXmmCopy(nodes, node, src2);
@ -298,7 +298,7 @@ namespace ARMeilleure.CodeGen.X86
// - The dividend is always in RDX:RAX. // - The dividend is always in RDX:RAX.
// - The result is always in RAX. // - The result is always in RAX.
// - Additionally it also writes the remainder in RDX. // - Additionally it also writes the remainder in RDX.
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
Operand src1 = node.GetSource(0); Operand src1 = node.GetSource(0);
@ -466,7 +466,7 @@ namespace ARMeilleure.CodeGen.X86
Operand dest = node.Destination; Operand dest = node.Destination;
Operand source = node.GetSource(0); Operand source = node.GetSource(0);
Debug.Assert(source.Type.IsInteger(), $"Invalid source type \"{source.Type}\"."); Debug.Assert(source.Type.IsInteger, $"Invalid source type \"{source.Type}\".");
Operation currentNode = node; Operation currentNode = node;
@ -654,10 +654,10 @@ namespace ARMeilleure.CodeGen.X86
switch (operation.Instruction) switch (operation.Instruction)
{ {
case Instruction.Add: case Instruction.Add:
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger(); return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger;
case Instruction.Multiply: case Instruction.Multiply:
case Instruction.Subtract: case Instruction.Subtract:
return !HardwareCapabilities.SupportsVexEncoding || operation.Destination.Type.IsInteger(); return !HardwareCapabilities.SupportsVexEncoding || operation.Destination.Type.IsInteger;
case Instruction.BitwiseAnd: case Instruction.BitwiseAnd:
case Instruction.BitwiseExclusiveOr: case Instruction.BitwiseExclusiveOr:
@ -672,7 +672,7 @@ namespace ARMeilleure.CodeGen.X86
return true; return true;
case Instruction.Divide: case Instruction.Divide:
return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger(); return !HardwareCapabilities.SupportsVexEncoding && !operation.Destination.Type.IsInteger;
case Instruction.VectorInsert: case Instruction.VectorInsert:
case Instruction.VectorInsert16: case Instruction.VectorInsert16:

View file

@ -35,7 +35,7 @@ namespace ARMeilleure.CodeGen.X86
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount < intMax; passOnReg = intCount < intMax;
} }
@ -62,7 +62,7 @@ namespace ARMeilleure.CodeGen.X86
if (passOnReg) if (passOnReg)
{ {
Operand argReg = source.Type.IsInteger() Operand argReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@ -80,7 +80,7 @@ namespace ARMeilleure.CodeGen.X86
InsertConstantRegCopies(nodes, nodes.AddBefore(node, spillOp)); InsertConstantRegCopies(nodes, nodes.AddBefore(node, spillOp));
stackOffset += source.Type.GetSizeInBytes(); stackOffset += source.Type.ByteSize;
} }
} }
@ -102,7 +102,7 @@ namespace ARMeilleure.CodeGen.X86
} }
else else
{ {
Operand retReg = dest.Type.IsInteger() Operand retReg = dest.Type.IsInteger
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type); : Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
@ -137,7 +137,7 @@ namespace ARMeilleure.CodeGen.X86
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount + 1 < intMax; passOnReg = intCount + 1 < intMax;
} }
@ -160,7 +160,7 @@ namespace ARMeilleure.CodeGen.X86
if (passOnReg) if (passOnReg)
{ {
Operand argReg = source.Type.IsInteger() Operand argReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount++), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount++), source.Type);
@ -210,7 +210,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
OperandType argType = cctx.FuncArgTypes[cIndex]; OperandType argType = cctx.FuncArgTypes[cIndex];
if (argType.IsInteger()) if (argType.IsInteger)
{ {
intCount++; intCount++;
} }
@ -226,7 +226,7 @@ namespace ARMeilleure.CodeGen.X86
bool passOnReg; bool passOnReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
passOnReg = intCount < CallingConvention.GetIntArgumentsOnRegsCount(); passOnReg = intCount < CallingConvention.GetIntArgumentsOnRegsCount();
} }
@ -265,7 +265,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand pArg = Local(dest.Type); Operand pArg = Local(dest.Type);
Operand argReg = dest.Type.IsInteger() Operand argReg = dest.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(intCount), dest.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type); : Xmm(CallingConvention.GetVecArgumentRegister(vecCount), dest.Type);
@ -320,7 +320,7 @@ namespace ARMeilleure.CodeGen.X86
} }
else else
{ {
Operand retReg = source.Type.IsInteger() Operand retReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntReturnRegister(), source.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), source.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), source.Type); : Xmm(CallingConvention.GetVecReturnRegister(), source.Type);

View file

@ -40,7 +40,7 @@ namespace ARMeilleure.CodeGen.X86
if (dest != default && dest.Type == OperandType.V128) if (dest != default && dest.Type == OperandType.V128)
{ {
int stackOffset = AllocateOnStack(dest.Type.GetSizeInBytes()); int stackOffset = AllocateOnStack(dest.Type.ByteSize);
arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64); arg0Reg = Gpr(CallingConvention.GetIntArgumentRegister(0), OperandType.I64);
@ -76,7 +76,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand stackAddr = Local(OperandType.I64); Operand stackAddr = Local(OperandType.I64);
int stackOffset = AllocateOnStack(source.Type.GetSizeInBytes()); int stackOffset = AllocateOnStack(source.Type.ByteSize);
nodes.AddBefore(node, Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset))); nodes.AddBefore(node, Operation(Instruction.StackAlloc, stackAddr, Const(stackOffset)));
@ -96,7 +96,7 @@ namespace ARMeilleure.CodeGen.X86
int argIndex = index + retArgs; int argIndex = index + retArgs;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
argReg = Gpr(CallingConvention.GetIntArgumentRegister(argIndex), source.Type); argReg = Gpr(CallingConvention.GetIntArgumentRegister(argIndex), source.Type);
} }
@ -140,7 +140,7 @@ namespace ARMeilleure.CodeGen.X86
} }
else else
{ {
Operand retReg = dest.Type.IsInteger() Operand retReg = dest.Type.IsInteger
? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type) ? Gpr(CallingConvention.GetIntReturnRegister(), dest.Type)
: Xmm(CallingConvention.GetVecReturnRegister(), dest.Type); : Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
@ -171,7 +171,7 @@ namespace ARMeilleure.CodeGen.X86
for (int index = 0; index < argsCount; index++) for (int index = 0; index < argsCount; index++)
{ {
Operand source = node.GetSource(1 + index); Operand source = node.GetSource(1 + index);
Operand argReg = source.Type.IsInteger() Operand argReg = source.Type.IsInteger
? Gpr(CallingConvention.GetIntArgumentRegister(index), source.Type) ? Gpr(CallingConvention.GetIntArgumentRegister(index), source.Type)
: Xmm(CallingConvention.GetVecArgumentRegister(index), source.Type); : Xmm(CallingConvention.GetVecArgumentRegister(index), source.Type);
@ -219,7 +219,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand argReg, pArg; Operand argReg, pArg;
if (dest.Type.IsInteger()) if (dest.Type.IsInteger)
{ {
argReg = Gpr(CallingConvention.GetIntArgumentRegister(index), dest.Type); argReg = Gpr(CallingConvention.GetIntArgumentRegister(index), dest.Type);
pArg = Local(dest.Type); pArg = Local(dest.Type);
@ -283,7 +283,7 @@ namespace ARMeilleure.CodeGen.X86
Operand source = node.GetSource(0); Operand source = node.GetSource(0);
Operand retReg; Operand retReg;
if (source.Type.IsInteger()) if (source.Type.IsInteger)
{ {
retReg = Gpr(CallingConvention.GetIntReturnRegister(), source.Type); retReg = Gpr(CallingConvention.GetIntReturnRegister(), source.Type);
} }

View file

@ -25,9 +25,9 @@ namespace ARMeilleure.CodeGen.X86
static class ComparisonX86Extensions static class ComparisonX86Extensions
{ {
public static X86Condition ToX86Condition(this Comparison comp) extension(Comparison comparison)
{ {
return comp switch public X86Condition X86 => comparison switch
{ {
#pragma warning disable IDE0055 // Disable formatting #pragma warning disable IDE0055 // Disable formatting
Comparison.Equal => X86Condition.Equal, Comparison.Equal => X86Condition.Equal,
@ -42,7 +42,7 @@ namespace ARMeilleure.CodeGen.X86
Comparison.LessUI => X86Condition.Below, Comparison.LessUI => X86Condition.Below,
#pragma warning restore IDE0055 #pragma warning restore IDE0055
_ => throw new ArgumentException(null, nameof(comp)), _ => throw new ArgumentException(null, nameof(comparison))
}; };
} }
} }

View file

@ -22,11 +22,11 @@ namespace ARMeilleure.Decoders
static class ConditionExtensions static class ConditionExtensions
{ {
public static Condition Invert(this Condition cond) extension(Condition condition)
{ {
// Bit 0 of all conditions is basically a negation bit, so // Bit 0 of all conditions is basically a negation bit, so
// inverting this bit has the effect of inverting the condition. // inverting this bit has the effect of inverting the condition.
return (Condition)((int)cond ^ 1); public Condition Inverse => (Condition)((int)condition ^ 1);
} }
} }
} }

View file

@ -16,7 +16,7 @@ namespace ARMeilleure.Instructions
public static Operand EmitCrc32(ArmEmitterContext context, Operand crc, Operand value, int size, bool castagnoli) public static Operand EmitCrc32(ArmEmitterContext context, Operand crc, Operand value, int size, bool castagnoli)
{ {
Debug.Assert(crc.Type.IsInteger() && value.Type.IsInteger()); Debug.Assert(crc.Type.IsInteger && value.Type.IsInteger);
Debug.Assert(size is >= 0 and < 4); Debug.Assert(size is >= 0 and < 4);
Debug.Assert((size < 3) || (value.Type == OperandType.I64)); Debug.Assert((size < 3) || (value.Type == OperandType.I64));

View file

@ -157,7 +157,7 @@ namespace ARMeilleure.Instructions
context.Copy(temp, value); context.Copy(temp, value);
if (!context.Memory.Type.IsHostMappedOrTracked()) if (!context.Memory.Type.IsHostMappedOrTracked)
{ {
context.Branch(lblEnd); context.Branch(lblEnd);
@ -198,7 +198,7 @@ namespace ARMeilleure.Instructions
SetInt(context, rt, value); SetInt(context, rt, value);
if (!context.Memory.Type.IsHostMappedOrTracked()) if (!context.Memory.Type.IsHostMappedOrTracked)
{ {
context.Branch(lblEnd); context.Branch(lblEnd);
@ -265,7 +265,7 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(rt), value); context.Copy(GetVec(rt), value);
if (!context.Memory.Type.IsHostMappedOrTracked()) if (!context.Memory.Type.IsHostMappedOrTracked)
{ {
context.Branch(lblEnd); context.Branch(lblEnd);
@ -312,7 +312,7 @@ namespace ARMeilleure.Instructions
break; break;
} }
if (!context.Memory.Type.IsHostMappedOrTracked()) if (!context.Memory.Type.IsHostMappedOrTracked)
{ {
context.Branch(lblEnd); context.Branch(lblEnd);
@ -385,7 +385,7 @@ namespace ARMeilleure.Instructions
break; break;
} }
if (!context.Memory.Type.IsHostMappedOrTracked()) if (!context.Memory.Type.IsHostMappedOrTracked)
{ {
context.Branch(lblEnd); context.Branch(lblEnd);
@ -399,11 +399,11 @@ namespace ARMeilleure.Instructions
public static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblSlowPath, bool write, int size) public static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblSlowPath, bool write, int size)
{ {
if (context.Memory.Type.IsHostMapped()) if (context.Memory.Type.IsHostMapped)
{ {
return EmitHostMappedPointer(context, address); return EmitHostMappedPointer(context, address);
} }
else if (context.Memory.Type.IsHostTracked()) else if (context.Memory.Type.IsHostTracked)
{ {
if (address.Type == OperandType.I32) if (address.Type == OperandType.I32)
{ {

View file

@ -1,692 +0,0 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFallback
{
#region "ShrImm64"
[UnmanagedCallersOnly]
public static long SignedShrImm64(long value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
if (value < 0L)
{
return -1L;
}
else /* if (value >= 0L) */
{
return 0L;
}
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
if (shift <= 63)
{
long add = value + roundConst;
if ((~value & (value ^ add)) < 0L)
{
return (long)((ulong)add >> shift);
}
else
{
return add >> shift;
}
}
else /* if (shift == 64) */
{
return 0L;
}
}
}
[UnmanagedCallersOnly]
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
ulong add = value + (ulong)roundConst;
if ((add < value) && (add < (ulong)roundConst))
{
if (shift <= 63)
{
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
}
else /* if (shift == 64) */
{
return 1UL;
}
}
else
{
if (shift <= 63)
{
return add >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
}
}
#endregion
#region "Saturation"
[UnmanagedCallersOnly]
public static int SatF32ToS32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF32ToS64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF32ToU32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF32ToU64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
[UnmanagedCallersOnly]
public static int SatF64ToS32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF64ToS64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF64ToU32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF64ToU64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
#endregion
#region "Count"
[UnmanagedCallersOnly]
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
value ^= value >> 1;
int highBit = size - 2;
for (int bit = highBit; bit >= 0; bit--)
{
if (((int)(value >> bit) & 0b1) != 0)
{
return (ulong)(highBit - bit);
}
}
return (ulong)(size - 1);
}
private static ReadOnlySpan<byte> ClzNibbleTbl => [4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
[UnmanagedCallersOnly]
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
if (value == 0ul)
{
return (ulong)size;
}
int nibbleIdx = size;
int preCount, count = 0;
do
{
nibbleIdx -= 4;
preCount = ClzNibbleTbl[(int)(value >> nibbleIdx) & 0b1111];
count += preCount;
}
while (preCount == 4);
return (ulong)count;
}
#endregion
#region "Table"
[UnmanagedCallersOnly]
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(default, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(default, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
}
[UnmanagedCallersOnly]
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(dest, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
}
private static V128 TblOrTbx(V128 dest, V128 vector, int bytes, params ReadOnlySpan<V128> tb)
{
byte[] res = new byte[16];
if (dest != default)
{
Buffer.BlockCopy(dest.ToArray(), 0, res, 0, bytes);
}
byte[] table = new byte[tb.Length * 16];
for (byte index = 0; index < tb.Length; index++)
{
Buffer.BlockCopy(tb[index].ToArray(), 0, table, index * 16, 16);
}
byte[] v = vector.ToArray();
for (byte index = 0; index < bytes; index++)
{
byte tblIndex = v[index];
if (tblIndex < table.Length)
{
res[index] = table[tblIndex];
}
}
return new V128(res);
}
#endregion
#region "Crc32"
private const uint Crc32RevPoly = 0xedb88320;
private const uint Crc32cRevPoly = 0x82f63b78;
[UnmanagedCallersOnly]
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
private static uint Crc32h(uint crc, uint poly, ushort val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
return crc;
}
private static uint Crc32w(uint crc, uint poly, uint val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
return crc;
}
private static uint Crc32x(uint crc, uint poly, ulong val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
crc = Crc32(crc, poly, (byte)(val >> 32));
crc = Crc32(crc, poly, (byte)(val >> 40));
crc = Crc32(crc, poly, (byte)(val >> 48));
crc = Crc32(crc, poly, (byte)(val >> 56));
return crc;
}
private static uint Crc32(uint crc, uint poly, byte val)
{
crc ^= val;
for (int bit = 7; bit >= 0; bit--)
{
uint mask = (uint)(-(int)(crc & 1));
crc = (crc >> 1) ^ (poly & mask);
}
return crc;
}
#endregion
#region "Aes"
[UnmanagedCallersOnly]
public static V128 Decrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 Encrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 InverseMixColumns(V128 value)
{
return CryptoHelper.AesInvMixColumns(value);
}
[UnmanagedCallersOnly]
public static V128 MixColumns(V128 value)
{
return CryptoHelper.AesMixColumns(value);
}
#endregion
#region "Sha1"
[UnmanagedCallersOnly]
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaChoose(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static uint FixedRotate(uint hash_e)
{
return hash_e.Rol(30);
}
[UnmanagedCallersOnly]
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaMajority(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaParity(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
{
ulong t2 = w4_7.Extract<ulong>(0);
ulong t1 = w0_3.Extract<ulong>(1);
V128 result = new(t1, t2);
return result ^ (w0_3 ^ w8_11);
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
{
V128 t = tw0_3 ^ (w12_15 >> 32);
uint tE0 = t.Extract<uint>(0);
uint tE1 = t.Extract<uint>(1);
uint tE2 = t.Extract<uint>(2);
uint tE3 = t.Extract<uint>(3);
return new V128(tE0.Rol(1), tE1.Rol(1), tE2.Rol(1), tE3.Rol(1) ^ tE0.Rol(2));
}
private static void Rol32_160(ref uint y, ref V128 x)
{
uint xE3 = x.Extract<uint>(3);
x <<= 32;
x.Insert(0, y);
y = xE3;
}
private static uint ShaChoose(uint x, uint y, uint z)
{
return ((y ^ z) & x) ^ z;
}
private static uint ShaMajority(uint x, uint y, uint z)
{
return (x & y) | ((x | y) & z);
}
private static uint ShaParity(uint x, uint y, uint z)
{
return x ^ y ^ z;
}
private static uint Rol(this uint value, int count)
{
return (value << count) | (value >> (32 - count));
}
#endregion
#region "Sha256"
[UnmanagedCallersOnly]
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
}
[UnmanagedCallersOnly]
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
{
V128 result = new();
for (int e = 0; e <= 3; e++)
{
uint elt = (e <= 2 ? w0_3 : w4_7).Extract<uint>(e <= 2 ? e + 1 : 0);
elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3);
elt += w0_3.Extract<uint>(e);
result.Insert(e, elt);
}
return result;
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
{
V128 result = new();
ulong t1 = w12_15.Extract<ulong>(1);
for (int e = 0; e <= 1; e++)
{
uint elt = t1.ULongPart(e);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + w8_11.Extract<uint>(e + 1);
result.Insert(e, elt);
}
t1 = result.Extract<ulong>(0);
for (int e = 2; e <= 3; e++)
{
uint elt = t1.ULongPart(e - 2);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + (e == 2 ? w8_11 : w12_15).Extract<uint>(e == 2 ? 3 : 0);
result.Insert(e, elt);
}
return result;
}
private static V128 Sha256Hash(V128 x, V128 y, V128 w, bool part1)
{
for (int e = 0; e <= 3; e++)
{
uint chs = ShaChoose(y.Extract<uint>(0),
y.Extract<uint>(1),
y.Extract<uint>(2));
uint maj = ShaMajority(x.Extract<uint>(0),
x.Extract<uint>(1),
x.Extract<uint>(2));
uint t1 = y.Extract<uint>(3) + ShaHashSigma1(y.Extract<uint>(0)) + chs + w.Extract<uint>(e);
uint t2 = t1 + x.Extract<uint>(3);
x.Insert(3, t2);
t2 = t1 + ShaHashSigma0(x.Extract<uint>(0)) + maj;
y.Insert(3, t2);
Rol32_256(ref y, ref x);
}
return part1 ? x : y;
}
private static void Rol32_256(ref V128 y, ref V128 x)
{
uint yE3 = y.Extract<uint>(3);
uint xE3 = x.Extract<uint>(3);
y <<= 32;
x <<= 32;
y.Insert(0, xE3);
x.Insert(0, yE3);
}
private static uint ShaHashSigma0(uint x)
{
return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22);
}
private static uint ShaHashSigma1(uint x)
{
return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25);
}
private static uint Ror(this uint value, int count)
{
return (value >> count) | (value << (32 - count));
}
private static uint Lsr(this uint value, int count)
{
return value >> count;
}
private static uint ULongPart(this ulong value, int part)
{
return part == 0
? (uint)(value & 0xFFFFFFFFUL)
: (uint)(value >> 32);
}
#endregion
[UnmanagedCallersOnly]
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
{
V128 result = V128.Zero;
V128 op2_128 = new(op2, 0);
for (int i = 0; i < 64; i++)
{
if (((op1 >> i) & 1) == 1)
{
result ^= op2_128 << i;
}
}
return result;
}
}
}

View file

@ -0,0 +1,32 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 Decrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 Encrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
}
[UnmanagedCallersOnly]
public static V128 InverseMixColumns(V128 value)
{
return CryptoHelper.AesInvMixColumns(value);
}
[UnmanagedCallersOnly]
public static V128 MixColumns(V128 value)
{
return CryptoHelper.AesMixColumns(value);
}
}
}

View file

@ -0,0 +1,50 @@
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
value ^= value >> 1;
int highBit = size - 2;
for (int bit = highBit; bit >= 0; bit--)
{
if (((int)(value >> bit) & 0b1) != 0)
{
return (ulong)(highBit - bit);
}
}
return (ulong)(size - 1);
}
private static ReadOnlySpan<byte> ClzNibbleTbl => [4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0];
[UnmanagedCallersOnly]
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
if (value == 0ul)
{
return (ulong)size;
}
int nibbleIdx = size;
int preCount, count = 0;
do
{
nibbleIdx -= 4;
preCount = ClzNibbleTbl[(int)(value >> nibbleIdx) & 0b1111];
count += preCount;
}
while (preCount == 4);
return (ulong)count;
}
}
}

View file

@ -0,0 +1,74 @@
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
private const uint Crc32RevPoly = 0xedb88320;
private const uint Crc32cRevPoly = 0x82f63b78;
[UnmanagedCallersOnly]
public static uint Crc32b(uint crc, byte value) => Crc32(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cb(uint crc, byte value) => Crc32(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
[UnmanagedCallersOnly]
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
private static uint Crc32h(uint crc, uint poly, ushort val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
return crc;
}
private static uint Crc32w(uint crc, uint poly, uint val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
return crc;
}
private static uint Crc32x(uint crc, uint poly, ulong val)
{
crc = Crc32(crc, poly, (byte)(val >> 0));
crc = Crc32(crc, poly, (byte)(val >> 8));
crc = Crc32(crc, poly, (byte)(val >> 16));
crc = Crc32(crc, poly, (byte)(val >> 24));
crc = Crc32(crc, poly, (byte)(val >> 32));
crc = Crc32(crc, poly, (byte)(val >> 40));
crc = Crc32(crc, poly, (byte)(val >> 48));
crc = Crc32(crc, poly, (byte)(val >> 56));
return crc;
}
private static uint Crc32(uint crc, uint poly, byte val)
{
crc ^= val;
for (int bit = 7; bit >= 0; bit--)
{
uint mask = (uint)(-(int)(crc & 1));
crc = (crc >> 1) ^ (poly & mask);
}
return crc;
}
}
}

View file

@ -0,0 +1,103 @@
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static int SatF32ToS32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF32ToS64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF32ToU32(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF32ToU64(float value)
{
if (float.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
[UnmanagedCallersOnly]
public static int SatF64ToS32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= int.MaxValue ? int.MaxValue :
value <= int.MinValue ? int.MinValue : (int)value;
}
[UnmanagedCallersOnly]
public static long SatF64ToS64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= long.MaxValue ? long.MaxValue :
value <= long.MinValue ? long.MinValue : (long)value;
}
[UnmanagedCallersOnly]
public static uint SatF64ToU32(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= uint.MaxValue ? uint.MaxValue :
value <= uint.MinValue ? uint.MinValue : (uint)value;
}
[UnmanagedCallersOnly]
public static ulong SatF64ToU64(double value)
{
if (double.IsNaN(value))
{
return 0;
}
return value >= ulong.MaxValue ? ulong.MaxValue :
value <= ulong.MinValue ? ulong.MinValue : (ulong)value;
}
}
}

View file

@ -0,0 +1,131 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 HashChoose(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaChoose(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static uint FixedRotate(uint hash_e)
{
return hash_e.Rol(30);
}
[UnmanagedCallersOnly]
public static V128 HashMajority(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaMajority(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 HashParity(V128 hash_abcd, uint hash_e, V128 wk)
{
for (int e = 0; e <= 3; e++)
{
uint t = ShaParity(hash_abcd.Extract<uint>(1),
hash_abcd.Extract<uint>(2),
hash_abcd.Extract<uint>(3));
hash_e += Rol(hash_abcd.Extract<uint>(0), 5) + t + wk.Extract<uint>(e);
t = Rol(hash_abcd.Extract<uint>(1), 30);
hash_abcd.Insert(1, t);
Rol32_160(ref hash_e, ref hash_abcd);
}
return hash_abcd;
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart1(V128 w0_3, V128 w4_7, V128 w8_11)
{
ulong t2 = w4_7.Extract<ulong>(0);
ulong t1 = w0_3.Extract<ulong>(1);
V128 result = new(t1, t2);
return result ^ (w0_3 ^ w8_11);
}
[UnmanagedCallersOnly]
public static V128 Sha1SchedulePart2(V128 tw0_3, V128 w12_15)
{
V128 t = tw0_3 ^ (w12_15 >> 32);
uint tE0 = t.Extract<uint>(0);
uint tE1 = t.Extract<uint>(1);
uint tE2 = t.Extract<uint>(2);
uint tE3 = t.Extract<uint>(3);
return new V128(tE0.Rol(1), tE1.Rol(1), tE2.Rol(1), tE3.Rol(1) ^ tE0.Rol(2));
}
private static void Rol32_160(ref uint y, ref V128 x)
{
uint xE3 = x.Extract<uint>(3);
x <<= 32;
x.Insert(0, y);
y = xE3;
}
private static uint ShaChoose(uint x, uint y, uint z)
{
return ((y ^ z) & x) ^ z;
}
private static uint ShaMajority(uint x, uint y, uint z)
{
return (x & y) | ((x | y) & z);
}
private static uint ShaParity(uint x, uint y, uint z)
{
return x ^ y ^ z;
}
private static uint Rol(this uint value, int count)
{
return (value << count) | (value >> (32 - count));
}
}
}

View file

@ -0,0 +1,140 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 HashLower(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: true);
}
[UnmanagedCallersOnly]
public static V128 HashUpper(V128 hash_abcd, V128 hash_efgh, V128 wk)
{
return Sha256Hash(hash_abcd, hash_efgh, wk, part1: false);
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart1(V128 w0_3, V128 w4_7)
{
V128 result = new();
for (int e = 0; e <= 3; e++)
{
uint elt = (e <= 2 ? w0_3 : w4_7).Extract<uint>(e <= 2 ? e + 1 : 0);
elt = elt.Ror(7) ^ elt.Ror(18) ^ elt.Lsr(3);
elt += w0_3.Extract<uint>(e);
result.Insert(e, elt);
}
return result;
}
[UnmanagedCallersOnly]
public static V128 Sha256SchedulePart2(V128 w0_3, V128 w8_11, V128 w12_15)
{
V128 result = new();
ulong t1 = w12_15.Extract<ulong>(1);
for (int e = 0; e <= 1; e++)
{
uint elt = t1.ULongPart(e);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + w8_11.Extract<uint>(e + 1);
result.Insert(e, elt);
}
t1 = result.Extract<ulong>(0);
for (int e = 2; e <= 3; e++)
{
uint elt = t1.ULongPart(e - 2);
elt = elt.Ror(17) ^ elt.Ror(19) ^ elt.Lsr(10);
elt += w0_3.Extract<uint>(e) + (e == 2 ? w8_11 : w12_15).Extract<uint>(e == 2 ? 3 : 0);
result.Insert(e, elt);
}
return result;
}
private static V128 Sha256Hash(V128 x, V128 y, V128 w, bool part1)
{
for (int e = 0; e <= 3; e++)
{
uint chs = ShaChoose(y.Extract<uint>(0),
y.Extract<uint>(1),
y.Extract<uint>(2));
uint maj = ShaMajority(x.Extract<uint>(0),
x.Extract<uint>(1),
x.Extract<uint>(2));
uint t1 = y.Extract<uint>(3) + ShaHashSigma1(y.Extract<uint>(0)) + chs + w.Extract<uint>(e);
uint t2 = t1 + x.Extract<uint>(3);
x.Insert(3, t2);
t2 = t1 + ShaHashSigma0(x.Extract<uint>(0)) + maj;
y.Insert(3, t2);
Rol32_256(ref y, ref x);
}
return part1 ? x : y;
}
private static void Rol32_256(ref V128 y, ref V128 x)
{
uint yE3 = y.Extract<uint>(3);
uint xE3 = x.Extract<uint>(3);
y <<= 32;
x <<= 32;
y.Insert(0, xE3);
x.Insert(0, yE3);
}
private static uint ShaHashSigma0(uint x)
{
return x.Ror(2) ^ x.Ror(13) ^ x.Ror(22);
}
private static uint ShaHashSigma1(uint x)
{
return x.Ror(6) ^ x.Ror(11) ^ x.Ror(25);
}
private static uint Ror(this uint value, int count)
{
return (value >> count) | (value << (32 - count));
}
private static uint Lsr(this uint value, int count)
{
return value >> count;
}
private static uint ULongPart(this ulong value, int part)
{
return part == 0
? (uint)(value & 0xFFFFFFFFUL)
: (uint)(value >> 32);
}
}
}

View file

@ -0,0 +1,93 @@
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static long SignedShrImm64(long value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
if (value < 0L)
{
return -1L;
}
else /* if (value >= 0L) */
{
return 0L;
}
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
if (shift <= 63)
{
long add = value + roundConst;
if ((~value & (value ^ add)) < 0L)
{
return (long)((ulong)add >> shift);
}
else
{
return add >> shift;
}
}
else /* if (shift == 64) */
{
return 0L;
}
}
}
[UnmanagedCallersOnly]
public static ulong UnsignedShrImm64(ulong value, long roundConst, int shift)
{
if (roundConst == 0L)
{
if (shift <= 63)
{
return value >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
else /* if (roundConst == 1L << (shift - 1)) */
{
ulong add = value + (ulong)roundConst;
if ((add < value) && (add < (ulong)roundConst))
{
if (shift <= 63)
{
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
}
else /* if (shift == 64) */
{
return 1UL;
}
}
else
{
if (shift <= 63)
{
return add >> shift;
}
else /* if (shift == 64) */
{
return 0UL;
}
}
}
}
}
}

View file

@ -0,0 +1,88 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 Tbl1(V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(default, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbl2(V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(default, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbl3(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbl4(V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(default, vector, bytes, tb0, tb1, tb2, tb3);
}
[UnmanagedCallersOnly]
public static V128 Tbx1(V128 dest, V128 vector, int bytes, V128 tb0)
{
return TblOrTbx(dest, vector, bytes, tb0);
}
[UnmanagedCallersOnly]
public static V128 Tbx2(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1);
}
[UnmanagedCallersOnly]
public static V128 Tbx3(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2);
}
[UnmanagedCallersOnly]
public static V128 Tbx4(V128 dest, V128 vector, int bytes, V128 tb0, V128 tb1, V128 tb2, V128 tb3)
{
return TblOrTbx(dest, vector, bytes, tb0, tb1, tb2, tb3);
}
private static V128 TblOrTbx(V128 dest, V128 vector, int bytes, params ReadOnlySpan<V128> tb)
{
byte[] res = new byte[16];
if (dest != default)
{
Buffer.BlockCopy(dest.ToArray(), 0, res, 0, bytes);
}
byte[] table = new byte[tb.Length * 16];
for (byte index = 0; index < tb.Length; index++)
{
Buffer.BlockCopy(tb[index].ToArray(), 0, table, index * 16, 16);
}
byte[] v = vector.ToArray();
for (byte index = 0; index < bytes; index++)
{
byte tblIndex = v[index];
if (tblIndex < table.Length)
{
res[index] = table[tblIndex];
}
}
return new V128(res);
}
}
}

View file

@ -0,0 +1,26 @@
using ARMeilleure.State;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static partial class SoftFallback
{
[UnmanagedCallersOnly]
public static V128 PolynomialMult64_128(ulong op1, ulong op2)
{
V128 result = V128.Zero;
V128 op2_128 = new(op2, 0);
for (int i = 0; i < 64; i++)
{
if (((op1 >> i) & 1) == 1)
{
result ^= op2_128 << i;
}
}
return result;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,111 @@
using ARMeilleure.State;
using System;
using System.Diagnostics;
namespace ARMeilleure.Instructions
{
static class SoftFloat
{
static SoftFloat()
{
RecipEstimateTable = BuildRecipEstimateTable();
RecipSqrtEstimateTable = BuildRecipSqrtEstimateTable();
}
public static readonly byte[] RecipEstimateTable;
public static readonly byte[] RecipSqrtEstimateTable;
private static byte[] BuildRecipEstimateTable()
{
byte[] tbl = new byte[256];
for (int idx = 0; idx < 256; idx++)
{
uint src = (uint)idx + 256u;
Debug.Assert(src is >= 256u and < 512u);
src = (src << 1) + 1u;
uint aux = (1u << 19) / src;
uint dst = (aux + 1u) >> 1;
Debug.Assert(dst is >= 256u and < 512u);
tbl[idx] = (byte)(dst - 256u);
}
return tbl;
}
private static byte[] BuildRecipSqrtEstimateTable()
{
byte[] tbl = new byte[384];
for (int idx = 0; idx < 384; idx++)
{
uint src = (uint)idx + 128u;
Debug.Assert(src is >= 128u and < 512u);
if (src < 256u)
{
src = (src << 1) + 1u;
}
else
{
src = (src >> 1) << 1;
src = (src + 1u) << 1;
}
uint aux = 512u;
while (src * (aux + 1u) * (aux + 1u) < (1u << 28))
{
aux++;
}
uint dst = (aux + 1u) >> 1;
Debug.Assert(dst is >= 256u and < 512u);
tbl[idx] = (byte)(dst - 256u);
}
return tbl;
}
public static void FPProcessException(FPException exc, ExecutionContext context)
{
FPProcessException(exc, context, context.Fpcr);
}
public static void FPProcessException(FPException exc, ExecutionContext context, FPCR fpcr)
{
int enable = (int)exc + 8;
if ((fpcr & (FPCR)(1 << enable)) != 0)
{
throw new NotImplementedException("Floating-point trap handling.");
}
else
{
context.Fpsr |= (FPSR)(1 << (int)exc);
}
}
extension(FPCR fpcr)
{
public FPRoundingMode RoundingMode
{
get
{
const int RModeShift = 22;
return (FPRoundingMode)(((uint)fpcr >> RModeShift) & 3u);
}
}
}
}
}

View file

@ -0,0 +1,212 @@
using ARMeilleure.State;
using System;
namespace ARMeilleure.Instructions
{
static class SoftFloat16
{
public static ushort FPDefaultNaN()
{
return (ushort)0x7E00u;
}
public static ushort FPInfinity(bool sign)
{
return sign ? (ushort)0xFC00u : (ushort)0x7C00u;
}
public static ushort FPZero(bool sign)
{
return sign ? (ushort)0x8000u : (ushort)0x0000u;
}
public static ushort FPMaxNormal(bool sign)
{
return sign ? (ushort)0xFBFFu : (ushort)0x7BFFu;
}
public static double FPUnpackCv(
this ushort valueBits,
out FPType type,
out bool sign,
ExecutionContext context)
{
sign = (~(uint)valueBits & 0x8000u) == 0u;
uint exp16 = ((uint)valueBits & 0x7C00u) >> 10;
uint frac16 = (uint)valueBits & 0x03FFu;
double real;
if (exp16 == 0u)
{
if (frac16 == 0u)
{
type = FPType.Zero;
real = 0d;
}
else
{
type = FPType.Nonzero; // Subnormal.
real = Math.Pow(2d, -14) * ((double)frac16 * Math.Pow(2d, -10));
}
}
else if (exp16 == 0x1Fu && (context.Fpcr & FPCR.Ahp) == 0)
{
if (frac16 == 0u)
{
type = FPType.Infinity;
real = Math.Pow(2d, 1000);
}
else
{
type = (~frac16 & 0x0200u) == 0u ? FPType.QNaN : FPType.SNaN;
real = 0d;
}
}
else
{
type = FPType.Nonzero; // Normal.
real = Math.Pow(2d, (int)exp16 - 15) * (1d + (double)frac16 * Math.Pow(2d, -10));
}
return sign ? -real : real;
}
public static ushort FPRoundCv(double real, ExecutionContext context)
{
const int MinimumExp = -14;
const int E = 5;
const int F = 10;
bool sign;
double mantissa;
if (real < 0d)
{
sign = true;
mantissa = -real;
}
else
{
sign = false;
mantissa = real;
}
int exponent = 0;
while (mantissa < 1d)
{
mantissa *= 2d;
exponent--;
}
while (mantissa >= 2d)
{
mantissa /= 2d;
exponent++;
}
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u)
{
mantissa /= Math.Pow(2d, MinimumExp - exponent);
}
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{
SoftFloat.FPProcessException(FPException.Underflow, context);
}
bool overflowToInf;
bool roundUp;
switch (context.Fpcr.RoundingMode)
{
case FPRoundingMode.ToNearest:
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
overflowToInf = true;
break;
case FPRoundingMode.TowardsPlusInfinity:
roundUp = (error != 0d && !sign);
overflowToInf = !sign;
break;
case FPRoundingMode.TowardsMinusInfinity:
roundUp = (error != 0d && sign);
overflowToInf = sign;
break;
case FPRoundingMode.TowardsZero:
roundUp = false;
overflowToInf = false;
break;
default:
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
}
if (roundUp)
{
intMant++;
if (intMant == 1u << F)
{
biasedExp = 1u;
}
if (intMant == 1u << (F + 1))
{
biasedExp++;
intMant >>= 1;
}
}
ushort resultBits;
if ((context.Fpcr & FPCR.Ahp) == 0)
{
if (biasedExp >= (1u << E) - 1u)
{
resultBits = overflowToInf ? FPInfinity(sign) : FPMaxNormal(sign);
SoftFloat.FPProcessException(FPException.Overflow, context);
error = 1d;
}
else
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | (biasedExp & 0x1Fu) << 10 | (intMant & 0x03FFu));
}
}
else
{
if (biasedExp >= 1u << E)
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
SoftFloat.FPProcessException(FPException.InvalidOp, context);
error = 0d;
}
else
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | (biasedExp & 0x1Fu) << 10 | (intMant & 0x03FFu));
}
}
if (error != 0d)
{
SoftFloat.FPProcessException(FPException.Inexact, context);
}
return resultBits;
}
}
}

View file

@ -0,0 +1,182 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat16_32
{
[UnmanagedCallersOnly]
public static float FPConvert(ushort valueBits)
{
ExecutionContext context = NativeInterface.GetContext();
double real = valueBits.FPUnpackCv(out FPType type, out bool sign, context);
float result;
if (type is FPType.SNaN or FPType.QNaN)
{
if ((context.Fpcr & FPCR.Dn) != 0)
{
result = SoftFloat32.FPDefaultNaN();
}
else
{
result = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
result = SoftFloat32.FPInfinity(sign);
}
else if (type == FPType.Zero)
{
result = SoftFloat32.FPZero(sign);
}
else
{
result = FPRoundCv(real, context);
}
return result;
}
private static float FPRoundCv(double real, ExecutionContext context)
{
const int MinimumExp = -126;
const int E = 8;
const int F = 23;
bool sign;
double mantissa;
if (real < 0d)
{
sign = true;
mantissa = -real;
}
else
{
sign = false;
mantissa = real;
}
int exponent = 0;
while (mantissa < 1d)
{
mantissa *= 2d;
exponent--;
}
while (mantissa >= 2d)
{
mantissa /= 2d;
exponent++;
}
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
{
context.Fpsr |= FPSR.Ufc;
return SoftFloat32.FPZero(sign);
}
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u)
{
mantissa /= Math.Pow(2d, MinimumExp - exponent);
}
uint intMant = (uint)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{
SoftFloat.FPProcessException(FPException.Underflow, context);
}
bool overflowToInf;
bool roundUp;
switch (context.Fpcr.RoundingMode)
{
case FPRoundingMode.ToNearest:
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
overflowToInf = true;
break;
case FPRoundingMode.TowardsPlusInfinity:
roundUp = (error != 0d && !sign);
overflowToInf = !sign;
break;
case FPRoundingMode.TowardsMinusInfinity:
roundUp = (error != 0d && sign);
overflowToInf = sign;
break;
case FPRoundingMode.TowardsZero:
roundUp = false;
overflowToInf = false;
break;
default:
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
}
if (roundUp)
{
intMant++;
if (intMant == 1u << F)
{
biasedExp = 1u;
}
if (intMant == 1u << (F + 1))
{
biasedExp++;
intMant >>= 1;
}
}
float result;
if (biasedExp >= (1u << E) - 1u)
{
result = overflowToInf ? SoftFloat32.FPInfinity(sign) : SoftFloat32.FPMaxNormal(sign);
SoftFloat.FPProcessException(FPException.Overflow, context);
error = 1d;
}
else
{
result = BitConverter.Int32BitsToSingle(
(int)((sign ? 1u : 0u) << 31 | (biasedExp & 0xFFu) << 23 | (intMant & 0x007FFFFFu)));
}
if (error != 0d)
{
SoftFloat.FPProcessException(FPException.Inexact, context);
}
return result;
}
private static float FPConvertNaN(ushort valueBits)
{
return BitConverter.Int32BitsToSingle(
(int)(((uint)valueBits & 0x8000u) << 16 | 0x7FC00000u | ((uint)valueBits & 0x01FFu) << 13));
}
}
}

View file

@ -0,0 +1,182 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat16_64
{
[UnmanagedCallersOnly]
public static double FPConvert(ushort valueBits)
{
ExecutionContext context = NativeInterface.GetContext();
double real = valueBits.FPUnpackCv(out FPType type, out bool sign, context);
double result;
if (type is FPType.SNaN or FPType.QNaN)
{
if ((context.Fpcr & FPCR.Dn) != 0)
{
result = SoftFloat64.FPDefaultNaN();
}
else
{
result = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
result = SoftFloat64.FPInfinity(sign);
}
else if (type == FPType.Zero)
{
result = SoftFloat64.FPZero(sign);
}
else
{
result = FPRoundCv(real, context);
}
return result;
}
private static double FPRoundCv(double real, ExecutionContext context)
{
const int MinimumExp = -1022;
const int E = 11;
const int F = 52;
bool sign;
double mantissa;
if (real < 0d)
{
sign = true;
mantissa = -real;
}
else
{
sign = false;
mantissa = real;
}
int exponent = 0;
while (mantissa < 1d)
{
mantissa *= 2d;
exponent--;
}
while (mantissa >= 2d)
{
mantissa /= 2d;
exponent++;
}
if ((context.Fpcr & FPCR.Fz) != 0 && exponent < MinimumExp)
{
context.Fpsr |= FPSR.Ufc;
return SoftFloat64.FPZero(sign);
}
uint biasedExp = (uint)Math.Max(exponent - MinimumExp + 1, 0);
if (biasedExp == 0u)
{
mantissa /= Math.Pow(2d, MinimumExp - exponent);
}
ulong intMant = (ulong)Math.Floor(mantissa * Math.Pow(2d, F));
double error = mantissa * Math.Pow(2d, F) - (double)intMant;
if (biasedExp == 0u && (error != 0d || (context.Fpcr & FPCR.Ufe) != 0))
{
SoftFloat.FPProcessException(FPException.Underflow, context);
}
bool overflowToInf;
bool roundUp;
switch (context.Fpcr.RoundingMode)
{
case FPRoundingMode.ToNearest:
roundUp = (error > 0.5d || (error == 0.5d && (intMant & 1u) == 1u));
overflowToInf = true;
break;
case FPRoundingMode.TowardsPlusInfinity:
roundUp = (error != 0d && !sign);
overflowToInf = !sign;
break;
case FPRoundingMode.TowardsMinusInfinity:
roundUp = (error != 0d && sign);
overflowToInf = sign;
break;
case FPRoundingMode.TowardsZero:
roundUp = false;
overflowToInf = false;
break;
default:
throw new ArgumentException($"Invalid rounding mode \"{context.Fpcr.RoundingMode}\".");
}
if (roundUp)
{
intMant++;
if (intMant == 1ul << F)
{
biasedExp = 1u;
}
if (intMant == 1ul << (F + 1))
{
biasedExp++;
intMant >>= 1;
}
}
double result;
if (biasedExp >= (1u << E) - 1u)
{
result = overflowToInf ? SoftFloat64.FPInfinity(sign) : SoftFloat64.FPMaxNormal(sign);
SoftFloat.FPProcessException(FPException.Overflow, context);
error = 1d;
}
else
{
result = BitConverter.Int64BitsToDouble(
(long)((sign ? 1ul : 0ul) << 63 | (biasedExp & 0x7FFul) << 52 | (intMant & 0x000FFFFFFFFFFFFFul)));
}
if (error != 0d)
{
SoftFloat.FPProcessException(FPException.Inexact, context);
}
return result;
}
private static double FPConvertNaN(ushort valueBits)
{
return BitConverter.Int64BitsToDouble(
(long)(((ulong)valueBits & 0x8000ul) << 48 | 0x7FF8000000000000ul | ((ulong)valueBits & 0x01FFul) << 42));
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,126 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat32_16
{
[UnmanagedCallersOnly]
public static ushort FPConvert(float value)
{
ExecutionContext context = NativeInterface.GetContext();
double real = value.FPUnpackCv(out FPType type, out bool sign, out uint valueBits, context);
bool altHp = (context.Fpcr & FPCR.Ahp) != 0;
ushort resultBits;
if (type is FPType.SNaN or FPType.QNaN)
{
if (altHp)
{
resultBits = SoftFloat16.FPZero(sign);
}
else if ((context.Fpcr & FPCR.Dn) != 0)
{
resultBits = SoftFloat16.FPDefaultNaN();
}
else
{
resultBits = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN || altHp)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
if (altHp)
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
else
{
resultBits = SoftFloat16.FPInfinity(sign);
}
}
else if (type == FPType.Zero)
{
resultBits = SoftFloat16.FPZero(sign);
}
else
{
resultBits = SoftFloat16.FPRoundCv(real, context);
}
return resultBits;
}
private static double FPUnpackCv(
this float value,
out FPType type,
out bool sign,
out uint valueBits,
ExecutionContext context)
{
valueBits = (uint)BitConverter.SingleToInt32Bits(value);
sign = (~valueBits & 0x80000000u) == 0u;
uint exp32 = (valueBits & 0x7F800000u) >> 23;
uint frac32 = valueBits & 0x007FFFFFu;
double real;
if (exp32 == 0u)
{
if (frac32 == 0u || (context.Fpcr & FPCR.Fz) != 0)
{
type = FPType.Zero;
real = 0d;
if (frac32 != 0u)
{
SoftFloat.FPProcessException(FPException.InputDenorm, context);
}
}
else
{
type = FPType.Nonzero; // Subnormal.
real = Math.Pow(2d, -126) * ((double)frac32 * Math.Pow(2d, -23));
}
}
else if (exp32 == 0xFFu)
{
if (frac32 == 0u)
{
type = FPType.Infinity;
real = Math.Pow(2d, 1000);
}
else
{
type = (~frac32 & 0x00400000u) == 0u ? FPType.QNaN : FPType.SNaN;
real = 0d;
}
}
else
{
type = FPType.Nonzero; // Normal.
real = Math.Pow(2d, (int)exp32 - 127) * (1d + (double)frac32 * Math.Pow(2d, -23));
}
return sign ? -real : real;
}
private static ushort FPConvertNaN(uint valueBits)
{
return (ushort)((valueBits & 0x80000000u) >> 16 | 0x7E00u | (valueBits & 0x003FE000u) >> 13);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,127 @@
using ARMeilleure.State;
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Instructions
{
static class SoftFloat64_16
{
[UnmanagedCallersOnly]
public static ushort FPConvert(double value)
{
ExecutionContext context = NativeInterface.GetContext();
double real = value.FPUnpackCv(out FPType type, out bool sign, out ulong valueBits, context);
bool altHp = (context.Fpcr & FPCR.Ahp) != 0;
ushort resultBits;
if (type is FPType.SNaN or FPType.QNaN)
{
if (altHp)
{
resultBits = SoftFloat16.FPZero(sign);
}
else if ((context.Fpcr & FPCR.Dn) != 0)
{
resultBits = SoftFloat16.FPDefaultNaN();
}
else
{
resultBits = FPConvertNaN(valueBits);
}
if (type == FPType.SNaN || altHp)
{
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
}
else if (type == FPType.Infinity)
{
if (altHp)
{
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
SoftFloat.FPProcessException(FPException.InvalidOp, context);
}
else
{
resultBits = SoftFloat16.FPInfinity(sign);
}
}
else if (type == FPType.Zero)
{
resultBits = SoftFloat16.FPZero(sign);
}
else
{
resultBits = SoftFloat16.FPRoundCv(real, context);
}
return resultBits;
}
private static double FPUnpackCv(
this double value,
out FPType type,
out bool sign,
out ulong valueBits,
ExecutionContext context)
{
valueBits = (ulong)BitConverter.DoubleToInt64Bits(value);
sign = (~valueBits & 0x8000000000000000ul) == 0u;
ulong exp64 = (valueBits & 0x7FF0000000000000ul) >> 52;
ulong frac64 = valueBits & 0x000FFFFFFFFFFFFFul;
double real;
if (exp64 == 0u)
{
if (frac64 == 0u || (context.Fpcr & FPCR.Fz) != 0)
{
type = FPType.Zero;
real = 0d;
if (frac64 != 0u)
{
SoftFloat.FPProcessException(FPException.InputDenorm, context);
}
}
else
{
type = FPType.Nonzero; // Subnormal.
real = Math.Pow(2d, -1022) * ((double)frac64 * Math.Pow(2d, -52));
}
}
else if (exp64 == 0x7FFul)
{
if (frac64 == 0u)
{
type = FPType.Infinity;
real = Math.Pow(2d, 1000000);
}
else
{
type = (~frac64 & 0x0008000000000000ul) == 0u ? FPType.QNaN : FPType.SNaN;
real = 0d;
}
}
else
{
type = FPType.Nonzero; // Normal.
real = Math.Pow(2d, (int)exp64 - 1023) * (1d + (double)frac64 * Math.Pow(2d, -52));
}
return sign ? -real : real;
}
private static ushort FPConvertNaN(ulong valueBits)
{
return (ushort)((valueBits & 0x8000000000000000ul) >> 48 | 0x7E00u |
(valueBits & 0x0007FC0000000000ul) >> 42);
}
}
}

View file

@ -16,9 +16,9 @@ namespace ARMeilleure.IntermediateRepresentation
static class ComparisonExtensions static class ComparisonExtensions
{ {
public static Comparison Invert(this Comparison comp) extension(Comparison comparison)
{ {
return (Comparison)((int)comp ^ 1); public Comparison Inverse => (Comparison)((int)comparison ^ 1);
} }
} }
} }

View file

@ -14,48 +14,38 @@ namespace ARMeilleure.IntermediateRepresentation
static class OperandTypeExtensions static class OperandTypeExtensions
{ {
public static bool IsInteger(this OperandType type) extension(OperandType type)
{ {
return type is OperandType.I32 or public bool IsInteger => type is OperandType.I32 or OperandType.I64;
OperandType.I64;
}
public static RegisterType ToRegisterType(this OperandType type) public RegisterType Register => type switch
{
return type switch
{ {
OperandType.FP32 => RegisterType.Vector, OperandType.FP32 => RegisterType.Vector,
OperandType.FP64 => RegisterType.Vector, OperandType.FP64 => RegisterType.Vector,
OperandType.I32 => RegisterType.Integer, OperandType.I32 => RegisterType.Integer,
OperandType.I64 => RegisterType.Integer, OperandType.I64 => RegisterType.Integer,
OperandType.V128 => RegisterType.Vector, OperandType.V128 => RegisterType.Vector,
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."), _ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
}; };
}
public static int GetSizeInBytes(this OperandType type) public int ByteSize => type switch
{
return type switch
{ {
OperandType.FP32 => 4, OperandType.FP32 => 4,
OperandType.FP64 => 8, OperandType.FP64 => 8,
OperandType.I32 => 4, OperandType.I32 => 4,
OperandType.I64 => 8, OperandType.I64 => 8,
OperandType.V128 => 16, OperandType.V128 => 16,
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."), _ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
}; };
}
public static int GetSizeInBytesLog2(this OperandType type) public int ByteSizeLog2 => type switch
{
return type switch
{ {
OperandType.FP32 => 2, OperandType.FP32 => 2,
OperandType.FP64 => 3, OperandType.FP64 => 3,
OperandType.I32 => 2, OperandType.I32 => 2,
OperandType.I64 => 3, OperandType.I64 => 3,
OperandType.V128 => 4, OperandType.V128 => 4,
_ => throw new InvalidOperationException($"Invalid operand type \"{type}\"."), _ => throw new InvalidOperationException($"Invalid operand type \"{type}\".")
}; };
} }
} }

View file

@ -45,19 +45,12 @@ namespace ARMeilleure.Memory
public static class MemoryManagerTypeExtensions public static class MemoryManagerTypeExtensions
{ {
public static bool IsHostMapped(this MemoryManagerType type) extension(MemoryManagerType type)
{ {
return type is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe; public bool IsHostMapped => type is MemoryManagerType.HostMapped or MemoryManagerType.HostMappedUnsafe;
} public bool IsHostTracked => type is MemoryManagerType.HostTracked or MemoryManagerType.HostTrackedUnsafe;
public static bool IsHostTracked(this MemoryManagerType type) public bool IsHostMappedOrTracked => type.IsHostMapped || type.IsHostTracked;
{
return type is MemoryManagerType.HostTracked or MemoryManagerType.HostTrackedUnsafe;
}
public static bool IsHostMappedOrTracked(this MemoryManagerType type)
{
return type.IsHostMapped() || type.IsHostTracked();
} }
} }
} }

View file

@ -412,7 +412,7 @@ namespace ARMeilleure.Translation
{ {
context.SyncQcFlag(); context.SyncQcFlag();
if (block.Branch != null && !block.Branch.Exit && block.Branch.Address <= block.Address) if (block.Branch is { Exit: false } && block.Branch.Address <= block.Address)
{ {
EmitSynchronization(context); EmitSynchronization(context);
} }
@ -429,14 +429,14 @@ namespace ARMeilleure.Translation
{ {
lblPredicateSkip = Label(); lblPredicateSkip = Label();
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Invert()); InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, context.CurrentIfThenBlockCond.Inverse);
} }
if (opCode is OpCode32 op && op.Cond < Condition.Al) if (opCode is OpCode32 { Cond: < Condition.Al } op)
{ {
lblPredicateSkip = Label(); lblPredicateSkip = Label();
InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Invert()); InstEmitFlowHelper.EmitCondBranch(context, lblPredicateSkip, op.Cond.Inverse);
} }
if (opCode.Instruction.Emitter != null) if (opCode.Instruction.Emitter != null)

View file

@ -58,16 +58,16 @@ namespace Ryujinx.Audio.Backends.CompatLayer
switch (realSampleFormat) switch (realSampleFormat)
{ {
case SampleFormat.PcmInt8: case SampleFormat.PcmInt8:
PcmHelper.ConvertSampleToPcm8(MemoryMarshal.Cast<byte, sbyte>(convertedSamples), samples); PcmHelper.ConvertSampleToPcm8(MemoryMarshal.Cast<byte, sbyte>(new Span<byte>(convertedSamples)), samples);
break; break;
case SampleFormat.PcmInt24: case SampleFormat.PcmInt24:
PcmHelper.ConvertSampleToPcm24(convertedSamples, samples); PcmHelper.ConvertSampleToPcm24(convertedSamples, samples);
break; break;
case SampleFormat.PcmInt32: case SampleFormat.PcmInt32:
PcmHelper.ConvertSampleToPcm32(MemoryMarshal.Cast<byte, int>(convertedSamples), samples); PcmHelper.ConvertSampleToPcm32(MemoryMarshal.Cast<byte, int>(new Span<byte>(convertedSamples)), samples);
break; break;
case SampleFormat.PcmFloat: case SampleFormat.PcmFloat:
PcmHelper.ConvertSampleToPcmFloat(MemoryMarshal.Cast<byte, float>(convertedSamples), samples); PcmHelper.ConvertSampleToPcmFloat(MemoryMarshal.Cast<byte, float>(new Span<byte>(convertedSamples)), samples);
break; break;
default: default:
throw new NotImplementedException($"Sample format conversion from {_userSampleFormat} to {realSampleFormat} not implemented."); throw new NotImplementedException($"Sample format conversion from {_userSampleFormat} to {realSampleFormat} not implemented.");

View file

@ -27,7 +27,7 @@ namespace Ryujinx.Audio.Integration
public void AppendBuffer(ReadOnlySpan<short> data, uint channelCount) public void AppendBuffer(ReadOnlySpan<short> data, uint channelCount)
{ {
data.CopyTo(MemoryMarshal.Cast<byte, short>(_buffer)); data.CopyTo(MemoryMarshal.Cast<byte, short>(new Span<byte>(_buffer)));
_session.QueueBuffer(new AudioBuffer _session.QueueBuffer(new AudioBuffer
{ {

View file

@ -17,7 +17,7 @@ namespace Ryujinx.Cpu.Jit
_functionTable = AddressTable<ulong>.CreateForArm(for64Bit, memory.Type); _functionTable = AddressTable<ulong>.CreateForArm(for64Bit, memory.Type);
_translator = new Translator(new JitMemoryAllocator(forJit: true), memory, _functionTable); _translator = new Translator(new JitMemoryAllocator(forJit: true), memory, _functionTable);
if (memory.Type.IsHostMappedOrTracked()) if (memory.Type.IsHostMappedOrTracked)
{ {
NativeSignalHandler.InitializeSignalHandler(); NativeSignalHandler.InitializeSignalHandler();
} }

View file

@ -26,7 +26,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32
return; return;
} }
if (_operand.Type.IsInteger()) if (_operand.Type.IsInteger)
{ {
_registerAllocator.FreeTempGprRegister(_operand.AsInt32()); _registerAllocator.FreeTempGprRegister(_operand.AsInt32());
} }

View file

@ -381,7 +381,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
if (currentCond != ArmCondition.Al) if (currentCond != ArmCondition.Al)
{ {
instructionPointer = context.CodeWriter.InstructionPointer; instructionPointer = context.CodeWriter.InstructionPointer;
context.Arm64Assembler.B(currentCond.Invert(), 0); context.Arm64Assembler.B(currentCond.Inverse, 0);
} }
} }
} }

View file

@ -104,7 +104,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
if (invert) if (invert)
{ {
conditions[i++] = ((ArmCondition)firstCond).Invert(); conditions[i++] = ((ArmCondition)firstCond).Inverse;
} }
else else
{ {

View file

@ -1129,7 +1129,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
// We don't need to mask the address for the safe mode, since it is already naturally limited to 32-bit // We don't need to mask the address for the safe mode, since it is already naturally limited to 32-bit
// and can never reach out of the guest address space. // and can never reach out of the guest address space.
if (mmType.IsHostTracked()) if (mmType.IsHostTracked)
{ {
int tempRegister = regAlloc.AllocateTempGprRegister(); int tempRegister = regAlloc.AllocateTempGprRegister();
@ -1141,7 +1141,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
regAlloc.FreeTempGprRegister(tempRegister); regAlloc.FreeTempGprRegister(tempRegister);
} }
else if (mmType.IsHostMapped()) else if (mmType.IsHostMapped)
{ {
asm.Add(destination64, basePointer, guestAddress); asm.Add(destination64, basePointer, guestAddress);
} }

View file

@ -132,7 +132,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64
InstName lastInstructionName = Instructions[^1].Name; InstName lastInstructionName = Instructions[^1].Name;
return lastInstructionName.IsCall() || lastInstructionName.IsException(); return lastInstructionName.IsCall || lastInstructionName.IsException;
} }
} }
} }

View file

@ -1042,126 +1042,39 @@ namespace Ryujinx.Cpu.LightningJit.Arm64
static class InstNameExtensions static class InstNameExtensions
{ {
public static bool IsCall(this InstName name) extension(InstName name)
{ {
return name is InstName.Bl or InstName.Blr; public bool IsCall => name is InstName.Bl or InstName.Blr;
}
public static bool IsControlFlowOrException(this InstName name) public bool IsControlFlowOrException => name is
{ InstName.BUncond or InstName.BCond or InstName.Bl or InstName.Blr or InstName.Br or InstName.Brk
switch (name) or InstName.Cbnz or InstName.Cbz or InstName.Ret or InstName.Tbnz or InstName.Tbz or InstName.Svc
{ or InstName.UdfPermUndef;
case InstName.BUncond:
case InstName.BCond:
case InstName.Bl:
case InstName.Blr:
case InstName.Br:
case InstName.Brk:
case InstName.Cbnz:
case InstName.Cbz:
case InstName.Ret:
case InstName.Tbnz:
case InstName.Tbz:
case InstName.Svc:
case InstName.UdfPermUndef:
return true;
}
return false; public bool IsException => name is InstName.Brk or InstName.Svc or InstName.UdfPermUndef;
}
public static bool IsException(this InstName name) public bool IsSystem => name switch
{ {
switch (name) InstName.Mrs or InstName.MsrImm or InstName.MsrReg => true,
{ _ => name.IsException
case InstName.Brk: };
case InstName.Svc:
case InstName.UdfPermUndef:
return true;
}
return false; public bool IsSystemOrCall => name.IsCall || name is
} InstName.Svc or InstName.Mrs or InstName.MsrImm or InstName.MsrReg
or InstName.Sysl;
public static bool IsSystem(this InstName name) public bool IsPrivileged => name is
{ InstName.Dcps1 or InstName.Dcps2 or InstName.Dcps3 or InstName.Drps or InstName.Eret or InstName.Ereta
switch (name) or InstName.Hvc or InstName.MsrImm or InstName.Smc;
{
case InstName.Mrs:
case InstName.MsrImm:
case InstName.MsrReg:
return true;
}
return name.IsException(); public bool IsPartialRegisterUpdateMemory => name is
} InstName.Ld1AdvsimdSnglAsNoPostIndex or InstName.Ld1AdvsimdSnglAsPostIndex
or InstName.Ld2AdvsimdSnglAsNoPostIndex or InstName.Ld2AdvsimdSnglAsPostIndex
or InstName.Ld3AdvsimdSnglAsNoPostIndex or InstName.Ld3AdvsimdSnglAsPostIndex
or InstName.Ld4AdvsimdSnglAsNoPostIndex or InstName.Ld4AdvsimdSnglAsPostIndex;
public static bool IsSystemOrCall(this InstName name) public bool IsPrefetchMemory => name is
{ InstName.PrfmImm or InstName.PrfmLit or InstName.PrfmReg or InstName.Prfum;
switch (name)
{
case InstName.Bl:
case InstName.Blr:
case InstName.Svc:
case InstName.Mrs:
case InstName.MsrImm:
case InstName.MsrReg:
case InstName.Sysl:
return true;
}
return false;
}
public static bool IsPrivileged(this InstName name)
{
switch (name)
{
case InstName.Dcps1:
case InstName.Dcps2:
case InstName.Dcps3:
case InstName.Drps:
case InstName.Eret:
case InstName.Ereta:
case InstName.Hvc:
case InstName.MsrImm:
case InstName.Smc:
return true;
}
return false;
}
public static bool IsPartialRegisterUpdateMemory(this InstName name)
{
switch (name)
{
case InstName.Ld1AdvsimdSnglAsNoPostIndex:
case InstName.Ld1AdvsimdSnglAsPostIndex:
case InstName.Ld2AdvsimdSnglAsNoPostIndex:
case InstName.Ld2AdvsimdSnglAsPostIndex:
case InstName.Ld3AdvsimdSnglAsNoPostIndex:
case InstName.Ld3AdvsimdSnglAsPostIndex:
case InstName.Ld4AdvsimdSnglAsNoPostIndex:
case InstName.Ld4AdvsimdSnglAsPostIndex:
return true;
}
return false;
}
public static bool IsPrefetchMemory(this InstName name)
{
switch (name)
{
case InstName.PrfmImm:
case InstName.PrfmLit:
case InstName.PrfmReg:
case InstName.Prfum:
return true;
}
return false;
} }
} }
} }

View file

@ -150,7 +150,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64
public static int CalculateMaxTemps(MemoryManagerType mmType) public static int CalculateMaxTemps(MemoryManagerType mmType)
{ {
return mmType.IsHostMapped() ? 1 : 2; return mmType.IsHostMapped ? 1 : 2;
} }
public static int CalculateMaxTempsInclFixed(MemoryManagerType mmType) public static int CalculateMaxTempsInclFixed(MemoryManagerType mmType)

View file

@ -247,7 +247,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64
} }
} }
if (!flags.HasFlag(InstFlags.ReadRt) || name.IsPartialRegisterUpdateMemory()) if (!flags.HasFlag(InstFlags.ReadRt) || name.IsPartialRegisterUpdateMemory)
{ {
if (flags.HasFlag(InstFlags.Rt)) if (flags.HasFlag(InstFlags.Rt))
{ {
@ -281,7 +281,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64
gprMask |= MaskFromIndex(ExtractRd(flags, encoding)); gprMask |= MaskFromIndex(ExtractRd(flags, encoding));
} }
if (!flags.HasFlag(InstFlags.ReadRt) || name.IsPartialRegisterUpdateMemory()) if (!flags.HasFlag(InstFlags.ReadRt) || name.IsPartialRegisterUpdateMemory)
{ {
if (flags.HasFlag(InstFlags.Rt)) if (flags.HasFlag(InstFlags.Rt))
{ {

View file

@ -364,7 +364,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
{ {
InstEmitMemory.RewriteSysInstruction(memoryManager.AddressSpaceBits, memoryManager.Type, writer, regAlloc, encoding); InstEmitMemory.RewriteSysInstruction(memoryManager.AddressSpaceBits, memoryManager.Type, writer, regAlloc, encoding);
} }
else if (instInfo.Name.IsSystem()) else if (instInfo.Name.IsSystem)
{ {
bool needsContextStoreLoad = InstEmitSystem.NeedsContextStoreLoad(instInfo.Name); bool needsContextStoreLoad = InstEmitSystem.NeedsContextStoreLoad(instInfo.Name);
@ -405,7 +405,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
lastInstructionEncoding = RegisterUtils.RemapRegisters(regAlloc, lastInstructionFlags, lastInstructionEncoding); lastInstructionEncoding = RegisterUtils.RemapRegisters(regAlloc, lastInstructionFlags, lastInstructionEncoding);
if (lastInstructionName.IsCall()) if (lastInstructionName.IsCall)
{ {
context.StoreToContextBeforeCall(blockIndex, pc + 4UL); context.StoreToContextBeforeCall(blockIndex, pc + 4UL);

View file

@ -257,7 +257,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
(name, flags, AddressForm addressForm) = InstTable.GetInstNameAndFlags(encoding, cpuPreset.Version, cpuPreset.Features); (name, flags, AddressForm addressForm) = InstTable.GetInstNameAndFlags(encoding, cpuPreset.Version, cpuPreset.Features);
if (name.IsPrivileged() || (name == InstName.Sys && IsPrivilegedSys(encoding))) if (name.IsPrivileged || (name == InstName.Sys && IsPrivilegedSys(encoding)))
{ {
name = InstName.UdfPermUndef; name = InstName.UdfPermUndef;
flags = InstFlags.None; flags = InstFlags.None;
@ -267,7 +267,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
(uint instGprReadMask, uint instFpSimdReadMask) = RegisterUtils.PopulateReadMasks(name, flags, encoding); (uint instGprReadMask, uint instFpSimdReadMask) = RegisterUtils.PopulateReadMasks(name, flags, encoding);
(uint instGprWriteMask, uint instFpSimdWriteMask) = RegisterUtils.PopulateWriteMasks(name, flags, encoding); (uint instGprWriteMask, uint instFpSimdWriteMask) = RegisterUtils.PopulateWriteMasks(name, flags, encoding);
if (name.IsCall()) if (name.IsCall)
{ {
instGprWriteMask |= 1u << RegisterUtils.LrIndex; instGprWriteMask |= 1u << RegisterUtils.LrIndex;
} }
@ -310,12 +310,12 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
fpSimdUseMask |= instFpSimdReadMask | instFpSimdWriteMask; fpSimdUseMask |= instFpSimdReadMask | instFpSimdWriteMask;
pStateUseMask |= instPStateReadMask | instPStateWriteMask; pStateUseMask |= instPStateReadMask | instPStateWriteMask;
if (name.IsSystemOrCall() && !hasHostCall) if (name.IsSystemOrCall && !hasHostCall)
{ {
hasHostCall = name.IsCall() || InstEmitSystem.NeedsCall(encoding); hasHostCall = name.IsCall || InstEmitSystem.NeedsCall(encoding);
} }
isControlFlow = name.IsControlFlowOrException(); isControlFlow = name.IsControlFlowOrException;
RegisterUse registerUse = new( RegisterUse registerUse = new(
instGprReadMask, instGprReadMask,
@ -339,7 +339,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
useMask = new(gprUseMask, fpSimdUseMask, pStateUseMask); useMask = new(gprUseMask, fpSimdUseMask, pStateUseMask);
return new(startAddress, address, insts, !isTruncated && !name.IsException(), isTruncated, isLoopEnd); return new(startAddress, address, insts, !isTruncated && !name.IsException, isTruncated, isLoopEnd);
} }
private static bool IsPrivilegedSys(uint encoding) private static bool IsPrivilegedSys(uint encoding)

View file

@ -55,7 +55,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
ulong pc, ulong pc,
uint encoding) uint encoding)
{ {
if (name.IsPrefetchMemory() && mmType == MemoryManagerType.HostTrackedUnsafe) if (name.IsPrefetchMemory && mmType == MemoryManagerType.HostTrackedUnsafe)
{ {
// Prefetch to invalid addresses do not cause faults, so for memory manager // Prefetch to invalid addresses do not cause faults, so for memory manager
// types where we need to access the page table before doing the prefetch, // types where we need to access the page table before doing the prefetch,
@ -544,7 +544,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
{ {
Operand basePointer = new(regAlloc.FixedPageTableRegister, RegisterType.Integer, OperandType.I64); Operand basePointer = new(regAlloc.FixedPageTableRegister, RegisterType.Integer, OperandType.I64);
if (mmType.IsHostTracked()) if (mmType.IsHostTracked)
{ {
int tempRegister = regAlloc.AllocateTempGprRegister(); int tempRegister = regAlloc.AllocateTempGprRegister();
@ -562,7 +562,7 @@ namespace Ryujinx.Cpu.LightningJit.Arm64.Target.Arm64
regAlloc.FreeTempGprRegister(tempRegister); regAlloc.FreeTempGprRegister(tempRegister);
} }
else if (mmType.IsHostMapped()) else if (mmType.IsHostMapped)
{ {
if (mmType == MemoryManagerType.HostMapped) if (mmType == MemoryManagerType.HostMapped)
{ {

View file

@ -22,9 +22,9 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
static class ArmConditionExtensions static class ArmConditionExtensions
{ {
public static ArmCondition Invert(this ArmCondition condition) extension(ArmCondition condition)
{ {
return (ArmCondition)((int)condition ^ 1); public ArmCondition Inverse => (ArmCondition)((int)condition ^ 1);
} }
} }
} }

View file

@ -673,7 +673,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
public readonly void Mov(Operand rd, Operand rn) public readonly void Mov(Operand rd, Operand rn)
{ {
Debug.Assert(rd.Type.IsInteger()); Debug.Assert(rd.Type.IsInteger);
Orr(rd, new Operand(ZrRegister, RegisterType.Integer, rd.Type), rn); Orr(rd, new Operand(ZrRegister, RegisterType.Integer, rd.Type), rn);
} }
@ -4544,7 +4544,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
uint instruction; uint instruction;
int scale; int scale;
if (type.IsInteger()) if (type.IsInteger)
{ {
instruction = intInst; instruction = intInst;
@ -4580,7 +4580,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
{ {
uint instruction; uint instruction;
if (type.IsInteger()) if (type.IsInteger)
{ {
instruction = intInst; instruction = intInst;
@ -4610,7 +4610,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
{ {
uint instruction; uint instruction;
if (type.IsInteger()) if (type.IsInteger)
{ {
instruction = intInst; instruction = intInst;

View file

@ -34,7 +34,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
int gprCalleeSavedRegsCount = BitOperations.PopCount(_gprMask); int gprCalleeSavedRegsCount = BitOperations.PopCount(_gprMask);
int fpSimdCalleeSavedRegsCount = BitOperations.PopCount(_fpSimdMask); int fpSimdCalleeSavedRegsCount = BitOperations.PopCount(_fpSimdMask);
return (_hasCall ? 16 : 0) + Align16(gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.GetSizeInBytes()); return (_hasCall ? 16 : 0) + Align16(gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.ByteSize);
} }
public void WritePrologue(ref Assembler asm) public void WritePrologue(ref Assembler asm)
@ -46,7 +46,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
int fpSimdCalleeSavedRegsCount = BitOperations.PopCount(fpSimdMask); int fpSimdCalleeSavedRegsCount = BitOperations.PopCount(fpSimdMask);
int reservedStackSize = Align16(_reservedStackSize); int reservedStackSize = Align16(_reservedStackSize);
int calleeSaveRegionSize = Align16(gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.GetSizeInBytes()) + reservedStackSize; int calleeSaveRegionSize = Align16(gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.ByteSize) + reservedStackSize;
int offset = 0; int offset = 0;
WritePrologueCalleeSavesPreIndexed(ref asm, ref gprMask, ref offset, calleeSaveRegionSize, OperandType.I64); WritePrologueCalleeSavesPreIndexed(ref asm, ref gprMask, ref offset, calleeSaveRegionSize, OperandType.I64);
@ -103,7 +103,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
asm.StrRiUn(Register(reg, type), Register(Assembler.SpRegister), 0); asm.StrRiUn(Register(reg, type), Register(Assembler.SpRegister), 0);
} }
offset += type.GetSizeInBytes(); offset += type.ByteSize;
} }
while (mask != 0) while (mask != 0)
@ -130,7 +130,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
asm.StpRiUn(Register(reg, type), Register(reg2, type), Register(Assembler.SpRegister), 0); asm.StpRiUn(Register(reg, type), Register(reg2, type), Register(Assembler.SpRegister), 0);
} }
offset += type.GetSizeInBytes() * 2; offset += type.ByteSize * 2;
} }
} }
@ -144,7 +144,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
bool misalignedVector = _fpSimdType == OperandType.V128 && (gprCalleeSavedRegsCount & 1) != 0; bool misalignedVector = _fpSimdType == OperandType.V128 && (gprCalleeSavedRegsCount & 1) != 0;
int offset = gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.GetSizeInBytes(); int offset = gprCalleeSavedRegsCount * 8 + fpSimdCalleeSavedRegsCount * _fpSimdType.ByteSize;
if (misalignedVector) if (misalignedVector)
{ {
@ -197,7 +197,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
mask &= ~(1u << reg2); mask &= ~(1u << reg2);
offset -= type.GetSizeInBytes() * 2; offset -= type.ByteSize * 2;
if (offset != 0) if (offset != 0)
{ {
@ -215,7 +215,7 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen.Arm64
} }
else else
{ {
offset -= type.GetSizeInBytes(); offset -= type.ByteSize;
if (offset != 0) if (offset != 0)
{ {

View file

@ -14,14 +14,11 @@ namespace Ryujinx.Cpu.LightningJit.CodeGen
static class OperandTypeExtensions static class OperandTypeExtensions
{ {
public static bool IsInteger(this OperandType type) extension(OperandType type)
{ {
return type is OperandType.I32 or OperandType.I64; public bool IsInteger => type is OperandType.I32 or OperandType.I64;
}
public static int GetSizeInBytes(this OperandType type) public int ByteSize => type switch
{
return type switch
{ {
OperandType.FP32 => 4, OperandType.FP32 => 4,
OperandType.FP64 => 8, OperandType.FP64 => 8,

View file

@ -48,7 +48,7 @@ namespace Ryujinx.Cpu.LightningJit
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub; FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
if (memory.Type.IsHostMappedOrTracked()) if (memory.Type.IsHostMappedOrTracked)
{ {
NativeSignalHandler.InitializeSignalHandler(); NativeSignalHandler.InitializeSignalHandler();
} }

View file

@ -41,22 +41,12 @@ namespace Ryujinx.Graphics.GAL
public static class BlendFactorExtensions public static class BlendFactorExtensions
{ {
public static bool IsDualSource(this BlendFactor factor) extension(BlendFactor factor)
{ {
switch (factor) public bool IsDualSource => factor is
{ BlendFactor.Src1Color or BlendFactor.Src1ColorGl or BlendFactor.Src1Alpha or BlendFactor.Src1AlphaGl
case BlendFactor.Src1Color: or BlendFactor.OneMinusSrc1Color or BlendFactor.OneMinusSrc1ColorGl or BlendFactor.OneMinusSrc1Alpha
case BlendFactor.Src1ColorGl: or BlendFactor.OneMinusSrc1AlphaGl;
case BlendFactor.Src1Alpha:
case BlendFactor.Src1AlphaGl:
case BlendFactor.OneMinusSrc1Color:
case BlendFactor.OneMinusSrc1ColorGl:
case BlendFactor.OneMinusSrc1Alpha:
case BlendFactor.OneMinusSrc1AlphaGl:
return true;
default:
return false;
}
} }
} }
} }

View file

@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.GAL namespace Ryujinx.Graphics.GAL
@ -10,5 +11,7 @@ namespace Ryujinx.Graphics.GAL
public static BufferHandle Null => new(0); public static BufferHandle Null => new(0);
private BufferHandle(ulong value) => _value = value; private BufferHandle(ulong value) => _value = value;
public static implicit operator int(BufferHandle handle) => (int)Unsafe.As<BufferHandle, ulong>(ref handle);
} }
} }

View file

@ -159,559 +159,132 @@ namespace Ryujinx.Graphics.GAL
/// </summary> /// </summary>
public const int MaxBufferFormatScalarSize = 4; public const int MaxBufferFormatScalarSize = 4;
extension(Format fmt)
{
/// <summary> /// <summary>
/// Gets the byte size for a single component of this format, or its packed size. /// Gets the byte size for a single component of this format, or its packed size.
/// </summary> /// </summary>
/// <param name="format">Texture format</param> public int ScalarSize => fmt switch
/// <returns>Byte size for a single component, or packed size</returns>
public static int GetScalarSize(this Format format)
{ {
switch (format) Format.R8Unorm or Format.R8Snorm or Format.R8Uint or Format.R8Sint or Format.R8G8Unorm
{ or Format.R8G8Snorm or Format.R8G8Uint or Format.R8G8Sint or Format.R8G8B8Unorm
case Format.R8Unorm: or Format.R8G8B8Snorm or Format.R8G8B8Uint or Format.R8G8B8Sint or Format.R8G8B8A8Unorm
case Format.R8Snorm: or Format.R8G8B8A8Snorm or Format.R8G8B8A8Uint or Format.R8G8B8A8Sint or Format.R8G8B8A8Srgb
case Format.R8Uint: or Format.R4G4Unorm or Format.R8Uscaled or Format.R8Sscaled or Format.R8G8Uscaled
case Format.R8Sint: or Format.R8G8Sscaled or Format.R8G8B8Uscaled or Format.R8G8B8Sscaled or Format.R8G8B8A8Uscaled
case Format.R8G8Unorm: or Format.R8G8B8A8Sscaled or Format.B8G8R8A8Unorm or Format.B8G8R8A8Srgb => 1,
case Format.R8G8Snorm: Format.R16Float or Format.R16Unorm or Format.R16Snorm or Format.R16Uint or Format.R16Sint
case Format.R8G8Uint: or Format.R16G16Float or Format.R16G16Unorm or Format.R16G16Snorm or Format.R16G16Uint
case Format.R8G8Sint: or Format.R16G16Sint or Format.R16G16B16Float or Format.R16G16B16Unorm or Format.R16G16B16Snorm
case Format.R8G8B8Unorm: or Format.R16G16B16Uint or Format.R16G16B16Sint or Format.R16G16B16A16Float
case Format.R8G8B8Snorm: or Format.R16G16B16A16Unorm or Format.R16G16B16A16Snorm or Format.R16G16B16A16Uint
case Format.R8G8B8Uint: or Format.R16G16B16A16Sint or Format.R4G4B4A4Unorm or Format.R5G5B5X1Unorm or Format.R5G5B5A1Unorm
case Format.R8G8B8Sint: or Format.R5G6B5Unorm or Format.R16Uscaled or Format.R16Sscaled or Format.R16G16Uscaled
case Format.R8G8B8A8Unorm: or Format.R16G16Sscaled or Format.R16G16B16Uscaled or Format.R16G16B16Sscaled
case Format.R8G8B8A8Snorm: or Format.R16G16B16A16Uscaled or Format.R16G16B16A16Sscaled or Format.B5G6R5Unorm
case Format.R8G8B8A8Uint: or Format.B5G5R5A1Unorm or Format.A1B5G5R5Unorm => 2,
case Format.R8G8B8A8Sint: Format.R32Float or Format.R32Uint or Format.R32Sint or Format.R32G32Float or Format.R32G32Uint
case Format.R8G8B8A8Srgb: or Format.R32G32Sint or Format.R32G32B32Float or Format.R32G32B32Uint or Format.R32G32B32Sint
case Format.R4G4Unorm: or Format.R32G32B32A32Float or Format.R32G32B32A32Uint or Format.R32G32B32A32Sint
case Format.R8Uscaled: or Format.R10G10B10A2Unorm or Format.R10G10B10A2Uint or Format.R11G11B10Float
case Format.R8Sscaled: or Format.R9G9B9E5Float or Format.R32Uscaled or Format.R32Sscaled or Format.R32G32Uscaled
case Format.R8G8Uscaled: or Format.R32G32Sscaled or Format.R32G32B32Uscaled or Format.R32G32B32Sscaled
case Format.R8G8Sscaled: or Format.R32G32B32A32Uscaled or Format.R32G32B32A32Sscaled or Format.R10G10B10A2Snorm
case Format.R8G8B8Uscaled: or Format.R10G10B10A2Sint or Format.R10G10B10A2Uscaled or Format.R10G10B10A2Sscaled
case Format.R8G8B8Sscaled: or Format.B10G10R10A2Unorm => 4,
case Format.R8G8B8A8Uscaled: Format.S8Uint => 1,
case Format.R8G8B8A8Sscaled: Format.D16Unorm => 2,
case Format.B8G8R8A8Unorm: Format.S8UintD24Unorm or Format.X8UintD24Unorm or Format.D32Float or Format.D24UnormS8Uint => 4,
case Format.B8G8R8A8Srgb: Format.D32FloatS8Uint => 8,
return 1; Format.Bc1RgbaUnorm or Format.Bc1RgbaSrgb => 8,
Format.Bc2Unorm or Format.Bc3Unorm or Format.Bc2Srgb or Format.Bc3Srgb or Format.Bc4Unorm
case Format.R16Float: or Format.Bc4Snorm or Format.Bc5Unorm or Format.Bc5Snorm or Format.Bc7Unorm or Format.Bc7Srgb
case Format.R16Unorm: or Format.Bc6HSfloat or Format.Bc6HUfloat => 16,
case Format.R16Snorm: Format.Etc2RgbUnorm or Format.Etc2RgbPtaUnorm or Format.Etc2RgbSrgb or Format.Etc2RgbPtaSrgb => 8,
case Format.R16Uint: Format.Etc2RgbaUnorm or Format.Etc2RgbaSrgb => 16,
case Format.R16Sint: Format.Astc4x4Unorm or Format.Astc5x4Unorm or Format.Astc5x5Unorm or Format.Astc6x5Unorm
case Format.R16G16Float: or Format.Astc6x6Unorm or Format.Astc8x5Unorm or Format.Astc8x6Unorm or Format.Astc8x8Unorm
case Format.R16G16Unorm: or Format.Astc10x5Unorm or Format.Astc10x6Unorm or Format.Astc10x8Unorm or Format.Astc10x10Unorm
case Format.R16G16Snorm: or Format.Astc12x10Unorm or Format.Astc12x12Unorm or Format.Astc4x4Srgb or Format.Astc5x4Srgb
case Format.R16G16Uint: or Format.Astc5x5Srgb or Format.Astc6x5Srgb or Format.Astc6x6Srgb or Format.Astc8x5Srgb
case Format.R16G16Sint: or Format.Astc8x6Srgb or Format.Astc8x8Srgb or Format.Astc10x5Srgb or Format.Astc10x6Srgb
case Format.R16G16B16Float: or Format.Astc10x8Srgb or Format.Astc10x10Srgb or Format.Astc12x10Srgb
case Format.R16G16B16Unorm: or Format.Astc12x12Srgb => 16,
case Format.R16G16B16Snorm: _ => 1
case Format.R16G16B16Uint: };
case Format.R16G16B16Sint:
case Format.R16G16B16A16Float:
case Format.R16G16B16A16Unorm:
case Format.R16G16B16A16Snorm:
case Format.R16G16B16A16Uint:
case Format.R16G16B16A16Sint:
case Format.R4G4B4A4Unorm:
case Format.R5G5B5X1Unorm:
case Format.R5G5B5A1Unorm:
case Format.R5G6B5Unorm:
case Format.R16Uscaled:
case Format.R16Sscaled:
case Format.R16G16Uscaled:
case Format.R16G16Sscaled:
case Format.R16G16B16Uscaled:
case Format.R16G16B16Sscaled:
case Format.R16G16B16A16Uscaled:
case Format.R16G16B16A16Sscaled:
case Format.B5G6R5Unorm:
case Format.B5G5R5A1Unorm:
case Format.A1B5G5R5Unorm:
return 2;
case Format.R32Float:
case Format.R32Uint:
case Format.R32Sint:
case Format.R32G32Float:
case Format.R32G32Uint:
case Format.R32G32Sint:
case Format.R32G32B32Float:
case Format.R32G32B32Uint:
case Format.R32G32B32Sint:
case Format.R32G32B32A32Float:
case Format.R32G32B32A32Uint:
case Format.R32G32B32A32Sint:
case Format.R10G10B10A2Unorm:
case Format.R10G10B10A2Uint:
case Format.R11G11B10Float:
case Format.R9G9B9E5Float:
case Format.R32Uscaled:
case Format.R32Sscaled:
case Format.R32G32Uscaled:
case Format.R32G32Sscaled:
case Format.R32G32B32Uscaled:
case Format.R32G32B32Sscaled:
case Format.R32G32B32A32Uscaled:
case Format.R32G32B32A32Sscaled:
case Format.R10G10B10A2Snorm:
case Format.R10G10B10A2Sint:
case Format.R10G10B10A2Uscaled:
case Format.R10G10B10A2Sscaled:
case Format.B10G10R10A2Unorm:
return 4;
case Format.S8Uint:
return 1;
case Format.D16Unorm:
return 2;
case Format.S8UintD24Unorm:
case Format.X8UintD24Unorm:
case Format.D32Float:
case Format.D24UnormS8Uint:
return 4;
case Format.D32FloatS8Uint:
return 8;
case Format.Bc1RgbaUnorm:
case Format.Bc1RgbaSrgb:
return 8;
case Format.Bc2Unorm:
case Format.Bc3Unorm:
case Format.Bc2Srgb:
case Format.Bc3Srgb:
case Format.Bc4Unorm:
case Format.Bc4Snorm:
case Format.Bc5Unorm:
case Format.Bc5Snorm:
case Format.Bc7Unorm:
case Format.Bc7Srgb:
case Format.Bc6HSfloat:
case Format.Bc6HUfloat:
return 16;
case Format.Etc2RgbUnorm:
case Format.Etc2RgbPtaUnorm:
case Format.Etc2RgbSrgb:
case Format.Etc2RgbPtaSrgb:
return 8;
case Format.Etc2RgbaUnorm:
case Format.Etc2RgbaSrgb:
return 16;
case Format.Astc4x4Unorm:
case Format.Astc5x4Unorm:
case Format.Astc5x5Unorm:
case Format.Astc6x5Unorm:
case Format.Astc6x6Unorm:
case Format.Astc8x5Unorm:
case Format.Astc8x6Unorm:
case Format.Astc8x8Unorm:
case Format.Astc10x5Unorm:
case Format.Astc10x6Unorm:
case Format.Astc10x8Unorm:
case Format.Astc10x10Unorm:
case Format.Astc12x10Unorm:
case Format.Astc12x12Unorm:
case Format.Astc4x4Srgb:
case Format.Astc5x4Srgb:
case Format.Astc5x5Srgb:
case Format.Astc6x5Srgb:
case Format.Astc6x6Srgb:
case Format.Astc8x5Srgb:
case Format.Astc8x6Srgb:
case Format.Astc8x8Srgb:
case Format.Astc10x5Srgb:
case Format.Astc10x6Srgb:
case Format.Astc10x8Srgb:
case Format.Astc10x10Srgb:
case Format.Astc12x10Srgb:
case Format.Astc12x12Srgb:
return 16;
}
return 1;
}
/// <summary> /// <summary>
/// Checks if the texture format is a depth or depth-stencil format. /// Checks if the texture format is a depth or depth-stencil format.
/// </summary> /// </summary>
/// <param name="format">Texture format</param> public bool HasDepth => fmt is
/// <returns>True if the format is a depth or depth-stencil format, false otherwise</returns> Format.D16Unorm or Format.D24UnormS8Uint or Format.S8UintD24Unorm or Format.X8UintD24Unorm
public static bool HasDepth(this Format format) or Format.D32Float or Format.D32FloatS8Uint;
{
switch (format)
{
case Format.D16Unorm:
case Format.D24UnormS8Uint:
case Format.S8UintD24Unorm:
case Format.X8UintD24Unorm:
case Format.D32Float:
case Format.D32FloatS8Uint:
return true;
}
return false;
}
/// <summary> /// <summary>
/// Checks if the texture format is a stencil or depth-stencil format. /// Checks if the texture format is a stencil or depth-stencil format.
/// </summary> /// </summary>
/// <param name="format">Texture format</param> public bool HasStencil => fmt is
/// <returns>True if the format is a stencil or depth-stencil format, false otherwise</returns> Format.D24UnormS8Uint or Format.S8UintD24Unorm or Format.D32FloatS8Uint or Format.S8Uint;
public static bool HasStencil(this Format format)
{
switch (format)
{
case Format.D24UnormS8Uint:
case Format.S8UintD24Unorm:
case Format.D32FloatS8Uint:
case Format.S8Uint:
return true;
}
return false;
}
/// <summary> /// <summary>
/// Checks if the texture format is valid to use as image format. /// Checks if the texture format is valid to use as image format.
/// </summary> /// </summary>
/// <param name="format">Texture format</param> public bool IsImageCompatible => fmt is
/// <returns>True if the texture can be used as image, false otherwise</returns> Format.R8Unorm or Format.R8Snorm or Format.R8Uint or Format.R8Sint or Format.R16Float or Format.R16Unorm
public static bool IsImageCompatible(this Format format) or Format.R16Snorm or Format.R16Uint or Format.R16Sint or Format.R32Float or Format.R32Uint
{ or Format.R32Sint or Format.R8G8Unorm or Format.R8G8Snorm or Format.R8G8Uint or Format.R8G8Sint
switch (format) or Format.R16G16Float or Format.R16G16Unorm or Format.R16G16Snorm or Format.R16G16Uint
{ or Format.R16G16Sint or Format.R32G32Float or Format.R32G32Uint or Format.R32G32Sint
case Format.R8Unorm: or Format.R8G8B8A8Unorm or Format.R8G8B8A8Snorm or Format.R8G8B8A8Uint or Format.R8G8B8A8Sint
case Format.R8Snorm: or Format.R16G16B16A16Float or Format.R16G16B16A16Unorm or Format.R16G16B16A16Snorm
case Format.R8Uint: or Format.R16G16B16A16Uint or Format.R16G16B16A16Sint or Format.R32G32B32A32Float
case Format.R8Sint: or Format.R32G32B32A32Uint or Format.R32G32B32A32Sint or Format.R10G10B10A2Unorm
case Format.R16Float: or Format.R10G10B10A2Uint or Format.R11G11B10Float or Format.B8G8R8A8Unorm;
case Format.R16Unorm:
case Format.R16Snorm:
case Format.R16Uint:
case Format.R16Sint:
case Format.R32Float:
case Format.R32Uint:
case Format.R32Sint:
case Format.R8G8Unorm:
case Format.R8G8Snorm:
case Format.R8G8Uint:
case Format.R8G8Sint:
case Format.R16G16Float:
case Format.R16G16Unorm:
case Format.R16G16Snorm:
case Format.R16G16Uint:
case Format.R16G16Sint:
case Format.R32G32Float:
case Format.R32G32Uint:
case Format.R32G32Sint:
case Format.R8G8B8A8Unorm:
case Format.R8G8B8A8Snorm:
case Format.R8G8B8A8Uint:
case Format.R8G8B8A8Sint:
case Format.R16G16B16A16Float:
case Format.R16G16B16A16Unorm:
case Format.R16G16B16A16Snorm:
case Format.R16G16B16A16Uint:
case Format.R16G16B16A16Sint:
case Format.R32G32B32A32Float:
case Format.R32G32B32A32Uint:
case Format.R32G32B32A32Sint:
case Format.R10G10B10A2Unorm:
case Format.R10G10B10A2Uint:
case Format.R11G11B10Float:
case Format.B8G8R8A8Unorm:
return true;
}
return false;
}
/// <summary> /// <summary>
/// Checks if the texture format is valid to use as render target color format. /// Checks if the texture format is valid to use as render target color format.
/// </summary> /// </summary>
/// <param name="format">Texture format</param> public bool IsRtColorCompatible => fmt is
/// <returns>True if the texture can be used as render target, false otherwise</returns> Format.R32G32B32A32Float or Format.R32G32B32A32Sint or Format.R32G32B32A32Uint
public static bool IsRtColorCompatible(this Format format) or Format.R16G16B16A16Unorm or Format.R16G16B16A16Snorm or Format.R16G16B16A16Sint
{ or Format.R16G16B16A16Uint or Format.R16G16B16A16Float or Format.R32G32Float or Format.R32G32Sint
switch (format) or Format.R32G32Uint or Format.B8G8R8A8Unorm or Format.B8G8R8A8Srgb or Format.B10G10R10A2Unorm
{ or Format.R10G10B10A2Unorm or Format.R10G10B10A2Uint or Format.R8G8B8A8Unorm or Format.R8G8B8A8Srgb
case Format.R32G32B32A32Float: or Format.R8G8B8A8Snorm or Format.R8G8B8A8Sint or Format.R8G8B8A8Uint or Format.R16G16Unorm
case Format.R32G32B32A32Sint: or Format.R16G16Snorm or Format.R16G16Sint or Format.R16G16Uint or Format.R16G16Float
case Format.R32G32B32A32Uint: or Format.R11G11B10Float or Format.R32Sint or Format.R32Uint or Format.R32Float
case Format.R16G16B16A16Unorm: or Format.B5G6R5Unorm or Format.B5G5R5A1Unorm or Format.R8G8Unorm or Format.R8G8Snorm
case Format.R16G16B16A16Snorm: or Format.R8G8Sint or Format.R8G8Uint or Format.R16Unorm or Format.R16Snorm or Format.R16Sint
case Format.R16G16B16A16Sint: or Format.R16Uint or Format.R16Float or Format.R8Unorm or Format.R8Snorm or Format.R8Sint
case Format.R16G16B16A16Uint: or Format.R8Uint;
case Format.R16G16B16A16Float:
case Format.R32G32Float:
case Format.R32G32Sint:
case Format.R32G32Uint:
case Format.B8G8R8A8Unorm:
case Format.B8G8R8A8Srgb:
case Format.B10G10R10A2Unorm:
case Format.R10G10B10A2Unorm:
case Format.R10G10B10A2Uint:
case Format.R8G8B8A8Unorm:
case Format.R8G8B8A8Srgb:
case Format.R8G8B8A8Snorm:
case Format.R8G8B8A8Sint:
case Format.R8G8B8A8Uint:
case Format.R16G16Unorm:
case Format.R16G16Snorm:
case Format.R16G16Sint:
case Format.R16G16Uint:
case Format.R16G16Float:
case Format.R11G11B10Float:
case Format.R32Sint:
case Format.R32Uint:
case Format.R32Float:
case Format.B5G6R5Unorm:
case Format.B5G5R5A1Unorm:
case Format.R8G8Unorm:
case Format.R8G8Snorm:
case Format.R8G8Sint:
case Format.R8G8Uint:
case Format.R16Unorm:
case Format.R16Snorm:
case Format.R16Sint:
case Format.R16Uint:
case Format.R16Float:
case Format.R8Unorm:
case Format.R8Snorm:
case Format.R8Sint:
case Format.R8Uint:
return true;
}
return false;
}
/// <summary> /// <summary>
/// Checks if the texture format is 16 bit packed. /// Checks if the texture format is 16 bit packed.
/// </summary> /// </summary>
/// <param name="format">Texture format</param> public bool Is16BitPacked => fmt is
/// <returns>True if the texture format is 16 bit packed, false otherwise</returns> Format.B5G6R5Unorm or Format.B5G5R5A1Unorm or Format.R5G5B5X1Unorm or Format.R5G5B5A1Unorm
public static bool Is16BitPacked(this Format format) or Format.R5G6B5Unorm or Format.R4G4B4A4Unorm;
{
switch (format)
{
case Format.B5G6R5Unorm:
case Format.B5G5R5A1Unorm:
case Format.R5G5B5X1Unorm:
case Format.R5G5B5A1Unorm:
case Format.R5G6B5Unorm:
case Format.R4G4B4A4Unorm:
return true;
}
return false;
}
/// <summary>
/// Checks if the texture format is an ASTC format.
/// </summary>
/// <param name="format">Texture format</param>
/// <returns>True if the texture format is an ASTC format, false otherwise</returns>
public static bool IsAstc(this Format format)
{
return format.IsAstcUnorm() || format.IsAstcSrgb();
}
/// <summary>
/// Checks if the texture format is an ASTC Unorm format.
/// </summary>
/// <param name="format">Texture format</param>
/// <returns>True if the texture format is an ASTC Unorm format, false otherwise</returns>
public static bool IsAstcUnorm(this Format format)
{
switch (format)
{
case Format.Astc4x4Unorm:
case Format.Astc5x4Unorm:
case Format.Astc5x5Unorm:
case Format.Astc6x5Unorm:
case Format.Astc6x6Unorm:
case Format.Astc8x5Unorm:
case Format.Astc8x6Unorm:
case Format.Astc8x8Unorm:
case Format.Astc10x5Unorm:
case Format.Astc10x6Unorm:
case Format.Astc10x8Unorm:
case Format.Astc10x10Unorm:
case Format.Astc12x10Unorm:
case Format.Astc12x12Unorm:
return true;
}
return false;
}
/// <summary>
/// Checks if the texture format is an ASTC SRGB format.
/// </summary>
/// <param name="format">Texture format</param>
/// <returns>True if the texture format is an ASTC SRGB format, false otherwise</returns>
public static bool IsAstcSrgb(this Format format)
{
switch (format)
{
case Format.Astc4x4Srgb:
case Format.Astc5x4Srgb:
case Format.Astc5x5Srgb:
case Format.Astc6x5Srgb:
case Format.Astc6x6Srgb:
case Format.Astc8x5Srgb:
case Format.Astc8x6Srgb:
case Format.Astc8x8Srgb:
case Format.Astc10x5Srgb:
case Format.Astc10x6Srgb:
case Format.Astc10x8Srgb:
case Format.Astc10x10Srgb:
case Format.Astc12x10Srgb:
case Format.Astc12x12Srgb:
return true;
}
return false;
}
/// <summary> /// <summary>
/// Checks if the texture format is an ETC2 format. /// Checks if the texture format is an ETC2 format.
/// </summary> /// </summary>
/// <param name="format">Texture format</param> public bool IsEtc2 => fmt is
/// <returns>True if the texture format is an ETC2 format, false otherwise</returns> Format.Etc2RgbaSrgb or Format.Etc2RgbaUnorm or Format.Etc2RgbPtaSrgb
public static bool IsEtc2(this Format format) or Format.Etc2RgbPtaUnorm or Format.Etc2RgbSrgb or Format.Etc2RgbUnorm;
{
switch (format)
{
case Format.Etc2RgbaSrgb:
case Format.Etc2RgbaUnorm:
case Format.Etc2RgbPtaSrgb:
case Format.Etc2RgbPtaUnorm:
case Format.Etc2RgbSrgb:
case Format.Etc2RgbUnorm:
return true;
}
return false;
}
/// <summary> /// <summary>
/// Checks if the texture format is a BGR format. /// Checks if the texture format is a BGR format.
/// </summary> /// </summary>
/// <param name="format">Texture format</param> public bool IsBgr => fmt is
/// <returns>True if the texture format is a BGR format, false otherwise</returns> Format.B5G6R5Unorm or Format.B5G5R5A1Unorm or Format.B8G8R8A8Unorm or Format.B8G8R8A8Srgb
public static bool IsBgr(this Format format) or Format.B10G10R10A2Unorm;
{
switch (format)
{
case Format.B5G6R5Unorm:
case Format.B5G5R5A1Unorm:
case Format.B8G8R8A8Unorm:
case Format.B8G8R8A8Srgb:
case Format.B10G10R10A2Unorm:
return true;
}
return false;
}
/// <summary> /// <summary>
/// Checks if the texture format is a depth, stencil or depth-stencil format. /// Checks if the texture format is a depth, stencil or depth-stencil format.
/// </summary> /// </summary>
/// <param name="format">Texture format</param> public bool IsDepthOrStencil => fmt is
/// <returns>True if the format is a depth, stencil or depth-stencil format, false otherwise</returns> Format.D16Unorm or Format.D24UnormS8Uint or Format.S8UintD24Unorm or Format.X8UintD24Unorm
public static bool IsDepthOrStencil(this Format format) or Format.D32Float or Format.D32FloatS8Uint or Format.S8Uint;
{
switch (format)
{
case Format.D16Unorm:
case Format.D24UnormS8Uint:
case Format.S8UintD24Unorm:
case Format.X8UintD24Unorm:
case Format.D32Float:
case Format.D32FloatS8Uint:
case Format.S8Uint:
return true;
}
return false;
}
/// <summary>
/// Checks if the texture format is an unsigned integer color format.
/// </summary>
/// <param name="format">Texture format</param>
/// <returns>True if the texture format is an unsigned integer color format, false otherwise</returns>
public static bool IsUint(this Format format)
{
switch (format)
{
case Format.R8Uint:
case Format.R16Uint:
case Format.R32Uint:
case Format.R8G8Uint:
case Format.R16G16Uint:
case Format.R32G32Uint:
case Format.R8G8B8Uint:
case Format.R16G16B16Uint:
case Format.R32G32B32Uint:
case Format.R8G8B8A8Uint:
case Format.R16G16B16A16Uint:
case Format.R32G32B32A32Uint:
case Format.R10G10B10A2Uint:
return true;
}
return false;
}
/// <summary>
/// Checks if the texture format is a signed integer color format.
/// </summary>
/// <param name="format">Texture format</param>
/// <returns>True if the texture format is a signed integer color format, false otherwise</returns>
public static bool IsSint(this Format format)
{
switch (format)
{
case Format.R8Sint:
case Format.R16Sint:
case Format.R32Sint:
case Format.R8G8Sint:
case Format.R16G16Sint:
case Format.R32G32Sint:
case Format.R8G8B8Sint:
case Format.R16G16B16Sint:
case Format.R32G32B32Sint:
case Format.R8G8B8A8Sint:
case Format.R16G16B16A16Sint:
case Format.R32G32B32A32Sint:
case Format.R10G10B10A2Sint:
return true;
}
return false;
}
/// <summary>
/// Checks if the texture format is an integer color format.
/// </summary>
/// <param name="format">Texture format</param>
/// <returns>True if the texture format is an integer color format, false otherwise</returns>
public static bool IsInteger(this Format format)
{
return format.IsUint() || format.IsSint();
}
/// <summary> /// <summary>
/// Checks if the texture format is a float or sRGB color format. /// Checks if the texture format is a float or sRGB color format.
@ -720,28 +293,57 @@ namespace Ryujinx.Graphics.GAL
/// Does not include normalized, compressed or depth formats. /// Does not include normalized, compressed or depth formats.
/// Float and sRGB formats do not participate in logical operations. /// Float and sRGB formats do not participate in logical operations.
/// </remarks> /// </remarks>
/// <param name="format">Texture format</param> public bool IsFloatOrSrgb => fmt is
/// <returns>True if the format is a float or sRGB color format, false otherwise</returns> Format.R8G8B8A8Srgb or Format.B8G8R8A8Srgb or Format.R16Float or Format.R16G16Float
public static bool IsFloatOrSrgb(this Format format) or Format.R16G16B16Float or Format.R16G16B16A16Float or Format.R32Float or Format.R32G32Float
{ or Format.R32G32B32Float or Format.R32G32B32A32Float or Format.R11G11B10Float
switch (format) or Format.R9G9B9E5Float;
{
case Format.R8G8B8A8Srgb:
case Format.B8G8R8A8Srgb:
case Format.R16Float:
case Format.R16G16Float:
case Format.R16G16B16Float:
case Format.R16G16B16A16Float:
case Format.R32Float:
case Format.R32G32Float:
case Format.R32G32B32Float:
case Format.R32G32B32A32Float:
case Format.R11G11B10Float:
case Format.R9G9B9E5Float:
return true;
}
return false; /// <summary>
/// Checks if the texture format is an ASTC Unorm format.
/// </summary>
public bool IsAstcUnorm => fmt is
Format.Astc4x4Unorm or Format.Astc5x4Unorm or Format.Astc5x5Unorm or Format.Astc6x5Unorm
or Format.Astc6x6Unorm or Format.Astc8x5Unorm or Format.Astc8x6Unorm or Format.Astc8x8Unorm
or Format.Astc10x5Unorm or Format.Astc10x6Unorm or Format.Astc10x8Unorm or Format.Astc10x10Unorm
or Format.Astc12x10Unorm or Format.Astc12x12Unorm;
/// <summary>
/// Checks if the texture format is an ASTC SRGB format.
/// </summary>
public bool IsAstcSrgb => fmt is
Format.Astc4x4Srgb or Format.Astc5x4Srgb or Format.Astc5x5Srgb or Format.Astc6x5Srgb
or Format.Astc6x6Srgb or Format.Astc8x5Srgb or Format.Astc8x6Srgb or Format.Astc8x8Srgb
or Format.Astc10x5Srgb or Format.Astc10x6Srgb or Format.Astc10x8Srgb or Format.Astc10x10Srgb
or Format.Astc12x10Srgb or Format.Astc12x12Srgb;
/// <summary>
/// Checks if the texture format is an ASTC format.
/// </summary>
public bool IsAstc => fmt.IsAstcUnorm || fmt.IsAstcSrgb;
/// <summary>
/// Checks if the texture format is an unsigned integer color format.
/// </summary>
public bool IsUnsignedInt => fmt is
Format.R8Uint or Format.R16Uint or Format.R32Uint or Format.R8G8Uint or Format.R16G16Uint
or Format.R32G32Uint or Format.R8G8B8Uint or Format.R16G16B16Uint or Format.R32G32B32Uint
or Format.R8G8B8A8Uint or Format.R16G16B16A16Uint or Format.R32G32B32A32Uint
or Format.R10G10B10A2Uint;
/// <summary>
/// Checks if the texture format is a signed integer color format.
/// </summary>
public bool IsSignedInt => fmt is
Format.R8Sint or Format.R16Sint or Format.R32Sint or Format.R8G8Sint or Format.R16G16Sint
or Format.R32G32Sint or Format.R8G8B8Sint or Format.R16G16B16Sint or Format.R32G32B32Sint
or Format.R8G8B8A8Sint or Format.R16G16B16A16Sint or Format.R32G32B32A32Sint
or Format.R10G10B10A2Sint;
/// <summary>
/// Checks if the texture format is an integer color format.
/// </summary>
public bool IsInt => fmt.IsUnsignedInt || fmt.IsSignedInt;
} }
} }
} }

View file

@ -16,14 +16,13 @@ namespace Ryujinx.Graphics.GAL
public static class TargetExtensions public static class TargetExtensions
{ {
public static bool IsMultisample(this Target target) extension(Target target)
{ {
return target is Target.Texture2DMultisample or Target.Texture2DMultisampleArray; public bool IsMultisample => target is Target.Texture2DMultisample or Target.Texture2DMultisampleArray;
}
public static bool HasDepthOrLayers(this Target target) public bool HasDepthOrLayers =>
{ target is
return target is Target.Texture3D or Target.Texture3D or
Target.Texture1DArray or Target.Texture1DArray or
Target.Texture2DArray or Target.Texture2DArray or
Target.Texture2DMultisampleArray or Target.Texture2DMultisampleArray or

View file

@ -171,7 +171,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
{ {
MemoryManager memoryManager = _channel.MemoryManager; MemoryManager memoryManager = _channel.MemoryManager;
Span<byte> data = MemoryMarshal.Cast<int, byte>(_buffer)[.._size]; Span<byte> data = MemoryMarshal.Cast<int, byte>(new Span<int>(_buffer))[.._size];
if (_isLinear && _lineCount == 1) if (_isLinear && _lineCount == 1)
{ {

View file

@ -176,7 +176,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
ulong vbSize = GetVertexBufferSize(address, endAddress.Pack(), vbStride, _indexed, instanced, _firstVertex, _count); ulong vbSize = GetVertexBufferSize(address, endAddress.Pack(), vbStride, _indexed, instanced, _firstVertex, _count);
ulong attributeOffset = (ulong)vertexAttrib.UnpackOffset(); ulong attributeOffset = (ulong)vertexAttrib.UnpackOffset();
int componentSize = format.GetScalarSize(); int componentSize = format.ScalarSize;
address += attributeOffset; address += attributeOffset;

View file

@ -849,8 +849,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
FormatInfo dsFormat = _state.State.RtDepthStencilState.Format.Convert(); FormatInfo dsFormat = _state.State.RtDepthStencilState.Format.Convert();
bool hasDepth = dsFormat.Format.HasDepth(); bool hasDepth = dsFormat.Format.HasDepth;
bool hasStencil = dsFormat.Format.HasStencil(); bool hasStencil = dsFormat.Format.HasStencil;
if (hasStencil && (!clearStencil || (clearAffectedByStencilMask && _state.State.StencilTestState.FrontMask != 0xff))) if (hasStencil && (!clearStencil || (clearAffectedByStencilMask && _state.State.StencilTestState.FrontMask != 0xff)))
{ {

View file

@ -297,7 +297,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
{ {
Format format = colorState.Format.Convert().Format; Format format = colorState.Format.Convert().Format;
AttributeType type = format.IsInteger() ? (format.IsSint() ? AttributeType.Sint : AttributeType.Uint) : AttributeType.Float; AttributeType type = format.IsInt
? (format.IsSignedInt ? AttributeType.Sint : AttributeType.Uint)
: AttributeType.Float;
if (type != fragmentOutputTypesSpan[index]) if (type != fragmentOutputTypesSpan[index])
{ {

View file

@ -534,7 +534,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
if (!_context.Capabilities.SupportsBgraFormat) if (!_context.Capabilities.SupportsBgraFormat)
{ {
_context.SupportBufferUpdater.SetRenderTargetIsBgra(index, color.Format.IsBgr()); _context.SupportBufferUpdater.SetRenderTargetIsBgra(index, color.Format.IsBgr);
} }
} }
} }
@ -1317,10 +1317,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
FilterBlendFactor(blend.AlphaDstFactor, index)); FilterBlendFactor(blend.AlphaDstFactor, index));
if (enable && if (enable &&
(blend.ColorSrcFactor.IsDualSource() || (blend.ColorSrcFactor.IsDualSource ||
blend.ColorDstFactor.IsDualSource() || blend.ColorDstFactor.IsDualSource ||
blend.AlphaSrcFactor.IsDualSource() || blend.AlphaSrcFactor.IsDualSource ||
blend.AlphaDstFactor.IsDualSource())) blend.AlphaDstFactor.IsDualSource))
{ {
dualSourceBlendEnabled = true; dualSourceBlendEnabled = true;
} }
@ -1345,10 +1345,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
FilterBlendFactor(blend.AlphaDstFactor, 0)); FilterBlendFactor(blend.AlphaDstFactor, 0));
if (enable && if (enable &&
(blend.ColorSrcFactor.IsDualSource() || (blend.ColorSrcFactor.IsDualSource ||
blend.ColorDstFactor.IsDualSource() || blend.ColorDstFactor.IsDualSource ||
blend.AlphaSrcFactor.IsDualSource() || blend.AlphaSrcFactor.IsDualSource ||
blend.AlphaDstFactor.IsDualSource())) blend.AlphaDstFactor.IsDualSource))
{ {
dualSourceBlendEnabled = true; dualSourceBlendEnabled = true;
} }

View file

@ -333,7 +333,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
// as copies between depth and color formats are not allowed. // as copies between depth and color formats are not allowed.
// For depth blit, the destination texture format should always match exactly. // For depth blit, the destination texture format should always match exactly.
if (srcTexture.Format.IsDepthOrStencil()) if (srcTexture.Format.IsDepthOrStencil)
{ {
dstCopyTextureFormat = srcTexture.Info.FormatInfo; dstCopyTextureFormat = srcTexture.Info.FormatInfo;
} }

View file

@ -662,7 +662,7 @@ namespace Ryujinx.Graphics.Gpu.Image
bool found = _textureFormats.TryGetValue((TextureFormat)encoded, out format); bool found = _textureFormats.TryGetValue((TextureFormat)encoded, out format);
if (found && isPacked && !format.Format.IsDepthOrStencil()) if (found && isPacked && !format.Format.IsDepthOrStencil)
{ {
// If the packed flag is set, then the components of the pixel are tightly packed into the // If the packed flag is set, then the components of the pixel are tightly packed into the
// GPU registers on the shader. // GPU registers on the shader.

View file

@ -643,7 +643,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// The decompression is slow, so we want to avoid it as much as possible. // The decompression is slow, so we want to avoid it as much as possible.
// This does a byte-by-byte check and skips the update if the data is equal in this case. // This does a byte-by-byte check and skips the update if the data is equal in this case.
// This improves the speed on applications that overwrites ASTC data without changing anything. // This improves the speed on applications that overwrites ASTC data without changing anything.
if (Info.FormatInfo.Format.IsAstc() && !_context.Capabilities.SupportsAstcCompression) if (Info.FormatInfo.Format.IsAstc && !_context.Capabilities.SupportsAstcCompression)
{ {
if (_updateCount < ByteComparisonSwitchThreshold) if (_updateCount < ByteComparisonSwitchThreshold)
{ {
@ -792,7 +792,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// Handle compressed cases not supported by the host: // Handle compressed cases not supported by the host:
// - ASTC is usually not supported on desktop cards. // - ASTC is usually not supported on desktop cards.
// - BC4/BC5 is not supported on 3D textures. // - BC4/BC5 is not supported on 3D textures.
if (!_context.Capabilities.SupportsAstcCompression && Format.IsAstc()) if (!_context.Capabilities.SupportsAstcCompression && Format.IsAstc)
{ {
using (result) using (result)
{ {
@ -823,7 +823,7 @@ namespace Ryujinx.Graphics.Gpu.Image
return decoded; return decoded;
} }
} }
else if (!_context.Capabilities.SupportsEtc2Compression && Format.IsEtc2()) else if (!_context.Capabilities.SupportsEtc2Compression && Format.IsEtc2)
{ {
switch (Format) switch (Format)
{ {
@ -924,7 +924,7 @@ namespace Ryujinx.Graphics.Gpu.Image
} }
} }
} }
else if (!_context.Capabilities.Supports5BitComponentFormat && Format.Is16BitPacked()) else if (!_context.Capabilities.Supports5BitComponentFormat && Format.Is16BitPacked)
{ {
switch (Format) switch (Format)
{ {
@ -1251,7 +1251,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewTargetCompatible(Info, info, ref caps)); result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewTargetCompatible(Info, info, ref caps));
bool bothMs = Info.Target.IsMultisample() && info.Target.IsMultisample(); bool bothMs = Info.Target.IsMultisample && info.Target.IsMultisample;
if (bothMs && (Info.SamplesInX != info.SamplesInX || Info.SamplesInY != info.SamplesInY)) if (bothMs && (Info.SamplesInX != info.SamplesInX || Info.SamplesInY != info.SamplesInY))
{ {
result = TextureViewCompatibility.Incompatible; result = TextureViewCompatibility.Incompatible;

View file

@ -180,7 +180,7 @@ namespace Ryujinx.Graphics.Gpu.Image
int widthAlignment = (info.IsLinear ? Constants.StrideAlignment : Constants.GobAlignment) / info.FormatInfo.BytesPerPixel; int widthAlignment = (info.IsLinear ? Constants.StrideAlignment : Constants.GobAlignment) / info.FormatInfo.BytesPerPixel;
if (!(info.FormatInfo.Format.IsDepthOrStencil() || info.FormatInfo.Components == 1)) if (!(info.FormatInfo.Format.IsDepthOrStencil || info.FormatInfo.Components == 1))
{ {
// Discount square textures that aren't depth-stencil like. (excludes game textures, cubemap faces, most 3D texture LUT, texture atlas) // Discount square textures that aren't depth-stencil like. (excludes game textures, cubemap faces, most 3D texture LUT, texture atlas)
// Detect if the texture is possibly square. Widths may be aligned, so to remove the uncertainty we align both the width and height. // Detect if the texture is possibly square. Widths may be aligned, so to remove the uncertainty we align both the width and height.

View file

@ -75,13 +75,14 @@ namespace Ryujinx.Graphics.Gpu.Image
if (!caps.SupportsAstcCompression) if (!caps.SupportsAstcCompression)
{ {
if (info.FormatInfo.Format.IsAstcUnorm()) if (info.FormatInfo.Format.IsAstcUnorm)
{ {
return GraphicsConfig.EnableTextureRecompression return GraphicsConfig.EnableTextureRecompression
? new FormatInfo(Format.Bc7Unorm, 4, 4, 16, 4) ? new FormatInfo(Format.Bc7Unorm, 4, 4, 16, 4)
: new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4); : new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4);
} }
else if (info.FormatInfo.Format.IsAstcSrgb())
if (info.FormatInfo.Format.IsAstcSrgb)
{ {
return GraphicsConfig.EnableTextureRecompression return GraphicsConfig.EnableTextureRecompression
? new FormatInfo(Format.Bc7Srgb, 4, 4, 16, 4) ? new FormatInfo(Format.Bc7Srgb, 4, 4, 16, 4)
@ -151,9 +152,9 @@ namespace Ryujinx.Graphics.Gpu.Image
return new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4); return new FormatInfo(Format.R8G8B8A8Unorm, 1, 1, 4, 4);
} }
} }
else if (!caps.Supports5BitComponentFormat && info.FormatInfo.Format.Is16BitPacked()) else if (!caps.Supports5BitComponentFormat && info.FormatInfo.Format.Is16BitPacked)
{ {
return new FormatInfo(info.FormatInfo.Format.IsBgr() ? Format.B8G8R8A8Unorm : Format.R8G8B8A8Unorm, 1, 1, 4, 4); return new FormatInfo(info.FormatInfo.Format.IsBgr ? Format.B8G8R8A8Unorm : Format.R8G8B8A8Unorm, 1, 1, 4, 4);
} }
return info.FormatInfo; return info.FormatInfo;
@ -388,7 +389,7 @@ namespace Ryujinx.Graphics.Gpu.Image
return stride == rhs.Stride ? TextureViewCompatibility.CopyOnly : TextureViewCompatibility.LayoutIncompatible; return stride == rhs.Stride ? TextureViewCompatibility.CopyOnly : TextureViewCompatibility.LayoutIncompatible;
} }
else if (lhs.Target.IsMultisample() != rhs.Target.IsMultisample() && alignedWidthMatches && lhsAlignedSize.Height == rhsAlignedSize.Height) else if (lhs.Target.IsMultisample != rhs.Target.IsMultisample && alignedWidthMatches && lhsAlignedSize.Height == rhsAlignedSize.Height)
{ {
// Copy between multisample and non-multisample textures with mismatching size is allowed, // Copy between multisample and non-multisample textures with mismatching size is allowed,
// as long aligned size matches. // as long aligned size matches.
@ -644,7 +645,7 @@ namespace Ryujinx.Graphics.Gpu.Image
FormatInfo lhsFormat = lhs.FormatInfo; FormatInfo lhsFormat = lhs.FormatInfo;
FormatInfo rhsFormat = rhs.FormatInfo; FormatInfo rhsFormat = rhs.FormatInfo;
if (lhsFormat.Format.IsDepthOrStencil() || rhsFormat.Format.IsDepthOrStencil()) if (lhsFormat.Format.IsDepthOrStencil || rhsFormat.Format.IsDepthOrStencil)
{ {
bool forSampler = flags.HasFlag(TextureSearchFlags.ForSampler); bool forSampler = flags.HasFlag(TextureSearchFlags.ForSampler);
bool depthAlias = flags.HasFlag(TextureSearchFlags.DepthAlias); bool depthAlias = flags.HasFlag(TextureSearchFlags.DepthAlias);

View file

@ -147,7 +147,7 @@ namespace Ryujinx.Graphics.Gpu.Image
_allOffsets = size.AllOffsets; _allOffsets = size.AllOffsets;
_sliceSizes = size.SliceSizes; _sliceSizes = size.SliceSizes;
if (Storage.Target.HasDepthOrLayers() && Storage.Info.GetSlices() > GranularLayerThreshold) if (Storage.Target.HasDepthOrLayers && Storage.Info.GetSlices() > GranularLayerThreshold)
{ {
_hasLayerViews = true; _hasLayerViews = true;
_hasMipViews = true; _hasMipViews = true;

View file

@ -660,7 +660,7 @@ namespace Ryujinx.Graphics.Gpu.Image
swizzleB, swizzleB,
swizzleA); swizzleA);
if (formatInfo.Format.IsDepthOrStencil()) if (formatInfo.Format.IsDepthOrStencil)
{ {
swizzleR = SwizzleComponent.Red; swizzleR = SwizzleComponent.Red;
swizzleG = SwizzleComponent.Red; swizzleG = SwizzleComponent.Red;

View file

@ -138,7 +138,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
{ {
if (item.Value._useGranular) if (item.Value._useGranular)
{ {
baseHandles.AddRange((item.Value._memoryTrackingGranular.GetHandles())); baseHandles.AddRange(item.Value._memoryTrackingGranular.Handles);
} }
else else
{ {

View file

@ -8,7 +8,7 @@ namespace Ryujinx.Graphics.OpenGL
{ {
public static void Clear(BufferHandle destination, int offset, int size, uint value) public static void Clear(BufferHandle destination, int offset, int size, uint value)
{ {
GL.BindBuffer(BufferTarget.CopyWriteBuffer, destination.ToInt32()); GL.BindBuffer(BufferTarget.CopyWriteBuffer, destination);
unsafe unsafe
{ {
@ -58,8 +58,8 @@ namespace Ryujinx.Graphics.OpenGL
public static void Copy(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size) public static void Copy(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
{ {
GL.BindBuffer(BufferTarget.CopyReadBuffer, source.ToInt32()); GL.BindBuffer(BufferTarget.CopyReadBuffer, source);
GL.BindBuffer(BufferTarget.CopyWriteBuffer, destination.ToInt32()); GL.BindBuffer(BufferTarget.CopyWriteBuffer, destination);
GL.CopyBufferSubData( GL.CopyBufferSubData(
BufferTarget.CopyReadBuffer, BufferTarget.CopyReadBuffer,
@ -86,7 +86,7 @@ namespace Ryujinx.Graphics.OpenGL
{ {
nint target = renderer.PersistentBuffers.Default.GetHostArray(size); nint target = renderer.PersistentBuffers.Default.GetHostArray(size);
GL.BindBuffer(BufferTarget.CopyReadBuffer, buffer.ToInt32()); GL.BindBuffer(BufferTarget.CopyReadBuffer, buffer);
GL.GetBufferSubData(BufferTarget.CopyReadBuffer, (nint)offset, size, target); GL.GetBufferSubData(BufferTarget.CopyReadBuffer, (nint)offset, size, target);
@ -96,13 +96,13 @@ namespace Ryujinx.Graphics.OpenGL
public static void Resize(BufferHandle handle, int size) public static void Resize(BufferHandle handle, int size)
{ {
GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle.ToInt32()); GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle);
GL.BufferData(BufferTarget.CopyWriteBuffer, size, nint.Zero, BufferUsageHint.StreamCopy); GL.BufferData(BufferTarget.CopyWriteBuffer, size, nint.Zero, BufferUsageHint.StreamCopy);
} }
public static void SetData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data) public static void SetData(BufferHandle buffer, int offset, ReadOnlySpan<byte> data)
{ {
GL.BindBuffer(BufferTarget.CopyWriteBuffer, buffer.ToInt32()); GL.BindBuffer(BufferTarget.CopyWriteBuffer, buffer);
unsafe unsafe
{ {
@ -115,7 +115,7 @@ namespace Ryujinx.Graphics.OpenGL
public static void Delete(BufferHandle buffer) public static void Delete(BufferHandle buffer)
{ {
GL.DeleteBuffer(buffer.ToInt32()); GL.DeleteBuffer(buffer);
} }
} }
} }

View file

@ -1,4 +1,3 @@
using Ryujinx.Graphics.GAL;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
@ -14,10 +13,5 @@ namespace Ryujinx.Graphics.OpenGL
return Unsafe.As<ulong, T>(ref handle64); return Unsafe.As<ulong, T>(ref handle64);
} }
public static int ToInt32(this BufferHandle handle)
{
return (int)Unsafe.As<BufferHandle, ulong>(ref handle);
}
} }
} }

View file

@ -139,7 +139,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
start = sizeAligned; start = sizeAligned;
} }
Span<uint> outSpan = MemoryMarshal.Cast<byte, uint>(output); Span<uint> outSpan = MemoryMarshal.Cast<byte, uint>(new Span<byte>(output));
ReadOnlySpan<uint> dataSpan = MemoryMarshal.Cast<byte, uint>(data); ReadOnlySpan<uint> dataSpan = MemoryMarshal.Cast<byte, uint>(data);
for (int i = start / sizeof(uint); i < dataSpan.Length; i++) for (int i = start / sizeof(uint); i < dataSpan.Length; i++)
{ {

View file

@ -97,7 +97,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
SizedInternalFormat format = (SizedInternalFormat)FormatTable.GetFormatInfo(Info.Format).PixelInternalFormat; SizedInternalFormat format = (SizedInternalFormat)FormatTable.GetFormatInfo(Info.Format).PixelInternalFormat;
GL.TexBufferRange(TextureBufferTarget.TextureBuffer, format, _buffer.ToInt32(), (nint)buffer.Offset, buffer.Size); GL.TexBufferRange(TextureBufferTarget.TextureBuffer, format, _buffer, (nint)buffer.Offset, buffer.Size);
} }
public void Dispose() public void Dispose()

View file

@ -53,7 +53,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
int layers, int layers,
int levels) int levels)
{ {
TextureView srcConverted = src.Format.IsBgr() != dst.Format.IsBgr() ? BgraSwap(src) : src; TextureView srcConverted = src.Format.IsBgr != dst.Format.IsBgr ? BgraSwap(src) : src;
(int oldDrawFramebufferHandle, int oldReadFramebufferHandle) = ((Pipeline)_renderer.Pipeline).GetBoundFramebuffers(); (int oldDrawFramebufferHandle, int oldReadFramebufferHandle) = ((Pipeline)_renderer.Pipeline).GetBoundFramebuffers();
@ -87,7 +87,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
ClearBufferMask mask = GetMask(src.Format); ClearBufferMask mask = GetMask(src.Format);
if ((mask & (ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit)) != 0 || src.Format.IsInteger()) if ((mask & (ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit)) != 0 || src.Format.IsInt)
{ {
linearFilter = false; linearFilter = false;
} }

View file

@ -84,7 +84,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
swizzleRgba[2] = temp2; swizzleRgba[2] = temp2;
swizzleRgba[3] = temp; swizzleRgba[3] = temp;
} }
else if (Info.Format.IsBgr()) else if (Info.Format.IsBgr)
{ {
// Swap B <-> R for BGRA formats, as OpenGL has no support for them // Swap B <-> R for BGRA formats, as OpenGL has no support for them
// and we need to manually swap the components on read/write on the GPU. // and we need to manually swap the components on read/write on the GPU.
@ -116,13 +116,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
{ {
TextureView destinationView = (TextureView)destination; TextureView destinationView = (TextureView)destination;
bool srcIsMultisample = Target.IsMultisample(); bool srcIsMultisample = Target.IsMultisample;
bool dstIsMultisample = destinationView.Target.IsMultisample(); bool dstIsMultisample = destinationView.Target.IsMultisample;
if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil()) if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil)
{ {
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer); int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
CopyWithBlitForDepthMS(destinationView, 0, firstLayer, layers); CopyWithBlitForDepthMultisample(destinationView, 0, firstLayer, layers);
} }
else if (!dstIsMultisample && srcIsMultisample) else if (!dstIsMultisample && srcIsMultisample)
{ {
@ -140,7 +140,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel); int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel);
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, 0, firstLayer, 0, firstLevel, layers, levels); _renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, 0, firstLayer, 0, firstLevel, layers, levels);
} }
else if (destinationView.Format.IsDepthOrStencil() != Format.IsDepthOrStencil()) else if (destinationView.Format.IsDepthOrStencil != Format.IsDepthOrStencil)
{ {
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer); int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel); int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel);
@ -172,12 +172,12 @@ namespace Ryujinx.Graphics.OpenGL.Image
{ {
TextureView destinationView = (TextureView)destination; TextureView destinationView = (TextureView)destination;
bool srcIsMultisample = Target.IsMultisample(); bool srcIsMultisample = Target.IsMultisample;
bool dstIsMultisample = destinationView.Target.IsMultisample(); bool dstIsMultisample = destinationView.Target.IsMultisample;
if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil()) if (dstIsMultisample != srcIsMultisample && Info.Format.IsDepthOrStencil)
{ {
CopyWithBlitForDepthMS(destinationView, srcLayer, dstLayer, 1); CopyWithBlitForDepthMultisample(destinationView, srcLayer, dstLayer, 1);
} }
else if (!dstIsMultisample && srcIsMultisample) else if (!dstIsMultisample && srcIsMultisample)
{ {
@ -191,7 +191,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
{ {
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1); _renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
} }
else if (destinationView.Format.IsDepthOrStencil() != Format.IsDepthOrStencil()) else if (destinationView.Format.IsDepthOrStencil != Format.IsDepthOrStencil)
{ {
int minWidth = Math.Min(Width, destinationView.Width); int minWidth = Math.Min(Width, destinationView.Width);
int minHeight = Math.Min(Height, destinationView.Height); int minHeight = Math.Min(Height, destinationView.Height);
@ -204,7 +204,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
} }
} }
private void CopyWithBlitForDepthMS(TextureView destinationView, int srcLayer, int dstLayer, int layers) private void CopyWithBlitForDepthMultisample(TextureView destinationView, int srcLayer, int dstLayer, int layers)
{ {
// This is currently used for multisample <-> non-multisample copies. // This is currently used for multisample <-> non-multisample copies.
// We can't do that with compute because it's not possible to write depth textures on compute. // We can't do that with compute because it's not possible to write depth textures on compute.
@ -216,9 +216,9 @@ namespace Ryujinx.Graphics.OpenGL.Image
Extents2D srcRegion = new(0, 0, Width, Height); Extents2D srcRegion = new(0, 0, Width, Height);
Extents2D dstRegion = new(0, 0, destinationView.Width, destinationView.Height); Extents2D dstRegion = new(0, 0, destinationView.Width, destinationView.Height);
if (destinationView.Target.IsMultisample()) if (destinationView.Target.IsMultisample)
{ {
TextureView intermmediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast( TextureView intermediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
Info.Target, Info.Target,
Info.BlockWidth, Info.BlockWidth,
Info.BlockHeight, Info.BlockHeight,
@ -230,8 +230,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
1, 1,
1); 1);
_renderer.TextureCopy.Copy(this, intermmediate, srcRegion, dstRegion, false); _renderer.TextureCopy.Copy(this, intermediate, srcRegion, dstRegion, false);
_renderer.TextureCopy.Copy(intermmediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1); _renderer.TextureCopy.Copy(intermediate, destinationView, dstRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
} }
else else
{ {
@ -242,7 +242,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
_ => Target, _ => Target,
}; };
TextureView intermmediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast( TextureView intermediate = _renderer.TextureCopy.IntermediatePool.GetOrCreateWithAtLeast(
target, target,
Info.BlockWidth, Info.BlockWidth,
Info.BlockHeight, Info.BlockHeight,
@ -254,8 +254,8 @@ namespace Ryujinx.Graphics.OpenGL.Image
1, 1,
1); 1);
_renderer.TextureCopy.Copy(this, intermmediate, srcRegion, srcRegion, false); _renderer.TextureCopy.Copy(this, intermediate, srcRegion, srcRegion, false);
_renderer.TextureCopy.Copy(intermmediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1); _renderer.TextureCopy.Copy(intermediate, destinationView, srcRegion, dstRegion, false, srcLayer, dstLayer, 0, 0, layers, 1);
} }
} }
@ -305,15 +305,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
{ {
return PinnedSpan<byte>.UnsafeFromSpan(_renderer.PersistentBuffers.Default.GetTextureData(this, size, layer, level)); return PinnedSpan<byte>.UnsafeFromSpan(_renderer.PersistentBuffers.Default.GetTextureData(this, size, layer, level));
} }
else
{
nint target = _renderer.PersistentBuffers.Default.GetHostArray(size); nint target = _renderer.PersistentBuffers.Default.GetHostArray(size);
int offset = WriteTo2D(target, layer, level); int offset = WriteTo2D(target, layer, level);
return new PinnedSpan<byte>((byte*)target.ToPointer() + offset, size); return new PinnedSpan<byte>((byte*)target.ToPointer() + offset, size);
} }
}
public void CopyTo(BufferRange range, int layer, int level, int stride) public void CopyTo(BufferRange range, int layer, int level, int stride)
{ {
@ -322,7 +320,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
throw new NotSupportedException("Stride conversion for texture copy to buffer not supported."); throw new NotSupportedException("Stride conversion for texture copy to buffer not supported.");
} }
GL.BindBuffer(BufferTarget.PixelPackBuffer, range.Handle.ToInt32()); GL.BindBuffer(BufferTarget.PixelPackBuffer, range.Handle);
FormatInfo format = FormatTable.GetFormatInfo(Info.Format); FormatInfo format = FormatTable.GetFormatInfo(Info.Format);
if (format.PixelFormat == PixelFormat.DepthStencil) if (format.PixelFormat == PixelFormat.DepthStencil)

View file

@ -26,7 +26,7 @@ namespace Ryujinx.Graphics.OpenGL
public void Map(BufferHandle handle, int size) public void Map(BufferHandle handle, int size)
{ {
GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle.ToInt32()); GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle);
nint ptr = GL.MapBufferRange(BufferTarget.CopyWriteBuffer, nint.Zero, size, BufferAccessMask.MapReadBit | BufferAccessMask.MapPersistentBit); nint ptr = GL.MapBufferRange(BufferTarget.CopyWriteBuffer, nint.Zero, size, BufferAccessMask.MapReadBit | BufferAccessMask.MapPersistentBit);
_maps[handle] = ptr; _maps[handle] = ptr;
@ -36,7 +36,7 @@ namespace Ryujinx.Graphics.OpenGL
{ {
if (_maps.ContainsKey(handle)) if (_maps.ContainsKey(handle))
{ {
GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle.ToInt32()); GL.BindBuffer(BufferTarget.CopyWriteBuffer, handle);
GL.UnmapBuffer(BufferTarget.CopyWriteBuffer); GL.UnmapBuffer(BufferTarget.CopyWriteBuffer);
_maps.Remove(handle); _maps.Remove(handle);
@ -140,7 +140,7 @@ namespace Ryujinx.Graphics.OpenGL
{ {
EnsureBuffer(size); EnsureBuffer(size);
GL.BindBuffer(BufferTarget.CopyReadBuffer, buffer.ToInt32()); GL.BindBuffer(BufferTarget.CopyReadBuffer, buffer);
GL.BindBuffer(BufferTarget.CopyWriteBuffer, _copyBufferHandle); GL.BindBuffer(BufferTarget.CopyWriteBuffer, _copyBufferHandle);
GL.CopyBufferSubData(BufferTarget.CopyReadBuffer, BufferTarget.CopyWriteBuffer, (nint)offset, nint.Zero, size); GL.CopyBufferSubData(BufferTarget.CopyReadBuffer, BufferTarget.CopyWriteBuffer, (nint)offset, nint.Zero, size);

View file

@ -587,7 +587,7 @@ namespace Ryujinx.Graphics.OpenGL
_vertexArray.SetRangeOfIndexBuffer(); _vertexArray.SetRangeOfIndexBuffer();
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32()); GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle);
GL.DrawElementsIndirect(_primitiveType, _elementsType, (nint)indirectBuffer.Offset); GL.DrawElementsIndirect(_primitiveType, _elementsType, (nint)indirectBuffer.Offset);
@ -608,8 +608,8 @@ namespace Ryujinx.Graphics.OpenGL
_vertexArray.SetRangeOfIndexBuffer(); _vertexArray.SetRangeOfIndexBuffer();
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32()); GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle);
GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32()); GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle);
GL.MultiDrawElementsIndirectCount( GL.MultiDrawElementsIndirectCount(
_primitiveType, _primitiveType,
@ -634,7 +634,7 @@ namespace Ryujinx.Graphics.OpenGL
PreDrawVbUnbounded(); PreDrawVbUnbounded();
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32()); GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle);
GL.DrawArraysIndirect(_primitiveType, (nint)indirectBuffer.Offset); GL.DrawArraysIndirect(_primitiveType, (nint)indirectBuffer.Offset);
@ -651,8 +651,8 @@ namespace Ryujinx.Graphics.OpenGL
PreDrawVbUnbounded(); PreDrawVbUnbounded();
GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle.ToInt32()); GL.BindBuffer((BufferTarget)All.DrawIndirectBuffer, indirectBuffer.Handle);
GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle.ToInt32()); GL.BindBuffer((BufferTarget)All.ParameterBuffer, parameterBuffer.Handle);
GL.MultiDrawArraysIndirectCount( GL.MultiDrawArraysIndirectCount(
_primitiveType, _primitiveType,
@ -812,10 +812,10 @@ namespace Ryujinx.Graphics.OpenGL
EnsureFramebuffer(); EnsureFramebuffer();
_framebuffer.SetDualSourceBlend( _framebuffer.SetDualSourceBlend(
blend.ColorSrcFactor.IsDualSource() || blend.ColorSrcFactor.IsDualSource ||
blend.ColorDstFactor.IsDualSource() || blend.ColorDstFactor.IsDualSource ||
blend.AlphaSrcFactor.IsDualSource() || blend.AlphaSrcFactor.IsDualSource ||
blend.AlphaDstFactor.IsDualSource()); blend.AlphaDstFactor.IsDualSource);
if (_blendConstant != blend.BlendConstant) if (_blendConstant != blend.BlendConstant)
{ {
@ -1178,7 +1178,7 @@ namespace Ryujinx.Graphics.OpenGL
if (color != null) if (color != null)
{ {
int isBgra = color.Format.IsBgr() ? 1 : 0; int isBgra = color.Format.IsBgr ? 1 : 0;
if (_fpIsBgra[index].X != isBgra) if (_fpIsBgra[index].X != isBgra)
{ {
@ -1349,7 +1349,7 @@ namespace Ryujinx.Graphics.OpenGL
Buffer.Resize(_tfbs[i], buffer.Size); Buffer.Resize(_tfbs[i], buffer.Size);
Buffer.Copy(buffer.Handle, _tfbs[i], buffer.Offset, 0, buffer.Size); Buffer.Copy(buffer.Handle, _tfbs[i], buffer.Offset, 0, buffer.Size);
GL.BindBufferBase(BufferRangeTarget.TransformFeedbackBuffer, i, _tfbs[i].ToInt32()); GL.BindBufferBase(BufferRangeTarget.TransformFeedbackBuffer, i, _tfbs[i]);
} }
if (_tfEnabled) if (_tfEnabled)
@ -1454,7 +1454,7 @@ namespace Ryujinx.Graphics.OpenGL
continue; continue;
} }
GL.BindBufferRange(target, assignment.Binding, buffer.Handle.ToInt32(), (nint)buffer.Offset, buffer.Size); GL.BindBufferRange(target, assignment.Binding, buffer.Handle, (nint)buffer.Offset, buffer.Size);
} }
} }

View file

@ -56,7 +56,7 @@ namespace Ryujinx.Graphics.OpenGL
minVertexCount = vertexCount; minVertexCount = vertexCount;
} }
GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (nint)vb.Buffer.Offset, vb.Stride); GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle, (nint)vb.Buffer.Offset, vb.Stride);
GL.VertexBindingDivisor(bindingIndex, vb.Divisor); GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
_vertexBuffersInUse |= 1u << bindingIndex; _vertexBuffersInUse |= 1u << bindingIndex;
} }
@ -134,19 +134,19 @@ namespace Ryujinx.Graphics.OpenGL
public void SetIndexBuffer(BufferRange range) public void SetIndexBuffer(BufferRange range)
{ {
_indexBuffer = range; _indexBuffer = range;
GL.BindBuffer(BufferTarget.ElementArrayBuffer, range.Handle.ToInt32()); GL.BindBuffer(BufferTarget.ElementArrayBuffer, range.Handle);
} }
public void SetRangeOfIndexBuffer() public void SetRangeOfIndexBuffer()
{ {
Buffer.Resize(_tempIndexBuffer, _indexBuffer.Size); Buffer.Resize(_tempIndexBuffer, _indexBuffer.Size);
Buffer.Copy(_indexBuffer.Handle, _tempIndexBuffer, _indexBuffer.Offset, 0, _indexBuffer.Size); Buffer.Copy(_indexBuffer.Handle, _tempIndexBuffer, _indexBuffer.Offset, 0, _indexBuffer.Size);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _tempIndexBuffer.ToInt32()); GL.BindBuffer(BufferTarget.ElementArrayBuffer, _tempIndexBuffer);
} }
public void RestoreIndexBuffer() public void RestoreIndexBuffer()
{ {
GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBuffer.Handle.ToInt32()); GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBuffer.Handle);
} }
public void PreDraw(int vertexCount) public void PreDraw(int vertexCount)
@ -188,7 +188,7 @@ namespace Ryujinx.Graphics.OpenGL
Buffer.Copy(vb.Buffer.Handle, tempVertexBuffer, vb.Buffer.Offset, currentTempVbOffset, vb.Buffer.Size); Buffer.Copy(vb.Buffer.Handle, tempVertexBuffer, vb.Buffer.Offset, currentTempVbOffset, vb.Buffer.Size);
Buffer.Clear(tempVertexBuffer, currentTempVbOffset + vb.Buffer.Size, requiredSize - vb.Buffer.Size, 0); Buffer.Clear(tempVertexBuffer, currentTempVbOffset + vb.Buffer.Size, requiredSize - vb.Buffer.Size, 0);
GL.BindVertexBuffer(vbIndex, tempVertexBuffer.ToInt32(), (nint)currentTempVbOffset, vb.Stride); GL.BindVertexBuffer(vbIndex, tempVertexBuffer, (nint)currentTempVbOffset, vb.Stride);
currentTempVbOffset += requiredSize; currentTempVbOffset += requiredSize;
_vertexBuffersLimited |= 1u << vbIndex; _vertexBuffersLimited |= 1u << vbIndex;
@ -234,7 +234,7 @@ namespace Ryujinx.Graphics.OpenGL
ref VertexBufferDescriptor vb = ref _vertexBuffers[vbIndex]; ref VertexBufferDescriptor vb = ref _vertexBuffers[vbIndex];
GL.BindVertexBuffer(vbIndex, vb.Buffer.Handle.ToInt32(), (nint)vb.Buffer.Offset, vb.Stride); GL.BindVertexBuffer(vbIndex, vb.Buffer.Handle, (nint)vb.Buffer.Offset, vb.Stride);
buffersLimited &= ~(1u << vbIndex); buffersLimited &= ~(1u << vbIndex);
} }

View file

@ -70,7 +70,7 @@ namespace Ryujinx.Graphics.OpenGL
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer); GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, drawFramebuffer);
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer); GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, readFramebuffer);
TextureView viewConverted = view.Format.IsBgr() ? _renderer.TextureCopy.BgraSwap(view) : view; TextureView viewConverted = view.Format.IsBgr ? _renderer.TextureCopy.BgraSwap(view) : view;
UpdateEffect(); UpdateEffect();
@ -80,7 +80,7 @@ namespace Ryujinx.Graphics.OpenGL
viewConverted = _antiAliasing.Run(viewConverted, _width, _height); viewConverted = _antiAliasing.Run(viewConverted, _width, _height);
if (viewConverted.Format.IsBgr()) if (viewConverted.Format.IsBgr)
{ {
TextureView swappedView = _renderer.TextureCopy.BgraSwap(viewConverted); TextureView swappedView = _renderer.TextureCopy.BgraSwap(viewConverted);
@ -152,14 +152,14 @@ namespace Ryujinx.Graphics.OpenGL
if (ScreenCaptureRequested) if (ScreenCaptureRequested)
{ {
CaptureFrame(srcX0, srcY0, srcX1, srcY1, view.Format.IsBgr(), crop.FlipX, crop.FlipY); CaptureFrame(srcX0, srcY0, srcX1, srcY1, view.Format.IsBgr, crop.FlipX, crop.FlipY);
ScreenCaptureRequested = false; ScreenCaptureRequested = false;
} }
if (_scalingFilter != null) if (_scalingFilter != null)
{ {
if (viewConverted.Format.IsBgr() && !_isBgra) if (viewConverted.Format.IsBgr && !_isBgra)
{ {
RecreateUpscalingTexture(true); RecreateUpscalingTexture(true);
} }

View file

@ -20,20 +20,18 @@ namespace Ryujinx.Graphics.Shader
static class AttributeTypeExtensions static class AttributeTypeExtensions
{ {
public static AggregateType ToAggregateType(this AttributeType type) extension(AttributeType type)
{ {
return (type & ~AttributeType.AnyPacked) switch public AggregateType Aggregate =>
(type & ~AttributeType.AnyPacked) switch
{ {
AttributeType.Float => AggregateType.FP32, AttributeType.Float => AggregateType.FP32,
AttributeType.Sint => AggregateType.S32, AttributeType.Sint => AggregateType.S32,
AttributeType.Uint => AggregateType.U32, AttributeType.Uint => AggregateType.U32,
_ => throw new ArgumentException($"Invalid attribute type \"{type}\"."), _ => throw new ArgumentException($"Invalid attribute type \"{type}\"."),
}; };
}
public static AggregateType ToAggregateType(this AttributeType type, bool supportsScaledFormats) public AggregateType AsAggregate(bool supportsScaledFormats) => (type & ~AttributeType.AnyPacked) switch
{
return (type & ~AttributeType.AnyPacked) switch
{ {
AttributeType.Float => AggregateType.FP32, AttributeType.Float => AggregateType.FP32,
AttributeType.Sint => AggregateType.S32, AttributeType.Sint => AggregateType.S32,

View file

@ -83,7 +83,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
if (context.Definitions.Stage == ShaderStage.Geometry) if (context.Definitions.Stage == ShaderStage.Geometry)
{ {
string inPrimitive = context.Definitions.InputTopology.ToGlslString(); string inPrimitive = context.Definitions.InputTopology.GlslString;
context.AppendLine($"layout (invocations = {context.Definitions.ThreadsPerInputPrimitive}, {inPrimitive}) in;"); context.AppendLine($"layout (invocations = {context.Definitions.ThreadsPerInputPrimitive}, {inPrimitive}) in;");
@ -98,7 +98,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
} }
else else
{ {
string outPrimitive = context.Definitions.OutputTopology.ToGlslString(); string outPrimitive = context.Definitions.OutputTopology.GlslString;
int maxOutputVertices = context.Definitions.MaxOutputVertices; int maxOutputVertices = context.Definitions.MaxOutputVertices;
context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;"); context.AppendLine($"layout ({outPrimitive}, max_vertices = {maxOutputVertices}) out;");
@ -123,8 +123,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
tessCw = !tessCw; tessCw = !tessCw;
} }
string patchType = context.Definitions.TessPatchType.ToGlsl(); string patchType = context.Definitions.TessPatchType.Glsl;
string spacing = context.Definitions.TessSpacing.ToGlsl(); string spacing = context.Definitions.TessSpacing.Glsl;
string windingOrder = tessCw ? "cw" : "ccw"; string windingOrder = tessCw ? "cw" : "ccw";
context.AppendLine($"layout ({patchType}, {spacing}, {windingOrder}) in;"); context.AppendLine($"layout ({patchType}, {spacing}, {windingOrder}) in;");
@ -351,7 +351,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
arrayDecl = "[]"; arrayDecl = "[]";
} }
string samplerTypeName = definition.Separate ? definition.Type.ToGlslTextureType() : definition.Type.ToGlslSamplerType(); string samplerTypeName = definition.Separate ? definition.Type.GlslTextureTypeName : definition.Type.GlslSamplerTypeName;
string layout = string.Empty; string layout = string.Empty;
@ -379,7 +379,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
arrayDecl = "[]"; arrayDecl = "[]";
} }
string imageTypeName = definition.Type.ToGlslImageType(definition.Format.GetComponentType()); string imageTypeName = definition.Type.GetGlslImageTypeName(definition.Format.GetComponentType());
if (definition.Flags.HasFlag(TextureUsageFlags.ImageCoherent)) if (definition.Flags.HasFlag(TextureUsageFlags.ImageCoherent))
{ {

View file

@ -54,7 +54,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
texCallBuilder.Append('('); texCallBuilder.Append('(');
texCallBuilder.Append(imageName); texCallBuilder.Append(imageName);
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount + (isArray ? 1 : 0); int pCount = coordsCount + (isArray ? 1 : 0);
@ -162,7 +162,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
{ {
AstTextureOperation texOp = (AstTextureOperation)operation; AstTextureOperation texOp = (AstTextureOperation)operation;
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int coordsIndex = 0; int coordsIndex = 0;
string samplerName = GetSamplerName(context, texOp, ref coordsIndex); string samplerName = GetSamplerName(context, texOp, ref coordsIndex);
@ -264,7 +264,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
texCall += "(" + samplerName; texCall += "(" + samplerName;
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount; int pCount = coordsCount;
@ -658,7 +658,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
samplerName = $"{samplerName}[{GetSourceExpr(context, texOp.GetSource(srcIndex++), AggregateType.S32)}]"; samplerName = $"{samplerName}[{GetSourceExpr(context, texOp.GetSource(srcIndex++), AggregateType.S32)}]";
} }
name = $"{texOp.Type.ToGlslSamplerType()}({name}, {samplerName})"; name = $"{texOp.Type.GlslSamplerTypeName}({name}, {samplerName})";
} }
return name; return name;

View file

@ -385,12 +385,12 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static void DeclarePerVertexBlock(CodeGenContext context) private static void DeclarePerVertexBlock(CodeGenContext context)
{ {
if (context.Definitions.Stage.IsVtg()) if (context.Definitions.Stage.IsVtg)
{ {
if (context.Definitions.Stage != ShaderStage.Vertex) if (context.Definitions.Stage != ShaderStage.Vertex)
{ {
SpvInstruction perVertexInputStructType = CreatePerVertexStructType(context); SpvInstruction perVertexInputStructType = CreatePerVertexStructType(context);
int arraySize = context.Definitions.Stage == ShaderStage.Geometry ? context.Definitions.InputTopology.ToInputVertices() : 32; int arraySize = context.Definitions.Stage == ShaderStage.Geometry ? context.Definitions.InputTopology.InputVertexCount : 32;
SpvInstruction perVertexInputArrayType = context.TypeArray(perVertexInputStructType, context.Constant(context.TypeU32(), arraySize)); SpvInstruction perVertexInputArrayType = context.TypeArray(perVertexInputStructType, context.Constant(context.TypeU32(), arraySize));
SpvInstruction perVertexInputPointerType = context.TypePointer(StorageClass.Input, perVertexInputArrayType); SpvInstruction perVertexInputPointerType = context.TypePointer(StorageClass.Input, perVertexInputArrayType);
SpvInstruction perVertexInputVariable = context.Variable(perVertexInputPointerType, StorageClass.Input); SpvInstruction perVertexInputVariable = context.Variable(perVertexInputPointerType, StorageClass.Input);
@ -537,7 +537,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (!isPerPatch && IoMap.IsPerVertex(ioVariable, context.Definitions.Stage, isOutput)) if (!isPerPatch && IoMap.IsPerVertex(ioVariable, context.Definitions.Stage, isOutput))
{ {
int arraySize = context.Definitions.Stage == ShaderStage.Geometry ? context.Definitions.InputTopology.ToInputVertices() : 32; int arraySize = context.Definitions.Stage == ShaderStage.Geometry ? context.Definitions.InputTopology.InputVertexCount : 32;
spvType = context.TypeArray(spvType, context.Constant(context.TypeU32(), arraySize)); spvType = context.TypeArray(spvType, context.Constant(context.TypeU32(), arraySize));
if (context.Definitions.GpPassthrough && context.HostCapabilities.SupportsGeometryShaderPassthrough) if (context.Definitions.GpPassthrough && context.HostCapabilities.SupportsGeometryShaderPassthrough)

View file

@ -615,7 +615,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
image = context.AccessChain(imagePointerType, image, textureIndex); image = context.AccessChain(imagePointerType, image, textureIndex);
} }
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount + (isArray ? 1 : 0); int pCount = coordsCount + (isArray ? 1 : 0);
@ -693,7 +693,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
image = context.Load(declaration.ImageType, image); image = context.Load(declaration.ImageType, image);
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount + (isArray ? 1 : 0); int pCount = coordsCount + (isArray ? 1 : 0);
@ -750,7 +750,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
image = context.Load(declaration.ImageType, image); image = context.Load(declaration.ImageType, image);
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount + (isArray ? 1 : 0); int pCount = coordsCount + (isArray ? 1 : 0);
@ -840,7 +840,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()]; SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()];
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex); SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
int pCount = texOp.Type.GetDimensions(); int pCount = texOp.Type.Dimensions;
SpvInstruction pCoords; SpvInstruction pCoords;
@ -1164,7 +1164,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()]; SamplerDeclaration declaration = context.Samplers[texOp.GetTextureSetAndBinding()];
SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex); SpvInstruction image = GenerateSampledImageLoad(context, texOp, declaration, ref srcIndex);
int coordsCount = texOp.Type.GetDimensions(); int coordsCount = texOp.Type.Dimensions;
int pCount = coordsCount; int pCount = coordsCount;
@ -1463,7 +1463,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
SamplerType type = context.SamplersTypes[texOp.GetTextureSetAndBinding()]; SamplerType type = context.SamplersTypes[texOp.GetTextureSetAndBinding()];
bool hasLod = !type.HasFlag(SamplerType.Multisample) && type != SamplerType.TextureBuffer; bool hasLod = !type.HasFlag(SamplerType.Multisample) && type != SamplerType.TextureBuffer;
int dimensions = (type & SamplerType.Mask) == SamplerType.TextureCube ? 2 : type.GetDimensions(); int dimensions = (type & SamplerType.Mask) == SamplerType.TextureCube ? 2 : type.Dimensions;
if (type.HasFlag(SamplerType.Array)) if (type.HasFlag(SamplerType.Array))
{ {
@ -1486,7 +1486,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
if (dimensions != 1) if (dimensions != 1)
{ {
result = context.CompositeExtract(context.TypeS32(), result, (SpvLiteralInteger)texOp.Index); result = context.CompositeExtract(context.TypeS32(), result, texOp.Index);
} }
return new OperationResult(AggregateType.S32, result); return new OperationResult(AggregateType.S32, result);

View file

@ -457,7 +457,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
case AttributeConsts.ClipDistance5: case AttributeConsts.ClipDistance5:
case AttributeConsts.ClipDistance6: case AttributeConsts.ClipDistance6:
case AttributeConsts.ClipDistance7: case AttributeConsts.ClipDistance7:
if (definitions.Stage.IsVtg()) if (definitions.Stage.IsVtg)
{ {
context.SetClipDistanceWritten((attr - AttributeConsts.ClipDistance0) / 4); context.SetClipDistanceWritten((attr - AttributeConsts.ClipDistance0) / 4);
} }

Some files were not shown because too many files have changed in this diff Show more