diff --git a/src/panfrost/compiler/kraid/proc/isa/encoder.rs b/src/panfrost/compiler/kraid/proc/isa/encoder.rs index ff5f5c4361d..f2c053a4889 100644 --- a/src/panfrost/compiler/kraid/proc/isa/encoder.rs +++ b/src/panfrost/compiler/kraid/proc/isa/encoder.rs @@ -725,6 +725,30 @@ impl InstrEncVariant { }; let f_ident = instr_field_ident(&field.name); + match field.mod_ { + FieldMod::None => (), + FieldMod::Align(n) => { + let n = proc_macro2::Literal::u8_unsuffixed(n); + ts.extend(quote! { + assert!(#f_ident % #n == 0); + }); + } + FieldMod::Minus(n) => { + let n = proc_macro2::Literal::u8_unsuffixed(n); + ts.extend(quote! { + assert!(#f_ident >= #n); + let #f_ident = #f_ident - #n; + }); + } + FieldMod::Shr(n) => { + let n = proc_macro2::Literal::u8_unsuffixed(n); + ts.extend(quote! { + assert!(#f_ident % (1 << #n) == 0); + let #f_ident = #f_ident >> #n; + }); + } + } + let start_bit = usize::from(field.bits.start); let end_bit = usize::from(field.bits.end); ts.extend(quote! { diff --git a/src/panfrost/compiler/kraid/proc/isa/instr.rs b/src/panfrost/compiler/kraid/proc/isa/instr.rs index 935d8809484..c625e509a6c 100644 --- a/src/panfrost/compiler/kraid/proc/isa/instr.rs +++ b/src/panfrost/compiler/kraid/proc/isa/instr.rs @@ -111,10 +111,46 @@ impl VirtualField { } } +pub enum FieldMod { + None, + Align(u8), + Shr(u8), + Minus(u8), +} + +impl FieldMod { + fn args_as_u8(a: &str) -> Result { + let a = a.strip_prefix("(").ok_or(err("Invalid modifier"))?; + let a = a.strip_suffix(")").ok_or(err("Invalid modifier"))?; + u8::from_str_radix(a, 10).map_err(|_| err("Invalid modifier")) + } + + fn from_attr(attr: &str) -> Result { + if let Some(a) = attr.strip_prefix("align") { + Ok(FieldMod::Align(FieldMod::args_as_u8(a)?)) + } else if let Some(a) = attr.strip_prefix("minus") { + Ok(FieldMod::Minus(FieldMod::args_as_u8(a)?)) + } else if let Some(a) = attr.strip_prefix("shr") { + Ok(FieldMod::Shr(FieldMod::args_as_u8(a)?)) + } else { + Err(err("Invalid modifier")) + } + } + + pub fn extra_bits(&self) -> u8 { + match self { + FieldMod::None | FieldMod::Align(_) => 0, + FieldMod::Minus(_) => 1, + FieldMod::Shr(n) => *n, + } + } +} + pub struct PhysicalField { pub name: String, pub ident: Ident, pub bits: Range, + pub mod_: FieldMod, pub type_: Option, pub expr: Option>, } @@ -136,11 +172,17 @@ impl PhysicalField { let ident = Ident::new(&snake_name, Span::call_site()); let bits = xml.get_bit_range()?; + let mod_ = if let Some(attr) = xml.attrs.get("modifier") { + FieldMod::from_attr(attr)? + } else { + FieldMod::None + }; + let type_name = xml.attrs.get("type"); let type_ = match type_name { Some(name) => Some(FieldType::from_name( name, - bits.len().try_into().unwrap(), + u8::try_from(bits.len()).unwrap() + mod_.extra_bits(), enums, )?), None => None, @@ -180,6 +222,7 @@ impl PhysicalField { name, ident, bits, + mod_, type_, expr, })