Exemplo n.º 1
0
 public static bool IsJump(ArmInstruction instruction)
 {
     return(!instruction.Details.BelongsToGroup(ArmInstructionGroupId.ARM_GRP_CALL) &&
            (instruction.Details.BelongsToGroup(ArmInstructionGroupId.ARM_GRP_BRANCH_RELATIVE) ||
             instruction.Details.BelongsToGroup(ArmInstructionGroupId.ARM_GRP_JUMP) ||
             instruction.Details.IsRegisterExplicitlyWritten(ArmRegisterId.ARM_REG_PC)));
 }
Exemplo n.º 2
0
        private IArmInstruction[] ConvertToArm(uint[] aRawInstructions, uint aStartingAddress)
        {
            // TODO: optimise this
            List <IArmInstruction> ret = new List <IArmInstruction>();
            //
            uint address = aStartingAddress;

            for (int i = 0; i < aRawInstructions.Length; i++, address += 4)
            {
                uint raw = aRawInstructions[i];
                foreach (ArmInstruction inst in iArmInstructions)
                {
                    if (inst.Matches(raw))
                    {
                        Type            type = inst.GetType();
                        ConstructorInfo ctor = type.GetConstructor(new Type[] { });
                        ArmInstruction  copy = (ArmInstruction)ctor.Invoke(new object[] { });
                        copy.AIAddress  = address;
                        copy.AIRawValue = raw;
                        ret.Add(copy);
                        Disassemble(copy);
                        break;
                    }
                }
            }
            //
            return(ret.ToArray());
        }
Exemplo n.º 3
0
        private void Read()
        {
            ulong absoluteFirstOffset = AbsolutePokemonIndexOffset(ActorDataList.First());

            // TODO: get rid of the ArmInstruction class and add encoding and decoding functions for
            // the instructions used here to CodeGenerationHelper instead.
            var firstOffsetInstruction = new ArmInstruction(BitConverter.ToUInt32(executable.Data, (int)absoluteFirstOffset));

            if (!firstOffsetInstruction.IsSupported)
            {
                throw new InvalidOperationException("Cannot read Actor database - maybe an incompatible version was used?");
            }

            foreach (var actorData in ActorDataList.Where(actorData => actorData.PokemonIndexEditable))
            {
                var instruction =
                    new ArmInstruction(BitConverter.ToUInt32(executable.Data, (int)AbsolutePokemonIndexOffset(actorData)));

                if (instruction.IsSupported)
                {
                    // It doesn't matter if the instruction is unsupported here because we can rely
                    // on the hardcoded values PegasusActDatabase.Data.cs and it will be readable after edits.
                    actorData.PokemonIndex = (CreatureIndex)instruction.Value;
                }
            }
        }
Exemplo n.º 4
0
        public void Write()
        {
            // TODO: get rid of the ArmInstruction class and add encoding and decoding functions for
            // the instructions used here to CodeGenerationHelper instead.
            foreach (var actorData in ActorDataList.Where(actorData => actorData.PokemonIndexEditable))
            {
                var instruction = new ArmInstruction(BitConverter.ToUInt32(executable.Data,
                                                                           (int)AbsolutePokemonIndexOffset(actorData)));
                if (instruction.IsSupported)
                {
                    instruction.Value = (ushort)actorData.PokemonIndex;
                }
                else if (instruction.Code == ArmInstructionCode.MovBitmaskImmediateToWRegister)
                {
                    // Replace the unsupported instruction with an equivalent one
                    instruction = new ArmInstruction(ArmInstructionCode.MovImmediateToWRegister, instruction.Register,
                                                     (ushort)actorData.PokemonIndex);
                }

                BitConverter.GetBytes(instruction.RawInstruction).CopyTo(executable.Data,
                                                                         (int)AbsolutePokemonIndexOffset(actorData));
            }
        }
        public ArmMachineInstruction(ArmInstruction instruction, Variable[] regVars)
            : base(instruction.Details.ConditionCode)
        {
            Instruction = instruction;
            var defs = instruction.Details.AllWrittenRegisters
                       .Where(reg => reg.Id != ArmRegisterId.ARM_REG_PC)
                       .Select(reg => regVars[ArmUtil.GetRegisterNumber(reg.Id)]);

            if (instruction.Details.BelongsToGroup(ArmInstructionGroupId.ARM_GRP_CALL))
            {
                defs = defs.Append(regVars[0]).Append(regVars[1])
                       .Append(regVars[2]).Append(regVars[3]).Append(regVars[16]);
            }
            if (instruction.Details.UpdateFlags && !instruction.Details.IsRegisterWritten(ArmRegisterId.ARM_REG_CPSR))
            {
                defs = defs.Append(regVars[16]);
            }
            VariableDefs.UnionWith(defs);
            var uses = instruction.Details.AllReadRegisters
                       .Where(reg => reg.Id != ArmRegisterId.ARM_REG_PC)
                       .Select(reg => regVars[ArmUtil.GetRegisterNumber(reg.Id)]);

            if (instruction.Details.ConditionCode != ArmConditionCode.ARM_CC_AL)
            {
                uses = uses.Append(regVars[16]);
            }
            if (instruction.Id == ArmInstructionId.ARM_INS_BX)
            {
                uses = uses.Append(regVars[ArmUtil.GetRegisterNumber(instruction.Details.Operands[0].Register.Id)]);
            }
            if (instruction.Details.BelongsToGroup(ArmInstructionGroupId.ARM_GRP_CALL) ||
                instruction.Id == ArmInstructionId.ARM_INS_BX)
            {
                uses = uses.Append(regVars[0]).Append(regVars[1]).Append(regVars[2]).Append(regVars[3])
                       .Append(regVars[13]);
            }
            VariableUses.UnionWith(uses);

            for (int i = 0; i < Instruction.Details.Operands.Length; i++)
            {
                var op = Instruction.Details.Operands[i];
                switch (op.Type)
                {
                case ArmOperandType.Register:
                    if (op.AccessType == OperandAccessType.Write ||
                        (Instruction.DisassembleMode == ArmDisassembleMode.Thumb &&
                         op.AccessType == (OperandAccessType.Read | OperandAccessType.Write) && i == 0))
                    {
                        Operands.Add((true, VariableDefs.FirstOrDefault(v =>
                                                                        v.Location == VariableLocation.Register &&
                                                                        v.Address == ArmUtil.GetRegisterNumber(op.Register.Id))));
                    }
                    else
                    {
                        Operands.Add((false, VariableUses.FirstOrDefault(v =>
                                                                         v.Location == VariableLocation.Register &&
                                                                         v.Address == ArmUtil.GetRegisterNumber(op.Register.Id))));
                        if (op.ShiftOperation >= ArmShiftOperation.ARM_SFT_LSL_REG)
                        {
                            Operands.Add((false, VariableUses.First(v =>
                                                                    v.Location == VariableLocation.Register &&
                                                                    v.Address == ArmUtil.GetRegisterNumber(op.ShiftRegister.Id))));
                        }
                    }

                    break;

                case ArmOperandType.Memory:
                    Operands.Add((false, VariableUses.First(v =>
                                                            v.Location == VariableLocation.Register &&
                                                            v.Address == ArmUtil.GetRegisterNumber(op.Memory.Base.Id))));
                    if (op.Memory.Index == null)
                    {
                        Operands.Add((false, new Constant((uint)op.Memory.Displacement)));
                    }
                    else
                    {
                        Operands.Add((false, VariableUses.First(v =>
                                                                v.Location == VariableLocation.Register &&
                                                                v.Address == ArmUtil.GetRegisterNumber(op.Memory.Index.Id))));
                    }
                    if (instruction.Details.WriteBack)
                    {
                        Operands.Add((true, VariableDefs.First(v =>
                                                               v.Location == VariableLocation.Register &&
                                                               v.Address == ArmUtil.GetRegisterNumber(op.Memory.Base.Id))));
                    }
                    break;

                case ArmOperandType.Immediate:
                    Operands.Add((false, new Constant((uint)op.Immediate)));
                    break;

                default:
                    Operands.Add((false, null));
                    break;
                }
            }

            if (VariableUses.Contains(regVars[16]))
            {
                FlagsUseOperand = regVars[16];
            }

            if (VariableDefs.Contains(regVars[16]))
            {
                FlagsDefOperand = regVars[16];
            }
        }
        internal override void Process(ArmPrologueHelper aProlog)
        {
            IArmInstruction instruction = base.Instruction;

            // Only unconditional instructions are handled
            if (instruction.AIConditionCode == TArmInstructionCondition.AL)
            {
                if (instruction is ArmInstruction)
                {
                    ArmInstruction armInst = (ArmInstruction)instruction;
                    //
                    if (armInst is Arm_LoadOrStoreMultiple)
                    {
                        Arm_LoadOrStoreMultiple lsmInstruction = (Arm_LoadOrStoreMultiple)instruction;

                        // We're looking for store operations
                        if (lsmInstruction.DataTransferType == TArmDataTransferType.EStore)
                        {
                            // We're looking for LSM's that involve SP.
                            if (lsmInstruction.BaseRegister == TArmRegisterType.EArmReg_SP)
                            {
                                if (lsmInstruction is Arm_LoadOrStoreMultiple_GP)
                                {
                                    Arm_LoadOrStoreMultiple_GP gpLsmInstruction = (Arm_LoadOrStoreMultiple_GP)lsmInstruction;
                                    HandleDTOperation(aProlog, gpLsmInstruction.Registers);
                                }
                                else if (lsmInstruction is Arm_LoadOrStoreMultiple_VFP)
                                {
                                    Arm_LoadOrStoreMultiple_VFP vfpLsmInstruction = (Arm_LoadOrStoreMultiple_VFP)lsmInstruction;
                                    HandleDTOperation(aProlog, vfpLsmInstruction.Registers);
                                }
                            }
                        }
                    }
                }
                else if (instruction is ThumbInstruction)
                {
                    ThumbInstruction thumbInst = (ThumbInstruction)instruction;
                    //
                    if (thumbInst is Thumb_LoadOrStoreMultiple)
                    {
                        // Special case that loads or stores multiple registers
                        Thumb_LoadOrStoreMultiple lsmThumb = (Thumb_LoadOrStoreMultiple)thumbInst;
                        if (lsmThumb.DataTransferType == TArmDataTransferType.EStore && lsmThumb.Rd == TArmRegisterType.EArmReg_SP)
                        {
                            HandleDTOperation(aProlog, lsmThumb.Registers);
                        }
                        else
                        {
                        }
                    }
                    else if (thumbInst is Thumb_LDR_RelativeToPC)
                    {
                        // When the Prologue needs to establish a working stack slurry, then often
                        // the scratch registers are used to build up a large subtraction from SP.
                        HandleDTLoad(aProlog, thumbInst as Thumb_LDR_RelativeToPC);
                    }
                }
                else
                {
                    throw new NotSupportedException("Instruction type not supported");
                }
            }
        }