re-implement formatting

This commit is contained in:
Richard Patel 2021-08-29 06:06:08 +02:00
parent 5833e81236
commit f04c68578b
5 changed files with 127 additions and 123 deletions

View File

@ -1,107 +1,122 @@
use std::fmt::{Display, LowerHex, UpperHex};
use std::io::Write;
use std::fmt::{Display, LowerHex, UpperHex, Formatter};
use num_traits::PrimInt;
use crate::Ins;
use crate::prelude::*;
/*
type IOResult = std::io::Result<()>;
pub struct FormattedIns(pub Ins);
pub trait AsmFormatter<W>
where
W: Write,
{
fn write_ins(ins: &Ins);
}
pub struct SimpleFormatter();
impl<W: Write> SimpleFormatter {
/// Writes the instruction mnemonic.
fn write_mnemonic(writer: &mut W, name: &str) -> IOResult {
write!(writer, "{}", name)
}
/// Separates the instruction mnemonic and arguments.
fn write_opcode_separator(writer: &mut W) -> IOResult {
write!(writer, " ")
}
/// Separates two instruction arguments (e.g. registers).
fn write_operand_separator(writer: &mut W) -> IOResult {
write!(writer, ", ")
}
/// Writes a general-purpose register argument.
fn write_gpr(writer: &mut W, reg: u8) -> IOResult {
write!(writer, "r{}", reg)
}
/// Writes a nullable general-purpose register argument.
fn write_gpr0(writer: &mut W, reg: u8) -> IOResult {
if reg != 0 {
Self::write_gpr(writer, reg)
} else {
write!(writer, "0")
}
}
/// Writes a floating point register argument.
fn write_fpr(writer: &mut W, reg: u8) -> IOResult {
write!(writer, "f{}", reg)
}
/// Writes a condition register argument.
fn write_cr(writer: &mut W, reg: u8) -> IOResult {
write!(writer, "cr{}", reg)
}
/// Writes a paired-singles quantization register argument.
fn write_qr(writer: &mut W, reg: u8) -> IOResult {
write!(writer, "qr{}", reg)
}
fn write_sr(writer: &mut W, reg: u8) -> IOResult {
write!(writer, "{}", reg)
}
/// Sets the mnemonic 'o' suffix.
fn write_oe(writer: &mut W, oe: u8) -> IOResult {
if oe != 0 {
write!(writer, "o")?;
}
Ok(())
}
/// Sets the mnemonic 'a' suffix.
fn write_aa(writer: &mut W, aa: u8) -> IOResult {
if aa != 0 {
write!(writer, "a")?;
}
Ok(())
}
/// Sets the mnemonic 'l' suffix.
fn write_lk(writer: &mut W, lk: u8) -> IOResult {
if lk != 0 {
write!(writer, "l")?;
}
Ok(())
}
/// Sets the mnemonic '.' suffix.
fn write_rc(writer: &mut W, rc: u8) -> IOResult {
if rc != 0 {
write!(writer, ".")?;
}
Ok(())
impl Display for FormattedIns {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.fmt_ins(f)
}
}
impl<W: Write> AsmFormatter<W> for SimpleFormatter<W> {
fn write_ins(ins: &Ins) {
todo!()
impl FormattedIns {
fn fmt_ins(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mnemonic = self.0.op.mnemonic();
write!(f, "{} ", mnemonic)?;
let fields = self.0.fields();
let mut writing_offset = false;
for (i, field) in fields.iter().enumerate() {
if let offset(o) = field {
writing_offset = true;
write!(f, "{:#x}(", ReallySigned(o.0))?;
continue;
}
Self::fmt_field(field, f)?;
if writing_offset {
write!(f, ")")?;
}
if i != fields.len() - 1 {
write!(f, ", ")?;
}
}
Ok(())
}
fn fmt_field(field: &Field, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match field {
simm(s) => Self::fmt_simm(*s, f),
uimm(u) => Self::fmt_uimm(*u, f),
BO(o) => Self::fmt_opaque_u(*o, f),
BI(o) => Self::fmt_opaque_u(*o, f),
BD(bd) => Self::fmt_branch_dest(*bd, f),
LI(bd) => Self::fmt_branch_dest(*bd, f),
SH(o) => Self::fmt_opaque_u(*o, f),
MB(o) => Self::fmt_opaque_u(*o, f),
ME(o) => Self::fmt_opaque_u(*o, f),
rS(gpr) => Self::fmt_gpr(*gpr, f),
rD(gpr) => Self::fmt_gpr(*gpr, f),
rA(gpr) => Self::fmt_gpr(*gpr, f),
rB(gpr) => Self::fmt_gpr(*gpr, f),
rC(gpr) => Self::fmt_gpr(*gpr, f),
sr(s) => Self::fmt_sr(*s, f),
spr(s) => Self::fmt_spr(*s, f),
frS(fpr) => Self::fmt_fpr(*fpr, f),
frD(fpr) => Self::fmt_fpr(*fpr, f),
frA(fpr) => Self::fmt_fpr(*fpr, f),
frB(fpr) => Self::fmt_fpr(*fpr, f),
frC(fpr) => Self::fmt_fpr(*fpr, f),
crbD(crb) => Self::fmt_crb(*crb, f),
crbA(crb) => Self::fmt_crb(*crb, f),
crbB(crb) => Self::fmt_crb(*crb, f),
crfD(crf) => Self::fmt_crf(*crf, f),
crfS(crf) => Self::fmt_crf(*crf, f),
crm(o) => Self::fmt_opaque_u(*o, f),
ps_l(gqr) => Self::fmt_gqr(*gqr, f),
ps_W(o) => Self::fmt_opaque_u(*o, f),
NB(o) => Self::fmt_opaque_u(*o, f),
tbr(o) => Self::fmt_opaque_u(*o, f),
mtfsf_FM(o) => Self::fmt_opaque_u(*o, f),
mtfsf_IMM(o) => Self::fmt_opaque_u(*o, f),
tw_TO(o) => Self::fmt_opaque_u(*o, f),
_ => Ok(()),
}
}
fn fmt_gpr(gpr: GPR, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "r{}", gpr.0)
}
fn fmt_fpr(gpr: FPR, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "fr{}", gpr.0)
}
fn fmt_opaque_u(u: OpaqueU, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", u.0)
}
fn fmt_gqr(gqr: GQR, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", gqr.0)
}
fn fmt_spr(s: SPR, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", s.0)
}
fn fmt_sr(s: SR, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", s.0)
}
fn fmt_crb(crb: CRField, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", crb.0)
}
fn fmt_crf(crf: CRBit, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", crf.0)
}
fn fmt_branch_dest(bd: BranchDest, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:#x}", ReallySigned(bd.0))
}
fn fmt_uimm(u: Uimm, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:#x}", u.0)
}
fn fmt_simm(s: Simm, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:#x}", ReallySigned(s.0))
}
}
@ -125,4 +140,3 @@ impl<N: PrimInt> UpperHex for ReallySigned<N> {
f.pad_integral(num >= 0, prefix, &bare_hex)
}
}
*/

View File

@ -1,9 +1,11 @@
//pub mod formatter;
pub mod formatter;
mod iter;
pub mod prelude {
pub use crate::Field;
pub use crate::Field::*;
pub use crate::Ins;
pub use crate::formatter::FormattedIns;
pub use crate::Opcode::*;
pub use crate::{
Bit, BranchDest, CRBit, CRField, Offset, OpaqueU, Simm, Uimm, FPR, GPR, GQR, SPR, SR,
@ -105,14 +107,3 @@ impl Ins {
}
ins_impl!();
/*
impl ToString for Ins {
fn to_string(&self) -> String {
let buf = Vec::<u8>::new();
let mut formatter = SimpleFormatter::new(buf);
self.write_string(&mut formatter).unwrap();
unsafe { String::from_utf8_unchecked(formatter.writer) }
}
}
*/

View File

@ -1,10 +1,17 @@
use ppc750cl::prelude::*;
macro_rules! assert_asm {
($ins:ident, $disasm:literal) => {{
assert_eq!(format!("{}", FormattedIns($ins)), $disasm)
}};
}
#[test]
fn test_ins_addc() {
let ins = Ins::new(0x7c002014, 0x8000_0000u32);
assert_eq!(ins.op, Addc);
assert_eq!(ins.fields(), vec![rD(GPR(0)), rA(GPR(0)), rB(GPR(4))]);
assert_asm!(ins, "addc r0, r0, r4");
}
#[test]
@ -17,6 +24,7 @@ fn test_ins_addi() {
);
assert_eq!(ins.defs(), vec![rD(GPR(0))]);
assert_eq!(ins.uses(), vec![rA(GPR(1))]);
assert_asm!(ins, "addi r0, r1, 0x140");
}
#[test]
@ -38,11 +46,6 @@ fn test_ins_psq_lx() {
}
/*
macro_rules! assert_asm {
($code:expr, $disasm:expr) => {{
assert_eq!(Ins::new($code, 0x8000_0000u32).to_string(), $disasm)
}};
}
#[test]
fn test_ins_addc() {

View File

@ -44,7 +44,7 @@ impl Field {
if self.name.strip_suffix(".nz").is_none() {
Some(to_rust_ident(&self.name))
} else {
return None;
None
}
}
@ -61,11 +61,7 @@ impl Field {
}
fn enum_variant_definition(&self) -> Option<TokenStream> {
let ident = if let Some(ident) = self.variant_identifier() {
ident
} else {
return None;
};
let ident = self.variant_identifier()?;
Some(if let Some(arg) = &self.arg {
let arg = TokenTree::Ident(Ident::new(arg, Span::call_site()));
quote! {

View File

@ -17,7 +17,7 @@ pub fn opcodes(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
};
match isa.gen_opcode_enum() {
Ok(v) => v.into(),
Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()),
Err(err) => proc_macro::TokenStream::from(err.to_compile_error()),
}
}
@ -29,7 +29,7 @@ pub fn fields(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
};
match isa.gen_field_enum() {
Ok(v) => v.into(),
Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()),
Err(err) => proc_macro::TokenStream::from(err.to_compile_error()),
}
}
@ -41,7 +41,7 @@ pub fn ins_impl(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
};
match isa.gen_ins_impl() {
Ok(v) => v.into(),
Err(err) => return proc_macro::TokenStream::from(err.to_compile_error()),
Err(err) => proc_macro::TokenStream::from(err.to_compile_error()),
}
}