//! # SMLAWB, SMLAWT
//!
//! Signed Multiply Accumulate (word by halfword) performs a signed multiply accumulate operation. The multiply acts on a signed 32-bit quantity and a signed 16-bit quantity. The signed 16-bit quantity is taken from either the bottom or the top half of its source register. The other half of the second source register is ignored. The top 32 bits of the 48-bit product are added to a 32-bit accumulate value and the result is written to the destination register. The bottom 16 bits of the 48-bit product are ignored.
#![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 IclassSmlawbA1
// ---------------------------------------------------------------------------
/// Type that represents the IclassSmlawbA1 instruction class.
pub(crate) struct IclassSmlawbA1;
impl IclassSmlawbA1 {
/// Tries to decode the instruction in `data`.
pub(crate) fn decode(data: u32, decoder: &mut Decoder) -> Result<Instruction> {
let M = (data >> 6) & 1;
let M_post = M;
let field_20 = (data >> 20) & 1;
let field_20_post = field_20;
let opc = (data >> 21) & 3;
let opc_post = opc;
let N = (data >> 5) & 1;
let N_post = N;
let Rm = (data >> 8) & 15;
let Rm_post = Rm;
let Ra = (data >> 12) & 15;
let Ra_post = Ra;
let Rd = (data >> 16) & 15;
let Rd_post = Rd;
let field_4 = (data >> 4) & 1;
let field_4_post = field_4;
let field_27 = (data >> 23) & 31;
let field_27_post = field_27;
let cond = (data >> 28) & 15;
let cond_post = cond;
let Rn = (data >> 0) & 15;
let Rn_post = Rn;
let field_7 = (data >> 7) & 1;
let field_7_post = field_7;
if (M_post == 0) {
return SmlawbA1::decode(data as u32, decoder);
}
if (M_post == 1) {
return SmlawtA1::decode(data as u32, decoder);
}
unreachable!()
}
}
/// SMLAWB A1 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="4">!= 1111</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">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">1</td>
/// <td style="text-align: center; border-right: none" colspan="1">0</td>
/// <td style="text-align: center" colspan="4">Rd</td>
/// <td style="text-align: center" colspan="4">Ra</td>
/// <td style="text-align: center" colspan="4">Rm</td>
/// <td style="text-align: center; border-right: none" colspan="1">1</td>
/// <td style="text-align: center" colspan="1">M</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" colspan="4">Rn</td>
/// </tr>
/// <tr>
/// <td style="text-align: center; border: none" colspan="4">cond</td>
/// <td style="text-align: center; border: none" colspan="5"></td>
/// <td style="text-align: center; border: none" colspan="2">opc</td>
/// <td style="text-align: center; border: none" colspan="1"></td>
/// <td style="text-align: center; border: none" colspan="4"></td>
/// <td style="text-align: center; border: none" colspan="4"></td>
/// <td style="text-align: center; border: none" colspan="4"></td>
/// <td style="text-align: center; border: none" colspan="1"></td>
/// <td style="text-align: center; border: none" colspan="1"></td>
/// <td style="text-align: center; border: none" colspan="1">N</td>
/// <td style="text-align: center; border: none" colspan="1"></td>
/// <td style="text-align: center; border: none" colspan="4"></td>
/// </tr>
/// </table>
pub struct SmlawbA1;
impl SmlawbA1 {
/// Returns the instruction mnemonic.
pub fn mnemonic(_instr: &Instruction) -> Mnemonic {
Mnemonic::SMLAWB
}
/// 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 cond = (data >> 28) & 15;
let cond_post = cond;
let Rd = (data >> 16) & 15;
let Rd_post = Rd;
let Ra = (data >> 12) & 15;
let Ra_post = Ra;
let Rm = (data >> 8) & 15;
let Rm_post = Rm;
let Rn = (data >> 0) & 15;
let Rn_post = Rn;
// Operand values are computed from the base fields.
let cond_post = cond;
let op_0 = MnemonicCondition::decode(cond_post)?;
let Rd_post = Rd;
let op_1 = Register::decode(Rd_post)?;
let Rn_post = Rn;
let op_2 = Register::decode(Rn_post)?;
let Rm_post = Rm;
let op_3 = Register::decode(Rm_post)?;
let Ra_post = Ra;
let op_4 = Register::decode(Ra_post)?;
// Instruction creation from the operands.
let mut instr = Instruction::builder(Code::SMLAWB_A1)
.operand(0, op_0)?
.operand(1, op_1)?
.operand(2, op_2)?
.operand(3, op_3)?
.operand(4, op_4)?
.build();
Ok(instr)
}
/// Encodes the instruction into `buf`.
pub fn encode(instr: &Instruction, buf: &mut Vec<u8>) -> Result<usize> {
// Retrieve all operand values.
let cond_pre = instr.op0().as_mnemonic_condition()?.encode();
let Rd_pre = instr.op1().as_register()?.encode();
let Rn_pre = instr.op2().as_register()?.encode();
let Rm_pre = instr.op3().as_register()?.encode();
let Ra_pre = instr.op4().as_register()?.encode();
// Compute all instruction fields from the operand values.
let cond = (cond_pre & 15);
let Rd = (Rd_pre & 15);
let Rn = (Rn_pre & 15);
let Rm = (Rm_pre & 15);
let Ra = (Ra_pre & 15);
// Add all fields to the base instruction encoding.
let mut instr: u32 = 0b00000001001000000000000010000000;
instr |= (cond & 15) << 28;
instr |= (Rd & 15) << 16;
instr |= (Rn & 15) << 0;
instr |= (Rm & 15) << 8;
instr |= (Ra & 15) << 12;
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::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::Register(r) = op {
return Ok(())
}
todo!()
}
/// Verifies that operand #4 is valid.
pub fn check_op4(instr: &Instruction, op: &Operand) -> Result<()> {
if let Operand::Register(r) = op {
return Ok(())
}
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.smlawb_a1, &instr)?;
fmt.format_operand(output, &config.global, &config.instructions.smlawb_a1, &instr, 0)?;
fmt.format_qualifier(output, &config.global, &config.instructions.smlawb_a1, &instr, FormatterQualifier::Wide, false, false)?;
fmt.format_punctuation(output, &config.global, &config.instructions.smlawb_a1, &instr, FormatterTextKind::Space)?;
fmt.format_operand(output, &config.global, &config.instructions.smlawb_a1, &instr, 1)?;
fmt.format_punctuation(output, &config.global, &config.instructions.smlawb_a1, &instr, FormatterTextKind::Comma)?;
fmt.format_operand(output, &config.global, &config.instructions.smlawb_a1, &instr, 2)?;
fmt.format_punctuation(output, &config.global, &config.instructions.smlawb_a1, &instr, FormatterTextKind::Comma)?;
fmt.format_operand(output, &config.global, &config.instructions.smlawb_a1, &instr, 3)?;
fmt.format_punctuation(output, &config.global, &config.instructions.smlawb_a1, &instr, FormatterTextKind::Comma)?;
fmt.format_operand(output, &config.global, &config.instructions.smlawb_a1, &instr, 4)?;
Ok(())
}
}
/// Type that represents alias identifiers for [`SmlawbA1`].
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum SmlawbA1Aliases {
None,
}
/// Type that represents encoding identifiers for [`SmlawbA1`].
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum SmlawbA1Encodings {
None
}
/// SMLAWT A1 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="4">!= 1111</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">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">1</td>
/// <td style="text-align: center; border-right: none" colspan="1">0</td>
/// <td style="text-align: center" colspan="4">Rd</td>
/// <td style="text-align: center" colspan="4">Ra</td>
/// <td style="text-align: center" colspan="4">Rm</td>
/// <td style="text-align: center; border-right: none" colspan="1">1</td>
/// <td style="text-align: center" colspan="1">M</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" colspan="4">Rn</td>
/// </tr>
/// <tr>
/// <td style="text-align: center; border: none" colspan="4">cond</td>
/// <td style="text-align: center; border: none" colspan="5"></td>
/// <td style="text-align: center; border: none" colspan="2">opc</td>
/// <td style="text-align: center; border: none" colspan="1"></td>
/// <td style="text-align: center; border: none" colspan="4"></td>
/// <td style="text-align: center; border: none" colspan="4"></td>
/// <td style="text-align: center; border: none" colspan="4"></td>
/// <td style="text-align: center; border: none" colspan="1"></td>
/// <td style="text-align: center; border: none" colspan="1"></td>
/// <td style="text-align: center; border: none" colspan="1">N</td>
/// <td style="text-align: center; border: none" colspan="1"></td>
/// <td style="text-align: center; border: none" colspan="4"></td>
/// </tr>
/// </table>
pub struct SmlawtA1;
impl SmlawtA1 {
/// Returns the instruction mnemonic.
pub fn mnemonic(_instr: &Instruction) -> Mnemonic {
Mnemonic::SMLAWT
}
/// 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 cond = (data >> 28) & 15;
let cond_post = cond;
let Rd = (data >> 16) & 15;
let Rd_post = Rd;
let Ra = (data >> 12) & 15;
let Ra_post = Ra;
let Rm = (data >> 8) & 15;
let Rm_post = Rm;
let Rn = (data >> 0) & 15;
let Rn_post = Rn;
// Operand values are computed from the base fields.
let cond_post = cond;
let op_0 = MnemonicCondition::decode(cond_post)?;
let Rd_post = Rd;
let op_1 = Register::decode(Rd_post)?;
let Rn_post = Rn;
let op_2 = Register::decode(Rn_post)?;
let Rm_post = Rm;
let op_3 = Register::decode(Rm_post)?;
let Ra_post = Ra;
let op_4 = Register::decode(Ra_post)?;
// Instruction creation from the operands.
let mut instr = Instruction::builder(Code::SMLAWT_A1)
.operand(0, op_0)?
.operand(1, op_1)?
.operand(2, op_2)?
.operand(3, op_3)?
.operand(4, op_4)?
.build();
Ok(instr)
}
/// Encodes the instruction into `buf`.
pub fn encode(instr: &Instruction, buf: &mut Vec<u8>) -> Result<usize> {
// Retrieve all operand values.
let cond_pre = instr.op0().as_mnemonic_condition()?.encode();
let Rd_pre = instr.op1().as_register()?.encode();
let Rn_pre = instr.op2().as_register()?.encode();
let Rm_pre = instr.op3().as_register()?.encode();
let Ra_pre = instr.op4().as_register()?.encode();
// Compute all instruction fields from the operand values.
let cond = (cond_pre & 15);
let Rd = (Rd_pre & 15);
let Rn = (Rn_pre & 15);
let Rm = (Rm_pre & 15);
let Ra = (Ra_pre & 15);
// Add all fields to the base instruction encoding.
let mut instr: u32 = 0b00000001001000000000000011000000;
instr |= (cond & 15) << 28;
instr |= (Rd & 15) << 16;
instr |= (Rn & 15) << 0;
instr |= (Rm & 15) << 8;
instr |= (Ra & 15) << 12;
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::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::Register(r) = op {
return Ok(())
}
todo!()
}
/// Verifies that operand #4 is valid.
pub fn check_op4(instr: &Instruction, op: &Operand) -> Result<()> {
if let Operand::Register(r) = op {
return Ok(())
}
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.smlawt_a1, &instr)?;
fmt.format_operand(output, &config.global, &config.instructions.smlawt_a1, &instr, 0)?;
fmt.format_qualifier(output, &config.global, &config.instructions.smlawt_a1, &instr, FormatterQualifier::Wide, false, false)?;
fmt.format_punctuation(output, &config.global, &config.instructions.smlawt_a1, &instr, FormatterTextKind::Space)?;
fmt.format_operand(output, &config.global, &config.instructions.smlawt_a1, &instr, 1)?;
fmt.format_punctuation(output, &config.global, &config.instructions.smlawt_a1, &instr, FormatterTextKind::Comma)?;
fmt.format_operand(output, &config.global, &config.instructions.smlawt_a1, &instr, 2)?;
fmt.format_punctuation(output, &config.global, &config.instructions.smlawt_a1, &instr, FormatterTextKind::Comma)?;
fmt.format_operand(output, &config.global, &config.instructions.smlawt_a1, &instr, 3)?;
fmt.format_punctuation(output, &config.global, &config.instructions.smlawt_a1, &instr, FormatterTextKind::Comma)?;
fmt.format_operand(output, &config.global, &config.instructions.smlawt_a1, &instr, 4)?;
Ok(())
}
}
/// Type that represents alias identifiers for [`SmlawtA1`].
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum SmlawtA1Aliases {
None,
}
/// Type that represents encoding identifiers for [`SmlawtA1`].
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum SmlawtA1Encodings {
None
}