diff options
-rw-r--r-- | src/armv8/a64.rs | 49 | ||||
-rw-r--r-- | test/armv8/a64.rs | 8 |
2 files changed, 56 insertions, 1 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs index 453778e..16a4116 100644 --- a/src/armv8/a64.rs +++ b/src/armv8/a64.rs @@ -641,6 +641,12 @@ impl Display for Instruction { Opcode::PACIZA => { write!(fmt, "paciza")?; } + Opcode::CCMN => { + write!(fmt, "ccmn")?; + } + Opcode::CCMP => { + write!(fmt, "ccmp")?; + } }; if self.operands[0] != Operand::Nothing { @@ -808,6 +814,8 @@ pub enum Opcode { CSINV, PACIA, PACIZA, + CCMN, + CCMP, } #[derive(Copy, Clone, Debug, PartialEq)] @@ -1175,7 +1183,46 @@ impl Decoder<ARMv8> for InstDecoder { }, 0b001 => { // Conditional compare (register/immediate) - return Err(DecodeError::IncompleteDecoder); + let imm_or_reg = (word >> 11) & 0x01; + + let o3 = (word >> 4) & 0x01; + let o2 = (word >> 10) & 0x01; + let S = (word >> 29) & 0x01; + let op = (word >> 30) & 0x01; + let sf = (word >> 31) & 0x01; + + if S != 1 || o2 != 0 || o3 != 0 { + inst.opcode = Opcode::Invalid; + return Err(DecodeError::InvalidOpcode); + } + + let size = if sf == 1 { + SizeCode::X + } else { + SizeCode::W + }; + + inst.opcode = if op == 1 { + Opcode::CCMP + } else { + Opcode::CCMN + }; + + let Rn = ((word >> 5) & 0x1f) as u16; + let Rm = ((word >> 16) & 0x1f) as u16; + let cond = ((word >> 12) & 0x0f) as u8; + let nzcv = (word & 0x0f) as u8; + + inst.operands = [ + Operand::Register(size, Rn), + if imm_or_reg == 1 { + Operand::Immediate(Rm as u32) + } else { + Operand::Register(size, Rm) + }, + Operand::Immediate(nzcv as u32), + Operand::ConditionCode(cond), + ] }, 0b010 => { // Conditional select diff --git a/test/armv8/a64.rs b/test/armv8/a64.rs index 0e25c93..5b480df 100644 --- a/test/armv8/a64.rs +++ b/test/armv8/a64.rs @@ -287,6 +287,14 @@ fn test_decode_mul() { } #[test] +fn test_decode_ccm() { + test_display([0x00, 0xa8, 0x42, 0x3a], "ccmn w0, 0x2, 0x0, ge"); + test_display([0x00, 0xa8, 0x42, 0xfa], "ccmp x0, 0x2, 0x0, ge"); + test_display([0x00, 0xa0, 0x42, 0xfa], "ccmp x0, x2, 0x0, ge"); + test_display([0x85, 0x80, 0x42, 0xfa], "ccmp x4, x2, 0x5, hi"); +} + +#[test] fn test_decode_chrome_entrypoint() { // 1400 instructions from the entrypoint of a chrome binary, sorted by // instruction word for no good reason. |