diff options
| author | iximeow <me@iximeow.net> | 2021-12-27 21:32:07 -0800 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2021-12-27 21:34:14 -0800 | 
| commit | cb833bf3b0d96d18f33e4032a915111cab71200c (patch) | |
| tree | e95ce121b625d2d1aa083cc74bcc4e6638bfc59a /src/armv8 | |
| parent | 999eb2ac6950c589e8649651f9b538b85900cf39 (diff) | |
crypto instructions and pac
Diffstat (limited to 'src/armv8')
| -rw-r--r-- | src/armv8/a64.rs | 370 | 
1 files changed, 363 insertions, 7 deletions
| diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs index a02be49..7c0b3a8 100644 --- a/src/armv8/a64.rs +++ b/src/armv8/a64.rs @@ -1827,6 +1827,84 @@ impl Display for Instruction {              Opcode::PRFM => {                  write!(fmt, "prfm");              } +            Opcode::AESE => { +                write!(fmt, "aese"); +            } +            Opcode::AESD => { +                write!(fmt, "aesd"); +            } +            Opcode::AESMC => { +                write!(fmt, "aesmc"); +            } +            Opcode::AESIMC => { +                write!(fmt, "aesimc"); +            } +            Opcode::SHA1H => { +                write!(fmt, "sha1h"); +            } +            Opcode::SHA1SU1 => { +                write!(fmt, "sha1su1"); +            } +            Opcode::SHA256SU0 => { +                write!(fmt, "sha256su0"); +            } +            Opcode::SM3TT1A => { +                write!(fmt, "sm3tt1a"); +            } +            Opcode::SM3TT1B => { +                write!(fmt, "sm3tt1b"); +            } +            Opcode::SM3TT2A => { +                write!(fmt, "sm3tt2a"); +            } +            Opcode::SM3TT2B => { +                write!(fmt, "sm3tt2b"); +            } +            Opcode::SHA512H => { +                write!(fmt, "sha512h"); +            } +            Opcode::SHA512H2 => { +                write!(fmt, "sha512h2"); +            } +            Opcode::SHA512SU1 => { +                write!(fmt, "sha512su1"); +            } +            Opcode::RAX1 => { +                write!(fmt, "rax1"); +            } +            Opcode::SM3PARTW1 => { +                write!(fmt, "sm3partw1"); +            } +            Opcode::SM3PARTW2 => { +                write!(fmt, "sm3partw2"); +            } +            Opcode::SM4EKEY => { +                write!(fmt, "sm4ekey"); +            } +            Opcode::BCAX => { +                write!(fmt, "bcax"); +            } +            Opcode::SM3SSI => { +                write!(fmt, "sm3ssi"); +            } +            Opcode::SHA512SU0 => { +                write!(fmt, "sha512su0"); +            } +            Opcode::SM4E => { +                write!(fmt, "sm4e"); +            } +            Opcode::EOR3 => { +                write!(fmt, "eor3"); +            } +            Opcode::XAR => { +                write!(fmt, "xar"); +            } +            Opcode::LDRAA => { +                write!(fmt, "ldraa"); +            } +            Opcode::LDRAB => { +                write!(fmt, "ldrab"); +            }          };          if self.operands[0] != Operand::Nothing { @@ -2306,6 +2384,36 @@ pub enum Opcode {      URSQRTE,      PRFM, + +    AESE, +    AESD, +    AESMC, +    AESIMC, + +    SHA1H, +    SHA1SU1, +    SHA256SU0, + +    SM3TT1A, +    SM3TT1B, +    SM3TT2A, +    SM3TT2B, +    SHA512H, +    SHA512H2, +    SHA512SU1, +    RAX1, +    SM3PARTW1, +    SM3PARTW2, +    SM4EKEY, +    BCAX, +    SM3SSI, +    SHA512SU0, +    SM4E, +    EOR3, +    XAR, + +    LDRAA, +    LDRAB,  }  #[derive(Copy, Clone, Debug, PartialEq)] @@ -5543,14 +5651,66 @@ impl Decoder<ARMv8> for InstDecoder {                                          return Err(DecodeError::IncompleteDecoder);                                      } else if op2 & 0b0111 == 0b0101 && op0 == 0b0101 {                                          // `Cryptographic two-register SHA` +                                        let Rd = word & 0b11111; +                                        let Rn = (word >> 5) & 0b11111;                                          let opcode = (word >> 12) & 0b11111;                                          let size = (word >> 22) & 0b11; -                                        return Err(DecodeError::IncompleteDecoder); + +                                        if size != 0b00 { +                                            return Err(DecodeError::InvalidOpcode); +                                        } + +                                        let opcode = match opcode { +                                            0b00000 => Opcode::SHA1H, +                                            0b00001 => Opcode::SHA1SU1, +                                            0b00010 => Opcode::SHA256SU0, +                                            _ => { +                                                return Err(DecodeError::InvalidOpcode); +                                            } +                                        }; +                                        inst.opcode = opcode; +                                        if opcode == Opcode::SHA1H { +                                            inst.operands = [ +                                                Operand::SIMDRegister(SIMDSizeCode::S, Rd as u16), +                                                Operand::SIMDRegister(SIMDSizeCode::S, Rn as u16), +                                                Operand::Nothing, +                                                Operand::Nothing, +                                            ]; +                                        } else { +                                            inst.operands = [ +                                                Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd as u16, SIMDSizeCode::S), +                                                Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn as u16, SIMDSizeCode::S), +                                                Operand::Nothing, +                                                Operand::Nothing, +                                            ]; +                                        }                                      } else if op2 & 0b0111 == 0b0101 && op0 == 0b0100 {                                          // `Cryptographic AES` +                                        let Rd = word & 0b11111; +                                        let Rn = (word >> 5) & 0b11111;                                          let opcode = (word >> 12) & 0b11111;                                          let size = (word >> 22) & 0b11; -                                        return Err(DecodeError::IncompleteDecoder); + +                                        if size != 0b00 { +                                            return Err(DecodeError::InvalidOpcode); +                                        } + +                                        let opcode = match opcode { +                                            0b00100 => Opcode::AESE, +                                            0b00101 => Opcode::AESD, +                                            0b00110 => Opcode::AESMC, +                                            0b00111 => Opcode::AESIMC, +                                            _ => { +                                                return Err(DecodeError::InvalidOpcode); +                                            } +                                        }; +                                        inst.opcode = opcode; +                                        inst.operands = [ +                                            Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd as u16, SIMDSizeCode::B), +                                            Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn as u16, SIMDSizeCode::B), +                                            Operand::Nothing, +                                            Operand::Nothing, +                                        ];                                      } else {                                          // unallocated                                          return Err(DecodeError::InvalidOpcode); @@ -5852,9 +6012,181 @@ impl Decoder<ARMv8> for InstDecoder {                              }                          }                      } +                } else if op0 == 0b1100 { +                    let Rd = (word & 0b11111) as u16; +                    let Rn = ((word >> 5) & 0b11111) as u16; + +                    if op1 == 0b00 { +                        if op2 & 0b1100 == 0b1000 { +                            // `Cryptographic three-register, imm2` +                            let Rm = ((word >> 16) & 0b11111) as u16; +                            let opcode = (word >> 10) & 0b11; +                            let imm2 = (word >> 12) & 0b11; + +                            inst.opcode = [ +                                Opcode::SM3TT1A, +                                Opcode::SM3TT1B, +                                Opcode::SM3TT2A, +                                Opcode::SM3TT2B, +                            ][opcode as usize]; + +                            inst.operands = [ +                                Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::S), +                                Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::S), +                                Operand::SIMDRegisterElementsLane(SIMDSizeCode::Q, Rn, SIMDSizeCode::S, imm2 as u8), +                                Operand::Nothing, +                            ]; +                        } else if op2 & 0b1100 == 0b1100 { +                            // `Cryptographic three-register SHA512` +                            let Rm = ((word >> 16) & 0b11111) as u16; +                            let opcode = (word >> 10) & 0b11; +                            let O = (word >> 14) & 0b1; +                            let Oop = (O << 2) | opcode; + +                            match Oop { +                                0b000 => { +                                    inst.opcode = Opcode::SHA512H; +                                    inst.operands = [ +                                        Operand::SIMDRegister(SIMDSizeCode::Q, Rd), +                                        Operand::SIMDRegister(SIMDSizeCode::Q, Rn), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rm, SIMDSizeCode::D), +                                        Operand::Nothing, +                                    ]; +                                } +                                0b001 => { +                                    inst.opcode = Opcode::SHA512H2; +                                    inst.operands = [ +                                        Operand::SIMDRegister(SIMDSizeCode::Q, Rd), +                                        Operand::SIMDRegister(SIMDSizeCode::Q, Rn), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rm, SIMDSizeCode::D), +                                        Operand::Nothing, +                                    ]; +                                } +                                0b010 => { +                                    inst.opcode = Opcode::SHA512SU1; +                                    inst.operands = [ +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::D), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::D), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rm, SIMDSizeCode::D), +                                        Operand::Nothing, +                                    ]; +                                } +                                0b011 => { +                                    inst.opcode = Opcode::RAX1; +                                    inst.operands = [ +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::D), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::D), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rm, SIMDSizeCode::D), +                                        Operand::Nothing, +                                    ]; +                                } +                                0b100 => { +                                    inst.opcode = Opcode::SM3PARTW1; +                                    inst.operands = [ +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::S), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::S), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rm, SIMDSizeCode::S), +                                        Operand::Nothing, +                                    ]; +                                } +                                0b101 => { +                                    inst.opcode = Opcode::SM3PARTW2; +                                    inst.operands = [ +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::S), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::S), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rm, SIMDSizeCode::S), +                                        Operand::Nothing, +                                    ]; +                                } +                                0b110 => { +                                    inst.opcode = Opcode::SM4EKEY; +                                    inst.operands = [ +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::S), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::S), +                                        Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rm, SIMDSizeCode::S), +                                        Operand::Nothing, +                                    ]; +                                } +                                _ => { +                                    return Err(DecodeError::InvalidOpcode); +                                } +                            } +                        } else { +                            // `Cryptographic four-register` +                            let Ra = ((word >> 10) & 0b11111) as u16; +                            let Rm = ((word >> 16) & 0b11111) as u16; +                            let Op0 = (word >> 21) & 0b11; + +                            if Op0 == 0b00 { +                                inst.opcode = Opcode::EOR3; +                                inst.operands = [ +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::B), +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::B), +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rm, SIMDSizeCode::B), +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Ra, SIMDSizeCode::B), +                                ]; +                            } else if Op0 == 0b01 { +                                inst.opcode = Opcode::BCAX; +                                inst.operands = [ +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::B), +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::B), +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rm, SIMDSizeCode::B), +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Ra, SIMDSizeCode::B), +                                ]; +                            } else if Op0 == 0b10 { +                                inst.opcode = Opcode::SM3SSI; +                                inst.operands = [ +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::S), +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::S), +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rm, SIMDSizeCode::S), +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Ra, SIMDSizeCode::S), +                                ]; +                            } else { +                                return Err(DecodeError::InvalidOpcode); +                            } +                        } +                    } else if op1 == 0b01 { +                        if op2 & 0b1100 == 0b0000 { +                            let imm6 = ((word >> 10) & 0b111111) as u16; +                            let Rm = ((word >> 16) & 0b11111) as u16; + +                            inst.opcode = Opcode::XAR; +                            inst.operands = [ +                                Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::D), +                                Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::D), +                                Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rm, SIMDSizeCode::D), +                                Operand::Imm16(imm6 as u16), +                            ]; +                            // `XAR` +                        } else { +                            // `Cryptographic two-register sha512` +                            let opcode = (word >> 10) & 0b11; +                            if opcode == 0b00 { +                                inst.opcode = Opcode::SHA512SU0; +                                inst.operands = [ +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::D), +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::D), +                                    Operand::Nothing, +                                    Operand::Nothing, +                                ]; +                            } else if opcode == 0b01 { +                                inst.opcode = Opcode::SM4E; +                                inst.operands = [ +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rd, SIMDSizeCode::S), +                                    Operand::SIMDRegisterElements(SIMDSizeCode::Q, Rn, SIMDSizeCode::S), +                                    Operand::Nothing, +                                    Operand::Nothing, +                                ]; +                            } else { +                                return Err(DecodeError::InvalidOpcode); +                            } +                        } +                    } else { +                        return Err(DecodeError::InvalidOpcode); +                    }                  } else { -                    // op0 != 0xx0, op0 != x0x1 -                    return Err(DecodeError::IncompleteDecoder); +                    // rest of this space is unallocated +                    return Err(DecodeError::InvalidOpcode);                  }              }              Section::Unallocated => { @@ -7410,14 +7742,38 @@ impl Decoder<ARMv8> for InstDecoder {                              match category {                                  0b00 => {                                      // Atomic memory operations -                                    // V==1 +                                    // V==0                                      return Err(DecodeError::IncompleteDecoder);                                  }                                  0b01 |                                  0b11 => {                                      // Load/store register (pac) -                                    // V==1 -                                    return Err(DecodeError::IncompleteDecoder); +                                    // V==0 +                                    let w = (word >> 11) & 1; +                                    let imm9 = ((word >> 12) & 0b1_1111_1111) as i16; +                                    let imm9 = (imm9 << 7) >> 7; +                                    let m = (word >> 23) & 1; +                                    let size = (word >> 30) & 0b11; +                                    if size != 0b11 { +                                        return Err(DecodeError::InvalidOpcode); +                                    } + +                                    if m == 0 { +                                        inst.opcode = Opcode::LDRAA; +                                    } else { +                                        inst.opcode = Opcode::LDRAB; +                                    } + +                                    inst.operands = [ +                                        Operand::Register(SizeCode::X, Rt), +                                        if w == 0 { +                                            Operand::RegOffset(Rn, imm9) +                                        } else { +                                            Operand::RegPreIndex(Rn, imm9 as i32, true) +                                        }, +                                        Operand::Nothing, +                                        Operand::Nothing, +                                    ];                                  }                                  0b10 => {                                      // Load/store register (register offset) | 
