From 9dda102601441f8520716750d1a4a2948e5bbe1c Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Wed, 27 May 2020 21:51:34 -0700 Subject: [PATCH] switch output format to JSON to allow easier parsing --- Cargo.lock | 82 ++++++++++++++++++++++ Cargo.toml | 2 + src/main.rs | 175 ++++++++++++++++++++++++++++------------------- src/serde_hex.rs | 21 ++++++ 4 files changed, 209 insertions(+), 71 deletions(-) create mode 100644 src/serde_hex.rs diff --git a/Cargo.lock b/Cargo.lock index dfc8fec..a7b295a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,87 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "itoa" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" + [[package]] name = "power-instruction-analyzer" version = "0.1.0" +dependencies = [ + "serde", + "serde_json", +] + +[[package]] +name = "proc-macro2" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "ryu" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" + +[[package]] +name = "serde" +version = "1.0.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef781e621ee763a2a40721a8861ec519cb76966aee03bb5d00adb6a31dc1c1de" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/Cargo.toml b/Cargo.toml index 543c7b3..8992fa9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,5 @@ edition = "2018" license = "LGPL-2.1-or-later" [dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 5cdde9e..3647f97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,16 +2,19 @@ // See Notices.txt for copyright information #![feature(llvm_asm)] -use std::fmt; -#[derive(Copy, Clone, Debug)] -struct OverflowFlags { - overflow: bool, - overflow32: bool, +mod serde_hex; + +use serde::{Deserialize, Serialize}; + +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub struct OverflowFlags { + pub overflow: bool, + pub overflow32: bool, } impl OverflowFlags { - fn from_xer(xer: u64) -> Self { + pub fn from_xer(xer: u64) -> Self { Self { overflow: (xer & 0x4000_0000) != 0, overflow32: (xer & 0x8_0000) != 0, @@ -19,75 +22,90 @@ impl OverflowFlags { } } -impl fmt::Display for OverflowFlags { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let Self { - overflow, - overflow32, - } = *self; - write!( - f, - "OV:{overflow}, OV32:{overflow32}", - overflow = overflow as i32, - overflow32 = overflow32 as i32, - ) - } +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub struct TestDivResult { + #[serde(with = "serde_hex::SerdeHex")] + pub result: u64, + #[serde(default, flatten, skip_serializing_if = "Option::is_none")] + pub overflow: Option, } -#[derive(Copy, Clone, Debug)] -struct TestDivResult { - result: u64, - overflow: Option, -} - -impl fmt::Display for TestDivResult { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let Self { result, overflow } = *self; - write!(f, "{:#X}", result)?; - if let Some(overflow) = overflow { - write!(f, ", {}", overflow)?; - } - Ok(()) - } +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub struct TestDivInput { + #[serde(with = "serde_hex::SerdeHex")] + pub dividend: u64, + #[serde(with = "serde_hex::SerdeHex")] + pub divisor: u64, + #[serde(with = "serde_hex::SerdeHex")] + pub result_prev: u64, } -#[derive(Copy, Clone, Debug)] -struct TestDivInput { - dividend: u64, - divisor: u64, - result_prev: u64, -} - -impl fmt::Display for TestDivInput { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let Self { - dividend, - divisor, - result_prev, - } = *self; - write!( - f, - "{:#X} div {:#X} (result_prev:{:#X})", - dividend, divisor, result_prev, - ) - } +#[derive(Copy, Clone, Debug, Serialize, Deserialize)] +pub struct TestDivCase { + pub instr: TestDivInstr, + #[serde(flatten)] + pub inputs: TestDivInput, + #[serde(flatten)] + pub outputs: TestDivResult, } macro_rules! make_div_functions { ( #[div] { - $($div_name:ident;)+ + $($div_enum:ident = $div_fn:ident ($div_instr:literal),)+ } #[rem] { - $($rem_name:ident;)+ + $($rem_enum:ident = $rem_fn:ident ($rem_instr:literal),)+ } ) => { + #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)] + pub enum TestDivInstr { + $( + #[serde(rename = $div_instr)] + $div_enum, + )+ + $( + #[serde(rename = $rem_instr)] + $rem_enum, + )+ + } + + impl TestDivInstr { + pub fn get_fn(self) -> fn(TestDivInput) -> TestDivResult { + match self { + $( + Self::$div_enum => TestDivInput::$div_fn, + )+ + $( + Self::$rem_enum => TestDivInput::$rem_fn, + )+ + } + } + pub fn name(self) -> &'static str { + match self { + $( + Self::$div_enum => $div_instr, + )+ + $( + Self::$rem_enum => $rem_instr, + )+ + } + } + pub const VALUES: &'static [Self] = &[ + $( + Self::$div_enum, + )+ + $( + Self::$rem_enum, + )+ + ]; + } + impl TestDivInput { $( - #[inline(never)] - pub fn $div_name(self) -> TestDivResult { + pub fn $div_fn(self) -> TestDivResult { let Self { dividend, divisor, @@ -98,7 +116,7 @@ macro_rules! make_div_functions { unsafe { llvm_asm!( concat!( - stringify!($div_name), + $div_instr, " $0, $3, $4\n", "mfxer $1" ) @@ -113,8 +131,7 @@ macro_rules! make_div_functions { } )+ $( - #[inline(never)] - pub fn $rem_name(self) -> TestDivResult { + pub fn $rem_fn(self) -> TestDivResult { let Self { dividend, divisor, @@ -124,7 +141,7 @@ macro_rules! make_div_functions { unsafe { llvm_asm!( concat!( - stringify!($rem_name), + $rem_instr, " $0, $2, $3" ) : "=&r"(result) @@ -136,19 +153,29 @@ macro_rules! make_div_functions { } } )+ - pub const FUNCTIONS: &'static [(fn(TestDivInput) -> TestDivResult, &'static str)] = &[ - $((Self::$div_name, stringify!($div_name)),)+ - $((Self::$rem_name, stringify!($rem_name)),)+ - ]; } }; } make_div_functions! { #[div] - {divdeo; divdeuo; divdo; divduo; divweo; divweuo; divwo; divwuo;} + { + DivDE = divde("divdeo"), + DivDEU = divdeu("divdeuo"), + DivD = divd("divdo"), + DivDU = divdu("divduo"), + DivWE = divwe("divweo"), + DivWEU = divweu("divweuo"), + DivW = divw("divwo"), + DivWU = divwu("divwuo"), + } #[rem] - {modsd; modud; modsw; moduw;} + { + ModSD = modsd("modsd"), + ModUD = modud("modud"), + ModSW = modsw("modsw"), + ModUW = moduw("moduw"), + } } const TEST_VALUES: &[u64] = &[ @@ -163,7 +190,8 @@ const TEST_VALUES: &[u64] = &[ ]; fn main() { - for &(f, name) in TestDivInput::FUNCTIONS { + let mut cases = Vec::new(); + for &instr in TestDivInstr::VALUES { for ÷nd in TEST_VALUES { for &divisor in TEST_VALUES { let inputs = TestDivInput { @@ -171,9 +199,14 @@ fn main() { divisor, result_prev: 0xFECD_BA98_7654_3210, }; - let outputs = f(inputs); - println!("{}: {} -> {}", name, inputs, outputs); + let outputs = instr.get_fn()(inputs); + cases.push(TestDivCase { + instr, + inputs, + outputs, + }); } } } + serde_json::to_writer_pretty(std::io::stdout().lock(), &cases).unwrap(); } diff --git a/src/serde_hex.rs b/src/serde_hex.rs new file mode 100644 index 0000000..c3f4bd0 --- /dev/null +++ b/src/serde_hex.rs @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// See Notices.txt for copyright information + +use serde::{Deserialize, Deserializer, Serializer}; + +pub(crate) trait SerdeHex { + fn serialize(&self, serializer: S) -> Result; + fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result + where + Self: Sized; +} + +impl SerdeHex for u64 { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_str(&format!("{:#X}", self)) + } + fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result { + let _text: &str = Deserialize::deserialize(deserializer)?; + todo!("parse text as 0x") + } +} -- 2.30.2