charm 0.0.1

ARM assembler & disassembler generated from the ARM exploration tools.
Documentation
//! # ADDG
//!
//! This instruction adds an immediate value scaled by the Tag Granule to the address in the source register, modifies the Logical Address Tag of the address using an immediate value, and writes the result to the destination register. Tags specified in *GCR_EL1* .Exclude are excluded from the possible outputs when modifying the Logical Address Tag.

#![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 IclassAddg64AddsubImmtags
// ---------------------------------------------------------------------------

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

impl IclassAddg64AddsubImmtags {
    /// Tries to decode the instruction in `data`.
    pub(crate) fn decode(data: u32, decoder: &mut Decoder) -> Result<Instruction> {
        let S = (data >> 29) & 1;
        let S_post = S;
        let field_28 = (data >> 26) & 7;
        let field_28_post = field_28;
        let op = (data >> 30) & 1;
        let op_post = op;
        let Rn = (data >> 5) & 31;
        let Rn_post = Rn;
        let imm4 = (data >> 10) & 15;
        let imm4_post = imm4;
        let sf = (data >> 31) & 1;
        let sf_post = sf;
        let Rd = (data >> 0) & 31;
        let Rd_post = Rd;
        let imm6 = (data >> 16) & 63;
        let imm6_post = imm6;
        let op3 = (data >> 14) & 3;
        let op3_post = op3;
        let field_25 = (data >> 22) & 15;
        let field_25_post = field_25;


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

        unreachable!()
    }
}

/// None-bit 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-right: none" colspan="1">0</td>
///          <td style="text-align: center; border-right: 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; 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">0</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">0</td>
/// <td style="text-align: center" colspan="6">imm6</td>
///          <td style="text-align: center; border-right: none" colspan="3">(0)</td>
///          <td style="text-align: center; border-left: none" colspan="3">(0)</td>
/// <td style="text-align: center" colspan="4">imm4</td>
/// <td style="text-align: center" colspan="5">Rn</td>
/// <td style="text-align: center" colspan="5">Rd</td>
///     </tr>
///     <tr>
/// <td style="text-align: center; border: none" colspan="1">sf</td>
/// <td style="text-align: center; border: none" colspan="1">op</td>
/// <td style="text-align: center; border: none" colspan="1">S</td>
/// <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="6"></td>
/// <td style="text-align: center; border: none" colspan="2">op3</td>
/// <td style="text-align: center; border: none" colspan="4"></td>
/// <td style="text-align: center; border: none" colspan="5"></td>
/// <td style="text-align: center; border: none" colspan="5"></td>
///     </tr>
/// </table>
pub struct Addg64AddsubImmtags;

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

    /// 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 imm6 = (data >> 16) & 63;
        let imm6_post = imm6;
        let imm4 = (data >> 10) & 15;
        let imm4_post = imm4;
        let Rn = (data >> 5) & 31;
        let Rn_post = Rn;
        let Rd = (data >> 0) & 31;
        let Rd_post = Rd;
        

        // Operand values are computed from the base fields.
        let Rd_post = Rd;
        let op_0 = Register::aarch64(Rd_post, true)?;
        let Rn_post = Rn;
        let op_1 = Register::aarch64(Rn_post, true)?;
        let imm6_post = (imm6) * 16;
        let op_2 = imm6_post as u32;
        let imm4_post = imm4;
        let op_3 = imm4_post as u32;

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

    /// Encodes the instruction into `buf`.
    pub fn encode(instr: &Instruction, buf: &mut Vec<u8>) -> Result<usize> {
        // Retrieve all operand values.
        let Rd_pre = instr.op0().as_register()?.encode();
        let Rn_pre = instr.op1().as_register()?.encode();
        let imm6_pre = instr.op2().as_unsigned_immediate()? as u32;
        let imm4_pre = instr.op3().as_unsigned_immediate()? as u32;

        // Compute all instruction fields from the operand values.
        let Rd = (Rd_pre & 31);
        let Rn = (Rn_pre & 31);
        let imm6_pre = (imm6_pre) / 16;
        let imm6 = (imm6_pre & 63);
        let imm4_pre = imm4_pre;
        let imm4 = (imm4_pre & 15);

        // Add all fields to the base instruction encoding.
        let mut instr: u32 = 0b10010001100000000000000000000000;
        instr |= (Rd & 31) << 0;
        instr |= (Rn & 31) << 5;
        instr |= (imm6 & 63) << 16;
        instr |= (imm4 & 15) << 10;

        let bytes = instr.to_le_bytes();
        let len = bytes.len();
        buf.extend(bytes);
        Ok(len)
    }

    /// 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::Register(r) = op {
            if !r.is_aarch64() {
                todo!()
            }
            
            if *r == Register::XZR {
                todo!()
            }
            return Ok(())
        }
        todo!()
    }
    
    /// Verifies that operand #1 is valid.
    pub fn check_op1(instr: &Instruction, op: &Operand) -> Result<()> {
        if let Operand::Register(r) = op {
            if !r.is_aarch64() {
                todo!()
            }
            
            if *r == Register::XZR {
                todo!()
            }
            return Ok(())
        }
        todo!()
    }
    
    /// Verifies that operand #2 is valid.
    pub fn check_op2(instr: &Instruction, op: &Operand) -> Result<()> {
        if let Operand::UnsignedImmediate(i) = op {
            if !(0..=1008).contains(i) {
                todo!()
            }
            return Ok(())
        }
        todo!()
    }
    
    /// Verifies that operand #3 is valid.
    pub fn check_op3(instr: &Instruction, op: &Operand) -> Result<()> {
        if let Operand::UnsignedImmediate(i) = op {
            if !(0..=15).contains(i) {
                todo!()
            }
            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.addg_64_addsub_immtags, instr)?;
        fmt.format_punctuation(output, &config.global, &config.instructions.addg_64_addsub_immtags, instr, FormatterTextKind::Space)?;
        fmt.format_operand(output, &config.global, &config.instructions.addg_64_addsub_immtags, instr, 0)?;
        fmt.format_punctuation(output, &config.global, &config.instructions.addg_64_addsub_immtags, instr, FormatterTextKind::Comma)?;
        fmt.format_operand(output, &config.global, &config.instructions.addg_64_addsub_immtags, instr, 1)?;
        fmt.format_punctuation(output, &config.global, &config.instructions.addg_64_addsub_immtags, instr, FormatterTextKind::Comma)?;
        fmt.format_punctuation(output, &config.global, &config.instructions.addg_64_addsub_immtags, instr, FormatterTextKind::NumSign)?;
        fmt.format_operand(output, &config.global, &config.instructions.addg_64_addsub_immtags, instr, 2)?;
        fmt.format_punctuation(output, &config.global, &config.instructions.addg_64_addsub_immtags, instr, FormatterTextKind::Comma)?;
        fmt.format_punctuation(output, &config.global, &config.instructions.addg_64_addsub_immtags, instr, FormatterTextKind::NumSign)?;
        fmt.format_operand(output, &config.global, &config.instructions.addg_64_addsub_immtags, instr, 3)?;
        Ok(())
    }
}

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