diff options
-rw-r--r-- | src/armv8/a64.rs | 51 | ||||
-rw-r--r-- | test/armv8/a64.rs | 2 |
2 files changed, 48 insertions, 5 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs index 258c650..94fd086 100644 --- a/src/armv8/a64.rs +++ b/src/armv8/a64.rs @@ -230,13 +230,41 @@ impl Display for Instruction { write!(fmt, "invalid")?; }, Opcode::MOVN => { - write!(fmt, "movn")?; + let imm = if let Operand::ImmShift(imm, shift) = self.operands[1] { + !((imm as u64) << shift) + } else { + unreachable!("movn operand 1 is always ImmShift"); + }; + let imm = if let Operand::Register(size, _) = self.operands[0] { + if size == SizeCode::W { + (imm as u32) as u64 + } else { + imm + } + } else { + unreachable!("movn operand 0 is always Register"); + }; + return write!(fmt, "mov {}, {:#x}", self.operands[0], imm); }, Opcode::MOVK => { write!(fmt, "movk")?; }, Opcode::MOVZ => { - write!(fmt, "movz")?; + let imm = if let Operand::ImmShift(imm, shift) = self.operands[1] { + (imm as u64) << shift + } else { + unreachable!("movz operand is always ImmShift"); + }; + let imm = if let Operand::Register(size, _) = self.operands[0] { + if size == SizeCode::W { + (imm as u32) as u64 + } else { + imm + } + } else { + unreachable!("movn operand 0 is always Register"); + }; + return write!(fmt, "mov {}, {:#x}", self.operands[0], imm); }, Opcode::ADC => { write!(fmt, "adc")?; @@ -265,11 +293,16 @@ impl Display for Instruction { return write!(fmt, "mov {}, {}", self.operands[0], self.operands[1]); } else if let Operand::RegShift(ShiftStyle::LSL, 0, size, r) = self.operands[2] { return write!(fmt, "mov {}, {}", self.operands[0], Operand::Register(size, r)); + } else { + return write!(fmt, "mov {}, {}", self.operands[0], self.operands[2]); } } write!(fmt, "orr")?; }, Opcode::ORN => { + if let Operand::Register(_, 31) = self.operands[1] { + return write!(fmt, "mvn {}, {}", self.operands[0], self.operands[2]); + } write!(fmt, "orn")?; }, Opcode::EOR => { @@ -279,6 +312,9 @@ impl Display for Instruction { write!(fmt, "eon")?; }, Opcode::ANDS => { + if let Operand::Register(_, 31) = self.operands[0] { + return write!(fmt, "tst {}, {}", self.operands[1], self.operands[2]); + } write!(fmt, "ands")?; }, Opcode::ADDS => { @@ -300,10 +336,15 @@ impl Display for Instruction { Opcode::SUBS => { if let Operand::Register(_, 31) = self.operands[0] { return write!(fmt, "cmp {}, {}", self.operands[1], self.operands[2]) + } else if let Operand::Register(_, 31) = self.operands[1] { + return write!(fmt, "negs {}, {}", self.operands[0], self.operands[2]) } write!(fmt, "subs")?; }, Opcode::SUB => { + if let Operand::Register(_, 31) = self.operands[1] { + return write!(fmt, "neg {}, {}", self.operands[0], self.operands[2]) + } write!(fmt, "sub")?; }, Opcode::BFM => { @@ -1027,7 +1068,7 @@ impl Display for Operand { write!(fmt, "{:#x}", i) }, _ => { - write!(fmt, "{:#x}, lsl {}", i, shift * 16) + write!(fmt, "{:#x}, lsl {}", i, shift) } } }, @@ -1635,7 +1676,7 @@ impl Decoder<ARMv8> for InstDecoder { let imm = ((word >> 3) & 0x1ffffc) | ((word >> 29) & 0x3); inst.operands = [ Operand::Register(SizeCode::X, (word & 0x1f) as u16), - Operand::Immediate(imm * 0x1000), + Operand::Immediate(imm.overflowing_mul(0x1000).0), Operand::Nothing, Operand::Nothing ]; @@ -1828,7 +1869,7 @@ impl Decoder<ARMv8> for InstDecoder { inst.operands = [ Operand::Register(size, Rd as u16), - Operand::ImmShift(imm16 as u16, hw as u8), + Operand::ImmShift(imm16 as u16, hw as u8 * 16), Operand::Nothing, Operand::Nothing ]; diff --git a/test/armv8/a64.rs b/test/armv8/a64.rs index c251d4a..dde9802 100644 --- a/test/armv8/a64.rs +++ b/test/armv8/a64.rs @@ -2,6 +2,8 @@ use yaxpeax_arch::{Arch, Decoder, LengthedInstruction}; use yaxpeax_arm::armv8::a64::{ARMv8, Instruction, Operand, Opcode, SizeCode, ShiftStyle}; use yaxpeax_arm::armv8::a64::DecodeError; +use std::fmt; + fn test_decode(data: [u8; 4], expected: Instruction) { let mut reader = yaxpeax_arch::U8Reader::new(&data[..]); let instr = <ARMv8 as Arch>::Decoder::default().decode(&mut reader).unwrap(); |