Skip to content

Commit

Permalink
Fix post-indexed imm support for ldr and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
SamboyCoding committed Sep 2, 2024
1 parent 1e282d6 commit db7e28c
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 24 deletions.
14 changes: 14 additions & 0 deletions Disarm.Tests/LoadStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,18 @@ public void LoadStoreRegFromRegOffset()

Assert.Equal("0x00000000 LDR W9, [X10, X9, LSL #2]", instruction.ToString());
}

[Fact]
public void LoadRegFromMemImmPostIndex()
{
var instruction = DisassembleAndCheckMnemonic(0xF8420688, Arm64Mnemonic.LDR);

Assert.Equal(Arm64Register.X8, instruction.Op0Reg);
Assert.Equal(Arm64OperandKind.Memory, instruction.Op1Kind);
Assert.Equal(Arm64Register.X20, instruction.MemBase);
Assert.Equal(0x20, instruction.MemOffset);
Assert.Equal(MemoryIndexMode.PostIndex, instruction.MemIndexMode);

Assert.Equal("0x00000000 LDR X8, [X20], #0x20", instruction.ToString());
}
}
11 changes: 7 additions & 4 deletions Disarm/Arm64Instruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public Arm64Instruction()
Op3Arrangement = Arm64ArrangementSpecifier.None;
MemBase = Arm64Register.INVALID;
MemAddendReg = Arm64Register.INVALID;
MemIsPreIndexed = false;
MemIndexMode = MemoryIndexMode.Offset;
MemOffset = 0;
MemExtendOrShiftAmount = 0;
Op0VectorElement = default;
Expand Down Expand Up @@ -92,7 +92,8 @@ public Arm64Instruction()

public Arm64Register MemBase { get; internal set; }
public Arm64Register MemAddendReg { get; internal set; }
public bool MemIsPreIndexed { get; internal set; }
public MemoryIndexMode MemIndexMode { get; internal set; }
public bool MemIsPreIndexed => MemIndexMode == MemoryIndexMode.PreIndex;
public long MemOffset { get; internal set; }
public Arm64ExtendType MemExtendType { get; internal set; }
public Arm64ShiftType MemShiftType { get; internal set; }
Expand Down Expand Up @@ -185,7 +186,7 @@ private void AppendMemory(StringBuilder sb)
if(MemAddendReg != Arm64Register.INVALID)
sb.Append(", ").Append(MemAddendReg.ToString());

if (MemOffset != 0)
if (MemOffset != 0 && MemIndexMode != MemoryIndexMode.PostIndex)
{
sb.Append(' ')
.Append(MemOffset < 0 ? '-' : '+')
Expand All @@ -203,7 +204,9 @@ private void AppendMemory(StringBuilder sb)

sb.Append(']');

if (MemIsPreIndexed)
if (MemIndexMode == MemoryIndexMode.PreIndex)
sb.Append('!');
else if(MemIndexMode == MemoryIndexMode.PostIndex && MemOffset != 0)
sb.Append(", #0x").Append(MemOffset.ToString("X"));
}
}
24 changes: 12 additions & 12 deletions Disarm/InternalDisassembly/Arm64LoadsStores.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@ private static Arm64Instruction DisassembleLoadStorePairs(uint instruction)
return op2 switch
{
0b00 => LoadStoreNoAllocatePairs(instruction), //load/store no-allocate pairs
0b01 => LoadStoreRegisterPair(instruction, MemoryAccessMode.PostIndex), //load/store register pair (post-indexed)
0b10 => LoadStoreRegisterPair(instruction, MemoryAccessMode.Offset), //load/store register pair (offset)
0b11 => LoadStoreRegisterPair(instruction, MemoryAccessMode.PreIndex), //load/store register pair (pre-indexed)
0b01 => LoadStoreRegisterPair(instruction, MemoryIndexMode.PostIndex), //load/store register pair (post-indexed)
0b10 => LoadStoreRegisterPair(instruction, MemoryIndexMode.Offset), //load/store register pair (offset)
0b11 => LoadStoreRegisterPair(instruction, MemoryIndexMode.PreIndex), //load/store register pair (pre-indexed)
_ => throw new("Loads/store pairs: Impossible op2 value")
};
}
Expand Down Expand Up @@ -215,14 +215,14 @@ private static Arm64Instruction DisassembleLoadStoreRegisterOrAtomic(uint instru
return op4 switch
{
0b00 => LoadStoreRegisterFromImmUnscaled(instruction), //Load/store (reg), (unscaled immediate)
0b01 => LoadStoreRegisterFromImm(instruction, MemoryAccessMode.PostIndex), //Load/store (reg), (post-indexed immediate)
0b01 => LoadStoreRegisterFromImm(instruction, MemoryIndexMode.PostIndex), //Load/store (reg), (post-indexed immediate)
0b10 => LoadStoreRegisterUnprivileged(instruction), //Load/store (reg), (unprivileged)
0b11 => LoadStoreRegisterFromImm(instruction, MemoryAccessMode.PreIndex), //Load/Store (reg), (pre-indexed immediate)
0b11 => LoadStoreRegisterFromImm(instruction, MemoryIndexMode.PreIndex), //Load/Store (reg), (pre-indexed immediate)
_ => throw new("Impossible op4"),
};
}

private static Arm64Instruction LoadStoreRegisterFromImm(uint instruction, MemoryAccessMode memoryAccessMode)
private static Arm64Instruction LoadStoreRegisterFromImm(uint instruction, MemoryIndexMode memoryIndexMode)
{
// Load/store immediate pre-indexed

Expand Down Expand Up @@ -309,7 +309,7 @@ private static Arm64Instruction LoadStoreRegisterFromImm(uint instruction, Memor
Mnemonic = mnemonic,
Op0Kind = Arm64OperandKind.Register,
Op1Kind = Arm64OperandKind.Memory,
MemIsPreIndexed = memoryAccessMode == MemoryAccessMode.PreIndex,
MemIndexMode = memoryIndexMode,
Op0Reg = regT,
MemBase = regN,
MemOffset = offset,
Expand All @@ -326,7 +326,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction)
};
}

private static Arm64Instruction LoadStoreRegisterPair(uint instruction, MemoryAccessMode mode)
private static Arm64Instruction LoadStoreRegisterPair(uint instruction, MemoryIndexMode mode)
{
//Page C4-559

Expand Down Expand Up @@ -395,7 +395,7 @@ private static Arm64Instruction LoadStoreRegisterPair(uint instruction, MemoryAc
Op1Reg = reg2,
MemBase = regN,
MemOffset = realImm7 * dataSizeBytes,
MemIsPreIndexed = mode == MemoryAccessMode.PreIndex,
MemIndexMode = mode,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
};
}
Expand Down Expand Up @@ -491,7 +491,7 @@ private static Arm64Instruction LoadStoreRegFromImmUnsigned(uint instruction)
Op0Reg = regT,
MemBase = regN,
MemOffset = immediate,
MemIsPreIndexed = false,
MemIndexMode = MemoryIndexMode.Offset,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
};
}
Expand Down Expand Up @@ -610,7 +610,7 @@ private static Arm64Instruction LoadStoreRegisterFromRegisterOffset(uint instruc
Op0Reg = baseReg + rt,
MemBase = Arm64Register.X0 + rn,
MemAddendReg = secondRegBase + rm,
MemIsPreIndexed = false,
MemIndexMode = MemoryIndexMode.Offset,
MemExtendType = isShiftedRegister ? Arm64ExtendType.NONE : extendKind,
MemShiftType = isShiftedRegister ? Arm64ShiftType.LSL : Arm64ShiftType.NONE,
MemExtendOrShiftAmount = shiftAmount,
Expand Down Expand Up @@ -716,7 +716,7 @@ private static Arm64Instruction LoadStoreRegisterFromImmUnscaled(uint instructio
Op0Reg = regT,
MemBase = regN,
MemOffset = immediate,
MemIsPreIndexed = false,
MemIndexMode = MemoryIndexMode.Offset,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
};
}
Expand Down
8 changes: 0 additions & 8 deletions Disarm/InternalDisassembly/MemoryAccessMode.cs

This file was deleted.

8 changes: 8 additions & 0 deletions Disarm/MemoryIndexMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Disarm;

public enum MemoryIndexMode
{
PreIndex,
PostIndex,
Offset
}

0 comments on commit db7e28c

Please sign in to comment.