aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-12-27 19:24:02 -0800
committeriximeow <me@iximeow.net>2021-12-27 19:24:02 -0800
commit1e26b5a52a7150565c1cfe7b92866a6f13c714fb (patch)
tree75c58f6c07a25f1bfbdc4f88fd60363ea15d23ee
parent4e28a1078e93c15bc8b9076504f2eba4656ccf76 (diff)
movi/mvni scalar/vector
-rw-r--r--src/armv8/a64.rs56
-rw-r--r--test/armv8/a64.rs20
2 files changed, 60 insertions, 16 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs
index 408bc13..8ab4542 100644
--- a/src/armv8/a64.rs
+++ b/src/armv8/a64.rs
@@ -2723,7 +2723,7 @@ impl Decoder<ARMv8> for InstDecoder {
Ok((Opcode::MVNI, SIMDSizeCode::H)), Ok((Opcode::BIC, SIMDSizeCode::H)),
Ok((Opcode::MVNI, SIMDSizeCode::H)), Ok((Opcode::BIC, SIMDSizeCode::H)),
Ok((Opcode::MVNI, SIMDSizeCode::S)), Ok((Opcode::BIC, SIMDSizeCode::S)),
- Ok((Opcode::MVNI, SIMDSizeCode::B)), Ok((Opcode::FMOV, SIMDSizeCode::B)),
+ Ok((Opcode::MOVI, SIMDSizeCode::D)), Ok((Opcode::FMOV, SIMDSizeCode::B)),
];
if cmode == 0b1111 && op == 1 && Q == 0 {
@@ -2739,25 +2739,49 @@ impl Decoder<ARMv8> for InstDecoder {
} else if opc == Opcode::ORR || opc == Opcode::BIC {
// abcdefgh
let abcdefgh = (abc << 5) | defgh;
- abcdefgh as u64
+ Operand::Imm64(abcdefgh as u64)
} else /* if opc == Opcode::MOVI || opc == Opcode::MVNI */ {
- 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;
-
- abcdefgh | (abcdefgh << 1)
+ if cmode == 0b1110 {
+ 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;
+
+ Operand::Imm64(abcdefgh | (abcdefgh << 1))
+ } else {
+ let abcdefgh = ((abc << 5) | defgh) as u64;
+ let imm8 = abcdefgh;
+ let amount = match size {
+ SIMDSizeCode::H => {
+ (cmode & 0b0010) << 1
+ }
+ SIMDSizeCode::S => {
+ (cmode & 0b0110) << 2
+ }
+ _ => 0,
+ };
+ Operand::ImmShift(imm8 as u16, amount as u8)
+ }
};
inst.opcode = opc;
- inst.operands = [
- Operand::SIMDRegisterElements(datasize, Rd as u16, size),
- Operand::Imm64(imm),
- Operand::Nothing,
- Operand::Nothing,
- ];
+ if Q == 0 && op == 1 && cmode == 0b1110 && o2 == 0 {
+ inst.operands = [
+ Operand::SIMDRegister(size, Rd as u16),
+ imm,
+ Operand::Nothing,
+ Operand::Nothing,
+ ];
+ } else {
+ inst.operands = [
+ Operand::SIMDRegisterElements(datasize, Rd as u16, size),
+ imm,
+ Operand::Nothing,
+ Operand::Nothing,
+ ];
+ }
}
} else {
// `Advanced SIMD vector x indexed element`
diff --git a/test/armv8/a64.rs b/test/armv8/a64.rs
index 4ee0bff..ed2b49d 100644
--- a/test/armv8/a64.rs
+++ b/test/armv8/a64.rs
@@ -4319,3 +4319,23 @@ fn test_simd_abs() {
assert!(errs.is_empty());
}
+
+#[test]
+fn test_movi() {
+ const TESTS: &[([u8; 4], &'static str)] = &[
+ ([0x1c, 0x04, 0x00, 0x0f], "movi v28.2s, 0x0"),
+ ([0x28, 0x04, 0x00, 0x0f], "movi v8.2s, 0x1"),
+ ([0x80, 0x66, 0x01, 0x0f], "movi v0.2s, 0x34, lsl 24"),
+ ([0x17, 0x64, 0x04, 0x0f], "movi v23.2s, 0x80, lsl 24"),
+ ([0x01, 0xe4, 0x00, 0x6f], "movi v1.2d, 0x0"),
+ ([0x02, 0xe4, 0x00, 0x6f], "movi v2.2d, 0x0"),
+ ([0x03, 0xe4, 0x00, 0x2f], "movi d3, 0x0"),
+ ];
+ let errs = run_tests(TESTS);
+
+ for err in errs.iter() {
+ println!("{}", err);
+ }
+
+ assert!(errs.is_empty());
+}