public static ICondition Emit(byte[] instruction, CompilationContext context) { // 1TMC00AA AAAAAAAA VVVVVVVV (VVVVVVVV) // T: Width of memory write (1, 2, 4, or 8 bytes). // M: Memory region to write to (0 = Main NSO, 1 = Heap). // C: Condition to use, see below. // A: Immediate offset to use from memory region base. // V: Value to compare to. byte operationWidth = instruction[OperationWidthIndex]; MemoryRegion memoryRegion = (MemoryRegion)instruction[MemoryRegionIndex]; Comparison comparison = (Comparison)instruction[ComparisonTypeIndex]; ulong address = InstructionHelper.GetImmediate(instruction, OffsetImmediateIndex, OffsetImmediateSize); Pointer sourceMemory = MemoryHelper.EmitPointer(memoryRegion, address, context); int valueSize = operationWidth <= 4 ? ValueImmediateSize4 : ValueImmediateSize8; ulong value = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, valueSize); Value <ulong> compareToValue = new Value <ulong>(value); return(InstructionHelper.CreateCondition(comparison, operationWidth, sourceMemory, compareToValue)); }
public static ICondition Emit(byte[] instruction, CompilationContext context) { // C0TcSX## // C0TcS0Ma aaaaaaaa // C0TcS1Mr // C0TcS2Ra aaaaaaaa // C0TcS3Rr // C0TcS400 VVVVVVVV (VVVVVVVV) // C0TcS5X0 // T: Width of memory write(1, 2, 4, or 8 bytes). // c: Condition to use, see below. // S: Source Register. // 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). // X: Other Register(operand type 5). // V: Value to compare to(operand type 4). byte operationWidth = instruction[OperationWidthIndex]; Comparison comparison = (Comparison)instruction[ComparisonTypeIndex]; Register sourceRegister = context.GetRegister(instruction[SourceRegisterIndex]); byte operandType = instruction[OperandTypeIndex]; byte registerOrMemoryRegion = instruction[RegisterOrMemoryRegionIndex]; byte offsetRegisterIndex = instruction[OffsetImmediateIndex]; ulong offsetImmediate; ulong valueImmediate; int valueImmediateSize; Register addressRegister; Register offsetRegister; IOperand sourceOperand; switch (operandType) { case MemoryRegionWithOffsetImmediate: // *(?x + #a) offsetImmediate = InstructionHelper.GetImmediate(instruction, OffsetImmediateIndex, OffsetImmediateSize); sourceOperand = MemoryHelper.EmitPointer((MemoryRegion)registerOrMemoryRegion, offsetImmediate, 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); offsetImmediate = InstructionHelper.GetImmediate(instruction, OffsetImmediateIndex, OffsetImmediateSize); sourceOperand = MemoryHelper.EmitPointer(addressRegister, offsetImmediate, context); break; case AddressRegisterWithOffsetRegister: // *($R + $r) addressRegister = context.GetRegister(registerOrMemoryRegion); offsetRegister = context.GetRegister(offsetRegisterIndex); sourceOperand = MemoryHelper.EmitPointer(addressRegister, offsetRegister, context); break; case OffsetImmediate: valueImmediateSize = operationWidth <= 4 ? ValueImmediateSize8 : ValueImmediateSize16; valueImmediate = InstructionHelper.GetImmediate(instruction, ValueImmediateIndex, valueImmediateSize); sourceOperand = new Value <ulong>(valueImmediate); break; case AddressRegister: // $V sourceOperand = context.GetRegister(registerOrMemoryRegion); break; default: throw new TamperCompilationException($"Invalid operand type {operandType} in Atmosphere cheat"); } return(InstructionHelper.CreateCondition(comparison, operationWidth, sourceRegister, sourceOperand)); }