private void WriteShift(ArmInstructionOperand op, MachineInstructionWriter writer) { switch (op.Shifter.Type) { case ArmShifterType.ASR: WriteImmShift("asr", op.Shifter.Value, writer); break; case ArmShifterType.LSL: WriteImmShift("lsl", op.Shifter.Value, writer); break; case ArmShifterType.LSR: WriteImmShift("lsr", op.Shifter.Value, writer); break; case ArmShifterType.ROR: WriteImmShift("ror", op.Shifter.Value, writer); break; case ArmShifterType.RRX: writer.Write(",rrx"); break; case ArmShifterType.ASR_REG: WriteRegShift("asr", op.Shifter.Value, writer); break; case ArmShifterType.LSL_REG: WriteRegShift("lsl", op.Shifter.Value, writer); break; case ArmShifterType.LSR_REG: WriteRegShift("lsr", op.Shifter.Value, writer); break; case ArmShifterType.ROR_REG: WriteRegShift("ror", op.Shifter.Value, writer); break; case ArmShifterType.RRX_REG: WriteRegShift("rrx", op.Shifter.Value, writer); break; case ArmShifterType.Invalid: break; } }
private Expression RewriteOp(ArmInstructionOperand op, DataType accessSize = null) { switch (op.Type) { case ArmInstructionOperandType.Register: return(GetReg(op.RegisterValue.Value)); case ArmInstructionOperandType.Immediate: if (accessSize != null) { return(Constant.Create(accessSize, op.ImmediateValue.Value)); } else { return(Constant.Int32(op.ImmediateValue.Value)); } case ArmInstructionOperandType.Memory: var mem = op.MemoryValue; var ea = EffectiveAddress(mem); return(emitter.Load(accessSize, ea)); default: throw new NotImplementedException(op.Type.ToString()); } }
private void MaybePostOperand(ArmInstructionOperand op) { if (instrs.Current.IsLastOperand(op)) { return; } if (op.Type != ArmInstructionOperandType.Memory) { return; } var lastOp = instr.ArchitectureDetail.Operands[instr.ArchitectureDetail.Operands.Length - 1]; Expression baseReg = Reg(op.MemoryValue.BaseRegister); var offset = Operand(lastOp); var ea = lastOp.IsSubtracted ? emitter.ISub(baseReg, offset) : emitter.IAdd(baseReg, offset); emitter.Assign(baseReg, ea); #if NYI if (memOp == null || memOp.Offset == null) { return; } if (memOp.Preindexed) { return; } Expression baseReg = frame.EnsureRegister(memOp.Base); var offset = Operand(memOp.Offset); var ea = memOp.Subtract ? emitter.ISub(baseReg, offset) : emitter.IAdd(baseReg, offset); emitter.Assign(baseReg, ea); #endif }
private Expression MaybeShiftOperand(Expression exp, ArmInstructionOperand op) { switch (op.Shifter.Type) { case ArmShifterType.ASR: return(emitter.Sar(exp, op.Shifter.Value)); case ArmShifterType.LSL: return(emitter.Shl(exp, op.Shifter.Value)); case ArmShifterType.LSR: return(emitter.Shr(exp, op.Shifter.Value)); case ArmShifterType.ROR: return(host.PseudoProcedure(PseudoProcedure.Ror, PrimitiveType.Word32, exp, Constant.Int32(op.Shifter.Value))); case ArmShifterType.RRX: return(host.PseudoProcedure("rrx", PrimitiveType.Word32, exp, Constant.Int32(op.Shifter.Value))); case ArmShifterType.ASR_REG: return(emitter.Sar(exp, Reg(op.Shifter.Value))); case ArmShifterType.LSL_REG: return(emitter.Shl(exp, Reg(op.Shifter.Value))); case ArmShifterType.LSR_REG: return(emitter.Shr(exp, Reg(op.Shifter.Value))); case ArmShifterType.ROR_REG: return(host.PseudoProcedure(PseudoProcedure.Ror, PrimitiveType.Word32, exp, Reg(op.Shifter.Value))); case ArmShifterType.RRX_REG: return(host.PseudoProcedure("rrx", PrimitiveType.Word32, exp, Reg(op.Shifter.Value))); default: return(exp); } }
private Expression Operand(ArmInstructionOperand op) { switch (op.Type) { case ArmInstructionOperandType.Register: var reg = frame.EnsureRegister(A32Registers.RegisterByCapstoneID[op.RegisterValue.Value]); return(MaybeShiftOperand(reg, op)); case ArmInstructionOperandType.SysRegister: var sysreg = frame.EnsureRegister(A32Registers.SysRegisterByCapstoneID[op.SysRegisterValue.Value]); return(sysreg); case ArmInstructionOperandType.Immediate: return(Constant.Word32(op.ImmediateValue.Value)); case ArmInstructionOperandType.CImmediate: case ArmInstructionOperandType.PImmediate: return(Constant.Byte((byte)op.ImmediateValue.Value)); case ArmInstructionOperandType.Memory: Expression baseReg = Reg(op.MemoryValue.BaseRegister); Expression ea = baseReg; if (op.MemoryValue.BaseRegister == ArmRegister.PC) // PC-relative address { var dst = (uint)((int)instrs.Current.Address.ToUInt32() + op.MemoryValue.Displacement) + 8u; ea = Address.Ptr32(dst); if (op.MemoryValue.IndexRegister != ArmRegister.Invalid) { var ireg = Reg(op.MemoryValue.IndexRegister); if (op.Shifter.Type == ArmShifterType.LSL) { ea = m.IAdd(ea, m.IMul(ireg, 1 << op.Shifter.Value)); } else { throw new NotImplementedException(); } } return(m.Mem(SizeFromLoadStore(instr), ea)); } if (op.MemoryValue.Displacement != 0 && instrs.Current.IsLastOperand(op)) { var offset = Constant.Int32(op.MemoryValue.Displacement); ea = op.MemoryValue.IndexRegisterScale < 0 ? m.ISub(ea, offset) : m.IAdd(ea, offset); } if (instrs.Current.IsLastOperand(op) && instr.ArchitectureDetail.WriteBack) { m.Assign(baseReg, ea); ea = baseReg; } return(m.Mem(SizeFromLoadStore(instr), ea)); case ArmInstructionOperandType.FloatingPoint: return(Constant.Real64(op.FloatingPointValue.Value)); } throw new NotImplementedException(op.Type.ToString()); }
private void WriteMemoryOperand(ArmInstructionOperand op, MachineInstructionWriter writer) { writer.Write('['); writer.Write(A32Registers.RegisterByCapstoneID[op.MemoryValue.BaseRegister].Name); int displacement = op.MemoryValue.Displacement; if (displacement != 0) { if (true) // preincInternal.ArchitectureDetail) { writer.Write(","); if (displacement < 0) { displacement = -displacement; writer.Write("-"); } writer.Write("#"); WriteImmediateValue(displacement, writer); writer.Write("]"); if (instruction.ArchitectureDetail.WriteBack) { writer.Write("!"); } } else { writer.Write("],"); if (displacement < 0) { displacement = -displacement; writer.Write("-"); } WriteImmediateValue(displacement, writer); } } else { if (op.MemoryValue.IndexRegister != ArmRegister.Invalid) { writer.Write(","); // NOTE: capstone.NET seems to reverse the sense of this scale parameter. if (op.IsSubtracted) { writer.Write("-"); } writer.Write(A32Registers.RegisterByCapstoneID[op.MemoryValue.IndexRegister].Name); } if (op.Shifter.Type != ArmShifterType.Invalid) { WriteShift(op, writer); } writer.Write(']'); if (instruction.ArchitectureDetail.WriteBack && IsLastOperand(op)) { writer.Write("!"); } } }
public void Write(ArmInstructionOperand op, MachineInstructionWriter writer) { switch (op.Type) { case ArmInstructionOperandType.Immediate: if (instruction.Id == Opcode.B || instruction.Id == Opcode.BL || instruction.Id == Opcode.BLX) { writer.Write("$"); writer.WriteAddress( string.Format("{0:X8}", op.ImmediateValue.Value), Address.Ptr32((uint)op.ImmediateValue.Value)); break; } writer.Write("#"); WriteImmediateValue(op.ImmediateValue.Value, writer); break; case ArmInstructionOperandType.CImmediate: writer.Write("c{0}", op.ImmediateValue); break; case ArmInstructionOperandType.PImmediate: writer.Write("p{0}", op.ImmediateValue); break; case ArmInstructionOperandType.Register: if (op.IsSubtracted) { writer.Write('-'); } writer.Write(A32Registers.RegisterByCapstoneID[op.RegisterValue.Value].Name); WriteShift(op, writer); break; case ArmInstructionOperandType.SysRegister: writer.Write(A32Registers.SysRegisterByCapstoneID[op.SysRegisterValue.Value].Name); break; case ArmInstructionOperandType.Memory: WriteMemoryOperand(op, writer); break; case ArmInstructionOperandType.SetEnd: writer.Write(op.SetEndValue.ToString().ToLowerInvariant()); break; default: throw new NotImplementedException(string.Format( "Can't disasseble {0} {1}. Unknown operand type: {2}", instruction.Mnemonic, instruction.Operand, op.Type)); } }
/// <summary> /// Create an ARM Instruction Operand. /// </summary> /// <param name="this"> /// A native ARM instruction operand. /// </param> /// <returns> /// An ARM instruction operand. /// </returns> public static ArmInstructionOperand AsArmInstructionOperand(this NativeArmInstructionOperand @this) { var @object = new ArmInstructionOperand(); @object.IsSubtracted = @this.IsSubtracted; @object.Shifter = @this.Shifter.AsArmShifter(); @object.Type = (ArmInstructionOperandType)@this.Type; @object.VectorIndex = @this.VectorIndex; // Set Values. // // ... switch (@object.Type) { case ArmInstructionOperandType.CImmediate: @object.ImmediateValue = @this.Value.Immediate; break; case ArmInstructionOperandType.FloatingPoint: @object.FloatingPointValue = @this.Value.FloatingPoint; break; case ArmInstructionOperandType.Immediate: @object.ImmediateValue = @this.Value.Immediate; break; case ArmInstructionOperandType.Memory: @object.MemoryValue = @this.Value.Memory.AsArmInstructionMemoryOperandValue(); break; case ArmInstructionOperandType.PImmediate: @object.ImmediateValue = @this.Value.Immediate; break; case ArmInstructionOperandType.Register: @object.RegisterValue = (ArmRegister)@this.Value.Register; break; case ArmInstructionOperandType.SetEnd: @object.SetEndValue = (ArmSetEndInstructionOperandType)@this.Value.SetEnd; break; case ArmInstructionOperandType.SysRegister: @object.SysRegisterValue = (ArmSysRegister)@this.Value.Register; break; } return(@object); }
/// <summary> /// Create an ARM Instruction Operand. /// </summary> /// <param name="this"> /// A native ARM instruction operand. /// </param> /// <returns> /// An ARM instruction operand. /// </returns> public static ArmInstructionOperand AsArmInstructionOperand(this NativeArmInstructionOperand @this) { var @object = new ArmInstructionOperand(); @object.IsSubtracted = @this.IsSubtracted; @object.Shifter = @this.Shifter.AsArmShifter(); @object.Type = (ArmInstructionOperandType) @this.Type; @object.VectorIndex = @this.VectorIndex; // Set Values. // // ... switch (@object.Type) { case ArmInstructionOperandType.CImmediate: @object.ImmediateValue = @this.Value.Immediate; break; case ArmInstructionOperandType.FloatingPoint: @object.FloatingPointValue = @this.Value.FloatingPoint; break; case ArmInstructionOperandType.Immediate: @object.ImmediateValue = @this.Value.Immediate; break; case ArmInstructionOperandType.Memory: @object.MemoryValue = @this.Value.Memory.AsArmInstructionMemoryOperandValue(); break; case ArmInstructionOperandType.PImmediate: @object.ImmediateValue = @this.Value.Immediate; break; case ArmInstructionOperandType.Register: @object.RegisterValue = (ArmRegister) @this.Value.Register; break; case ArmInstructionOperandType.SetEnd: @object.SetEndValue = (ArmSetEndInstructionOperandType) @this.Value.SetEnd; break; case ArmInstructionOperandType.SysRegister: @object.SysRegisterValue = (ArmSysRegister) @this.Value.Register; break; } return @object; }
private Expression Operand(ArmInstructionOperand op) { switch (op.Type) { case ArmInstructionOperandType.Register: var reg = frame.EnsureRegister(A32Registers.RegisterByCapstoneID[op.RegisterValue.Value]); return(MaybeShiftOperand(reg, op)); case ArmInstructionOperandType.Immediate: return(Constant.Word32(op.ImmediateValue.Value)); case ArmInstructionOperandType.Memory: Expression baseReg = Reg(op.MemoryValue.BaseRegister); Expression ea = baseReg; if (op.MemoryValue.BaseRegister == ArmRegister.PC) // PC-relative address { if (op.MemoryValue.Displacement != 0) { var dst = (uint)((int)instrs.Current.Address.ToUInt32() + op.MemoryValue.Displacement) + 8u; return(emitter.Load(SizeFromLoadStore(instr), Address.Ptr32(dst))); } } if (op.MemoryValue.Displacement != 0 && instrs.Current.IsLastOperand(op)) { var offset = Constant.Int32(op.MemoryValue.Displacement); ea = op.MemoryValue.IndexRegisterScale < 0 ? emitter.ISub(ea, offset) : emitter.IAdd(ea, offset); } if (instrs.Current.IsLastOperand(op) && instr.ArchitectureDetail.WriteBack) { emitter.Assign(baseReg, ea); ea = baseReg; } return(emitter.Load(SizeFromLoadStore(instr), ea)); } throw new NotImplementedException(op.Type.ToString()); }
/// <summary> /// Returns true if <paramref name="op"/> is the last operand of the instruction. /// </summary> /// <param name="op"></param> /// <returns></returns> public bool IsLastOperand(ArmInstructionOperand op) { var ops = instruction.ArchitectureDetail.Operands; return(op == ops[ops.Length - 1]); }
public void Write(ArmInstructionOperand op, MachineInstructionWriter writer, MachineInstructionWriterOptions options) { switch (op.Type) { case ArmInstructionOperandType.Immediate: if (instruction.Id == Opcode.B || instruction.Id == Opcode.BL || instruction.Id == Opcode.BLX) { writer.Write("$"); writer.WriteAddress( string.Format("{0:X8}", op.ImmediateValue.Value), Address.Ptr32((uint)op.ImmediateValue.Value)); break; } writer.Write("#"); WriteImmediateValue(op.ImmediateValue.Value, writer); break; case ArmInstructionOperandType.CImmediate: writer.Write("c{0}", op.ImmediateValue); break; case ArmInstructionOperandType.PImmediate: writer.Write("p{0}", op.ImmediateValue); break; case ArmInstructionOperandType.Register: if (op.IsSubtracted) { writer.Write('-'); } writer.Write(A32Registers.RegisterByCapstoneID[op.RegisterValue.Value].Name); WriteShift(op, writer); break; case ArmInstructionOperandType.SysRegister: writer.Write(A32Registers.SysRegisterByCapstoneID[op.SysRegisterValue.Value].Name); break; case ArmInstructionOperandType.Memory: if (op.MemoryValue.BaseRegister == ArmRegister.PC) { var uAddr = (uint)((int)this.Address.ToUInt32() + op.MemoryValue.Displacement) + 8u; var addr = Address.Ptr32(uAddr); if (op.MemoryValue.IndexRegister == ArmRegister.Invalid && (options & MachineInstructionWriterOptions.ResolvePcRelativeAddress) != 0) { writer.Write('['); writer.WriteAddress(addr.ToString(), addr); writer.Write(']'); var sr = new StringRenderer(); WriteMemoryOperand(op, sr); writer.AddAnnotation(sr.ToString()); } else { WriteMemoryOperand(op, writer); writer.AddAnnotation(addr.ToString()); } return; } WriteMemoryOperand(op, writer); break; case ArmInstructionOperandType.SetEnd: writer.Write(op.SetEndValue.ToString().ToLowerInvariant()); break; case ArmInstructionOperandType.FloatingPoint: var f = op.FloatingPointValue.Value.ToString("g", CultureInfo.InvariantCulture); if (f.IndexOfAny(nosuffixRequired) < 0) { f += ".0"; } writer.Write("#{0}", f); break; default: throw new NotImplementedException(string.Format( "Can't disassemble {0} {1}. Unknown operand type: {2}", instruction.Mnemonic, instruction.Operand, op.Type)); } }