switch output format to JSON to allow easier parsing
authorJacob Lifshay <programmerjake@gmail.com>
Thu, 28 May 2020 04:51:34 +0000 (21:51 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Thu, 28 May 2020 04:51:34 +0000 (21:51 -0700)
Cargo.lock
Cargo.toml
src/main.rs
src/serde_hex.rs [new file with mode: 0644]

index dfc8fec07ada3f501b0b74aa8bb20338967e4a22..a7b295ab2e8e36355727d94e5f8d33246a87538f 100644 (file)
@@ -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"
index 543c7b3305f331e55a5312d22c5d7f6be063513e..8992fa9fd037c80cc999147ffa8f3390c8ccf020 100644 (file)
@@ -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
index 5cdde9e0030f0d9c49d68b3cac42349d555d2b75..3647f97364bd85895e5695f9874edf6713b757d6 100644 (file)
@@ -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<OverflowFlags>,
 }
 
-#[derive(Copy, Clone, Debug)]
-struct TestDivResult {
-    result: u64,
-    overflow: Option<OverflowFlags>,
-}
-
-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 &dividend 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 (file)
index 0000000..c3f4bd0
--- /dev/null
@@ -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<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
+    fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
+    where
+        Self: Sized;
+}
+
+impl SerdeHex for u64 {
+    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
+        serializer.serialize_str(&format!("{:#X}", self))
+    }
+    fn deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
+        let _text: &str = Deserialize::deserialize(deserializer)?;
+        todo!("parse text as 0x<HEXDIGITS>")
+    }
+}