disasm-py: add fields() method
This commit is contained in:
parent
88c6a478e2
commit
9dab42c364
|
@ -31,6 +31,14 @@ impl Ins {
|
|||
fn __str__(&self) -> String {
|
||||
FormattedIns(self.0.clone()).to_string()
|
||||
}
|
||||
|
||||
fn fields(&self) -> Vec<(&'static str, i64)> {
|
||||
self.0
|
||||
.fields()
|
||||
.iter()
|
||||
.flat_map(|field| field.argument().map(|arg| (field.name(), arg.into())))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
|
|
|
@ -1167,6 +1167,92 @@ pub enum Field {
|
|||
ctr,
|
||||
lr,
|
||||
}
|
||||
impl Field {
|
||||
pub fn argument(&self) -> Option<Argument> {
|
||||
match self {
|
||||
Field::simm(x) => Some(Argument::Simm(*x)),
|
||||
Field::uimm(x) => Some(Argument::Uimm(*x)),
|
||||
Field::offset(x) => Some(Argument::Offset(*x)),
|
||||
Field::ps_offset(x) => Some(Argument::Offset(*x)),
|
||||
Field::BO(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::BI(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::BD(x) => Some(Argument::BranchDest(*x)),
|
||||
Field::LI(x) => Some(Argument::BranchDest(*x)),
|
||||
Field::SH(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::MB(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::ME(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::rS(x) => Some(Argument::GPR(*x)),
|
||||
Field::rD(x) => Some(Argument::GPR(*x)),
|
||||
Field::rA(x) => Some(Argument::GPR(*x)),
|
||||
Field::rB(x) => Some(Argument::GPR(*x)),
|
||||
Field::rC(x) => Some(Argument::GPR(*x)),
|
||||
Field::sr(x) => Some(Argument::SR(*x)),
|
||||
Field::spr(x) => Some(Argument::SPR(*x)),
|
||||
Field::frS(x) => Some(Argument::FPR(*x)),
|
||||
Field::frD(x) => Some(Argument::FPR(*x)),
|
||||
Field::frA(x) => Some(Argument::FPR(*x)),
|
||||
Field::frB(x) => Some(Argument::FPR(*x)),
|
||||
Field::frC(x) => Some(Argument::FPR(*x)),
|
||||
Field::crbD(x) => Some(Argument::CRBit(*x)),
|
||||
Field::crbA(x) => Some(Argument::CRBit(*x)),
|
||||
Field::crbB(x) => Some(Argument::CRBit(*x)),
|
||||
Field::crfD(x) => Some(Argument::CRField(*x)),
|
||||
Field::crfS(x) => Some(Argument::CRField(*x)),
|
||||
Field::crm(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::ps_l(x) => Some(Argument::GQR(*x)),
|
||||
Field::ps_W(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::NB(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::tbr(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::mtfsf_FM(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::mtfsf_IMM(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::TO(x) => Some(Argument::OpaqueU(*x)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
Field::simm(_) => "simm",
|
||||
Field::uimm(_) => "uimm",
|
||||
Field::offset(_) => "offset",
|
||||
Field::ps_offset(_) => "ps_offset",
|
||||
Field::BO(_) => "BO",
|
||||
Field::BI(_) => "BI",
|
||||
Field::BD(_) => "BD",
|
||||
Field::LI(_) => "LI",
|
||||
Field::SH(_) => "SH",
|
||||
Field::MB(_) => "MB",
|
||||
Field::ME(_) => "ME",
|
||||
Field::rS(_) => "rS",
|
||||
Field::rD(_) => "rD",
|
||||
Field::rA(_) => "rA",
|
||||
Field::rB(_) => "rB",
|
||||
Field::rC(_) => "rC",
|
||||
Field::sr(_) => "sr",
|
||||
Field::spr(_) => "spr",
|
||||
Field::frS(_) => "frS",
|
||||
Field::frD(_) => "frD",
|
||||
Field::frA(_) => "frA",
|
||||
Field::frB(_) => "frB",
|
||||
Field::frC(_) => "frC",
|
||||
Field::crbD(_) => "crbD",
|
||||
Field::crbA(_) => "crbA",
|
||||
Field::crbB(_) => "crbB",
|
||||
Field::crfD(_) => "crfD",
|
||||
Field::crfS(_) => "crfS",
|
||||
Field::crm(_) => "crm",
|
||||
Field::ps_l(_) => "ps_l",
|
||||
Field::ps_W(_) => "ps_W",
|
||||
Field::NB(_) => "NB",
|
||||
Field::tbr(_) => "tbr",
|
||||
Field::mtfsf_FM(_) => "mtfsf_FM",
|
||||
Field::mtfsf_IMM(_) => "mtfsf_IMM",
|
||||
Field::TO(_) => "TO",
|
||||
Field::xer => "xer",
|
||||
Field::ctr => "ctr",
|
||||
Field::lr => "lr",
|
||||
}
|
||||
}
|
||||
}
|
||||
#[allow(clippy::all, unused_mut)]
|
||||
impl Ins {
|
||||
pub(crate) fn _fields(&self) -> Vec<Field> {
|
||||
|
|
|
@ -166,50 +166,33 @@ impl Display for Argument {
|
|||
}
|
||||
}
|
||||
|
||||
impl Field {
|
||||
pub fn argument(&self) -> Option<Argument> {
|
||||
impl Into<i64> for Argument {
|
||||
fn into(self) -> i64 {
|
||||
match self {
|
||||
Field::simm(x) => Some(Argument::Simm(*x)),
|
||||
Field::uimm(x) => Some(Argument::Uimm(*x)),
|
||||
Field::offset(x) => Some(Argument::Offset(*x)),
|
||||
Field::ps_offset(x) => Some(Argument::Offset(*x)),
|
||||
Field::BO(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::BI(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::BD(x) => Some(Argument::BranchDest(*x)),
|
||||
Field::LI(x) => Some(Argument::BranchDest(*x)),
|
||||
Field::SH(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::MB(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::ME(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::rS(x) => Some(Argument::GPR(*x)),
|
||||
Field::rD(x) => Some(Argument::GPR(*x)),
|
||||
Field::rA(x) => Some(Argument::GPR(*x)),
|
||||
Field::rB(x) => Some(Argument::GPR(*x)),
|
||||
Field::rC(x) => Some(Argument::GPR(*x)),
|
||||
Field::sr(x) => Some(Argument::SR(*x)),
|
||||
Field::spr(x) => Some(Argument::SPR(*x)),
|
||||
Field::frS(x) => Some(Argument::FPR(*x)),
|
||||
Field::frD(x) => Some(Argument::FPR(*x)),
|
||||
Field::frA(x) => Some(Argument::FPR(*x)),
|
||||
Field::frB(x) => Some(Argument::FPR(*x)),
|
||||
Field::frC(x) => Some(Argument::FPR(*x)),
|
||||
Field::crbD(x) => Some(Argument::CRBit(*x)),
|
||||
Field::crbA(x) => Some(Argument::CRBit(*x)),
|
||||
Field::crbB(x) => Some(Argument::CRBit(*x)),
|
||||
Field::crfD(x) => Some(Argument::CRField(*x)),
|
||||
Field::crfS(x) => Some(Argument::CRField(*x)),
|
||||
Field::crm(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::ps_l(x) => Some(Argument::GQR(*x)),
|
||||
Field::ps_W(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::NB(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::tbr(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::mtfsf_FM(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::mtfsf_IMM(x) => Some(Argument::OpaqueU(*x)),
|
||||
Field::TO(x) => Some(Argument::OpaqueU(*x)),
|
||||
_ => None,
|
||||
Argument::GPR(x) => x.0 as i64,
|
||||
Argument::FPR(x) => x.0 as i64,
|
||||
Argument::SR(x) => x.0 as i64,
|
||||
Argument::SPR(x) => x.0 as i64,
|
||||
Argument::CRField(x) => x.0 as i64,
|
||||
Argument::CRBit(x) => x.0 as i64,
|
||||
Argument::GQR(x) => x.0 as i64,
|
||||
Argument::Uimm(x) => x.0 as i64,
|
||||
Argument::Simm(x) => x.0 as i64,
|
||||
Argument::Offset(x) => x.0 as i64,
|
||||
Argument::BranchDest(x) => x.0 as i64,
|
||||
Argument::Bit(x) => x.0 as i64,
|
||||
Argument::OpaqueU(x) => x.0 as i64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryInto<Argument> for &Field {
|
||||
type Error = ();
|
||||
fn try_into(self) -> Result<Argument, Self::Error> {
|
||||
self.argument().ok_or(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Opcode {
|
||||
/// Detects the opcode of a machine code instruction.
|
||||
pub fn detect(code: u32) -> Self {
|
||||
|
|
|
@ -40,6 +40,7 @@ fn _main() -> Result<()> {
|
|||
)?;
|
||||
writeln!(&mut unformatted_code, "{}", isa.gen_opcode_enum()?)?;
|
||||
writeln!(&mut unformatted_code, "{}", isa.gen_field_enum()?)?;
|
||||
writeln!(&mut unformatted_code, "{}", isa.gen_field_impl()?)?;
|
||||
writeln!(&mut unformatted_code, "{}", isa.gen_ins_impl()?)?;
|
||||
|
||||
let formatted_code = rustfmt(unformatted_code);
|
||||
|
@ -160,7 +161,7 @@ impl Field {
|
|||
})
|
||||
}
|
||||
|
||||
fn construct_variant(&self, code: TokenStream) -> TokenStream {
|
||||
pub(crate) fn construct_variant(&self, code: TokenStream) -> TokenStream {
|
||||
let field_variant = self.variant_identifier();
|
||||
if let Some(arg) = &self.arg {
|
||||
let field_arg = TokenTree::Ident(Ident::new(arg, Span::call_site()));
|
||||
|
@ -334,7 +335,7 @@ impl Isa {
|
|||
Ok(mnemonic_fn)
|
||||
}
|
||||
|
||||
pub(crate) fn gen_opcode_detect(&self) -> Result<TokenStream> {
|
||||
fn gen_opcode_detect(&self) -> Result<TokenStream> {
|
||||
// Generate if chain.
|
||||
let if_chain = self
|
||||
.opcodes
|
||||
|
@ -363,7 +364,7 @@ impl Isa {
|
|||
Ok(func)
|
||||
}
|
||||
|
||||
pub(crate) fn gen_field_enum(&self) -> Result<TokenStream> {
|
||||
fn gen_field_enum(&self) -> Result<TokenStream> {
|
||||
// Create enum variants.
|
||||
let mut enum_variants = Vec::new();
|
||||
for field in &self.fields {
|
||||
|
@ -384,7 +385,58 @@ impl Isa {
|
|||
Ok(field_enum)
|
||||
}
|
||||
|
||||
pub(crate) fn gen_ins_impl(&self) -> Result<TokenStream> {
|
||||
fn gen_field_argument(&self) -> Result<TokenStream> {
|
||||
let mut match_arms = Vec::new();
|
||||
for field in &self.fields {
|
||||
if let Some(variant) = field.variant_identifier() {
|
||||
if let Some(arg_str) = field.arg.as_ref() {
|
||||
let arg = Ident::new(arg_str, Span::call_site());
|
||||
match_arms.push(quote! { Field::#variant(x) => Some(Argument::#arg(*x)), });
|
||||
}
|
||||
}
|
||||
}
|
||||
let match_arms = token_stream!(match_arms);
|
||||
Ok(quote! {
|
||||
pub fn argument(&self) -> Option<Argument> {
|
||||
match self {
|
||||
#match_arms
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn gen_field_name(&self) -> Result<TokenStream> {
|
||||
let mut match_arms = Vec::new();
|
||||
for field in &self.fields {
|
||||
if let Some(variant) = field.variant_identifier() {
|
||||
let name = LitStr::new(&variant.to_string(), Span::call_site());
|
||||
let arg = field.arg.as_ref().map(|_| quote!((_)));
|
||||
match_arms.push(quote! { Field::#variant #arg => #name, });
|
||||
}
|
||||
}
|
||||
let match_arms = token_stream!(match_arms);
|
||||
Ok(quote! {
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
#match_arms
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn gen_field_impl(&self) -> Result<TokenStream> {
|
||||
let field_argument = self.gen_field_argument()?;
|
||||
let field_name = self.gen_field_name()?;
|
||||
Ok(quote! {
|
||||
impl Field {
|
||||
#field_argument
|
||||
#field_name
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn gen_ins_impl(&self) -> Result<TokenStream> {
|
||||
// Map fields by name.
|
||||
let mut field_by_name = HashMap::<String, &Field>::new();
|
||||
for field in &self.fields {
|
||||
|
|
Loading…
Reference in New Issue