kraid/isa: Add support for field modifiers

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41841>
This commit is contained in:
Faith Ekstrand 2026-05-27 10:19:10 -04:00 committed by Marge Bot
parent b5147b070c
commit 0a4cd88f67
2 changed files with 68 additions and 1 deletions

View file

@ -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! {

View file

@ -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<u8> {
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<FieldMod> {
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<u8>,
pub mod_: FieldMod,
pub type_: Option<FieldType>,
pub expr: Option<Box<Expr>>,
}
@ -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,
})