Tamper generic explosion and code style

This commit is contained in:
Aaron Robinson 2025-11-19 22:28:50 -06:00
parent b9da6a15d7
commit 529d6f44bb
30 changed files with 180 additions and 98 deletions

View file

@ -68,8 +68,8 @@ namespace Ryujinx.HLE.Generators
public void Initialize(IncrementalGeneratorInitializationContext context) public void Initialize(IncrementalGeneratorInitializationContext context)
{ {
var predicate = (SyntaxNode node, CancellationToken _) => node is MethodDeclarationSyntax; Func<SyntaxNode, CancellationToken, bool> predicate = (node, _) => node is MethodDeclarationSyntax;
var transform = (GeneratorAttributeSyntaxContext ctx, CancellationToken _) => Func<GeneratorAttributeSyntaxContext, CancellationToken, CommandData> transform = (ctx, _) =>
{ {
var target = (IMethodSymbol)ctx.TargetSymbol; var target = (IMethodSymbol)ctx.TargetSymbol;
return new CommandData return new CommandData
@ -80,27 +80,28 @@ namespace Ryujinx.HLE.Generators
CommandIds = ctx.Attributes.Select(attr => (int)attr.ConstructorArguments[0].Value!).ToImmutableArray(), CommandIds = ctx.Attributes.Select(attr => (int)attr.ConstructorArguments[0].Value!).ToImmutableArray(),
}; };
}; };
var cmifCommands = IncrementalValuesProvider<CommandData> cmifCommands =
context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.CommandCmifAttribute", context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.CommandCmifAttribute",
predicate, predicate,
transform transform
); );
var tipcCommands = IncrementalValuesProvider<CommandData> tipcCommands =
context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.CommandTipcAttribute", context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.CommandTipcAttribute",
predicate, predicate,
transform transform
); );
var allCommands = cmifCommands.Collect().Combine(tipcCommands.Collect()); IncrementalValueProvider<(ImmutableArray<CommandData> Left, ImmutableArray<CommandData> Right)> allCommands =
cmifCommands.Collect().Combine(tipcCommands.Collect());
var types = allCommands.SelectMany((commands, _) => IncrementalValuesProvider<ServiceData> types = allCommands.SelectMany((commands, _) =>
{ {
var cmif = commands.Left.ToLookup(c => (c.Namespace, c.TypeName)); ILookup<(string Namespace, string TypeName), CommandData> cmif = commands.Left.ToLookup(c => (c.Namespace, c.TypeName));
var tipc = commands.Right.ToLookup(c => (c.Namespace, c.TypeName)); ILookup<(string Namespace, string TypeName), CommandData> tipc = commands.Right.ToLookup(c => (c.Namespace, c.TypeName));
var builder = ImmutableArray.CreateBuilder<ServiceData>(); ImmutableArray<ServiceData>.Builder builder = ImmutableArray.CreateBuilder<ServiceData>();
foreach (var type in cmif.Select(c => c.Key).Union(tipc.Select(t => t.Key))) foreach ((string Namespace, string TypeName) type in cmif.Select(c => c.Key).Union(tipc.Select(t => t.Key)))
{ {
builder.Add(new ServiceData builder.Add(new ServiceData
{ {
@ -143,7 +144,7 @@ namespace Ryujinx.HLE.Generators
{ {
generator.EnterScope($"protected override RC Invoke{commandType}Method(int id, ServiceCtx context)"); generator.EnterScope($"protected override RC Invoke{commandType}Method(int id, ServiceCtx context)");
generator.EnterScope("switch (id)"); generator.EnterScope("switch (id)");
foreach (var command in commands) foreach (CommandData command in commands)
{ {
generator.AppendLine($"case {string.Join(" or ", command.CommandIds)}:"); generator.AppendLine($"case {string.Join(" or ", command.CommandIds)}:");
generator.IncreaseIndentation(); generator.IncreaseIndentation();
@ -157,7 +158,7 @@ namespace Ryujinx.HLE.Generators
generator.EnterScope($"public override int {commandType}CommandIdByMethodName(string name)"); generator.EnterScope($"public override int {commandType}CommandIdByMethodName(string name)");
generator.EnterScope("return name switch"); generator.EnterScope("return name switch");
foreach (var command in commands) foreach (CommandData command in commands)
{ {
// just return the first command with this name // just return the first command with this name
generator.AppendLine($"\"{command.MethodName}\" => {command.CommandIds[0]},"); generator.AppendLine($"\"{command.MethodName}\" => {command.CommandIds[0]},");

View file

@ -28,12 +28,12 @@ namespace Ryujinx.HLE.Generators
public void Initialize(IncrementalGeneratorInitializationContext context) public void Initialize(IncrementalGeneratorInitializationContext context)
{ {
var pipeline = context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.ServiceAttribute", IncrementalValuesProvider<ServiceData> pipeline = context.SyntaxProvider.ForAttributeWithMetadataName("Ryujinx.HLE.HOS.Services.ServiceAttribute",
predicate: (node, _) => node is ClassDeclarationSyntax decl && !decl.Modifiers.Any(SyntaxKind.AbstractKeyword) && !decl.Modifiers.Any(SyntaxKind.PrivateKeyword), predicate: (node, _) => node is ClassDeclarationSyntax decl && !decl.Modifiers.Any(SyntaxKind.AbstractKeyword) && !decl.Modifiers.Any(SyntaxKind.PrivateKeyword),
transform: (ctx, _) => transform: (ctx, _) =>
{ {
var target = (INamedTypeSymbol)ctx.TargetSymbol; var target = (INamedTypeSymbol)ctx.TargetSymbol;
var instances = ctx.Attributes.Select(attr => IEnumerable<(string, string param)> instances = ctx.Attributes.Select(attr =>
{ {
string param = attr.ConstructorArguments is [_, { IsNull: false } arg] ? arg.ToCSharpString() : null; string param = attr.ConstructorArguments is [_, { IsNull: false } arg] ? arg.ToCSharpString() : null;
return ((string)attr.ConstructorArguments[0].Value, param); return ((string)attr.ConstructorArguments[0].Value, param);
@ -60,9 +60,9 @@ namespace Ryujinx.HLE.Generators
generator.EnterScope("return name switch"); generator.EnterScope("return name switch");
foreach (var serviceImpl in data) foreach (ServiceData serviceImpl in data)
{ {
foreach (var instance in serviceImpl.Instances) foreach ((string ServiceName, string ParameterValue) instance in serviceImpl.Instances)
{ {
if (instance.ParameterValue == null) if (instance.ParameterValue == null)
{ {

View file

@ -48,7 +48,7 @@ namespace Ryujinx.HLE.Exceptions
{ {
StringBuilder sb = new(); StringBuilder sb = new();
var commandId = Request.Type > IpcMessageType.TipcCloseSession int commandId = Request.Type > IpcMessageType.TipcCloseSession
? Service.TipcCommandIdByMethodName(MethodName) ? Service.TipcCommandIdByMethodName(MethodName)
: Service.CmifCommandIdByMethodName(MethodName); : Service.CmifCommandIdByMethodName(MethodName);

View file

@ -69,7 +69,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
throw new TamperCompilationException($"Invalid right-hand side switch {rightHandSideIsImmediate} in Atmosphere cheat"); throw new TamperCompilationException($"Invalid right-hand side switch {rightHandSideIsImmediate} in Atmosphere cheat");
} }
void EmitCore<TOp>(IOperand rhs = null) where TOp : IOperation void EmitCore<TOp>(IOperand rhs = null) where TOp : IOperationFactory
{ {
InstructionHelper.Emit<TOp>(operationWidth, context, destinationRegister, leftHandSideRegister, rhs); InstructionHelper.Emit<TOp>(operationWidth, context, destinationRegister, leftHandSideRegister, rhs);
} }
@ -77,34 +77,34 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
switch (operation) switch (operation)
{ {
case Add: case Add:
EmitCore<OpAdd<byte>>(rightHandSideOperand); EmitCore<OpAddFactory>(rightHandSideOperand);
break; break;
case Sub: case Sub:
EmitCore<OpSub<byte>>(rightHandSideOperand); EmitCore<OpSubFactory>(rightHandSideOperand);
break; break;
case Mul: case Mul:
EmitCore<OpMul<byte>>(rightHandSideOperand); EmitCore<OpMulFactory>(rightHandSideOperand);
break; break;
case Lsh: case Lsh:
EmitCore<OpLsh<byte>>(rightHandSideOperand); EmitCore<OpLshFactory>(rightHandSideOperand);
break; break;
case Rsh: case Rsh:
EmitCore<OpRsh<byte>>(rightHandSideOperand); EmitCore<OpRshFactory>(rightHandSideOperand);
break; break;
case And: case And:
EmitCore<OpAnd<byte>>(rightHandSideOperand); EmitCore<OpAndFactory>(rightHandSideOperand);
break; break;
case Or: case Or:
EmitCore<OpOr<byte>>(rightHandSideOperand); EmitCore<OpOrFactory>(rightHandSideOperand);
break; break;
case Not: case Not:
EmitCore<OpNot<byte>>(); EmitCore<OpNotFactory>();
break; break;
case Xor: case Xor:
EmitCore<OpXor<byte>>(rightHandSideOperand); EmitCore<OpXorFactory>(rightHandSideOperand);
break; break;
case Mov: case Mov:
EmitCore<OpMov<byte>>(); EmitCore<OpMovFactory>();
break; break;
default: default:
throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat"); throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");

View file

@ -37,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
ulong immediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, ValueImmediateSize); ulong immediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, ValueImmediateSize);
Value<ulong> rightHandSideValue = new(immediate); Value<ulong> rightHandSideValue = new(immediate);
void EmitCore<TOp>() where TOp : IOperation void EmitCore<TOp>() where TOp : IOperationFactory
{ {
InstructionHelper.Emit<TOp>(operationWidth, context, register, register, rightHandSideValue); InstructionHelper.Emit<TOp>(operationWidth, context, register, register, rightHandSideValue);
} }
@ -45,19 +45,19 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
switch (operation) switch (operation)
{ {
case Add: case Add:
EmitCore<OpAdd<byte>>(); EmitCore<OpAddFactory>();
break; break;
case Sub: case Sub:
EmitCore<OpAdd<byte>>(); EmitCore<OpAddFactory>();
break; break;
case Mul: case Mul:
EmitCore<OpMul<byte>>(); EmitCore<OpMulFactory>();
break; break;
case Lsh: case Lsh:
EmitCore<OpLsh<byte>>(); EmitCore<OpLshFactory>();
break; break;
case Rsh: case Rsh:
EmitCore<OpRsh<byte>>(); EmitCore<OpRshFactory>();
break; break;
default: default:
throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat"); throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");

View file

@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
throw new TamperCompilationException($"Invalid source mode {useDestinationAsSourceIndex} in Atmosphere cheat"); throw new TamperCompilationException($"Invalid source mode {useDestinationAsSourceIndex} in Atmosphere cheat");
} }
InstructionHelper.Emit<OpMov<byte>>(operationWidth, context, destinationRegister, sourceMemory, null); InstructionHelper.Emit<OpMovFactory>(operationWidth, context, destinationRegister, sourceMemory, null);
} }
} }
} }

View file

@ -37,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
ulong valueImmediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, valueImmediateSize); ulong valueImmediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, valueImmediateSize);
Value<ulong> storeValue = new(valueImmediate); Value<ulong> storeValue = new(valueImmediate);
InstructionHelper.Emit<OpMov<byte>>(operationWidth, context, dstMem, storeValue, null); InstructionHelper.Emit<OpMovFactory>(operationWidth, context, dstMem, storeValue, null);
} }
} }
} }

View file

@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
throw new TamperCompilationException($"Invalid offset mode {useOffsetRegister} in Atmosphere cheat"); throw new TamperCompilationException($"Invalid offset mode {useOffsetRegister} in Atmosphere cheat");
} }
InstructionHelper.Emit<OpMov<byte>>(operationWidth, context, destinationMemory, storeValue, null); InstructionHelper.Emit<OpMovFactory>(operationWidth, context, destinationMemory, storeValue, null);
switch (incrementAddressRegister) switch (incrementAddressRegister)
{ {

View file

@ -79,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
throw new TamperCompilationException($"Invalid offset type {offsetType} in Atmosphere cheat"); throw new TamperCompilationException($"Invalid offset type {offsetType} in Atmosphere cheat");
} }
InstructionHelper.Emit<OpMov<byte>>(operationWidth, context, destinationMemory, sourceRegister, null); InstructionHelper.Emit<OpMovFactory>(operationWidth, context, destinationMemory, sourceRegister, null);
switch (incrementAddressRegister) switch (incrementAddressRegister)
{ {

View file

@ -3,6 +3,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Conditions namespace Ryujinx.HLE.HOS.Tamper.Conditions
{ {
sealed class CondEQFactory : IConditionFactory
{
private CondEQFactory() { }
public static ICondition CreateFor<T>(IOperand lhs, IOperand rhs) where T : unmanaged, INumber<T>
=> new CondEQ<T>(lhs, rhs);
}
class CondEQ<T> : ICondition where T : unmanaged, INumber<T> class CondEQ<T> : ICondition where T : unmanaged, INumber<T>
{ {
private readonly IOperand _lhs; private readonly IOperand _lhs;
@ -18,8 +25,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions
{ {
return _lhs.Get<T>() == _rhs.Get<T>(); return _lhs.Get<T>() == _rhs.Get<T>();
} }
public static ICondition CreateFor<T1>(IOperand lhs, IOperand rhs) where T1 : INumber<T1>
=> new CondEQ<T>(lhs, rhs);
} }
} }

View file

@ -3,6 +3,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Conditions namespace Ryujinx.HLE.HOS.Tamper.Conditions
{ {
sealed class CondGEFactory : IConditionFactory
{
private CondGEFactory() { }
public static ICondition CreateFor<T>(IOperand lhs, IOperand rhs) where T : unmanaged, INumber<T>
=> new CondGE<T>(lhs, rhs);
}
class CondGE<T> : ICondition where T : unmanaged, INumber<T> class CondGE<T> : ICondition where T : unmanaged, INumber<T>
{ {
private readonly IOperand _lhs; private readonly IOperand _lhs;
@ -18,8 +25,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions
{ {
return _lhs.Get<T>() >= _rhs.Get<T>(); return _lhs.Get<T>() >= _rhs.Get<T>();
} }
public static ICondition CreateFor<T1>(IOperand lhs, IOperand rhs) where T1 : INumber<T1>
=> new CondGE<T>(lhs, rhs);
} }
} }

View file

@ -3,6 +3,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Conditions namespace Ryujinx.HLE.HOS.Tamper.Conditions
{ {
sealed class CondGTFactory : IConditionFactory
{
private CondGTFactory() { }
public static ICondition CreateFor<T>(IOperand lhs, IOperand rhs) where T : unmanaged, INumber<T>
=> new CondGT<T>(lhs, rhs);
}
class CondGT<T> : ICondition where T : unmanaged, INumber<T> class CondGT<T> : ICondition where T : unmanaged, INumber<T>
{ {
private readonly IOperand _lhs; private readonly IOperand _lhs;
@ -18,8 +25,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions
{ {
return _lhs.Get<T>() > _rhs.Get<T>(); return _lhs.Get<T>() > _rhs.Get<T>();
} }
public static ICondition CreateFor<T1>(IOperand lhs, IOperand rhs) where T1 : INumber<T1>
=> new CondGT<T>(lhs, rhs);
} }
} }

View file

@ -3,6 +3,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Conditions namespace Ryujinx.HLE.HOS.Tamper.Conditions
{ {
sealed class CondLEFactory : IConditionFactory
{
private CondLEFactory() { }
public static ICondition CreateFor<T>(IOperand lhs, IOperand rhs) where T : unmanaged, INumber<T>
=> new CondLE<T>(lhs, rhs);
}
class CondLE<T> : ICondition where T : unmanaged, INumber<T> class CondLE<T> : ICondition where T : unmanaged, INumber<T>
{ {
private readonly IOperand _lhs; private readonly IOperand _lhs;
@ -18,8 +25,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Conditions
{ {
return _lhs.Get<T>() <= _rhs.Get<T>(); return _lhs.Get<T>() <= _rhs.Get<T>();
} }
public static ICondition CreateFor<T1>(IOperand lhs, IOperand rhs) where T1 : INumber<T1>
=> new CondLE<T>(lhs, rhs);
} }
} }

View file

@ -3,6 +3,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Conditions namespace Ryujinx.HLE.HOS.Tamper.Conditions
{ {
sealed class CondLTFactory : IConditionFactory
{
private CondLTFactory() { }
public static ICondition CreateFor<T>(IOperand lhs, IOperand rhs) where T : unmanaged, INumber<T>
=> new CondLT<T>(lhs, rhs);
}
class CondLT<T> : ICondition where T : unmanaged, INumber<T> class CondLT<T> : ICondition where T : unmanaged, INumber<T>
{ {
private readonly IOperand _lhs; private readonly IOperand _lhs;

View file

@ -3,6 +3,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Conditions namespace Ryujinx.HLE.HOS.Tamper.Conditions
{ {
sealed class CondNEFactory : IConditionFactory
{
private CondNEFactory() { }
public static ICondition CreateFor<T>(IOperand lhs, IOperand rhs) where T : unmanaged, INumber<T>
=> new CondNE<T>(lhs, rhs);
}
class CondNE<T> : ICondition where T : unmanaged, INumber<T> class CondNE<T> : ICondition where T : unmanaged, INumber<T>
{ {
private readonly IOperand _lhs; private readonly IOperand _lhs;

View file

@ -1,13 +1,7 @@
using Ryujinx.HLE.HOS.Tamper.Operations;
using System;
using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Conditions namespace Ryujinx.HLE.HOS.Tamper.Conditions
{ {
interface ICondition interface ICondition
{ {
bool Evaluate(); bool Evaluate();
static virtual ICondition CreateFor<T>(IOperand lhs, IOperand rhs) where T : INumber<T> => throw new NotImplementedException();
} }
} }

View file

@ -0,0 +1,10 @@
using Ryujinx.HLE.HOS.Tamper.Operations;
using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Conditions
{
interface IConditionFactory
{
static abstract ICondition CreateFor<T>(IOperand lhs, IOperand rhs) where T : unmanaged, INumber<T>;
}
}

View file

@ -15,14 +15,14 @@ namespace Ryujinx.HLE.HOS.Tamper
context.CurrentOperations.Add(operation); context.CurrentOperations.Add(operation);
} }
public static void Emit<TOp>(byte width, CompilationContext context, IOperand destination, IOperand lhs, IOperand rhs) where TOp : IOperation public static void Emit<TOp>(byte width, CompilationContext context, IOperand destination, IOperand lhs, IOperand rhs) where TOp : IOperationFactory
{ {
Emit(Create<TOp>(width, destination, lhs, rhs), context); Emit(Create<TOp>(width, destination, lhs, rhs), context);
} }
public static ICondition CreateCondition(Comparison comparison, byte width, IOperand lhs, IOperand rhs) public static ICondition CreateCondition(Comparison comparison, byte width, IOperand lhs, IOperand rhs)
{ {
ICondition CreateCore<TOp>() where TOp : ICondition ICondition CreateCore<TOp>() where TOp : IConditionFactory
{ {
return width switch return width switch
{ {
@ -36,17 +36,17 @@ namespace Ryujinx.HLE.HOS.Tamper
return comparison switch return comparison switch
{ {
Comparison.Greater => CreateCore<CondGT<byte>>(), Comparison.Greater => CreateCore<CondGTFactory>(),
Comparison.GreaterOrEqual => CreateCore<CondGE<byte>>(), Comparison.GreaterOrEqual => CreateCore<CondGEFactory>(),
Comparison.Less => CreateCore<CondLT<byte>>(), Comparison.Less => CreateCore<CondLTFactory>(),
Comparison.LessOrEqual => CreateCore<CondLE<byte>>(), Comparison.LessOrEqual => CreateCore<CondLEFactory>(),
Comparison.Equal => CreateCore<CondEQ<byte>>(), Comparison.Equal => CreateCore<CondEQFactory>(),
Comparison.NotEqual => CreateCore<CondNE<byte>>(), Comparison.NotEqual => CreateCore<CondNEFactory>(),
_ => throw new TamperCompilationException($"Invalid comparison {comparison} in Atmosphere cheat"), _ => throw new TamperCompilationException($"Invalid comparison {comparison} in Atmosphere cheat"),
}; };
} }
public static IOperation Create<TOp>(byte width, IOperand destination, IOperand lhs, IOperand rhs) where TOp : IOperation public static IOperation Create<TOp>(byte width, IOperand destination, IOperand lhs, IOperand rhs) where TOp : IOperationFactory
{ {
return width switch return width switch
{ {

View file

@ -6,8 +6,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
interface IOperation interface IOperation
{ {
void Execute(); void Execute();
static virtual IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
=> throw new NotImplementedException();
} }
} }

View file

@ -0,0 +1,10 @@
using System;
using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Operations
{
interface IOperationFactory
{
static abstract IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>;
}
}

View file

@ -2,6 +2,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Operations namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
sealed class OpAddFactory : IOperationFactory
{
private OpAddFactory() { }
public static IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
=> new OpAdd<T>(destination, lhs, rhs);
}
class OpAdd<T> : IOperation where T : unmanaged, INumber<T> class OpAdd<T> : IOperation where T : unmanaged, INumber<T>
{ {
readonly IOperand _destination; readonly IOperand _destination;
@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
_destination.Set(_lhs.Get<T>() + _rhs.Get<T>()); _destination.Set(_lhs.Get<T>() + _rhs.Get<T>());
} }
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
=> new OpAdd<T1>(destination, lhs, rhs);
} }
} }

View file

@ -2,6 +2,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Operations namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
sealed class OpAndFactory : IOperationFactory
{
private OpAndFactory() { }
public static IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
=> new OpAnd<T>(destination, lhs, rhs);
}
class OpAnd<T> : IOperation where T : unmanaged, IBinaryNumber<T> class OpAnd<T> : IOperation where T : unmanaged, IBinaryNumber<T>
{ {
readonly IOperand _destination; readonly IOperand _destination;
@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
_destination.Set(_lhs.Get<T>() & _rhs.Get<T>()); _destination.Set(_lhs.Get<T>() & _rhs.Get<T>());
} }
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
=> new OpAnd<T1>(destination, lhs, rhs);
} }
} }

View file

@ -2,6 +2,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Operations namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
sealed class OpLshFactory : IOperationFactory
{
private OpLshFactory() { }
public static IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
=> new OpLsh<T>(destination, lhs, rhs);
}
class OpLsh<T> : IOperation where T : unmanaged, IBinaryInteger<T> class OpLsh<T> : IOperation where T : unmanaged, IBinaryInteger<T>
{ {
readonly IOperand _destination; readonly IOperand _destination;
@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
_destination.Set(_lhs.Get<T>() << int.CreateTruncating(_rhs.Get<T>())); _destination.Set(_lhs.Get<T>() << int.CreateTruncating(_rhs.Get<T>()));
} }
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
=> new OpLsh<T1>(destination, lhs, rhs);
} }
} }

View file

@ -2,6 +2,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Operations namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
sealed class OpMovFactory : IOperationFactory
{
private OpMovFactory() { }
public static IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
=> new OpMov<T>(destination, lhs);
}
class OpMov<T> : IOperation where T : unmanaged, INumber<T> class OpMov<T> : IOperation where T : unmanaged, INumber<T>
{ {
readonly IOperand _destination; readonly IOperand _destination;
@ -17,8 +24,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
_destination.Set(_source.Get<T>()); _destination.Set(_source.Get<T>());
} }
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
=> new OpMov<T1>(destination, lhs);
} }
} }

View file

@ -2,6 +2,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Operations namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
sealed class OpMulFactory : IOperationFactory
{
private OpMulFactory() { }
public static IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
=> new OpMul<T>(destination, lhs, rhs);
}
class OpMul<T> : IOperation where T : unmanaged, INumber<T> class OpMul<T> : IOperation where T : unmanaged, INumber<T>
{ {
readonly IOperand _destination; readonly IOperand _destination;
@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
_destination.Set(_lhs.Get<T>() * _rhs.Get<T>()); _destination.Set(_lhs.Get<T>() * _rhs.Get<T>());
} }
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
=> new OpMul<T1>(destination, lhs, rhs);
} }
} }

View file

@ -2,6 +2,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Operations namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
sealed class OpNotFactory : IOperationFactory
{
private OpNotFactory() { }
public static IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
=> new OpNot<T>(destination, lhs);
}
class OpNot<T> : IOperation where T : unmanaged, IBinaryNumber<T> class OpNot<T> : IOperation where T : unmanaged, IBinaryNumber<T>
{ {
readonly IOperand _destination; readonly IOperand _destination;
@ -17,8 +24,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
_destination.Set(~_source.Get<T>()); _destination.Set(~_source.Get<T>());
} }
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
=> new OpNot<T1>(destination, lhs);
} }
} }

View file

@ -2,6 +2,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Operations namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
sealed class OpOrFactory : IOperationFactory
{
private OpOrFactory() { }
public static IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
=> new OpOr<T>(destination, lhs, rhs);
}
class OpOr<T> : IOperation where T : unmanaged, IBinaryNumber<T> class OpOr<T> : IOperation where T : unmanaged, IBinaryNumber<T>
{ {
readonly IOperand _destination; readonly IOperand _destination;
@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
_destination.Set(_lhs.Get<T>() | _rhs.Get<T>()); _destination.Set(_lhs.Get<T>() | _rhs.Get<T>());
} }
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
=> new OpOr<T1>(destination, lhs, rhs);
} }
} }

View file

@ -2,6 +2,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Operations namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
sealed class OpRshFactory : IOperationFactory
{
private OpRshFactory() { }
public static IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
=> new OpRsh<T>(destination, lhs, rhs);
}
class OpRsh<T> : IOperation where T : unmanaged, IBinaryInteger<T> class OpRsh<T> : IOperation where T : unmanaged, IBinaryInteger<T>
{ {
readonly IOperand _destination; readonly IOperand _destination;
@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
_destination.Set(_lhs.Get<T>() >> int.CreateTruncating(_rhs.Get<T>())); _destination.Set(_lhs.Get<T>() >> int.CreateTruncating(_rhs.Get<T>()));
} }
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
=> new OpRsh<T1>(destination, lhs, rhs);
} }
} }

View file

@ -2,6 +2,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Operations namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
sealed class OpSubFactory : IOperationFactory
{
private OpSubFactory() { }
public static IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
=> new OpSub<T>(destination, lhs, rhs);
}
class OpSub<T> : IOperation where T : unmanaged, INumber<T> class OpSub<T> : IOperation where T : unmanaged, INumber<T>
{ {
readonly IOperand _destination; readonly IOperand _destination;
@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
_destination.Set(_lhs.Get<T>() - _rhs.Get<T>()); _destination.Set(_lhs.Get<T>() - _rhs.Get<T>());
} }
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
=> new OpSub<T1>(destination, lhs, rhs);
} }
} }

View file

@ -2,6 +2,13 @@ using System.Numerics;
namespace Ryujinx.HLE.HOS.Tamper.Operations namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
sealed class OpXorFactory : IOperationFactory
{
private OpXorFactory() { }
public static IOperation CreateFor<T>(IOperand destination, IOperand lhs, IOperand rhs) where T : unmanaged, IBinaryInteger<T>
=> new OpXor<T>(destination, lhs, rhs);
}
class OpXor<T> : IOperation where T : unmanaged, IBinaryNumber<T> class OpXor<T> : IOperation where T : unmanaged, IBinaryNumber<T>
{ {
readonly IOperand _destination; readonly IOperand _destination;
@ -19,8 +26,5 @@ namespace Ryujinx.HLE.HOS.Tamper.Operations
{ {
_destination.Set(_lhs.Get<T>() ^ _rhs.Get<T>()); _destination.Set(_lhs.Get<T>() ^ _rhs.Get<T>());
} }
public static IOperation CreateFor<T1>(IOperand destination, IOperand lhs, IOperand rhs) where T1 : unmanaged, IBinaryInteger<T1>
=> new OpXor<T1>(destination, lhs, rhs);
} }
} }