charm 0.0.1

ARM assembler & disassembler generated from the ARM exploration tools.
Documentation
//! # PLI (register)
//!
//! Preload Instruction signals the memory system that instruction memory accesses from a specified address are likely in the near future. The memory system can respond by taking actions that are expected to speed up the memory accesses when they do occur, such as pre-loading the cache line containing the specified address into the instruction cache.

#![allow(non_snake_case)]
#![allow(unused)]
use crate::error::Result;
use crate::utils::*;
use super::super::formatter::*;
use super::super::instruction::*;
use super::super::operand::*;
use super::super::consts::*;
use super::super::config::*;
use super::super::decoder::*;

// ---------------------------------------------------------------------------
// Iclass IclassPliRT1
// ---------------------------------------------------------------------------

/// Type that represents the IclassPliRT1 instruction class.
pub(crate) struct IclassPliRT1;

impl IclassPliRT1 {
    /// Tries to decode the instruction in `data`.
    pub(crate) fn decode(data: u32, decoder: &mut Decoder) -> Result<Instruction> {
        let Rt = (data >> 12) & 15;
        let Rt_post = Rt;
        let size = (data >> 21) & 3;
        let size_post = size;
        let field_20 = (data >> 20) & 1;
        let field_20_post = field_20;
        let Rm = (data >> 0) & 15;
        let Rm_post = Rm;
        let field_28 = (data >> 25) & 15;
        let field_28_post = field_28;
        let field_31 = (data >> 29) & 7;
        let field_31_post = field_31;
        let Rn = (data >> 16) & 15;
        let Rn_post = Rn;
        let imm2 = (data >> 4) & 3;
        let imm2_post = imm2;
        let field_24 = (data >> 23) & 3;
        let field_24_post = field_24;
        let field_11 = (data >> 6) & 63;
        let field_11_post = field_11;


        return PliRT1::decode(data as u32, decoder);

        unreachable!()
    }
}

/// PLI T1 encoding.
///
/// # Encoding
///
/// <table style="font-family: courier, monospace">
///     <tr>
///         <td style="border: none">31</td>
///         <td style="border: none">30</td>
///         <td style="border: none">29</td>
///         <td style="border: none">28</td>
///         <td style="border: none">27</td>
///         <td style="border: none">26</td>
///         <td style="border: none">25</td>
///         <td style="border: none">24</td>
///         <td style="border: none">23</td>
///         <td style="border: none">22</td>
///         <td style="border: none">21</td>
///         <td style="border: none">20</td>
///         <td style="border: none">19</td>
///         <td style="border: none">18</td>
///         <td style="border: none">17</td>
///         <td style="border: none">16</td>
///         <td style="border: none">15</td>
///         <td style="border: none">14</td>
///         <td style="border: none">13</td>
///         <td style="border: none">12</td>
///         <td style="border: none">11</td>
///         <td style="border: none">10</td>
///         <td style="border: none">9</td>
///         <td style="border: none">8</td>
///         <td style="border: none">7</td>
///         <td style="border: none">6</td>
///         <td style="border: none">5</td>
///         <td style="border: none">4</td>
///         <td style="border: none">3</td>
///         <td style="border: none">2</td>
///         <td style="border: none">1</td>
///         <td style="border: none">0</td>
///     </tr>
///     <tr>
///          <td style="text-align: center; border-right: none" colspan="1">1</td>
///          <td style="text-align: center; border-left: none; border-right: none" colspan="1">1</td>
///          <td style="text-align: center; border-left: none" colspan="1">1</td>
///          <td style="text-align: center; border-right: none" colspan="1">1</td>
///          <td style="text-align: center; border-left: none; border-right: none" colspan="1">1</td>
///          <td style="text-align: center; border-left: none; border-right: none" colspan="1">0</td>
///          <td style="text-align: center; border-left: none" colspan="1">0</td>
///          <td style="text-align: center; border-right: none" colspan="1">1</td>
///          <td style="text-align: center; border-left: none" colspan="1">0</td>
///          <td style="text-align: center; border-right: none" colspan="1">0</td>
///          <td style="text-align: center; border-left: none" colspan="1">0</td>
///          <td style="text-align: center; border-right: none" colspan="1">1</td>
///          <td style="text-align: center; border-right: none" colspan="4">!= 1111</td>
///          <td style="text-align: center; border-right: none" colspan="1">1</td>
///          <td style="text-align: center; border-left: none; border-right: none" colspan="1">1</td>
///          <td style="text-align: center; border-left: none; border-right: none" colspan="1">1</td>
///          <td style="text-align: center; border-left: none" colspan="1">1</td>
///          <td style="text-align: center; border-right: none" colspan="1">0</td>
///          <td style="text-align: center; border-left: none; border-right: none" colspan="1">0</td>
///          <td style="text-align: center; border-left: none; border-right: none" colspan="1">0</td>
///          <td style="text-align: center; border-left: none; border-right: none" colspan="1">0</td>
///          <td style="text-align: center; border-left: none; border-right: none" colspan="1">0</td>
///          <td style="text-align: center; border-left: none" colspan="1">0</td>
/// <td style="text-align: center" colspan="2">imm2</td>
/// <td style="text-align: center" colspan="4">Rm</td>
///     </tr>
///     <tr>
/// <td style="text-align: center; border: none" colspan="3"></td>
/// <td style="text-align: center; border: none" colspan="4"></td>
/// <td style="text-align: center; border: none" colspan="2"></td>
/// <td style="text-align: center; border: none" colspan="2">size</td>
/// <td style="text-align: center; border: none" colspan="1"></td>
/// <td style="text-align: center; border: none" colspan="4">Rn</td>
/// <td style="text-align: center; border: none" colspan="4">Rt</td>
/// <td style="text-align: center; border: none" colspan="6"></td>
/// <td style="text-align: center; border: none" colspan="2"></td>
/// <td style="text-align: center; border: none" colspan="4"></td>
///     </tr>
/// </table>
pub struct PliRT1;

impl PliRT1 {
    /// Returns the instruction mnemonic.
    pub fn mnemonic(_instr: &Instruction) -> Mnemonic {
        Mnemonic::PLI
    }

    /// Returns the instruction condition information.
    pub fn condition(instr: &Instruction) -> ConditionalInstruction {
        ConditionalInstruction::Condition(0, false, false)
    }

    /// Returns the instruction size.
    pub fn size(_instr: &Instruction) -> usize {4}

    /// Decodes the instruction in `data`.
    pub fn decode(data: u32, decoder: &mut Decoder) -> Result<Instruction> {
        // Fields are extracted from the input value.
        let Rn = (data >> 16) & 15;
        let Rn_post = Rn;
        let imm2 = (data >> 4) & 3;
        let imm2_post = imm2;
        let Rm = (data >> 0) & 15;
        let Rm_post = Rm;
        
        // Compute the dependency values for the operands.
        let imm2_post = imm2;
        let Rn_post = Rn;
        let Rm_post = Rm;

        // Operand values are computed from the base fields and the dependencies.
        let op_0 = MnemonicCondition::Al;
        let op_1 = Register::decode(Rn_post)?;
        let op_2 = Register::decode(Rm_post)?;
        let op_3 = if imm2_post == 0 {
    Operand::None
} else {
    Operand::Shift(Shift::LSL(imm2_post))
};

        // Instruction creation from the operands.
        let mut instr = Instruction::builder(Code::PLI_r_T1)
            .operand(0, op_0)?
            .operand(1, op_1)?
            .operand(2, op_2)?
            .operand(3, op_3)?
            .build();
        
        Ok(instr)
    }

    pub fn encode(instr: &Instruction, buf: &mut Vec<u8>) -> Result<usize> {
        // Retrieve all operand values.
        let Rn_pre = instr.op1().as_register()?.encode();
        let Rm_pre = instr.op2().as_register()?.encode();
        let imm2_pre = match instr.op3() {
    Operand::None => 0,
    Operand::Shift(Shift::LSL(value)) => *value,
    _ => todo!()
};

        // Compute all instruction fields from the operand values.
        let Rn = (Rn_pre & 15);
        let Rm = (Rm_pre & 15);
        let imm2_pre = imm2_pre;
        let imm2 = (imm2_pre & 3);

        // Add all fields to the base instruction encoding.
        let mut instr: u32 = 0b11111001000100001111000000000000;
        instr |= (Rn & 15) << 16;
        instr |= (Rm & 15) << 0;
        instr |= (imm2 & 3) << 4;

        let instr_1 = (instr & 0xffff) as u16;
        let instr_2 = ((instr >> 16) & 0xffff) as u16;
        buf.extend(instr_2.to_le_bytes());
        buf.extend(instr_1.to_le_bytes());
        Ok(4)
    }

    /// Encode an instruction part of an instruction block into `buf`.
    pub fn encode_block(instr: &mut Instruction, buf: &mut Vec<u8>, labels: &std::collections::HashMap<u64, u64>) -> Result<usize> {
        Self::encode(instr, buf)
    }
    
    /// Verifies that operand #0 is valid.
    pub fn check_op0(instr: &Instruction, op: &Operand) -> Result<()> {
        if let Operand::MnemonicCondition(r) = op {
            return Ok(())
        }
        todo!()
    }
    
    /// Verifies that operand #1 is valid.
    pub fn check_op1(instr: &Instruction, op: &Operand) -> Result<()> {
        
        if let Operand::Register(r) = op {
            return Ok(())
        }
        todo!()
    }
    
    /// Verifies that operand #2 is valid.
    pub fn check_op2(instr: &Instruction, op: &Operand) -> Result<()> {
        
        if let Operand::Register(r) = op {
            return Ok(())
        }
        todo!()
    }
    
    /// Verifies that operand #3 is valid.
    pub fn check_op3(instr: &Instruction, op: &Operand) -> Result<()> {
        if let Operand::None = op {
            return Ok(())
        }
        if let Operand::Shift(Shift::LSL(_)) = op {
            return Ok(())
        }
        todo!()
    }
    
    /// Verifies that operand #4 is valid.
    pub fn check_op4(instr: &Instruction, op: &Operand) -> Result<()> {
        todo!()
    }
    
    /// Verifies that operand #5 is valid.
    pub fn check_op5(instr: &Instruction, op: &Operand) -> Result<()> {
        todo!()
    }
    
    /// Verifies that operand #6 is valid.
    pub fn check_op6(instr: &Instruction, op: &Operand) -> Result<()> {
        todo!()
    }

    /// Formats the instruction.
    pub fn format(instr: &Instruction, fmt: &mut impl Formatter, output: &mut impl FormatterOutput, config: &Config) -> Result<()> {
        fmt.format_mnemonic(output, &config.global, &config.instructions.pli_r_t1, &instr)?;
        fmt.format_operand(output, &config.global, &config.instructions.pli_r_t1, &instr, 0)?;
        fmt.format_qualifier(output, &config.global, &config.instructions.pli_r_t1, &instr, FormatterQualifier::Wide, false, false)?;
        fmt.format_punctuation(output, &config.global, &config.instructions.pli_r_t1, &instr, FormatterTextKind::Space)?;
        fmt.format_punctuation(output, &config.global, &config.instructions.pli_r_t1, &instr, FormatterTextKind::BracketLeft)?;
        fmt.format_operand(output, &config.global, &config.instructions.pli_r_t1, &instr, 1)?;
        fmt.format_punctuation(output, &config.global, &config.instructions.pli_r_t1, &instr, FormatterTextKind::Comma)?;
        fmt.format_punctuation(output, &config.global, &config.instructions.pli_r_t1, &instr, FormatterTextKind::Plus)?;
        fmt.format_operand(output, &config.global, &config.instructions.pli_r_t1, &instr, 2)?;
        if !instr.op3().is_none() {
            fmt.format_punctuation(output, &config.global, &config.instructions.pli_r_t1, &instr, FormatterTextKind::Comma)?;
            fmt.format_operand(output, &config.global, &config.instructions.pli_r_t1, &instr, 3)?;
        };
        fmt.format_punctuation(output, &config.global, &config.instructions.pli_r_t1, &instr, FormatterTextKind::BracketRight)?;;
        Ok(())
    }
}

/// Type that represents alias identifiers for [`PliRT1`].
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum PliRT1Aliases {
    None,
}

/// Type that represents encoding identifiers for [`PliRT1`].
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum PliRT1Encodings {
    None
}