aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2024-03-16 21:10:00 +0000
committeriximeow <me@iximeow.net>2024-03-16 21:12:02 +0000
commitf551a6bed26e1c5e9938a1c45b47f1531ed64555 (patch)
treec35fe9b778c6dcb15a85340e2886eeba48c6286e
parent507a1c14b335a273304070289cb35a4bef7d1de3 (diff)
fix movi (immediate) to unpack immediate correctly
.... and add tests that exercise movi with an immediate other than 0
-rw-r--r--src/armv8/a64.rs12
-rw-r--r--tests/armv8/a64.rs2
2 files changed, 8 insertions, 6 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs
index 55fbbed..6d3b29f 100644
--- a/src/armv8/a64.rs
+++ b/src/armv8/a64.rs
@@ -3454,13 +3454,13 @@ impl Decoder<ARMv8> for InstDecoder {
} else /* if opc == Opcode::MOVI || opc == Opcode::MVNI */ {
if cmode == 0b1110 && op == 1 {
let abcdefgh = ((abc << 5) | defgh) as u64;
- let abcdefgh = (abcdefgh | (abcdefgh << 16)) & 0x000000ff000000ff;
- let abcdefgh = (abcdefgh | (abcdefgh << 8)) & 0x00ff00ff00ff00ff;
- let abcdefgh = (abcdefgh | (abcdefgh << 4)) & 0x0f0f0f0f0f0f0f0f;
- let abcdefgh = (abcdefgh | (abcdefgh << 2)) & 0x3333333333333333;
- let abcdefgh = (abcdefgh | (abcdefgh << 1)) & 0x5555555555555555;
+ let mut bytes = [0u8; 8];
+ for i in 0..8 {
+ let byte = ((abcdefgh as i8) << (7 - i)) >> 7;
+ bytes[i] = byte as u8;
+ }
- Operand::Imm64(abcdefgh | (abcdefgh << 1))
+ Operand::Imm64(u64::from_le_bytes(bytes))
} else {
let abcdefgh = ((abc << 5) | defgh) as u64;
let imm8 = abcdefgh;
diff --git a/tests/armv8/a64.rs b/tests/armv8/a64.rs
index 6af5291..3f8c4e4 100644
--- a/tests/armv8/a64.rs
+++ b/tests/armv8/a64.rs
@@ -4331,6 +4331,8 @@ fn test_movi() {
([0x01, 0xe4, 0x00, 0x6f], "movi v1.2d, #0x0"),
([0x02, 0xe4, 0x00, 0x6f], "movi v2.2d, #0x0"),
([0x03, 0xe4, 0x00, 0x2f], "movi d3, #0x0"),
+ ([0x23, 0xe4, 0x00, 0x2f], "movi d3, #0xff"),
+ ([0xa3, 0xe4, 0x00, 0x2f], "movi d3, #0xff00ff"),
];
let errs = run_tests(TESTS);