disasm-py: add fields() method
This commit is contained in:
parent
88c6a478e2
commit
9dab42c364
|
@ -31,6 +31,14 @@ impl Ins {
|
||||||
fn __str__(&self) -> String {
|
fn __str__(&self) -> String {
|
||||||
FormattedIns(self.0.clone()).to_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)]
|
#[allow(non_snake_case)]
|
||||||
|
|
|
@ -1167,6 +1167,92 @@ pub enum Field {
|
||||||
ctr,
|
ctr,
|
||||||
lr,
|
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)]
|
#[allow(clippy::all, unused_mut)]
|
||||||
impl Ins {
|
impl Ins {
|
||||||
pub(crate) fn _fields(&self) -> Vec<Field> {
|
pub(crate) fn _fields(&self) -> Vec<Field> {
|
||||||
|
|
|
@ -166,50 +166,33 @@ impl Display for Argument {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Field {
|
impl Into<i64> for Argument {
|
||||||
pub fn argument(&self) -> Option<Argument> {
|
fn into(self) -> i64 {
|
||||||
match self {
|
match self {
|
||||||
Field::simm(x) => Some(Argument::Simm(*x)),
|
Argument::GPR(x) => x.0 as i64,
|
||||||
Field::uimm(x) => Some(Argument::Uimm(*x)),
|
Argument::FPR(x) => x.0 as i64,
|
||||||
Field::offset(x) => Some(Argument::Offset(*x)),
|
Argument::SR(x) => x.0 as i64,
|
||||||
Field::ps_offset(x) => Some(Argument::Offset(*x)),
|
Argument::SPR(x) => x.0 as i64,
|
||||||
Field::BO(x) => Some(Argument::OpaqueU(*x)),
|
Argument::CRField(x) => x.0 as i64,
|
||||||
Field::BI(x) => Some(Argument::OpaqueU(*x)),
|
Argument::CRBit(x) => x.0 as i64,
|
||||||
Field::BD(x) => Some(Argument::BranchDest(*x)),
|
Argument::GQR(x) => x.0 as i64,
|
||||||
Field::LI(x) => Some(Argument::BranchDest(*x)),
|
Argument::Uimm(x) => x.0 as i64,
|
||||||
Field::SH(x) => Some(Argument::OpaqueU(*x)),
|
Argument::Simm(x) => x.0 as i64,
|
||||||
Field::MB(x) => Some(Argument::OpaqueU(*x)),
|
Argument::Offset(x) => x.0 as i64,
|
||||||
Field::ME(x) => Some(Argument::OpaqueU(*x)),
|
Argument::BranchDest(x) => x.0 as i64,
|
||||||
Field::rS(x) => Some(Argument::GPR(*x)),
|
Argument::Bit(x) => x.0 as i64,
|
||||||
Field::rD(x) => Some(Argument::GPR(*x)),
|
Argument::OpaqueU(x) => x.0 as i64,
|
||||||
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,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryInto<Argument> for &Field {
|
||||||
|
type Error = ();
|
||||||
|
fn try_into(self) -> Result<Argument, Self::Error> {
|
||||||
|
self.argument().ok_or(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Opcode {
|
impl Opcode {
|
||||||
/// Detects the opcode of a machine code instruction.
|
/// Detects the opcode of a machine code instruction.
|
||||||
pub fn detect(code: u32) -> Self {
|
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_opcode_enum()?)?;
|
||||||
writeln!(&mut unformatted_code, "{}", isa.gen_field_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()?)?;
|
writeln!(&mut unformatted_code, "{}", isa.gen_ins_impl()?)?;
|
||||||
|
|
||||||
let formatted_code = rustfmt(unformatted_code);
|
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();
|
let field_variant = self.variant_identifier();
|
||||||
if let Some(arg) = &self.arg {
|
if let Some(arg) = &self.arg {
|
||||||
let field_arg = TokenTree::Ident(Ident::new(arg, Span::call_site()));
|
let field_arg = TokenTree::Ident(Ident::new(arg, Span::call_site()));
|
||||||
|
@ -334,7 +335,7 @@ impl Isa {
|
||||||
Ok(mnemonic_fn)
|
Ok(mnemonic_fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn gen_opcode_detect(&self) -> Result<TokenStream> {
|
fn gen_opcode_detect(&self) -> Result<TokenStream> {
|
||||||
// Generate if chain.
|
// Generate if chain.
|
||||||
let if_chain = self
|
let if_chain = self
|
||||||
.opcodes
|
.opcodes
|
||||||
|
@ -363,7 +364,7 @@ impl Isa {
|
||||||
Ok(func)
|
Ok(func)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn gen_field_enum(&self) -> Result<TokenStream> {
|
fn gen_field_enum(&self) -> Result<TokenStream> {
|
||||||
// Create enum variants.
|
// Create enum variants.
|
||||||
let mut enum_variants = Vec::new();
|
let mut enum_variants = Vec::new();
|
||||||
for field in &self.fields {
|
for field in &self.fields {
|
||||||
|
@ -384,7 +385,58 @@ impl Isa {
|
||||||
Ok(field_enum)
|
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.
|
// Map fields by name.
|
||||||
let mut field_by_name = HashMap::<String, &Field>::new();
|
let mut field_by_name = HashMap::<String, &Field>::new();
|
||||||
for field in &self.fields {
|
for field in &self.fields {
|
||||||
|
|
Loading…
Reference in New Issue