SaveOrRestoreRegister.cs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. using Ryujinx.HLE.Exceptions;
  2. using Ryujinx.HLE.HOS.Tamper.Operations;
  3. namespace Ryujinx.HLE.HOS.Tamper.CodeEmitters
  4. {
  5. /// <summary>
  6. /// Code type 0xC1 performs saving or restoring of registers.
  7. /// NOTE: Registers are saved and restored to a different set of registers than the ones used
  8. /// for the other opcodes (Save Registers).
  9. /// </summary>
  10. class SaveOrRestoreRegister
  11. {
  12. private const int DestinationRegisterIndex = 3;
  13. private const int SourceRegisterIndex = 5;
  14. private const int OperationTypeIndex = 6;
  15. private const int RestoreRegister = 0;
  16. private const int SaveRegister = 1;
  17. private const int ClearSavedValue = 2;
  18. private const int ClearRegister = 3;
  19. public static void Emit(byte[] instruction, CompilationContext context)
  20. {
  21. // C10D0Sx0
  22. // D: Destination index.
  23. // S: Source index.
  24. // x: Operand Type, see below.
  25. byte destinationRegIndex = instruction[DestinationRegisterIndex];
  26. byte sourceRegIndex = instruction[SourceRegisterIndex];
  27. byte operationType = instruction[OperationTypeIndex];
  28. Impl(operationType, destinationRegIndex, sourceRegIndex, context);
  29. }
  30. public static void Impl(byte operationType, byte destinationRegIndex, byte sourceRegIndex, CompilationContext context)
  31. {
  32. IOperand destinationOperand;
  33. IOperand sourceOperand;
  34. switch (operationType)
  35. {
  36. case RestoreRegister:
  37. destinationOperand = context.GetRegister(destinationRegIndex);
  38. sourceOperand = context.GetSavedRegister(sourceRegIndex);
  39. break;
  40. case SaveRegister:
  41. destinationOperand = context.GetSavedRegister(destinationRegIndex);
  42. sourceOperand = context.GetRegister(sourceRegIndex);
  43. break;
  44. case ClearSavedValue:
  45. destinationOperand = new Value<ulong>(0);
  46. sourceOperand = context.GetSavedRegister(sourceRegIndex);
  47. break;
  48. case ClearRegister:
  49. destinationOperand = new Value<ulong>(0);
  50. sourceOperand = context.GetRegister(sourceRegIndex);
  51. break;
  52. default:
  53. throw new TamperCompilationException($"Invalid register operation type {operationType} in Atmosphere cheat");
  54. }
  55. context.CurrentOperations.Add(new OpMov<ulong>(destinationOperand, sourceOperand));
  56. }
  57. }
  58. }