diff options
| author | iximeow <me@iximeow.net> | 2021-10-21 17:47:46 -0700 | 
|---|---|---|
| committer | iximeow <me@iximeow.net> | 2021-10-21 17:47:46 -0700 | 
| commit | 097888dd845b7292bb107af80d87bc926001a9a1 (patch) | |
| tree | a1ae941215a682feeffb0931087909aced003aed /src/armv8 | |
| parent | 4a03599767c0ebac12e730a837abe1d15ac800e5 (diff) | |
data processing (three source)
Diffstat (limited to 'src/armv8')
| -rw-r--r-- | src/armv8/a64.rs | 92 | 
1 files changed, 90 insertions, 2 deletions
diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs index 60bbbed..3609103 100644 --- a/src/armv8/a64.rs +++ b/src/armv8/a64.rs @@ -134,7 +134,7 @@ mod docs {      }  } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Copy, Clone)]  pub enum DecodeError {      ExhaustedInput,      InvalidOpcode, @@ -665,6 +665,30 @@ impl Display for Instruction {              Opcode::CLS => {                  write!(fmt, "cls")?;              } +            Opcode::MADD => { +                write!(fmt, "madd")?; +            } +            Opcode::MSUB => { +                write!(fmt, "msub")?; +            } +            Opcode::SMADDL => { +                write!(fmt, "smaddl")?; +            } +            Opcode::SMSUBL => { +                write!(fmt, "smsubl")?; +            } +            Opcode::SMULH => { +                write!(fmt, "smulh")?; +            } +            Opcode::UMADDL => { +                write!(fmt, "umaddl")?; +            } +            Opcode::UMSUBL => { +                write!(fmt, "umsubl")?; +            } +            Opcode::UMULH => { +                write!(fmt, "umulh")?; +            }          };          if self.operands[0] != Operand::Nothing { @@ -840,6 +864,14 @@ pub enum Opcode {      REV32,      CLZ,      CLS, +    MADD, +    MSUB, +    SMADDL, +    SMSUBL, +    SMULH, +    UMADDL, +    UMSUBL, +    UMULH,  }  #[derive(Copy, Clone, Debug, PartialEq)] @@ -1414,7 +1446,63 @@ impl Decoder<ARMv8> for InstDecoder {                          },                          _ => {                              // Data processing (3 source) -                            return Err(DecodeError::IncompleteDecoder); +                            let op0 = ((word >> 15) & 0x01) as u8; +                            let op31 = ((word >> 21) & 0x07) as u8; +                            let op54 = ((word >> 29) & 0x03) as u8; +                            let op = op0 | (op31 << 1) | (op54 << 4); +                            let sf = ((word >> 31) & 0x01) as u8; + +                            let Rd = ((word >> 0) & 0x1f) as u16; +                            let Rn = ((word >> 5) & 0x1f) as u16; +                            let Ra = ((word >> 10) & 0x1f) as u16; +                            let Rm = ((word >> 16) & 0x1f) as u16; + +                            const DATA_PROCESSING_3_SOURCE: &[Result<(Opcode, SizeCode, SizeCode), DecodeError>] = &[ +                                Ok((Opcode::MADD, SizeCode::W, SizeCode::W)), +                                Ok((Opcode::MADD, SizeCode::X, SizeCode::X)), +                                Ok((Opcode::MSUB, SizeCode::W, SizeCode::W)), +                                Ok((Opcode::MSUB, SizeCode::X, SizeCode::X)), +                                Err(DecodeError::InvalidOpcode), +                                Ok((Opcode::SMADDL, SizeCode::W, SizeCode::X)), +                                Err(DecodeError::InvalidOpcode), +                                Ok((Opcode::SMSUBL, SizeCode::W, SizeCode::X)), +                                Err(DecodeError::InvalidOpcode), +                                Ok((Opcode::SMULH, SizeCode::W, SizeCode::X)), +                                Err(DecodeError::InvalidOpcode), +                                Err(DecodeError::InvalidOpcode), +                                Err(DecodeError::InvalidOpcode), +                                Err(DecodeError::InvalidOpcode), +                                Err(DecodeError::InvalidOpcode), +                                Err(DecodeError::InvalidOpcode), +                                Err(DecodeError::InvalidOpcode), +                                Err(DecodeError::InvalidOpcode), +                                Err(DecodeError::InvalidOpcode), +                                Err(DecodeError::InvalidOpcode), +                                Err(DecodeError::InvalidOpcode), +                                Ok((Opcode::UMADDL, SizeCode::W, SizeCode::X)), +                                Err(DecodeError::InvalidOpcode), +                                Ok((Opcode::UMSUBL, SizeCode::W, SizeCode::X)), +                                Err(DecodeError::InvalidOpcode), +                                Ok((Opcode::UMULH, SizeCode::X, SizeCode::X)), +                                Err(DecodeError::InvalidOpcode), +                            ]; + +                            let compound_idx = (op << 1) | sf; +                            crate::armv8::a64::std::eprintln!("word: {:#08x}, compound_idx: {:x}", word, compound_idx); +                            let (opcode, source_size, dest_size) = DATA_PROCESSING_3_SOURCE.get(compound_idx as usize) +                                .map(std::borrow::ToOwned::to_owned) +                                .unwrap_or(Err(DecodeError::InvalidOpcode))?; + +                            inst.opcode = opcode; +                            inst.operands = [ +                                Operand::Register(dest_size, Rd), +                                Operand::Register(source_size, Rn), +                                Operand::Register(source_size, Rm), +                                Operand::Register(dest_size, Ra), // in practice these match up with the corresponding operand. +                            ]; +                            if opcode == Opcode::UMULH { +                                inst.operands[3] = Operand::Nothing; +                            }                          }                      }                  } else {  | 
