mirror of
https://github.com/encounter/ppc750cl.git
synced 2025-08-14 08:09:13 +00:00
re-implement formatting
This commit is contained in:
parent
5833e81236
commit
f04c68578b
@ -1,107 +1,122 @@
|
|||||||
use std::fmt::{Display, LowerHex, UpperHex};
|
use std::fmt::{Display, LowerHex, UpperHex, Formatter};
|
||||||
use std::io::Write;
|
|
||||||
|
|
||||||
use num_traits::PrimInt;
|
use num_traits::PrimInt;
|
||||||
|
|
||||||
use crate::Ins;
|
use crate::prelude::*;
|
||||||
|
|
||||||
/*
|
pub struct FormattedIns(pub Ins);
|
||||||
type IOResult = std::io::Result<()>;
|
|
||||||
|
|
||||||
pub trait AsmFormatter<W>
|
impl Display for FormattedIns {
|
||||||
where
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
W: Write,
|
self.fmt_ins(f)
|
||||||
{
|
|
||||||
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<W: Write> AsmFormatter<W> for SimpleFormatter<W> {
|
impl FormattedIns {
|
||||||
fn write_ins(ins: &Ins) {
|
fn fmt_ins(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
todo!()
|
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)
|
f.pad_integral(num >= 0, prefix, &bare_hex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
//pub mod formatter;
|
pub mod formatter;
|
||||||
mod iter;
|
mod iter;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
pub use crate::Field;
|
||||||
pub use crate::Field::*;
|
pub use crate::Field::*;
|
||||||
pub use crate::Ins;
|
pub use crate::Ins;
|
||||||
|
pub use crate::formatter::FormattedIns;
|
||||||
pub use crate::Opcode::*;
|
pub use crate::Opcode::*;
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
Bit, BranchDest, CRBit, CRField, Offset, OpaqueU, Simm, Uimm, FPR, GPR, GQR, SPR, SR,
|
Bit, BranchDest, CRBit, CRField, Offset, OpaqueU, Simm, Uimm, FPR, GPR, GQR, SPR, SR,
|
||||||
@ -105,14 +107,3 @@ impl Ins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ins_impl!();
|
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) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
use ppc750cl::prelude::*;
|
use ppc750cl::prelude::*;
|
||||||
|
|
||||||
|
macro_rules! assert_asm {
|
||||||
|
($ins:ident, $disasm:literal) => {{
|
||||||
|
assert_eq!(format!("{}", FormattedIns($ins)), $disasm)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ins_addc() {
|
fn test_ins_addc() {
|
||||||
let ins = Ins::new(0x7c002014, 0x8000_0000u32);
|
let ins = Ins::new(0x7c002014, 0x8000_0000u32);
|
||||||
assert_eq!(ins.op, Addc);
|
assert_eq!(ins.op, Addc);
|
||||||
assert_eq!(ins.fields(), vec![rD(GPR(0)), rA(GPR(0)), rB(GPR(4))]);
|
assert_eq!(ins.fields(), vec![rD(GPR(0)), rA(GPR(0)), rB(GPR(4))]);
|
||||||
|
assert_asm!(ins, "addc r0, r0, r4");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -17,6 +24,7 @@ fn test_ins_addi() {
|
|||||||
);
|
);
|
||||||
assert_eq!(ins.defs(), vec![rD(GPR(0))]);
|
assert_eq!(ins.defs(), vec![rD(GPR(0))]);
|
||||||
assert_eq!(ins.uses(), vec![rA(GPR(1))]);
|
assert_eq!(ins.uses(), vec![rA(GPR(1))]);
|
||||||
|
assert_asm!(ins, "addi r0, r1, 0x140");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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]
|
#[test]
|
||||||
fn test_ins_addc() {
|
fn test_ins_addc() {
|
||||||
|
@ -44,7 +44,7 @@ impl Field {
|
|||||||
if self.name.strip_suffix(".nz").is_none() {
|
if self.name.strip_suffix(".nz").is_none() {
|
||||||
Some(to_rust_ident(&self.name))
|
Some(to_rust_ident(&self.name))
|
||||||
} else {
|
} else {
|
||||||
return None;
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,11 +61,7 @@ impl Field {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn enum_variant_definition(&self) -> Option<TokenStream> {
|
fn enum_variant_definition(&self) -> Option<TokenStream> {
|
||||||
let ident = if let Some(ident) = self.variant_identifier() {
|
let ident = self.variant_identifier()?;
|
||||||
ident
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
};
|
|
||||||
Some(if let Some(arg) = &self.arg {
|
Some(if let Some(arg) = &self.arg {
|
||||||
let arg = TokenTree::Ident(Ident::new(arg, Span::call_site()));
|
let arg = TokenTree::Ident(Ident::new(arg, Span::call_site()));
|
||||||
quote! {
|
quote! {
|
||||||
|
@ -17,7 +17,7 @@ pub fn opcodes(_: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|||||||
};
|
};
|
||||||
match isa.gen_opcode_enum() {
|
match isa.gen_opcode_enum() {
|
||||||
Ok(v) => v.into(),
|
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() {
|
match isa.gen_field_enum() {
|
||||||
Ok(v) => v.into(),
|
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() {
|
match isa.gen_ins_impl() {
|
||||||
Ok(v) => v.into(),
|
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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user