diff options
Diffstat (limited to 'src/armv8')
| -rw-r--r-- | src/armv8/a64.rs | 86 | 
1 files changed, 86 insertions, 0 deletions
| diff --git a/src/armv8/a64.rs b/src/armv8/a64.rs index e6ed329..9dec1d4 100644 --- a/src/armv8/a64.rs +++ b/src/armv8/a64.rs @@ -1240,6 +1240,15 @@ pub enum Opcode {      TBX,      FCADD, + +    LDGM, +    LDG, +    STGM, +    STZGM, +    STG, +    STZG, +    ST2G, +    STZ2G,  }  impl Display for Opcode { @@ -2001,6 +2010,14 @@ impl Display for Opcode {              Opcode::TBL => "tbl",              Opcode::TBX => "tbx",              Opcode::FCADD => "fcadd", +            Opcode::LDGM => "ldgm", +            Opcode::LDG => "ldm", +            Opcode::STGM => "stgm", +            Opcode::STZGM => "stzgm", +            Opcode::STG => "stg", +            Opcode::STZG => "stzg", +            Opcode::ST2G => "st2g", +            Opcode::STZ2G => "stz2g",              Opcode::Bcc(cond) => {                  return write!(fmt, "b.{}", Operand::ConditionCode(cond)); @@ -7405,6 +7422,75 @@ impl Decoder<ARMv8> for InstDecoder {                              Operand::Nothing,                          ];                      }, +                    0b01010 | +                    0b01011 => { +                        // `Load/store memory tags`, `Load/store exclusive` +                        let op0 = (word >> 28) & 0b11111; +                        let op3 = (word >> 16) & 0b111111; +                        let op4 = (word >> 10) & 0b11; + +                        if op3 & 0b100000 == 0 { +                            if op4 != 0b00 { +                                return Err(DecodeError::InvalidOpcode); +                            } +                            // else, `LDAPR/STLR (unscaled immediate)` +                        } else { +                            if op0 != 0b1101 { +                                return Err(DecodeError::InvalidOpcode); +                            } +                            // else, `Load/store memory tags` +                            let opc = (word >> 22) & 0b11; +                            let imm9 = (word >> 12) & 0b111_111_111; +                            let op2 = (word >> 10) & 0b11; +                            let Rn = ((word >> 5) & 0b11111) as u16; +                            let Rt = ((word >> 0) & 0b11111) as u16; + +                            let simm = ((imm9 as i16) << 7) >> 7; + +                            let opcode = &[ +                                Opcode::STZGM, Opcode::STG, Opcode::STG, Opcode::STG, +                                Opcode::LDG, Opcode::STZG, Opcode::STZG, Opcode::STZG, +                                Opcode::STGM, Opcode::ST2G, Opcode::ST2G, Opcode::ST2G, +                                Opcode::LDGM, Opcode::STZ2G, Opcode::STZ2G, Opcode::STZ2G, +                            ][((opc << 2) | (op2)) as usize]; + +                            inst.opcode = *opcode; + +                            if op2 == 0 && imm9 != 0 { +                                if opc == 0b01 { +                                    // ldg +                                    inst.operands = [ +                                        Operand::Register(SizeCode::X, Rt), +                                        Operand::RegOffset(Rn, simm), +                                        Operand::Nothing, +                                        Operand::Nothing, +                                    ]; +                                    return Ok(()); +                                } else { +                                    return Err(DecodeError::InvalidOperand); +                                } +                            } + +                            inst.operands = [ +                                if op2 == 0b00 { +                                    Operand::Register(SizeCode::X, Rt) +                                } else { +                                    Operand::RegisterOrSP(SizeCode::X, Rt) +                                }, +                                if op2 == 0b00 { +                                    Operand::RegOffset(Rn, 0) +                                } else if op2 == 0b01 { +                                    Operand::RegPostIndex(Rn, simm as i32) +                                } else if op2 == 0b10 { +                                    Operand::RegOffset(Rn, simm) +                                } else { +                                    Operand::RegPreIndex(Rn, simm as i32, true) +                                }, +                                Operand::Nothing, +                                Operand::Nothing, +                            ]; +                        } +                    },                      0b01100 |                      0b01101 => {                          // load register (literal) | 
