LegacyArithmetic.cs 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. using Ryujinx.HLE.Exceptions;
  2. using Ryujinx.HLE.HOS.Tamper.Operations;
  3. using System;
  4. namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
  5. {
  6. /// <summary>
  7. /// Code type 7 allows performing arithmetic on registers. However, it has been deprecated by Code
  8. /// type 9, and is only kept for backwards compatibility.
  9. /// </summary>
  10. class LegacyArithmetic
  11. {
  12. const int OperationWidthIndex = 1;
  13. const int DestinationRegisterIndex = 3;
  14. const int OperationTypeIndex = 4;
  15. const int ValueImmediateIndex = 8;
  16. const int ValueImmediateSize = 8;
  17. private const byte Add = 0; // reg += rhs
  18. private const byte Sub = 1; // reg -= rhs
  19. private const byte Mul = 2; // reg *= rhs
  20. private const byte Lsh = 3; // reg <<= rhs
  21. private const byte Rsh = 4; // reg >>= rhs
  22. public static void Emit(byte[] instruction, CompilationContext context)
  23. {
  24. // 7T0RC000 VVVVVVVV
  25. // T: Width of arithmetic operation(1, 2, 4, or 8 bytes).
  26. // R: Register to apply arithmetic to.
  27. // C: Arithmetic operation to apply, see below.
  28. // V: Value to use for arithmetic operation.
  29. byte operationWidth = instruction[OperationWidthIndex];
  30. Register register = context.GetRegister(instruction[DestinationRegisterIndex]);
  31. byte operation = instruction[OperationTypeIndex];
  32. ulong immediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, ValueImmediateSize);
  33. Value<ulong> rightHandSideValue = new Value<ulong>(immediate);
  34. void Emit(Type operationType)
  35. {
  36. InstructionHelper.Emit(operationType, operationWidth, context, register, register, rightHandSideValue);
  37. }
  38. switch (operation)
  39. {
  40. case Add: Emit(typeof(OpAdd<>)); break;
  41. case Sub: Emit(typeof(OpSub<>)); break;
  42. case Mul: Emit(typeof(OpMul<>)); break;
  43. case Lsh: Emit(typeof(OpLsh<>)); break;
  44. case Rsh: Emit(typeof(OpRsh<>)); break;
  45. default:
  46. throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");
  47. }
  48. }
  49. }
  50. }