public IpRelMemOpInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP64) { Debug.Assert(instruction.IsIPRelativeMemoryOp); this.instruction = instruction; instrKind = InstrKind.Uninitialized; string errorMessage; instruction.MemoryBase = Register.RIP; ripInstructionSize = (uint)blockEncoder.NullEncoder.Encode(ref instruction, instruction.IP64, out errorMessage); if (errorMessage != null) { ripInstructionSize = DecoderConstants.MaxInstructionLength; } instruction.MemoryBase = Register.EIP; eipInstructionSize = (uint)blockEncoder.NullEncoder.Encode(ref instruction, instruction.IP64, out errorMessage); if (errorMessage != null) { eipInstructionSize = DecoderConstants.MaxInstructionLength; } Debug.Assert(eipInstructionSize >= ripInstructionSize); Size = eipInstructionSize; }
public IpRelMemOpInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP) { Debug.Assert(instruction.IsIPRelativeMemoryOperand); this.instruction = instruction; instrKind = InstrKind.Uninitialized; string errorMessage; var instrCopy = instruction; instrCopy.MemoryBase = Register.RIP; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, instrCopy.IP, out ripInstructionSize, out errorMessage)) { ripInstructionSize = DecoderConstants.MaxInstructionLength; } instrCopy.MemoryBase = Register.EIP; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, instrCopy.IP, out eipInstructionSize, out errorMessage)) { eipInstructionSize = DecoderConstants.MaxInstructionLength; } Debug.Assert(eipInstructionSize >= ripInstructionSize); Size = eipInstructionSize; }
public JccInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP64) { bitness = blockEncoder.Bitness; this.instruction = instruction; instrKind = InstrKind.Uninitialized; string errorMessage; if (!blockEncoder.FixBranches) { instrKind = InstrKind.Unchanged; Size = (uint)blockEncoder.NullEncoder.Encode(ref instruction, instruction.IP64, out errorMessage); if (errorMessage != null) { Size = DecoderConstants.MaxInstructionLength; } } else { Instruction instrCopy; instrCopy = instruction; instrCopy.Code = instruction.Code.ToShortBranchCode(); instrCopy.NearBranch64Target = 0; shortInstructionSize = (uint)blockEncoder.NullEncoder.Encode(ref instrCopy, 0, out errorMessage); if (errorMessage != null) { shortInstructionSize = DecoderConstants.MaxInstructionLength; } instrCopy = instruction; instrCopy.Code = instruction.Code.ToNearBranchCode(); instrCopy.NearBranch64Target = 0; nearInstructionSize = (uint)blockEncoder.NullEncoder.Encode(ref instrCopy, 0, out errorMessage); if (errorMessage != null) { nearInstructionSize = DecoderConstants.MaxInstructionLength; } if (blockEncoder.Bitness == 64) { // Make sure it's not shorter than the real instruction. It can happen if there are extra prefixes. Size = Math.Max(nearInstructionSize, longInstructionSize64); } else { Size = nearInstructionSize; } } }
bool TryOptimize() { if (instrKind == InstrKind.Unchanged || instrKind == InstrKind.Short) { return(false); } var targetAddress = targetInstr.GetAddress(); var nextRip = IP + shortInstructionSize; long diff = (long)(targetAddress - nextRip); if (sbyte.MinValue <= diff && diff <= sbyte.MaxValue) { if (pointerData != null) { pointerData.IsValid = false; } instrKind = InstrKind.Short; Size = shortInstructionSize; return(true); } // If it's in the same block, we assume the target is at most 2GB away. bool useNear = bitness != 64 || targetInstr.IsInBlock(Block); if (!useNear) { targetAddress = targetInstr.GetAddress(); nextRip = IP + nearInstructionSize; diff = (long)(targetAddress - nextRip); useNear = int.MinValue <= diff && diff <= int.MaxValue; } if (useNear) { if (pointerData != null) { pointerData.IsValid = false; } instrKind = InstrKind.Near; Size = nearInstructionSize; return(true); } if (pointerData == null) { pointerData = Block.AllocPointerLocation(); } instrKind = InstrKind.Long; return(false); }
public JmpInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP64) { bitness = blockEncoder.Bitness; this.instruction = instruction; instrKind = InstrKind.Uninitialized; string errorMessage; Instruction instrCopy; if (!blockEncoder.FixBranches) { instrKind = InstrKind.Unchanged; instrCopy = instruction; instrCopy.NearBranch64 = 0; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out Size, out errorMessage)) { Size = DecoderConstants.MaxInstructionLength; } } else { instrCopy = instruction; instrCopy.Code = instruction.Code.ToShortBranchCode(); instrCopy.NearBranch64 = 0; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out shortInstructionSize, out errorMessage)) { shortInstructionSize = DecoderConstants.MaxInstructionLength; } instrCopy = instruction; instrCopy.Code = instruction.Code.ToNearBranchCode(); instrCopy.NearBranch64 = 0; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out nearInstructionSize, out errorMessage)) { nearInstructionSize = DecoderConstants.MaxInstructionLength; } if (blockEncoder.Bitness == 64) { // Make sure it's not shorter than the real instruction. It can happen if there are extra prefixes. Size = Math.Max(nearInstructionSize, CallOrJmpPointerDataInstructionSize64); } else { Size = nearInstructionSize; } } }
bool TryOptimize() { if (instrKind == InstrKind.Unchanged || instrKind == InstrKind.Rip || instrKind == InstrKind.Eip) { return(false); } // If it's in the same block, we assume the target is at most 2GB away. bool useRip = targetInstr.IsInBlock(Block); var targetAddress = targetInstr.GetAddress(); if (!useRip) { var nextRip = IP + ripInstructionSize; long diff = (long)(targetAddress - nextRip); useRip = int.MinValue <= diff && diff <= int.MaxValue; } if (useRip) { Size = ripInstructionSize; instrKind = InstrKind.Rip; return(true); } // If it's in the lower 4GB we can use EIP relative addressing if (targetAddress <= uint.MaxValue) { Size = eipInstructionSize; instrKind = InstrKind.Eip; return(true); } instrKind = InstrKind.Long; return(false); }
public SimpleBranchInstr(BlockEncoder blockEncoder, ref Instruction instruction) : base(blockEncoder, instruction.IP) { bitness = blockEncoder.Bitness; this.instruction = instruction; instrKind = InstrKind.Uninitialized; string errorMessage; Instruction instrCopy; if (!blockEncoder.FixBranches) { instrKind = InstrKind.Unchanged; instrCopy = instruction; instrCopy.NearBranch64 = 0; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out Size, out errorMessage)) { Size = DecoderConstants.MaxInstructionLength; } } else { instrCopy = instruction; instrCopy.NearBranch64 = 0; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out shortInstructionSize, out errorMessage)) { shortInstructionSize = DecoderConstants.MaxInstructionLength; } nativeCode = ToNativeBranchCode(instruction.Code, blockEncoder.Bitness); if (nativeCode == instruction.Code) { nativeInstructionSize = shortInstructionSize; } else { instrCopy = instruction; instrCopy.Code = nativeCode; instrCopy.NearBranch64 = 0; if (!blockEncoder.NullEncoder.TryEncode(ref instrCopy, 0, out nativeInstructionSize, out errorMessage)) { nativeInstructionSize = DecoderConstants.MaxInstructionLength; } } switch (blockEncoder.Bitness) { case 16: nearInstructionSize = nativeInstructionSize + 2 + 3; break; case 32: case 64: nearInstructionSize = nativeInstructionSize + 2 + 5; break; default: throw new InvalidOperationException(); } if (blockEncoder.Bitness == 64) { longInstructionSize = nativeInstructionSize + 2 + CallOrJmpPointerDataInstructionSize64; Size = Math.Max(Math.Max(shortInstructionSize, nearInstructionSize), longInstructionSize); } else { Size = Math.Max(shortInstructionSize, nearInstructionSize); } } }