Пример #1
0
        private const byte Rsh = 4; // reg >>= rhs

        public static void Emit(byte[] instruction, CompilationContext context)
        {
            // 7T0RC000 VVVVVVVV
            // T: Width of arithmetic operation(1, 2, 4, or 8 bytes).
            // R: Register to apply arithmetic to.
            // C: Arithmetic operation to apply, see below.
            // V: Value to use for arithmetic operation.

            byte          operationWidth     = instruction[OperationWidthIndex];
            Register      register           = context.GetRegister(instruction[DestinationRegisterIndex]);
            byte          operation          = instruction[OperationTypeIndex];
            ulong         immediate          = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, ValueImmediateSize);
            Value <ulong> rightHandSideValue = new Value <ulong>(immediate);

            void Emit(Type operationType)
            {
                InstructionHelper.Emit(operationType, operationWidth, context, register, register, rightHandSideValue);
            }

            switch (operation)
            {
            case Add: Emit(typeof(OpAdd <>)); break;

            case Sub: Emit(typeof(OpSub <>)); break;

            case Mul: Emit(typeof(OpMul <>)); break;

            case Lsh: Emit(typeof(OpLsh <>)); break;

            case Rsh: Emit(typeof(OpRsh <>)); break;

            default:
                throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");
            }
        }
Пример #2
0
        public static void Emit(byte[] instruction, CompilationContext context)
        {
            // FFFTIX##
            // FFFTI0Ma aaaaaaaa
            // FFFTI1Mr
            // FFFTI2Ra aaaaaaaa
            // FFFTI3Rr
            // FFFTI4V0
            // T: Width of memory write (1, 2, 4, or 8 bytes).
            // I: Log id.
            // X: Operand Type, see below.
            // M: Memory Type (operand types 0 and 1).
            // R: Address Register (operand types 2 and 3).
            // a: Relative Address (operand types 0 and 2).
            // r: Offset Register (operand types 1 and 3).
            // V: Value Register (operand type 4).

            byte     operationWidth         = instruction[OperationWidthIndex];
            byte     logId                  = instruction[LogIdIndex];
            byte     operandType            = instruction[OperandTypeIndex];
            byte     registerOrMemoryRegion = instruction[RegisterOrMemoryRegionIndex];
            byte     offsetRegisterIndex    = instruction[OffsetRegisterOrImmediateIndex];
            ulong    immediate;
            Register addressRegister;
            Register offsetRegister;
            IOperand sourceOperand;

            switch (operandType)
            {
            case MemoryRegionWithOffsetImmediate:
                // *(?x + #a)
                immediate     = InstructionHelper.GetImmediate(instruction, OffsetRegisterOrImmediateIndex, OffsetImmediateSize);
                sourceOperand = MemoryHelper.EmitPointer((MemoryRegion)registerOrMemoryRegion, immediate, context);
                break;

            case MemoryRegionWithOffsetRegister:
                // *(?x + $r)
                offsetRegister = context.GetRegister(offsetRegisterIndex);
                sourceOperand  = MemoryHelper.EmitPointer((MemoryRegion)registerOrMemoryRegion, offsetRegister, context);
                break;

            case AddressRegisterWithOffsetImmediate:
                // *($R + #a)
                addressRegister = context.GetRegister(registerOrMemoryRegion);
                immediate       = InstructionHelper.GetImmediate(instruction, OffsetRegisterOrImmediateIndex, OffsetImmediateSize);
                sourceOperand   = MemoryHelper.EmitPointer(addressRegister, immediate, context);
                break;

            case AddressRegisterWithOffsetRegister:
                // *($R + $r)
                addressRegister = context.GetRegister(registerOrMemoryRegion);
                offsetRegister  = context.GetRegister(offsetRegisterIndex);
                sourceOperand   = MemoryHelper.EmitPointer(addressRegister, offsetRegister, context);
                break;

            case ValueRegister:
                // $V
                sourceOperand = context.GetRegister(registerOrMemoryRegion);
                break;

            default:
                throw new TamperCompilationException($"Invalid operand type {operandType} in Atmosphere cheat");
            }

            InstructionHelper.Emit(typeof(OpLog <>), operationWidth, context, logId, sourceOperand);
        }
Пример #3
0
        private const byte Mov = 9; // lhs (discards right-hand operand)

        public static void Emit(byte[] instruction, CompilationContext context)
        {
            // 9TCRS0s0
            // T: Width of arithmetic operation(1, 2, 4, or 8 bytes).
            // C: Arithmetic operation to apply, see below.
            // R: Register to store result in.
            // S: Register to use as left - hand operand.
            // s: Register to use as right - hand operand.

            // 9TCRS100 VVVVVVVV (VVVVVVVV)
            // T: Width of arithmetic operation(1, 2, 4, or 8 bytes).
            // C: Arithmetic operation to apply, see below.
            // R: Register to store result in.
            // S: Register to use as left - hand operand.
            // V: Value to use as right - hand operand.

            byte     operationWidth           = instruction[OperationWidthIndex];
            byte     operation                = instruction[OperationTypeIndex];
            Register destinationRegister      = context.GetRegister(instruction[DestinationRegisterIndex]);
            Register leftHandSideRegister     = context.GetRegister(instruction[LeftHandSideRegisterIndex]);
            byte     rightHandSideIsImmediate = instruction[UseImmediateAsRhsIndex];
            IOperand rightHandSideOperand;

            switch (rightHandSideIsImmediate)
            {
            case 0:
                // Use a register as right-hand side.
                rightHandSideOperand = context.GetRegister(instruction[RightHandSideRegisterIndex]);
                break;

            case 1:
                // Use an immediate as right-hand side.
                int   immediateSize = operationWidth <= 4 ? RightHandSideImmediate8 : RightHandSideImmediate16;
                ulong immediate     = InstructionHelper.GetImmediate(instruction, RightHandSideImmediateIndex, immediateSize);
                rightHandSideOperand = new Value <ulong>(immediate);
                break;

            default:
                throw new TamperCompilationException($"Invalid right-hand side switch {rightHandSideIsImmediate} in Atmosphere cheat");
            }

            void Emit(Type operationType, IOperand rhs = null)
            {
                List <IOperand> operandList = new List <IOperand>();

                operandList.Add(destinationRegister);
                operandList.Add(leftHandSideRegister);

                if (rhs != null)
                {
                    operandList.Add(rhs);
                }

                InstructionHelper.Emit(operationType, operationWidth, context, operandList.ToArray());
            }

            switch (operation)
            {
            case Add: Emit(typeof(OpAdd <>), rightHandSideOperand); break;

            case Sub: Emit(typeof(OpSub <>), rightHandSideOperand); break;

            case Mul: Emit(typeof(OpMul <>), rightHandSideOperand); break;

            case Lsh: Emit(typeof(OpLsh <>), rightHandSideOperand); break;

            case Rsh: Emit(typeof(OpRsh <>), rightHandSideOperand); break;

            case And: Emit(typeof(OpAnd <>), rightHandSideOperand); break;

            case Or:  Emit(typeof(OpOr <>), rightHandSideOperand); break;

            case Not: Emit(typeof(OpNot <>)); break;

            case Xor: Emit(typeof(OpXor <>), rightHandSideOperand); break;

            case Mov: Emit(typeof(OpMov <>)); break;

            default:
                throw new TamperCompilationException($"Invalid arithmetic operation {operation} in Atmosphere cheat");
            }
        }