This commit is contained in:
wtfsck 2021-05-10 18:44:14 +02:00
parent 9fa4b84e10
commit 9cd6bb89aa
9 changed files with 44 additions and 22 deletions

View File

@ -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";

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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;