mirror of https://github.com/icedland/iced.git
Port #162 to C#
This commit is contained in:
parent
9fa4b84e10
commit
9cd6bb89aa
|
@ -271,17 +271,20 @@ namespace Iced.Intel {
|
|||
bool updated = false;
|
||||
foreach (var block in blocks) {
|
||||
ulong ip = block.RIP;
|
||||
ulong gained = 0;
|
||||
foreach (var instr in block.Instructions) {
|
||||
instr.IP = ip;
|
||||
var oldSize = instr.Size;
|
||||
if (instr.Optimize()) {
|
||||
if (instr.Optimize(gained)) {
|
||||
if (instr.Size > oldSize) {
|
||||
errorMessage = "Internal error: new size > old size";
|
||||
result = null;
|
||||
return false;
|
||||
}
|
||||
if (instr.Size < oldSize)
|
||||
if (instr.Size < oldSize) {
|
||||
gained += oldSize - instr.Size;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
else if (instr.Size != oldSize) {
|
||||
errorMessage = "Internal error: new size != old size";
|
||||
|
|
|
@ -40,12 +40,12 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
|
||||
public override void Initialize(BlockEncoder blockEncoder) {
|
||||
targetInstr = blockEncoder.GetTarget(instruction.NearBranchTarget);
|
||||
TryOptimize();
|
||||
TryOptimize(0);
|
||||
}
|
||||
|
||||
public override bool Optimize() => TryOptimize();
|
||||
public override bool Optimize(ulong gained) => TryOptimize(gained);
|
||||
|
||||
bool TryOptimize() {
|
||||
bool TryOptimize(ulong gained) {
|
||||
if (done)
|
||||
return false;
|
||||
|
||||
|
@ -55,6 +55,7 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
var targetAddress = targetInstr.GetAddress();
|
||||
var nextRip = IP + origInstructionSize;
|
||||
long diff = (long)(targetAddress - nextRip);
|
||||
diff = CorrectDiff(targetInstr.IsInBlock(Block), diff, gained);
|
||||
useShort = int.MinValue <= diff && diff <= int.MaxValue;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#if ENCODER && BLOCK_ENCODER
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Iced.Intel.BlockEncoderInternal {
|
||||
abstract class Instr {
|
||||
|
@ -28,7 +29,7 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
/// Returns <see langword="true"/> if the instruction was updated to a shorter instruction, <see langword="false"/> if nothing changed
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public abstract bool Optimize();
|
||||
public abstract bool Optimize(ulong gained);
|
||||
|
||||
public abstract string? TryEncode(Encoder encoder, out ConstantOffsets constantOffsets, out bool isOriginalInstruction);
|
||||
|
||||
|
@ -256,6 +257,15 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static long CorrectDiff(bool inBlock, long diff, ulong gained) {
|
||||
if (inBlock && diff >= 0) {
|
||||
Debug.Assert((ulong)diff >= gained);
|
||||
return diff - (long)gained;
|
||||
}
|
||||
else
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -44,12 +44,12 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
|
||||
public override void Initialize(BlockEncoder blockEncoder) {
|
||||
targetInstr = blockEncoder.GetTarget(instruction.IPRelativeMemoryAddress);
|
||||
TryOptimize();
|
||||
TryOptimize(0);
|
||||
}
|
||||
|
||||
public override bool Optimize() => TryOptimize();
|
||||
public override bool Optimize(ulong gained) => TryOptimize(gained);
|
||||
|
||||
bool TryOptimize() {
|
||||
bool TryOptimize(ulong gained) {
|
||||
if (instrKind == InstrKind.Unchanged || instrKind == InstrKind.Rip || instrKind == InstrKind.Eip)
|
||||
return false;
|
||||
|
||||
|
@ -59,6 +59,7 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
if (!useRip) {
|
||||
var nextRip = IP + ripInstructionSize;
|
||||
long diff = (long)(targetAddress - nextRip);
|
||||
diff = CorrectDiff(targetInstr.IsInBlock(Block), diff, gained);
|
||||
useRip = int.MinValue <= diff && diff <= int.MaxValue;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,18 +67,19 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
|
||||
public override void Initialize(BlockEncoder blockEncoder) {
|
||||
targetInstr = blockEncoder.GetTarget(instruction.NearBranchTarget);
|
||||
TryOptimize();
|
||||
TryOptimize(0);
|
||||
}
|
||||
|
||||
public override bool Optimize() => TryOptimize();
|
||||
public override bool Optimize(ulong gained) => TryOptimize(gained);
|
||||
|
||||
bool TryOptimize() {
|
||||
bool TryOptimize(ulong gained) {
|
||||
if (instrKind == InstrKind.Unchanged || instrKind == InstrKind.Short)
|
||||
return false;
|
||||
|
||||
var targetAddress = targetInstr.GetAddress();
|
||||
var nextRip = IP + shortInstructionSize;
|
||||
long diff = (long)(targetAddress - nextRip);
|
||||
diff = CorrectDiff(targetInstr.IsInBlock(Block), diff, gained);
|
||||
if (sbyte.MinValue <= diff && diff <= sbyte.MaxValue) {
|
||||
if (pointerData is not null)
|
||||
pointerData.IsValid = false;
|
||||
|
@ -93,6 +94,7 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
targetAddress = targetInstr.GetAddress();
|
||||
nextRip = IP + nearInstructionSize;
|
||||
diff = (long)(targetAddress - nextRip);
|
||||
diff = CorrectDiff(targetInstr.IsInBlock(Block), diff, gained);
|
||||
useNear = int.MinValue <= diff && diff <= int.MaxValue;
|
||||
}
|
||||
if (useNear) {
|
||||
|
|
|
@ -62,18 +62,19 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
|
||||
public override void Initialize(BlockEncoder blockEncoder) {
|
||||
targetInstr = blockEncoder.GetTarget(instruction.NearBranchTarget);
|
||||
TryOptimize();
|
||||
TryOptimize(0);
|
||||
}
|
||||
|
||||
public override bool Optimize() => TryOptimize();
|
||||
public override bool Optimize(ulong gained) => TryOptimize(gained);
|
||||
|
||||
bool TryOptimize() {
|
||||
bool TryOptimize(ulong gained) {
|
||||
if (instrKind == InstrKind.Unchanged || instrKind == InstrKind.Short)
|
||||
return false;
|
||||
|
||||
var targetAddress = targetInstr.GetAddress();
|
||||
var nextRip = IP + shortInstructionSize;
|
||||
long diff = (long)(targetAddress - nextRip);
|
||||
diff = CorrectDiff(targetInstr.IsInBlock(Block), diff, gained);
|
||||
if (sbyte.MinValue <= diff && diff <= sbyte.MaxValue) {
|
||||
if (pointerData is not null)
|
||||
pointerData.IsValid = false;
|
||||
|
@ -88,6 +89,7 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
targetAddress = targetInstr.GetAddress();
|
||||
nextRip = IP + nearInstructionSize;
|
||||
diff = (long)(targetAddress - nextRip);
|
||||
diff = CorrectDiff(targetInstr.IsInBlock(Block), diff, gained);
|
||||
useNear = int.MinValue <= diff && diff <= int.MaxValue;
|
||||
}
|
||||
if (useNear) {
|
||||
|
|
|
@ -178,18 +178,19 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
|
||||
public override void Initialize(BlockEncoder blockEncoder) {
|
||||
targetInstr = blockEncoder.GetTarget(instruction.NearBranchTarget);
|
||||
TryOptimize();
|
||||
TryOptimize(0);
|
||||
}
|
||||
|
||||
public override bool Optimize() => TryOptimize();
|
||||
public override bool Optimize(ulong gained) => TryOptimize(gained);
|
||||
|
||||
bool TryOptimize() {
|
||||
bool TryOptimize(ulong gained) {
|
||||
if (instrKind == InstrKind.Unchanged || instrKind == InstrKind.Short)
|
||||
return false;
|
||||
|
||||
var targetAddress = targetInstr.GetAddress();
|
||||
var nextRip = IP + shortInstructionSize;
|
||||
long diff = (long)(targetAddress - nextRip);
|
||||
diff = CorrectDiff(targetInstr.IsInBlock(Block), diff, gained);
|
||||
if (sbyte.MinValue <= diff && diff <= sbyte.MaxValue) {
|
||||
if (pointerData is not null)
|
||||
pointerData.IsValid = false;
|
||||
|
@ -204,6 +205,7 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
targetAddress = targetInstr.GetAddress();
|
||||
nextRip = IP + nearInstructionSize;
|
||||
diff = (long)(targetAddress - nextRip);
|
||||
diff = CorrectDiff(targetInstr.IsInBlock(Block), diff, gained);
|
||||
useNear = int.MinValue <= diff && diff <= int.MaxValue;
|
||||
}
|
||||
if (useNear) {
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
}
|
||||
|
||||
public override void Initialize(BlockEncoder blockEncoder) { }
|
||||
public override bool Optimize() => false;
|
||||
public override bool Optimize(ulong gained) => false;
|
||||
|
||||
public override string? TryEncode(Encoder encoder, out ConstantOffsets constantOffsets, out bool isOriginalInstruction) {
|
||||
isOriginalInstruction = true;
|
||||
|
|
|
@ -53,18 +53,19 @@ namespace Iced.Intel.BlockEncoderInternal {
|
|||
|
||||
public override void Initialize(BlockEncoder blockEncoder) {
|
||||
targetInstr = blockEncoder.GetTarget(instruction.NearBranchTarget);
|
||||
TryOptimize();
|
||||
TryOptimize(0);
|
||||
}
|
||||
|
||||
public override bool Optimize() => TryOptimize();
|
||||
public override bool Optimize(ulong gained) => TryOptimize(gained);
|
||||
|
||||
bool TryOptimize() {
|
||||
bool TryOptimize(ulong gained) {
|
||||
if (instrKind == InstrKind.Unchanged || instrKind == InstrKind.Rel16)
|
||||
return false;
|
||||
|
||||
var targetAddress = targetInstr.GetAddress();
|
||||
var nextRip = IP + shortInstructionSize;
|
||||
long diff = (long)(targetAddress - nextRip);
|
||||
diff = CorrectDiff(targetInstr.IsInBlock(Block), diff, gained);
|
||||
if (short.MinValue <= diff && diff <= short.MaxValue) {
|
||||
instrKind = InstrKind.Rel16;
|
||||
Size = shortInstructionSize;
|
||||
|
|
Loading…
Reference in New Issue