From db7e28c220a40160d3f2e256a46c8d962104748b Mon Sep 17 00:00:00 2001 From: Sam Byass Date: Mon, 2 Sep 2024 13:26:32 +0100 Subject: [PATCH] Fix post-indexed imm support for ldr and add test --- Disarm.Tests/LoadStoreTests.cs | 14 +++++++++++ Disarm/Arm64Instruction.cs | 11 +++++---- .../InternalDisassembly/Arm64LoadsStores.cs | 24 +++++++++---------- .../InternalDisassembly/MemoryAccessMode.cs | 8 ------- Disarm/MemoryIndexMode.cs | 8 +++++++ 5 files changed, 41 insertions(+), 24 deletions(-) delete mode 100644 Disarm/InternalDisassembly/MemoryAccessMode.cs create mode 100644 Disarm/MemoryIndexMode.cs diff --git a/Disarm.Tests/LoadStoreTests.cs b/Disarm.Tests/LoadStoreTests.cs index 1b52961..6163134 100644 --- a/Disarm.Tests/LoadStoreTests.cs +++ b/Disarm.Tests/LoadStoreTests.cs @@ -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()); + } } diff --git a/Disarm/Arm64Instruction.cs b/Disarm/Arm64Instruction.cs index f208368..3ae04e4 100644 --- a/Disarm/Arm64Instruction.cs +++ b/Disarm/Arm64Instruction.cs @@ -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; @@ -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; } @@ -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 ? '-' : '+') @@ -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")); } } diff --git a/Disarm/InternalDisassembly/Arm64LoadsStores.cs b/Disarm/InternalDisassembly/Arm64LoadsStores.cs index c1892a4..6e40c88 100644 --- a/Disarm/InternalDisassembly/Arm64LoadsStores.cs +++ b/Disarm/InternalDisassembly/Arm64LoadsStores.cs @@ -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") }; } @@ -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 @@ -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, @@ -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 @@ -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, }; } @@ -491,7 +491,7 @@ private static Arm64Instruction LoadStoreRegFromImmUnsigned(uint instruction) Op0Reg = regT, MemBase = regN, MemOffset = immediate, - MemIsPreIndexed = false, + MemIndexMode = MemoryIndexMode.Offset, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, }; } @@ -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, @@ -716,7 +716,7 @@ private static Arm64Instruction LoadStoreRegisterFromImmUnscaled(uint instructio Op0Reg = regT, MemBase = regN, MemOffset = immediate, - MemIsPreIndexed = false, + MemIndexMode = MemoryIndexMode.Offset, MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister, }; } diff --git a/Disarm/InternalDisassembly/MemoryAccessMode.cs b/Disarm/InternalDisassembly/MemoryAccessMode.cs deleted file mode 100644 index ea1e5d3..0000000 --- a/Disarm/InternalDisassembly/MemoryAccessMode.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Disarm.InternalDisassembly; - -internal enum MemoryAccessMode -{ - PreIndex, - PostIndex, - Offset -} \ No newline at end of file diff --git a/Disarm/MemoryIndexMode.cs b/Disarm/MemoryIndexMode.cs new file mode 100644 index 0000000..dce126d --- /dev/null +++ b/Disarm/MemoryIndexMode.cs @@ -0,0 +1,8 @@ +namespace Disarm; + +public enum MemoryIndexMode +{ + PreIndex, + PostIndex, + Offset +} \ No newline at end of file