//! Lui instruction // Imports use super::ModifiesReg; use crate::inst::{ basic::{Decode, Encode}, parse::LineArg, DisplayCtx, InstDisplay, InstFmtArg, Parsable, ParseCtx, ParseError, Register, }; use int_conv::{Truncated, ZeroExtended}; use std::{array, convert::TryInto}; /// Load instructions #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct Inst { /// Destination register, `rt` pub dst: Register, /// Value pub value: u16, } impl Decode for Inst { #[bitmatch::bitmatch] fn decode(raw: u32) -> Option { let [t, i] = #[bitmatch] match raw { "001111_?????_ttttt_iiiii_iiiii_iiiiii" => [t, i], _ => return None, }; Some(Self { dst: Register::new(t)?, value: i.truncated::(), }) } } impl Encode for Inst { #[bitmatch::bitmatch] fn encode(&self) -> u32 { let t = self.dst.idx(); let i = self.value.zero_extended::(); bitpack!("001111_?????_ttttt_iiiii_iiiii_iiiiii") } } impl<'a> Parsable<'a> for Inst { fn parse(mnemonic: &'a str, args: &'a [LineArg], _ctx: &'a Ctx) -> Result { if mnemonic != "lui" { return Err(ParseError::UnknownMnemonic); } match *args { [LineArg::Register(dst), LineArg::Literal(value)] => Ok(Self { dst, value: value.try_into().map_err(|_| ParseError::LiteralOutOfRange)?, }), _ => Err(ParseError::InvalidArguments), } } } impl<'a> InstDisplay<'a> for Inst { type Args = array::IntoIter, 2>; type Mnemonic = &'static str; fn mnemonic(&'a self, _ctx: &Ctx) -> Self::Mnemonic { "lui" } fn args(&'a self, _ctx: &Ctx) -> Self::Args { let &Self { dst, value } = self; array::IntoIter::new([InstFmtArg::Register(dst), InstFmtArg::literal(value)]) } } impl ModifiesReg for Inst { fn modifies_reg(&self, reg: Register) -> bool { self.dst == reg } }