AArch32: vdup had destructive bitwise AND operations instead of OR and missing Thumb constructor constraints #6542
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
As part of a research project testing the accuracy of the SLEIGH specifications compared to real hardware, we observed an unexpected behaviour in the
vdup
instruction for both, AArch32 (ARM:LE:32:v8
) & Thumb (ARM:LE:32:v8T
).According to the manual, it duplicates a single element of a vector/general-purpose register into every element of the destination vector. However, we noticed the output was incorrect. This was due to destructive bitwise AND operations instead of OR & missing thumb constructor constraints causing a thumb instruction to execute like AArch32 instruction.
e.g, for AArch32 with,
Instruction:
0x600cf1f3, vdup.8 q8,d16[0x0]
initial_registers:
{ "q8": 0xdf60afddae76036c20f35d532cdd79eb }
We get:
Hardware:
{ "q8": 0xebebebebebebebebebebebebebebebeb }
Patched Spec:
{ "q8": 0xebebebebebebebebebebebebebebebeb }
Existing Spec:
{ "q8": 0x0 }
and,
Instruction:
0x900ba0be, vduplt.32 q8,r0
initial_registers:
{ "r0": 0x80, "NG": 0x1, "OV": 0x0 }
We get:
Hardware:
{ "q8": 80000000800000008000000080 }
Patched Spec:
{ "q8": 80000000800000008000000080 }
Existing Spec:
{ "q8": 0x0 }
e.g, for Thumb with,
Instruction:
0xa0ee900b, vdup.32 q8,r0
initial_registers:
{ "r0": 0xd1c8a9dc, "lr": 0xaa41700d }
We get:
Hardware:
{ "q8": 0xd1c8a9dcd1c8a9dcd1c8a9dcd1c8a9dc }
Patched Spec:
{ "q8": 0xd1c8a9dcd1c8a9dcd1c8a9dcd1c8a9dc }
Existing Spec (with AND/OR fix):
{ "q8": 0x700d700d700d700d700d700d700d700d }
Existing Spec:
{ "q8": 0x0 }
Note: The patched spec does introduce disassembly changes for the patched thumb variant. (eg, 0xa0ee900b is vdup.32 q8,r0 instead of vdup.32 q8,lr in Thumb.)