aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoriximeow <me@iximeow.net>2021-10-26 00:17:49 -0700
committeriximeow <me@iximeow.net>2021-10-26 00:17:49 -0700
commitd1213dc138d58678a1b4a9fe09dcb2ecf2147c18 (patch)
treee2f29eca01ac6f330e72777f827f9019868d3f03 /src
parent21201e75aa67ec6e6326197e4f5ce660fbe1e88b (diff)
extr
Diffstat (limited to 'src')
-rw-r--r--src/armv8/a64.rs29
1 files changed, 26 insertions, 3 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs
index 662ea99..07397ef 100644
--- a/src/armv8/a64.rs
+++ b/src/armv8/a64.rs
@@ -468,6 +468,11 @@ impl Display for Instruction {
write!(fmt, "adrp")?;
},
Opcode::EXTR => {
+ if let (Operand::Register(_, Rn), Operand::Register(_, Rm)) = (self.operands[1], self.operands[2]) {
+ if Rn == Rm {
+ return write!(fmt, "ror {}, {}, {}", self.operands[0], self.operands[2], self.operands[3]);
+ }
+ }
write!(fmt, "extr")?;
},
Opcode::LDP => {
@@ -2248,23 +2253,41 @@ impl Decoder<ARMv8> for InstDecoder {
let sf_op21 = word >> 29;
- if sf_op21 == 0b000 {
+ let size = if sf_op21 == 0b000 {
if No0 != 0b00 || imms >= 0x10 {
inst.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
} else {
inst.opcode = Opcode::EXTR;
+ SizeCode::W
}
} else if sf_op21 == 0b100 {
if No0 != 0b10 {
inst.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
} else {
inst.opcode = Opcode::EXTR;
+ SizeCode::X
}
} else {
inst.opcode = Opcode::Invalid;
+ return Err(DecodeError::InvalidOpcode);
+ };
+
+ if imms > 15 && size == SizeCode::W {
+ return Err(DecodeError::InvalidOperand);
}
- // eprintln!("decode Rd: {}, Rn: {}, imms: {}, Rm: {}, No0: {}", Rd, Rn, imms, Rm, No0);
- return Err(DecodeError::IncompleteDecoder);
+
+ let Rd = (word & 0x1f) as u16;
+ let Rn = ((word >> 5) & 0x1f) as u16;
+ let Rm = ((word >> 16) & 0x1f) as u16;
+
+ inst.operands = [
+ Operand::Register(size, Rd),
+ Operand::Register(size, Rn),
+ Operand::Register(size, Rm),
+ Operand::Immediate(imms),
+ ];
}
_ => { unreachable!("group is three bits") }
}