public LoadConstant(ArmConditionCode condition, Variable dst, uint constant) : base(condition) { Constant = constant; VariableDefs.Add(dst); Operands.Add((true, dst)); }
public FunctionEntrance(Function func, Variable[] regVars) : base(ArmConditionCode.ARM_CC_AL) { VariableDefs.Add(regVars[0]); VariableDefs.Add(regVars[1]); VariableDefs.Add(regVars[2]); VariableDefs.Add(regVars[3]); VariableDefs.Add(regVars[13]); VariableDefs.Add(regVars[14]); foreach (var stackVar in func.StackVariables) { if (stackVar.Address >= 0) { VariableDefs.Add(stackVar); } } }
public LongAdd(Variable dstLo, Variable dstHi, Variable opALo, Variable opAHi, Operand opBLo, Operand opBHi) : base(ArmConditionCode.ARM_CC_AL) { Operands.Add((true, dstLo)); Operands.Add((true, dstHi)); Operands.Add((false, opALo)); Operands.Add((false, opAHi)); Operands.Add((false, opBLo)); Operands.Add((false, opBHi)); VariableUses.Add(opALo); VariableUses.Add(opAHi); if (opBLo is Variable) { VariableUses.Add((Variable)opBLo); } if (opBHi is Variable) { VariableUses.Add((Variable)opBHi); } VariableDefs.Add(dstLo); VariableDefs.Add(dstHi); }
public override IEnumerable <IRInstruction> GetIRInstructions(IRContext context, IRBasicBlock parentBlock) { switch (Instruction.Id) { case ArmInstructionId.ARM_INS_ADD: if (Instruction.Details.Operands[0].Register.Id == ArmRegisterId.ARM_REG_PC) { yield break; } if (Instruction.DisassembleMode == ArmDisassembleMode.Thumb && Instruction.Details.Operands.Length == 2) { yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 0) + GetIRSecondOperand(context, 1))); } else if (Instruction.DisassembleMode == ArmDisassembleMode.Thumb && Instruction.Details.Operands.Length == 3 && Instruction.Details.Operands[2].Type == ArmOperandType.Immediate && Instruction.Details.Operands[2].Immediate == 0) { yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1))); } else { yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1) + GetIRSecondOperand(context, 2))); } break; case ArmInstructionId.ARM_INS_SUB: if (Instruction.DisassembleMode == ArmDisassembleMode.Thumb && Instruction.Details.Operands.Length == 2) { yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 0) - GetIRSecondOperand(context, 1))); } else { yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1) - GetIRSecondOperand(context, 2))); } break; case ArmInstructionId.ARM_INS_RSB: yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIRSecondOperand(context, 2) - GetIROperand(context, 1))); break; case ArmInstructionId.ARM_INS_AND: yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1) & GetIRSecondOperand(context, 2))); break; case ArmInstructionId.ARM_INS_ORR: yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1) | GetIRSecondOperand(context, 2))); break; case ArmInstructionId.ARM_INS_EOR: yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1) ^ GetIRSecondOperand(context, 2))); break; case ArmInstructionId.ARM_INS_BIC: yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1) & ~GetIRSecondOperand(context, 2))); break; case ArmInstructionId.ARM_INS_LSL: if (Instruction.DisassembleMode == ArmDisassembleMode.Arm) { goto case ArmInstructionId.ARM_INS_MOV; } yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1).ShiftLeft(GetIRSecondOperand(context, 2)))); break; case ArmInstructionId.ARM_INS_LSR: if (Instruction.DisassembleMode == ArmDisassembleMode.Arm) { goto case ArmInstructionId.ARM_INS_MOV; } yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1).ShiftRightLogical(GetIRSecondOperand(context, 2)))); break; case ArmInstructionId.ARM_INS_ASR: if (Instruction.DisassembleMode == ArmDisassembleMode.Arm) { goto case ArmInstructionId.ARM_INS_MOV; } yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1).ShiftRightArithmetic(GetIRSecondOperand(context, 2)))); break; case ArmInstructionId.ARM_INS_ROR: if (Instruction.DisassembleMode == ArmDisassembleMode.Arm) { goto case ArmInstructionId.ARM_INS_MOV; } throw new NotImplementedException(); break; case ArmInstructionId.ARM_INS_RRX: if (Instruction.DisassembleMode == ArmDisassembleMode.Arm) { goto case ArmInstructionId.ARM_INS_MOV; } throw new NotImplementedException(); break; case ArmInstructionId.ARM_INS_MOV: yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIRSecondOperand(context, 1))); break; case ArmInstructionId.ARM_INS_MVN: yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), ~GetIRSecondOperand(context, 1))); break; case ArmInstructionId.ARM_INS_MUL: yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1) * GetIROperand(context, 2))); break; case ArmInstructionId.ARM_INS_MLA: yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), GetIROperand(context, 1) * GetIROperand(context, 2) + GetIROperand(context, 3))); break; case ArmInstructionId.ARM_INS_SMULL: yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), (GetIROperand(context, 2).Cast(IRPrimitive.S32).Cast(IRPrimitive.S64) * GetIROperand(context, 3).Cast(IRPrimitive.S32).Cast(IRPrimitive.S64)).Cast(IRPrimitive.U32))); yield return(new IRAssignment(parentBlock, GetIROperand(context, 1), (GetIROperand(context, 2).Cast(IRPrimitive.S32).Cast(IRPrimitive.S64) * GetIROperand(context, 3).Cast(IRPrimitive.S32).Cast(IRPrimitive.S64)).ShiftRightLogical(32) .Cast(IRPrimitive.U32))); break; case ArmInstructionId.ARM_INS_LDR: case ArmInstructionId.ARM_INS_LDRH: case ArmInstructionId.ARM_INS_LDRSH: case ArmInstructionId.ARM_INS_LDRB: case ArmInstructionId.ARM_INS_LDRSB: { IRType type = IRPrimitive.Void; switch (Instruction.Id) { case ArmInstructionId.ARM_INS_LDR: type = IRPrimitive.U32; break; case ArmInstructionId.ARM_INS_LDRH: type = IRPrimitive.U16; break; case ArmInstructionId.ARM_INS_LDRSH: type = IRPrimitive.S16; break; case ArmInstructionId.ARM_INS_LDRB: type = IRPrimitive.U8; break; case ArmInstructionId.ARM_INS_LDRSB: type = IRPrimitive.S8; break; } if (Instruction.Details.WriteBack) { throw new NotImplementedException("Unimplemented instruction!"); } if (Instruction.Details.Operands[1].Memory.Base.Id == ArmRegisterId.ARM_REG_SP) { yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), context.VariableMapping[VariableUses.First(v => v.Location == VariableLocation.Stack)])); break; } if (Instruction.Details.Operands[1].Memory.Index == null && Instruction.Details.Operands[1].Memory.Displacement == 0) { yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), new IRDerefExpression(type, GetIROperand(context, 1)).Cast(IRPrimitive.U32))); break; } else if (Instruction.Details.Operands[1].Memory.Index == null) { var deref = new IRDerefExpression(type, GetIROperand(context, 1) + (uint)Instruction.Details.Operands[1].Memory.Displacement); yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), deref.Cast(IRPrimitive.U32))); break; } else { if (Instruction.Details.Operands[1].ShiftOperation == ArmShiftOperation.Invalid || (Instruction.Details.Operands[1].ShiftOperation == ArmShiftOperation.ARM_SFT_LSL && Instruction.Details.Operands[1].ShiftValue == 0)) { var deref = new IRDerefExpression(type, GetIROperand(context, 1) + GetIROperand(context, 2)); yield return(new IRAssignment(parentBlock, GetIROperand(context, 0), deref.Cast(IRPrimitive.U32))); break; } else { throw new NotImplementedException("Unimplemented instruction!"); } } } case ArmInstructionId.ARM_INS_STR: case ArmInstructionId.ARM_INS_STRH: case ArmInstructionId.ARM_INS_STRB: { var type = IRPrimitive.Void; switch (Instruction.Id) { case ArmInstructionId.ARM_INS_STR: type = IRPrimitive.U32; break; case ArmInstructionId.ARM_INS_STRH: type = IRPrimitive.U16; break; case ArmInstructionId.ARM_INS_STRB: type = IRPrimitive.U8; break; } if (Instruction.Details.WriteBack) { throw new NotImplementedException("Unimplemented instruction!"); } if (Instruction.Details.Operands[1].Memory.Base.Id == ArmRegisterId.ARM_REG_SP) { yield return(new IRAssignment(parentBlock, context.VariableMapping[VariableDefs.First(v => v.Location == VariableLocation.Stack)], GetIROperand(context, 0))); break; } if (Instruction.Details.Operands[1].Memory.Index == null && Instruction.Details.Operands[1].Memory.Displacement == 0) { yield return(new IRStore(parentBlock, type, GetIROperand(context, 1), GetIROperand(context, 0))); break; } else if (Instruction.Details.Operands[1].Memory.Index == null) { yield return(new IRStore(parentBlock, type, GetIROperand(context, 1) + (uint)Instruction.Details.Operands[1].Memory.Displacement, GetIROperand(context, 0))); break; } else { if (Instruction.Details.Operands[1].ShiftOperation == ArmShiftOperation.Invalid || (Instruction.Details.Operands[1].ShiftOperation == ArmShiftOperation.ARM_SFT_LSL && Instruction.Details.Operands[1].ShiftValue == 0)) { yield return(new IRStore(parentBlock, type, GetIROperand(context, 1) + GetIROperand(context, 2), GetIROperand(context, 0))); break; } else { throw new NotImplementedException("Unimplemented instruction!"); } } } case ArmInstructionId.ARM_INS_BL: yield return(new IRAssignment(parentBlock, context.VariableMapping[VariableDefs .First(v => v.Location == VariableLocation.Register && v.Address == 0)], new IRCallExpression(IRPrimitive.U32, $"sub_{Instruction.Details.Operands[0].Immediate:X08}", context.VariableMapping[VariableUses .First(v => v.Location == VariableLocation.Register && v.Address == 0)], context.VariableMapping[VariableUses .First(v => v.Location == VariableLocation.Register && v.Address == 1)], context.VariableMapping[VariableUses .First(v => v.Location == VariableLocation.Register && v.Address == 2)], context.VariableMapping[VariableUses .First(v => v.Location == VariableLocation.Register && v.Address == 3)] ))); break; case ArmInstructionId.ARM_INS_BLX: if (Instruction.Details.Operands[0].Type == ArmOperandType.Immediate) { goto case ArmInstructionId.ARM_INS_BL; } yield return(new IRAssignment(parentBlock, context.VariableMapping[VariableDefs .First(v => v.Location == VariableLocation.Register && v.Address == 0)], new IRCallExpression(IRPrimitive.U32, ((Variable)Operands[0].op).Name, context.VariableMapping[VariableUses .First(v => v.Location == VariableLocation.Register && v.Address == 0)], context.VariableMapping[VariableUses .First(v => v.Location == VariableLocation.Register && v.Address == 1)], context.VariableMapping[VariableUses .First(v => v.Location == VariableLocation.Register && v.Address == 2)], context.VariableMapping[VariableUses .First(v => v.Location == VariableLocation.Register && v.Address == 3)] ))); break; case ArmInstructionId.ARM_INS_LDM: if (Instruction.Details.Operands[0].Register.Id == ArmRegisterId.ARM_REG_SP && Instruction.Details.WriteBack) { break; } goto default; case ArmInstructionId.ARM_INS_STMDB: if (Instruction.Details.Operands[0].Register.Id == ArmRegisterId.ARM_REG_SP && Instruction.Details.WriteBack) { break; } goto default; case ArmInstructionId.ARM_INS_PUSH: case ArmInstructionId.ARM_INS_POP: case ArmInstructionId.ARM_INS_CMP: case ArmInstructionId.ARM_INS_B: case ArmInstructionId.ARM_INS_BX: break; default: throw new NotImplementedException("Unimplemented instruction!"); } }
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]; } }