diff options
Diffstat (limited to 'src/armv8')
| -rw-r--r-- | src/armv8/a64.rs | 49 | 
1 files changed, 48 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 | 
