Simple program to output Markdown
5 files changed, 234 insertions(+), 59 deletions(-)

A => .hgignore
A => Cargo.lock
A => Cargo.toml
M instructions.toml
A => src/main.rs
A => .hgignore +1 -0
@@ 0,0 1,1 @@ 
+^target/

          
A => Cargo.lock +118 -0
@@ 0,0 1,118 @@ 
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "argh"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbb41d85d92dfab96cb95ab023c265c5e4261bb956c0fb49ca06d90c570f1958"
+dependencies = [
+ "argh_derive",
+ "argh_shared",
+]
+
+[[package]]
+name = "argh_derive"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be69f70ef5497dd6ab331a50bd95c6ac6b8f7f17a7967838332743fbd58dc3b5"
+dependencies = [
+ "argh_shared",
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "argh_shared"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6f8c380fa28aa1b36107cd97f0196474bb7241bb95a453c5c01a15ac74b2eac"
+
+[[package]]
+name = "heck"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
+dependencies = [
+ "unicode-segmentation",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec757218438d5fda206afc041538b2f6d889286160d649a86a24d37e1235afd1"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "riscv-reference"
+version = "0.1.0"
+dependencies = [
+ "argh",
+ "serde",
+ "serde_derive",
+ "toml",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.137"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
+
+[[package]]
+name = "serde_derive"
+version = "1.0.137"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "toml"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "unicode-segmentation"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"

          
A => Cargo.toml +12 -0
@@ 0,0 1,12 @@ 
+[package]
+name = "riscv-reference"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+toml = "0.5"
+serde = "1"
+serde_derive = "1"
+argh = "0.1"

          
M instructions.toml +59 -59
@@ 49,7 49,7 @@ NOT rd, rs).
 
 [ORI]
 name = "OR immediate"
-opcode = "OP-IMM / "
+opcode = "OP-IMM / ORI"
 encoding = "I"
 extension = "I"
 long_description = """

          
@@ 61,7 61,7 @@ NOT rd, rs).
 
 [XORI]
 name = "XOR immediate"
-opcode = "OP-IMM / "
+opcode = "OP-IMM / XORI"
 encoding = "I"
 extension = "I"
 long_description = """

          
@@ 74,6 74,7 @@ NOT rd, rs).
 [SLLI]
 name = "Shift left logical immediate"
 opcode = "OP-IMM / SLLI"
+encoding = "I"
 extension = "I"
 long_description = """
 Shifts by a constant are encoded as a specialization of the I-type

          
@@ 485,7 486,7 @@ instructions with rd=x0. Hence, like the
 visible state, except for advancing the pc and any applicable performance counters. Implementations are always allowed to ignore the encoded hints.
 """
 
-[FENCE.I]
+["FENCE.I"]
 name = "Fence"
 opcode = "MISC-MEM / FENCE.I"
 encoding = "I"

          
@@ 634,8 635,7 @@ auipc rd, delta[31 : 12] + delta[11]
 addi rd, rd, delta[11:0]
 """
 
-
-[LB/LH/LW/LD]
+["LB/LH/LW/LD"]
 name = "Load global byte/halfword/word/double"
 opcode = ""
 encoding = "pseudo"

          
@@ 647,7 647,7 @@ auipc rd, delta[31 : 12] + delta[11]
 l{b|h|w|d} rd, delta[11:0](rd)
 """
 
-[SB/SH/SW/SD]
+["SB/SH/SW/SD"]
 name = "Store global byte/halfword/word/double"
 opcode = ""
 encoding = "pseudo"

          
@@ 713,7 713,7 @@ subw rd, x0, rs
 """
 
 
-[SEXT.W]
+["SEXT.W"]
 name = "Sign extend word"
 opcode = ""
 encoding = "pseudo"

          
@@ 1087,7 1087,7 @@ corresponding signed and unsigned remain
 always sign-extend the 32-bit result to 64 bits, including on a divide by zero.
 """
 
-[LR.W]
+["LR.W"]
 name = "Load reserved word"
 opcode = "AMO / width / LR.W"
 encoding = "R"

          
@@ 1105,7 1105,7 @@ any reservation held by this hart. LR.D 
 available on RV64. For RV64, LR.W and SC.W sign-extend the value placed in rd.
 """
 
-[LR.D]
+["LR.D"]
 name = "Load reserved doubleword"
 opcode = "AMO / width / LR.D"
 encoding = "R"

          
@@ 1123,7 1123,7 @@ any reservation held by this hart. LR.D 
 available on RV64. For RV64, LR.W and SC.W sign-extend the value placed in rd.
 """
 
-[SC.W]
+["SC.W"]
 name = "Store conditional word"
 opcode = "AMO / width / SC.W"
 encoding = "R"

          
@@ 1141,7 1141,7 @@ any reservation held by this hart. LR.D 
 available on RV64. For RV64, LR.W and SC.W sign-extend the value placed in rd.
 """
 
-[SC.D]
+["SC.D"]
 name = "Store conditional doubleword"
 opcode = "AMO / width / SC.D"
 encoding = "R"

          
@@ 1160,7 1160,7 @@ available on RV64. For RV64, LR.W and SC
 """
 
 
-[AMOSWAP.W]
+["AMOSWAP.W"]
 name = "Atomic swap word"
 opcode = "AMO / width / AMOSWAP.W"
 encoding = "R"

          
@@ 1179,7 1179,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOSWAP.D]
+["AMOSWAP.D"]
 name = "Atomic swap doubleword"
 opcode = "AMO / width / AMOSWAP.D"
 encoding = "R"

          
@@ 1199,7 1199,7 @@ discarded by writing to x0.
 """
 
 
-[AMOADD.W]
+["AMOADD.W"]
 name = "Atomic ADD word"
 opcode = "AMO / width / AMOADD.W"
 encoding = "R"

          
@@ 1218,7 1218,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOADD.D]
+["AMOADD.D"]
 name = "Atomic ADD doubleword"
 opcode = "AMO / width / AMOADD.D"
 encoding = "R"

          
@@ 1237,7 1237,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOAND.W]
+["AMOAND.W"]
 name = "Atomic AND word"
 opcode = "AMO / width / AMOAND.W"
 encoding = "R"

          
@@ 1256,7 1256,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOAND.D]
+["AMOAND.D"]
 name = "Atomic AND doubleword"
 opcode = "AMO / width / AMOAND.D"
 encoding = "R"

          
@@ 1275,7 1275,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOOR.W]
+["AMOOR.W"]
 name = "Atomic OR word"
 opcode = "AMO / width / AMOOR.W"
 encoding = "R"

          
@@ 1294,7 1294,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOOR.D]
+["AMOOR.D"]
 name = "Atomic OR doubleword"
 opcode = "AMO / width / AMOOR.D"
 encoding = "R"

          
@@ 1313,7 1313,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOXOR.W]
+["AMOXOR.W"]
 name = "Atomic XOR word"
 opcode = "AMO / width / AMOXOR.W"
 encoding = "R"

          
@@ 1332,7 1332,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOXOR.D]
+["AMOXOR.D"]
 name = "Atomic XOR doubleword"
 opcode = "AMO / width / AMOXOR.D"
 encoding = "R"

          
@@ 1351,7 1351,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOMAX.W]
+["AMOMAX.W"]
 name = "Atomic MAX word"
 opcode = "AMO / width / AMOMAX.W"
 encoding = "R"

          
@@ 1370,7 1370,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOMAX.D]
+["AMOMAX.D"]
 name = "Atomic MAX doubleword"
 opcode = "AMO / width / AMOMAX.D"
 encoding = "R"

          
@@ 1389,7 1389,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOMAXU.W]
+["AMOMAXU.W"]
 name = "Atomic MAXU word"
 opcode = "AMO / width / AMOMAXU.W"
 encoding = "R"

          
@@ 1408,7 1408,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOMAXU.D]
+["AMOMAXU.D"]
 name = "Atomic MAXU doubleword"
 opcode = "AMO / width / AMOMAXU.D"
 encoding = "R"

          
@@ 1427,7 1427,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOMIN.W]
+["AMOMIN.W"]
 name = "Atomic MIN word"
 opcode = "AMO / width / AMOMIN.W"
 encoding = "R"

          
@@ 1446,7 1446,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOMIN.D]
+["AMOMIN.D"]
 name = "Atomic MIN doubleword"
 opcode = "AMO / width / AMOMIN.D"
 encoding = "R"

          
@@ 1465,7 1465,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOMINU.W]
+["AMOMINU.W"]
 name = "Atomic MINU word"
 opcode = "AMO / width / AMOMINU.W"
 encoding = "R"

          
@@ 1484,7 1484,7 @@ can be used to implement parallel reduct
 discarded by writing to x0.
 """
 
-[AMOMINU.D]
+["AMOMINU.D"]
 name = "Atomic MINU doubleword"
 opcode = "AMO / width / AMOMINU.D"
 encoding = "R"

          
@@ 1709,7 1709,7 @@ and writes the final result to rd. FNMADD.S computes -(rs1×rs2)-rs3.
 
 
 
-[FCVT.W.S]
+["FCVT.W.S"]
 name = "Convert single floating point to word integer"
 opcode = "OP-FP / FCVT"
 encoding = "F"

          
@@ 1731,7 1731,7 @@ to the rm field. A floating-point regist
 FCVT.S.W rd, x0, which will never set any exception flags.
 """
 
-[FCVT.L.S]
+["FCVT.L.S"]
 name = "Convert single floating point to doubleword integer"
 opcode = "OP-FP / FCVT"
 encoding = "F"

          
@@ 1753,7 1753,7 @@ to the rm field. A floating-point regist
 FCVT.S.W rd, x0, which will never set any exception flags.
 """
 
-[FCVT.WU.S]
+["FCVT.WU.S"]
 name = "Convert single floating point to unsigned word integer"
 opcode = "OP-FP / FCVT"
 encoding = "F"

          
@@ 1775,7 1775,7 @@ to the rm field. A floating-point regist
 FCVT.S.W rd, x0, which will never set any exception flags.
 """
 
-[FCVT.LU.S]
+["FCVT.LU.S"]
 name = "Convert single floating point to unsigned doubleword integer"
 opcode = "OP-FP / FCVT"
 encoding = "F"

          
@@ 1799,7 1799,7 @@ FCVT.S.W rd, x0, which will never set an
 
 
 
-[FCVT.S.W]
+["FCVT.S.W"]
 name = "Convert word integer to single floating point"
 opcode = "OP-FP / FCVT"
 encoding = "F"

          
@@ 1822,7 1822,7 @@ FCVT.S.W rd, x0, which will never set an
 """
 
 
-[FCVT.S.L]
+["FCVT.S.L"]
 name = "Convert double word integer to single floating point"
 opcode = "OP-FP / FCVT"
 encoding = "F"

          
@@ 1844,7 1844,7 @@ to the rm field. A floating-point regist
 FCVT.S.W rd, x0, which will never set any exception flags.
 """
 
-[FCVT.S.WU]
+["FCVT.S.WU"]
 name = "Convert unsigned word integer to single floating point"
 opcode = "OP-FP / FCVT"
 encoding = "F"

          
@@ 1867,7 1867,7 @@ FCVT.S.W rd, x0, which will never set an
 """
 
 
-[FCVT.S.LU]
+["FCVT.S.LU"]
 name = "Convert unsigned double word integer to single floating point"
 opcode = "OP-FP / FCVT"
 encoding = "F"

          
@@ 1889,7 1889,7 @@ to the rm field. A floating-point regist
 FCVT.S.W rd, x0, which will never set any exception flags.
 """
 
-[FSGNJ.S]
+["FSGNJ.S"]
 name = "Floating point sign injection"
 opcode = "OP-FP / FSGNJ"
 encoding = "R"

          
@@ 1905,7 1905,7 @@ to rx (assembler pseudoinstruction FNEG.
 value of ry to rx (assembler pseudoinstruction FABS.S rx, ry).
 """
 
-[FSGNJN.S]
+["FSGNJN.S"]
 name = "Floating point sign injection with negation"
 opcode = "OP-FP / FSGNJ"
 encoding = "R"

          
@@ 1921,7 1921,7 @@ to rx (assembler pseudoinstruction FNEG.
 value of ry to rx (assembler pseudoinstruction FABS.S rx, ry).
 """
 
-[FSGNJX.S]
+["FSGNJX.S"]
 name = "Floating point sign injection with SOR"
 opcode = "OP-FP / FSGNJ"
 encoding = "R"

          
@@ 1937,7 1937,7 @@ to rx (assembler pseudoinstruction FNEG.
 value of ry to rx (assembler pseudoinstruction FABS.S rx, ry).
 """
 
-[FMV.W.X]
+["FMV.W.X"]
 name = "Move single floating point to integer register"
 opcode = "OP-FP / FMV.W.X"
 encoding = "R"

          
@@ 1953,7 1953,7 @@ lower 32 bits of integer register rs1 to
 the transfer, and in particular, the payloads of non-canonical NaNs are preserved.
 """
 
-[FMV.X.W]
+["FMV.X.W"]
 name = "Move word integer to single floating point register"
 opcode = "OP-FP / FMV.X.W"
 encoding = "R"

          
@@ 1969,7 1969,7 @@ lower 32 bits of integer register rs1 to
 the transfer, and in particular, the payloads of non-canonical NaNs are preserved.
 """
 
-[FEQ.S]
+["FEQ.S"]
 name = "Floating point single precision equal"
 opcode = "OP-FP / EQ / FCMP"
 encoding = "R"

          
@@ 1984,7 1984,7 @@ comparison: it only sets the invalid ope
 all three instructions, the result is 0 if either operand is NaN.
 """
 
-[FLT.S]
+["FLT.S"]
 name = "Floating point single precision less than"
 opcode = "OP-FP / LT / FCMP"
 encoding = "R"

          
@@ 1999,7 1999,7 @@ comparison: it only sets the invalid ope
 all three instructions, the result is 0 if either operand is NaN.
 """
 
-[FLE.S]
+["FLE.S"]
 name = "Floating point single precision less than or equal"
 opcode = "OP-FP / LE / FCMP"
 encoding = "R"

          
@@ 2014,7 2014,7 @@ comparison: it only sets the invalid ope
 all three instructions, the result is 0 if either operand is NaN.
 """
 
-[FCLASS.S]
+["FCLASS.S"]
 name = "Floating point single precision classify"
 opcode = "OP-FP / FCLASS"
 encoding = "R"

          
@@ 2027,7 2027,7 @@ and clear otherwise. All other bits in r
 FCLASS.S does not set the floating-point exception flags.
 """
 
-[FMV.S]
+["FMV.S"]
 name = "Copy single precision floating point register"
 opcode = ""
 encoding = "pseudo"

          
@@ 2036,7 2036,7 @@ long_description = """
 fsgnj.s rd, rs, rs
 """
 
-[FABS.S]
+["FABS.S"]
 name = "Single precision absolute value"
 opcode = ""
 encoding = "pseudo"

          
@@ 2045,7 2045,7 @@ long_description = """
 fsgnjx.s rd, rs, rs
 """
 
-[FNEG.S]
+["FNEG.S"]
 name = "Single precision negate"
 opcode = ""
 encoding = "pseudo"

          
@@ 2054,7 2054,7 @@ long_description = """
 fsgnjn.s rd, rs, rs
 """
 
-[FMV.D]
+["FMV.D"]
 name = "Copy double precision floating point register"
 opcode = ""
 encoding = "pseudo"

          
@@ 2063,7 2063,7 @@ long_description = """
 fsgnj.d rd, rs, rs
 """
 
-[FABS.D]
+["FABS.D"]
 name = "Double precision absolute value"
 opcode = ""
 encoding = "pseudo"

          
@@ 2072,7 2072,7 @@ long_description = """
 fsgnjx.d rd, rs, rs
 """
 
-[FNEG.D]
+["FNEG.D"]
 name = "Double precision negate"
 opcode = ""
 encoding = "pseudo"

          
@@ 2081,12 2081,12 @@ long_description = """
 fsgnjn.d rd, rs, rs
 """
 
-[]
-name = ""
-opcode = ""
-encoding = ""
-extension = ""
-long_description = """
-"""
+#[]
+#name = ""
+#opcode = ""
+#encoding = ""
+#extension = ""
+#long_description = """
+#"""
 
 

          
A => src/main.rs +44 -0
@@ 0,0 1,44 @@ 
+use std::collections::BTreeMap;
+use std::path::PathBuf;
+
+use argh::FromArgs;
+use serde::{Deserialize, Serialize};
+use serde_derive::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
+struct Instruction {
+    name: String,
+    opcode: String,
+    encoding: String,
+    extension: String,
+    long_description: String,
+}
+
+/// simple generator to read the instructions.toml file and produce some kind of output.
+#[derive(FromArgs, Debug, Clone)]
+struct Opts {
+    /// input file name
+    #[argh(positional)]
+    file: PathBuf,
+}
+
+fn output_md(instrs: &mut dyn Iterator<Item = (&String, &Instruction)>) {
+    for (name, i) in instrs {
+        println!("# {}", name);
+        println!("**Name:** {}", i.name);
+        println!("**Opcode:** {}", i.opcode);
+        println!("**Encoding:** {}", i.encoding);
+        println!("**Extension:** {}", i.extension);
+        println!();
+        println!("{}", i.long_description);
+    }
+}
+
+fn main() {
+    let opts: Opts = argh::from_env();
+    println!("Parsing {}", opts.file.display());
+    let contents = std::fs::read_to_string(&opts.file).unwrap();
+    let deserialized: BTreeMap<String, Instruction> = toml::from_str(&contents).unwrap();
+    let iter = &mut deserialized.iter();
+    output_md(iter);
+}