Skip to content

Commit 65fed55

Browse files
committed
Improve test coverage on Loads/stores, fix bugs found
1 parent f6bcba5 commit 65fed55

3 files changed

Lines changed: 303 additions & 42 deletions

File tree

‎Disarm.Tests/LoadStoreTests.cs‎

Lines changed: 256 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,268 @@ public void TestLoadRegisterLiteral()
153153
public void TestLoadStoredOrdered()
154154
{
155155
var insn = DisassembleAndCheckMnemonic(0xC8DFFE88, Arm64Mnemonic.LDAR);
156-
157-
Assert.Equal("0x00000000 LDAR X8, X20", insn.ToString());
156+
Assert.Equal("0x00000000 LDAR X8, [X20]", insn.ToString());
157+
158+
insn = DisassembleAndCheckMnemonic(0x08DFFC41, Arm64Mnemonic.LDARB);
159+
Assert.Equal("0x00000000 LDARB W1, [X2]", insn.ToString());
160+
161+
insn = DisassembleAndCheckMnemonic(0x089FFC83, Arm64Mnemonic.STLRB);
162+
Assert.Equal("0x00000000 STLRB W3, [X4]", insn.ToString());
163+
164+
insn = DisassembleAndCheckMnemonic(0x48DFFCC5, Arm64Mnemonic.LDARH);
165+
Assert.Equal("0x00000000 LDARH W5, [X6]", insn.ToString());
166+
167+
insn = DisassembleAndCheckMnemonic(0x489FFD07, Arm64Mnemonic.STLRH);
168+
Assert.Equal("0x00000000 STLRH W7, [X8]", insn.ToString());
169+
170+
insn = DisassembleAndCheckMnemonic(0x88DFFD49, Arm64Mnemonic.LDAR);
171+
Assert.Equal("0x00000000 LDAR W9, [X10]", insn.ToString());
172+
173+
insn = DisassembleAndCheckMnemonic(0x889FFD8B, Arm64Mnemonic.STLR);
174+
Assert.Equal("0x00000000 STLR W11, [X12]", insn.ToString());
175+
176+
insn = DisassembleAndCheckMnemonic(0xC89FFE0F, Arm64Mnemonic.STLR);
177+
Assert.Equal("0x00000000 STLR X15, [X16]", insn.ToString());
178+
179+
insn = DisassembleAndCheckMnemonic(0xC8DF7E51, Arm64Mnemonic.LDLAR);
180+
Assert.Equal("0x00000000 LDLAR X17, [X18]", insn.ToString());
181+
182+
insn = DisassembleAndCheckMnemonic(0x889F7E93, Arm64Mnemonic.STLLR);
183+
Assert.Equal("0x00000000 STLLR W19, [X20]", insn.ToString());
158184
}
159185

160186
[Fact]
161187
public void TestLoadRegExtended()
162188
{
163189
var insn = DisassembleAndCheckMnemonic(0xF8685928, Arm64Mnemonic.LDR);
164-
190+
165191
Assert.Equal("0x00000000 LDR X8, [X9, W8, UXTW #3]", insn.ToString());
166192
}
193+
194+
[Fact]
195+
public void TestVector128RegOffset()
196+
{
197+
//STR Q1, [X2, X3, LSL #4]
198+
var insn = DisassembleAndCheckMnemonic(0x3CA37841, Arm64Mnemonic.STR);
199+
200+
Assert.Equal(Arm64Register.V1, insn.Op0Reg);
201+
Assert.Equal(Arm64Register.X2, insn.MemBase);
202+
Assert.Equal(Arm64Register.X3, insn.MemAddendReg);
203+
Assert.Equal(Arm64ShiftType.LSL, insn.MemShiftType);
204+
Assert.Equal(4, insn.MemExtendOrShiftAmount);
205+
206+
Assert.Equal("0x00000000 STR V1, [X2, X3, LSL #4]", insn.ToString());
207+
208+
//LDR Q30, [X5, W6, UXTW #4]
209+
insn = DisassembleAndCheckMnemonic(0x3CE658BE, Arm64Mnemonic.LDR);
210+
211+
Assert.Equal(Arm64Register.V30, insn.Op0Reg);
212+
Assert.Equal(Arm64ExtendType.UXTW, insn.MemExtendType);
213+
Assert.Equal(4, insn.MemExtendOrShiftAmount);
214+
215+
Assert.Equal("0x00000000 LDR V30, [X5, W6, UXTW #4]", insn.ToString());
216+
}
217+
218+
[Fact]
219+
public void TestVectorRegOffset()
220+
{
221+
var insn = DisassembleAndCheckMnemonic(0x3C256883, Arm64Mnemonic.STR);
222+
Assert.Equal("0x00000000 STR B3, [X4, X5]", insn.ToString());
223+
224+
insn = DisassembleAndCheckMnemonic(0x7C25D883, Arm64Mnemonic.STR);
225+
Assert.Equal("0x00000000 STR H3, [X4, W5, SXTW #1]", insn.ToString());
226+
227+
insn = DisassembleAndCheckMnemonic(0xBC627829, Arm64Mnemonic.LDR);
228+
Assert.Equal("0x00000000 LDR S9, [X1, X2, LSL #2]", insn.ToString());
229+
230+
insn = DisassembleAndCheckMnemonic(0xFC645867, Arm64Mnemonic.LDR);
231+
Assert.Equal("0x00000000 LDR D7, [X3, W4, UXTW #3]", insn.ToString());
232+
}
233+
234+
[Fact]
235+
public void TestGpRegOffset()
236+
{
237+
var insn = DisassembleAndCheckMnemonic(0xF82CD96A, Arm64Mnemonic.STR);
238+
Assert.Equal("0x00000000 STR X10, [X11, W12, SXTW #3]", insn.ToString());
239+
240+
insn = DisassembleAndCheckMnemonic(0xB863C841, Arm64Mnemonic.LDR);
241+
Assert.Equal("0x00000000 LDR W1, [X2, W3, SXTW]", insn.ToString());
242+
243+
insn = DisassembleAndCheckMnemonic(0x38296907, Arm64Mnemonic.STRB);
244+
Assert.Equal("0x00000000 STRB W7, [X8, X9]", insn.ToString());
245+
246+
insn = DisassembleAndCheckMnemonic(0x38294907, Arm64Mnemonic.STRB);
247+
Assert.Equal("0x00000000 STRB W7, [X8, W9, UXTW]", insn.ToString());
248+
249+
//LSL #0 with the S flag set is encoded distinctly from a plain register offset
250+
insn = DisassembleAndCheckMnemonic(0x38697907, Arm64Mnemonic.LDRB);
251+
Assert.Equal("0x00000000 LDRB W7, [X8, X9, LSL #0]", insn.ToString());
252+
253+
insn = DisassembleAndCheckMnemonic(0x782778C5, Arm64Mnemonic.STRH);
254+
Assert.Equal("0x00000000 STRH W5, [X6, X7, LSL #1]", insn.ToString());
255+
256+
insn = DisassembleAndCheckMnemonic(0x7867D8C5, Arm64Mnemonic.LDRH);
257+
Assert.Equal("0x00000000 LDRH W5, [X6, W7, SXTW #1]", insn.ToString());
258+
259+
insn = DisassembleAndCheckMnemonic(0xF876FAB4, Arm64Mnemonic.LDR);
260+
Assert.Equal("0x00000000 LDR X20, [X21, X22, SXTX #3]", insn.ToString());
261+
262+
insn = DisassembleAndCheckMnemonic(0xF876EAB4, Arm64Mnemonic.LDR);
263+
Assert.Equal("0x00000000 LDR X20, [X21, X22, SXTX]", insn.ToString());
264+
}
265+
266+
[Fact]
267+
public void TestSignedLoadRegOffset()
268+
{
269+
var insn = DisassembleAndCheckMnemonic(0x38A36841, Arm64Mnemonic.LDRSB);
270+
Assert.Equal("0x00000000 LDRSB X1, [X2, X3]", insn.ToString());
271+
272+
insn = DisassembleAndCheckMnemonic(0x38E34841, Arm64Mnemonic.LDRSB);
273+
Assert.Equal("0x00000000 LDRSB W1, [X2, W3, UXTW]", insn.ToString());
274+
275+
insn = DisassembleAndCheckMnemonic(0x78AB7949, Arm64Mnemonic.LDRSH);
276+
Assert.Equal("0x00000000 LDRSH X9, [X10, X11, LSL #1]", insn.ToString());
277+
278+
insn = DisassembleAndCheckMnemonic(0x78EBD949, Arm64Mnemonic.LDRSH);
279+
Assert.Equal("0x00000000 LDRSH W9, [X10, W11, SXTW #1]", insn.ToString());
280+
281+
insn = DisassembleAndCheckMnemonic(0xB8A57883, Arm64Mnemonic.LDRSW);
282+
Assert.Equal("0x00000000 LDRSW X3, [X4, X5, LSL #2]", insn.ToString());
283+
284+
insn = DisassembleAndCheckMnemonic(0xB8A55883, Arm64Mnemonic.LDRSW);
285+
Assert.Equal("0x00000000 LDRSW X3, [X4, W5, UXTW #2]", insn.ToString());
286+
}
287+
288+
[Fact]
289+
public void TestSignedLoadFromImm()
290+
{
291+
var insn = DisassembleAndCheckMnemonic(0x39801441, Arm64Mnemonic.LDRSB);
292+
Assert.Equal("0x00000000 LDRSB X1, [X2 + 0x5]", insn.ToString());
293+
294+
insn = DisassembleAndCheckMnemonic(0x39C01441, Arm64Mnemonic.LDRSB);
295+
Assert.Equal("0x00000000 LDRSB W1, [X2 + 0x5]", insn.ToString());
296+
297+
insn = DisassembleAndCheckMnemonic(0x79800C83, Arm64Mnemonic.LDRSH);
298+
Assert.Equal("0x00000000 LDRSH X3, [X4 + 0x6]", insn.ToString());
299+
300+
insn = DisassembleAndCheckMnemonic(0x79C00C83, Arm64Mnemonic.LDRSH);
301+
Assert.Equal("0x00000000 LDRSH W3, [X4 + 0x6]", insn.ToString());
302+
303+
insn = DisassembleAndCheckMnemonic(0xB9804107, Arm64Mnemonic.LDRSW);
304+
Assert.Equal("0x00000000 LDRSW X7, [X8 + 0x40]", insn.ToString());
305+
306+
//LDRSB X5, [X6], #-16 (post-index)
307+
insn = DisassembleAndCheckMnemonic(0x389F04C5, Arm64Mnemonic.LDRSB);
308+
Assert.Equal("0x00000000 LDRSB X5, [X6], #-0x10", insn.ToString());
309+
310+
//LDRSB W5, [X6, #-16]! (pre-index)
311+
insn = DisassembleAndCheckMnemonic(0x38DF0CC5, Arm64Mnemonic.LDRSB);
312+
Assert.Equal("0x00000000 LDRSB W5, [X6 - 0x10]!", insn.ToString());
313+
}
314+
315+
[Fact]
316+
public void TestUnscaledLoadsStores()
317+
{
318+
var insn = DisassembleAndCheckMnemonic(0x3C1FD041, Arm64Mnemonic.STUR);
319+
Assert.Equal("0x00000000 STUR B1, [X2 - 0x3]", insn.ToString());
320+
321+
insn = DisassembleAndCheckMnemonic(0x7C4070A4, Arm64Mnemonic.LDUR);
322+
Assert.Equal("0x00000000 LDUR H4, [X5 + 0x7]", insn.ToString());
323+
324+
insn = DisassembleAndCheckMnemonic(0xBC1F70E6, Arm64Mnemonic.STUR);
325+
Assert.Equal("0x00000000 STUR S6, [X7 - 0x9]", insn.ToString());
326+
327+
insn = DisassembleAndCheckMnemonic(0xFC40B128, Arm64Mnemonic.LDUR);
328+
Assert.Equal("0x00000000 LDUR D8, [X9 + 0xB]", insn.ToString());
329+
330+
insn = DisassembleAndCheckMnemonic(0x3C9F316A, Arm64Mnemonic.STUR);
331+
Assert.Equal("0x00000000 STUR V10, [X11 - 0xD]", insn.ToString());
332+
333+
insn = DisassembleAndCheckMnemonic(0x3CC0F1AC, Arm64Mnemonic.LDUR);
334+
Assert.Equal("0x00000000 LDUR V12, [X13 + 0xF]", insn.ToString());
335+
336+
insn = DisassembleAndCheckMnemonic(0xB81EF1EE, Arm64Mnemonic.STUR);
337+
Assert.Equal("0x00000000 STUR W14, [X15 - 0x11]", insn.ToString());
338+
339+
insn = DisassembleAndCheckMnemonic(0xF8413230, Arm64Mnemonic.LDUR);
340+
Assert.Equal("0x00000000 LDUR X16, [X17 + 0x13]", insn.ToString());
341+
342+
insn = DisassembleAndCheckMnemonic(0x381EB272, Arm64Mnemonic.STURB);
343+
Assert.Equal("0x00000000 STURB W18, [X19 - 0x15]", insn.ToString());
344+
345+
insn = DisassembleAndCheckMnemonic(0x784172B4, Arm64Mnemonic.LDURH);
346+
Assert.Equal("0x00000000 LDURH W20, [X21 + 0x17]", insn.ToString());
347+
348+
insn = DisassembleAndCheckMnemonic(0x389E72F6, Arm64Mnemonic.LDURSB);
349+
Assert.Equal("0x00000000 LDURSB X22, [X23 - 0x19]", insn.ToString());
350+
351+
insn = DisassembleAndCheckMnemonic(0x38DE72F6, Arm64Mnemonic.LDURSB);
352+
Assert.Equal("0x00000000 LDURSB W22, [X23 - 0x19]", insn.ToString());
353+
354+
insn = DisassembleAndCheckMnemonic(0x7881B338, Arm64Mnemonic.LDURSH);
355+
Assert.Equal("0x00000000 LDURSH X24, [X25 + 0x1B]", insn.ToString());
356+
357+
insn = DisassembleAndCheckMnemonic(0x78C1B338, Arm64Mnemonic.LDURSH);
358+
Assert.Equal("0x00000000 LDURSH W24, [X25 + 0x1B]", insn.ToString());
359+
360+
insn = DisassembleAndCheckMnemonic(0xB89E337A, Arm64Mnemonic.LDURSW);
361+
Assert.Equal("0x00000000 LDURSW X26, [X27 - 0x1D]", insn.ToString());
362+
}
363+
364+
[Fact]
365+
public void TestLoadStorePairs()
366+
{
367+
var insn = DisassembleAndCheckMnemonic(0x29010861, Arm64Mnemonic.STP);
368+
Assert.Equal("0x00000000 STP W1, W2, [X3 + 0x8]", insn.ToString());
369+
370+
insn = DisassembleAndCheckMnemonic(0xA97F14C4, Arm64Mnemonic.LDP);
371+
Assert.Equal("0x00000000 LDP X4, X5, [X6 - 0x10]", insn.ToString());
372+
373+
insn = DisassembleAndCheckMnemonic(0x2D01A127, Arm64Mnemonic.STP);
374+
Assert.Equal("0x00000000 STP S7, S8, [X9 + 0xC]", insn.ToString());
375+
376+
insn = DisassembleAndCheckMnemonic(0x6D7EAD8A, Arm64Mnemonic.LDP);
377+
Assert.Equal("0x00000000 LDP D10, D11, [X12 - 0x18]", insn.ToString());
378+
379+
insn = DisassembleAndCheckMnemonic(0xAD0139ED, Arm64Mnemonic.STP);
380+
Assert.Equal("0x00000000 STP V13, V14, [X15 + 0x20]", insn.ToString());
381+
382+
insn = DisassembleAndCheckMnemonic(0x697FC650, Arm64Mnemonic.LDPSW);
383+
Assert.Equal("0x00000000 LDPSW X16, X17, [X18 - 0x4]", insn.ToString());
384+
385+
insn = DisassembleAndCheckMnemonic(0xA9C152B3, Arm64Mnemonic.LDP);
386+
Assert.Equal("0x00000000 LDP X19, X20, [X21 + 0x10]!", insn.ToString());
387+
388+
insn = DisassembleAndCheckMnemonic(0xA8BE5F16, Arm64Mnemonic.STP);
389+
Assert.Equal("0x00000000 STP X22, X23, [X24], #-0x20", insn.ToString());
390+
391+
insn = DisassembleAndCheckMnemonic(0x69008861, Arm64Mnemonic.STGP);
392+
Assert.Equal("0x00000000 STGP X1, X2, [X3 + 0x10]", insn.ToString());
393+
}
394+
395+
[Fact]
396+
public void TestLoadStoreNoAllocatePairs()
397+
{
398+
var insn = DisassembleAndCheckMnemonic(0x28010861, Arm64Mnemonic.STNP);
399+
Assert.Equal("0x00000000 STNP W1, W2, [X3 + 0x8]", insn.ToString());
400+
401+
insn = DisassembleAndCheckMnemonic(0xA87F14C4, Arm64Mnemonic.LDNP);
402+
Assert.Equal("0x00000000 LDNP X4, X5, [X6 - 0x10]", insn.ToString());
403+
404+
insn = DisassembleAndCheckMnemonic(0x2C01A127, Arm64Mnemonic.STNP);
405+
Assert.Equal("0x00000000 STNP S7, S8, [X9 + 0xC]", insn.ToString());
406+
407+
insn = DisassembleAndCheckMnemonic(0x6C7EAD8A, Arm64Mnemonic.LDNP);
408+
Assert.Equal("0x00000000 LDNP D10, D11, [X12 - 0x18]", insn.ToString());
409+
410+
insn = DisassembleAndCheckMnemonic(0xAC4139ED, Arm64Mnemonic.LDNP);
411+
Assert.Equal("0x00000000 LDNP V13, V14, [X15 + 0x20]", insn.ToString());
412+
}
413+
414+
[Fact]
415+
public void TestRegOffsetUndefinedOption()
416+
{
417+
//option<1> == 0 is unallocated for register offset loads/stores
418+
Assert.Throws<Arm64UndefinedInstructionException>(() => Disassembler.DisassembleSingleInstruction(0xB8638841));
419+
}
167420
}

‎Disarm/Arm64Instruction.cs‎

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,19 +219,24 @@ private void AppendMemory(StringBuilder sb)
219219
.Append(Math.Abs(MemOffset).ToString("X"));
220220
}
221221

222-
if(MemExtendType != Arm64ExtendType.NONE)
222+
if (MemExtendType != Arm64ExtendType.NONE)
223+
{
223224
sb.Append(", ").Append(MemExtendType.ToString());
224-
else if(MemShiftType != Arm64ShiftType.NONE)
225-
sb.Append(", ").Append(MemShiftType.ToString());
226-
227-
if(MemExtendOrShiftAmount != 0)
228-
sb.Append(" #").Append(MemExtendOrShiftAmount);
225+
226+
if(MemExtendOrShiftAmount != 0)
227+
sb.Append(" #").Append(MemExtendOrShiftAmount);
228+
}
229+
else if (MemShiftType != Arm64ShiftType.NONE)
230+
{
231+
//explicit shifts always print their amount, an lsl #0 is a distinct encoding from no shift at all
232+
sb.Append(", ").Append(MemShiftType.ToString()).Append(" #").Append(MemExtendOrShiftAmount);
233+
}
229234

230235
sb.Append(']');
231236

232237
if (MemIndexMode == Arm64MemoryIndexMode.PreIndex)
233238
sb.Append('!');
234239
else if(MemIndexMode == Arm64MemoryIndexMode.PostIndex && MemOffset != 0)
235-
sb.Append(", #0x").Append(MemOffset.ToString("X"));
240+
sb.Append(", #").Append(MemOffset < 0 ? "-0x" : "0x").Append(Math.Abs(MemOffset).ToString("X"));
236241
}
237242
}

0 commit comments

Comments
 (0)