diff options
author | iximeow <me@iximeow.net> | 2021-10-26 00:17:49 -0700 |
---|---|---|
committer | iximeow <me@iximeow.net> | 2021-10-26 00:17:49 -0700 |
commit | d1213dc138d58678a1b4a9fe09dcb2ecf2147c18 (patch) | |
tree | e2f29eca01ac6f330e72777f827f9019868d3f03 | |
parent | 21201e75aa67ec6e6326197e4f5ce660fbe1e88b (diff) |
extr
-rw-r--r-- | src/armv8/a64.rs | 29 |
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") } } |