Skip to content

Commit

Permalink
More tests for #22 - SIMD and load/store mem tags
Browse files Browse the repository at this point in the history
  • Loading branch information
SamboyCoding committed Sep 10, 2024
1 parent 71c0f3e commit 9a0fc56
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 192 deletions.
40 changes: 39 additions & 1 deletion Disarm.Tests/LoadStoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,46 @@ public void LoadRegFromMemImmPostIndex()
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(Arm64MemoryIndexMode.PostIndex, instruction.MemIndexMode);

Assert.Equal("0x00000000 LDR X8, [X20], #0x20", instruction.ToString());
}

[Fact]
public void TestLoadStoreMemoryTags()
{
var insn = DisassembleAndCheckMnemonic(0xD920341F, Arm64Mnemonic.STG);

Assert.Equal(Arm64OperandKind.Register, insn.Op0Kind);
Assert.Equal(Arm64OperandKind.Memory, insn.Op1Kind);

Assert.Equal(Arm64Register.X0, insn.Op0Reg);
Assert.Equal(Arm64Register.X31, insn.MemBase);
Assert.Equal(0x30, insn.MemOffset);

Assert.Equal(Arm64MemoryIndexMode.PostIndex, insn.MemIndexMode);

Assert.Equal("0x00000000 STG X0, [X31], #0x30", insn.ToString());

insn = DisassembleAndCheckMnemonic(0xD920041F, Arm64Mnemonic.STZGM);
Assert.Equal("0x00000000 STZGM X0, X31", insn.ToString());

insn = DisassembleAndCheckMnemonic(0xD960341F, Arm64Mnemonic.STZG);
Assert.Equal("0x00000000 STZG X0, [X31], #0x30", insn.ToString());

insn = DisassembleAndCheckMnemonic(0xD960001F, Arm64Mnemonic.LDG);
Assert.Equal("0x00000000 LDG X0, X31", insn.ToString());

insn = DisassembleAndCheckMnemonic(0xD9A0001F, Arm64Mnemonic.STGM);
Assert.Equal("0x00000000 STGM X0, X31", insn.ToString());

insn = DisassembleAndCheckMnemonic(0xD9A0341F, Arm64Mnemonic.ST2G);
Assert.Equal("0x00000000 ST2G X0, [X31], #0x30", insn.ToString());

insn = DisassembleAndCheckMnemonic(0xD9E0341F, Arm64Mnemonic.STZ2G);
Assert.Equal("0x00000000 STZ2G X0, [X31], #0x30", insn.ToString());

insn = DisassembleAndCheckMnemonic(0xD9E0001F, Arm64Mnemonic.LDGM);
Assert.Equal("0x00000000 LDGM X0, X31", insn.ToString());
}
}
16 changes: 16 additions & 0 deletions Disarm.Tests/SimdTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,20 @@ public void TestCryptoThreeRegSha()

Assert.Equal("0x00000000 SHA256SU1 V0.4S, V1.4S, V2.4S", insn.ToString());
}

[Fact]
public void TestAdvancedSimdThreeSame()
{
var insn = DisassembleAndCheckMnemonic(0x0EA21C20, Arm64Mnemonic.ORR);

Assert.Equal(Arm64OperandKind.Register, insn.Op0Kind);
Assert.Equal(Arm64OperandKind.Register, insn.Op1Kind);
Assert.Equal(Arm64OperandKind.Register, insn.Op2Kind);

Assert.Equal(Arm64Register.V0, insn.Op0Reg);
Assert.Equal(Arm64Register.V1, insn.Op1Reg);
Assert.Equal(Arm64Register.V2, insn.Op2Reg);

Assert.Equal("0x00000000 ORR V0.8B, V1.8B, V2.8B", insn.ToString());
}
}
12 changes: 6 additions & 6 deletions Disarm/Arm64Instruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public Arm64Instruction()
Op4Arrangement = Arm64ArrangementSpecifier.None;
MemBase = Arm64Register.INVALID;
MemAddendReg = Arm64Register.INVALID;
MemIndexMode = MemoryIndexMode.Offset;
MemIndexMode = Arm64MemoryIndexMode.Offset;
MemOffset = 0;
MemExtendOrShiftAmount = 0;
Op0VectorElement = default;
Expand Down Expand Up @@ -106,8 +106,8 @@ public Arm64Instruction()

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

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

sb.Append(']');

if (MemIndexMode == MemoryIndexMode.PreIndex)
if (MemIndexMode == Arm64MemoryIndexMode.PreIndex)
sb.Append('!');
else if(MemIndexMode == MemoryIndexMode.PostIndex && MemOffset != 0)
else if(MemIndexMode == Arm64MemoryIndexMode.PostIndex && MemOffset != 0)
sb.Append(", #0x").Append(MemOffset.ToString("X"));
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Disarm;

public enum MemoryIndexMode
public enum Arm64MemoryIndexMode
{
PreIndex,
PostIndex,
Expand Down
5 changes: 4 additions & 1 deletion Disarm/InternalDisassembly/Arm64CommonUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ namespace Disarm.InternalDisassembly;
/// </summary>
internal static class Arm64CommonUtils
{
public const int LOG2_TAG_GRANULE = 4;
public const int TAG_GRANULE = 1 << LOG2_TAG_GRANULE;

/// <summary>
/// Extends the given bit array to the given length by continuously adding the leftmost bit to the left until the length is reached.
/// </summary>
Expand All @@ -20,7 +23,7 @@ private static BitArray SignExtend(BitArray value, int size)

var startOffset = size - value.Length;
//Copy bottom n bits of value to result
for (var i = startOffset; i < size - 1; i++)
for (var i = startOffset; i < size; i++)
{
result[i] = value[i - startOffset];
}
Expand Down
83 changes: 43 additions & 40 deletions Disarm/InternalDisassembly/Arm64LoadsStores.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,13 @@ private static Arm64Instruction DisassembleAdvancedLoadStore(uint instruction)
private static Arm64Instruction DisassembleLoadStoreMemoryTags(uint instruction)
{
var opc = (instruction >> 22) & 0b11; // Bits 22-23
var offset = Arm64CommonUtils.SignExtend((instruction >> 12) & 0b1_1111_1111, 9, 64) << (1 << 4); // Bits 12-20
var imm9 = (long) (instruction >> 12) & 0b1_1111_1111; // Bits 12-20
var op2 = (instruction >> 10) & 0b11; // Bits 10-11
var rn = (int)(instruction >> 5) & 0b1_1111; // Bits 5-9
var rt = (int)instruction & 0b1_1111; // Bits 0-5

imm9 = Arm64CommonUtils.SignExtend(imm9, 9, 64);
var offset = imm9 << Arm64CommonUtils.LOG2_TAG_GRANULE;

return opc switch
{
Expand All @@ -82,16 +85,16 @@ private static Arm64Instruction DisassembleLoadStoreMemoryTags(uint instruction)
MnemonicCategory = Arm64MnemonicCategory.MemoryTagging,
MemIndexMode = op2 switch
{
0b01 => MemoryIndexMode.PostIndex,
0b10 => MemoryIndexMode.Offset,
0b11 => MemoryIndexMode.PreIndex,
0b01 => Arm64MemoryIndexMode.PostIndex,
0b10 => Arm64MemoryIndexMode.Offset,
0b11 => Arm64MemoryIndexMode.PreIndex,
_ => throw new Arm64UndefinedInstructionException("Bad memory index mode")
},
MemOffset = offset,
Op0Kind = Arm64OperandKind.Register,
Op1Kind = Arm64OperandKind.Register,
Op1Kind = Arm64OperandKind.Memory,
Op0Reg = Arm64Register.X0 + rn,
Op1Reg = Arm64Register.X0 + rt
MemBase = Arm64Register.X0 + rt
},
0b00 when offset == 0 => new()
{
Expand All @@ -106,7 +109,7 @@ private static Arm64Instruction DisassembleLoadStoreMemoryTags(uint instruction)
{
Mnemonic = Arm64Mnemonic.LDG,
MnemonicCategory = Arm64MnemonicCategory.MemoryTagging,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MemOffset = offset,
Op0Kind = Arm64OperandKind.Register,
Op1Kind = Arm64OperandKind.Register,
Expand All @@ -119,33 +122,33 @@ private static Arm64Instruction DisassembleLoadStoreMemoryTags(uint instruction)
MnemonicCategory = Arm64MnemonicCategory.MemoryTagging,
MemIndexMode = op2 switch
{
0b01 => MemoryIndexMode.PostIndex,
0b10 => MemoryIndexMode.Offset,
0b11 => MemoryIndexMode.PreIndex,
0b01 => Arm64MemoryIndexMode.PostIndex,
0b10 => Arm64MemoryIndexMode.Offset,
0b11 => Arm64MemoryIndexMode.PreIndex,
_ => throw new Arm64UndefinedInstructionException("Bad memory index mode")
},
MemOffset = offset,
Op0Kind = Arm64OperandKind.Register,
Op1Kind = Arm64OperandKind.Register,
Op1Kind = Arm64OperandKind.Memory,
Op0Reg = Arm64Register.X0 + rn,
Op1Reg = Arm64Register.X0 + rt
MemBase = Arm64Register.X0 + rt
},
0b10 when offset != 0 => new()
{
Mnemonic = Arm64Mnemonic.ST2G,
MnemonicCategory = Arm64MnemonicCategory.MemoryTagging,
MemIndexMode = op2 switch
{
0b01 => MemoryIndexMode.PostIndex,
0b10 => MemoryIndexMode.Offset,
0b11 => MemoryIndexMode.PreIndex,
0b01 => Arm64MemoryIndexMode.PostIndex,
0b10 => Arm64MemoryIndexMode.Offset,
0b11 => Arm64MemoryIndexMode.PreIndex,
_ => throw new Arm64UndefinedInstructionException("Bad memory index mode")
},
MemOffset = offset,
Op0Kind = Arm64OperandKind.Register,
Op1Kind = Arm64OperandKind.Register,
Op1Kind = Arm64OperandKind.Memory,
Op0Reg = Arm64Register.X0 + rn,
Op1Reg = Arm64Register.X0 + rt
MemBase = Arm64Register.X0 + rt
},
0b10 when offset == 0 && op2 == 0 => new()
{
Expand All @@ -162,16 +165,16 @@ private static Arm64Instruction DisassembleLoadStoreMemoryTags(uint instruction)
MnemonicCategory = Arm64MnemonicCategory.MemoryTagging,
MemIndexMode = op2 switch
{
0b01 => MemoryIndexMode.PostIndex,
0b10 => MemoryIndexMode.Offset,
0b11 => MemoryIndexMode.PreIndex,
0b01 => Arm64MemoryIndexMode.PostIndex,
0b10 => Arm64MemoryIndexMode.Offset,
0b11 => Arm64MemoryIndexMode.PreIndex,
_ => throw new Arm64UndefinedInstructionException("Bad memory index mode")
},
MemOffset = offset,
Op0Kind = Arm64OperandKind.Register,
Op1Kind = Arm64OperandKind.Register,
Op1Kind = Arm64OperandKind.Memory,
Op0Reg = Arm64Register.X0 + rn,
Op1Reg = Arm64Register.X0 + rt
MemBase = Arm64Register.X0 + rt
},
0b11 when offset == 0 && op2 == 0 => new()
{
Expand Down Expand Up @@ -336,9 +339,9 @@ private static Arm64Instruction DisassembleLoadStorePairs(uint instruction)
return op2 switch
{
0b00 => LoadStoreNoAllocatePairs(instruction), //load/store no-allocate pairs
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)
0b01 => LoadStoreRegisterPair(instruction, Arm64MemoryIndexMode.PostIndex), //load/store register pair (post-indexed)
0b10 => LoadStoreRegisterPair(instruction, Arm64MemoryIndexMode.Offset), //load/store register pair (offset)
0b11 => LoadStoreRegisterPair(instruction, Arm64MemoryIndexMode.PreIndex), //load/store register pair (pre-indexed)
_ => throw new("Loads/store pairs: Impossible op2 value")
};
}
Expand Down Expand Up @@ -371,14 +374,14 @@ private static Arm64Instruction DisassembleLoadStoreRegisterOrAtomic(uint instru
return op4 switch
{
0b00 => LoadStoreRegisterFromImmUnscaled(instruction), //Load/store (reg), (unscaled immediate)
0b01 => LoadStoreRegisterFromImm(instruction, MemoryIndexMode.PostIndex), //Load/store (reg), (post-indexed immediate)
0b01 => LoadStoreRegisterFromImm(instruction, Arm64MemoryIndexMode.PostIndex), //Load/store (reg), (post-indexed immediate)
0b10 => LoadStoreRegisterUnprivileged(instruction), //Load/store (reg), (unprivileged)
0b11 => LoadStoreRegisterFromImm(instruction, MemoryIndexMode.PreIndex), //Load/Store (reg), (pre-indexed immediate)
0b11 => LoadStoreRegisterFromImm(instruction, Arm64MemoryIndexMode.PreIndex), //Load/Store (reg), (pre-indexed immediate)
_ => throw new("Impossible op4"),
};
}

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

Expand Down Expand Up @@ -492,7 +495,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction)
{
Mnemonic = Arm64Mnemonic.STNP,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MemOffset = offset,
MemBase = (opc == 0b00 ? Arm64Register.W0 : Arm64Register.X0) + rn,
Op0Kind = Arm64OperandKind.Register,
Expand All @@ -505,7 +508,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction)
{
Mnemonic = Arm64Mnemonic.LDNP,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MemOffset = offset,
MemBase = (opc == 0b00 ? Arm64Register.W0 : Arm64Register.X0) + rn,
Op0Kind = Arm64OperandKind.Register,
Expand All @@ -518,7 +521,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction)
{
Mnemonic = Arm64Mnemonic.STNP,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MemOffset = offset,
MemBase = Arm64Register.X0 + rn,
Op0Kind = Arm64OperandKind.Register,
Expand All @@ -531,7 +534,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction)
{
Mnemonic = Arm64Mnemonic.STNP,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MemOffset = offset,
MemBase = Arm64Register.X0 + rn,
Op0Kind = Arm64OperandKind.Register,
Expand All @@ -544,7 +547,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction)
{
Mnemonic = Arm64Mnemonic.STNP,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MemOffset = offset,
MemBase = Arm64Register.X0 + rn,
Op0Kind = Arm64OperandKind.Register,
Expand All @@ -557,7 +560,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction)
{
Mnemonic = Arm64Mnemonic.LDNP,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MemOffset = offset,
MemBase = Arm64Register.X0 + rn,
Op0Kind = Arm64OperandKind.Register,
Expand All @@ -570,7 +573,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction)
{
Mnemonic = Arm64Mnemonic.LDNP,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MemOffset = offset,
MemBase = Arm64Register.X0 + rn,
Op0Kind = Arm64OperandKind.Register,
Expand All @@ -583,7 +586,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction)
{
Mnemonic = Arm64Mnemonic.LDNP,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MemOffset = offset,
MemBase = Arm64Register.X0 + rn,
Op0Kind = Arm64OperandKind.Register,
Expand All @@ -596,7 +599,7 @@ private static Arm64Instruction LoadStoreNoAllocatePairs(uint instruction)
};
}

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

Expand Down Expand Up @@ -761,7 +764,7 @@ private static Arm64Instruction LoadStoreRegFromImmUnsigned(uint instruction)
Op0Reg = regT,
MemBase = regN,
MemOffset = immediate,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
};
}
Expand Down Expand Up @@ -880,7 +883,7 @@ private static Arm64Instruction LoadStoreRegisterFromRegisterOffset(uint instruc
Op0Reg = baseReg + rt,
MemBase = Arm64Register.X0 + rn,
MemAddendReg = secondRegBase + rm,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MemExtendType = isShiftedRegister ? Arm64ExtendType.NONE : extendKind,
MemShiftType = isShiftedRegister ? Arm64ShiftType.LSL : Arm64ShiftType.NONE,
MemExtendOrShiftAmount = shiftAmount,
Expand Down Expand Up @@ -986,7 +989,7 @@ private static Arm64Instruction LoadStoreRegisterFromImmUnscaled(uint instructio
Op0Reg = regT,
MemBase = regN,
MemOffset = immediate,
MemIndexMode = MemoryIndexMode.Offset,
MemIndexMode = Arm64MemoryIndexMode.Offset,
MnemonicCategory = Arm64MnemonicCategory.MemoryToOrFromRegister,
};
}
Expand Down
Loading

0 comments on commit 9a0fc56

Please sign in to comment.