commit 69d9753fffff47ae3ea8c32302ca5dde4b308c60 Author: Richard Date: Fri Aug 22 22:06:40 2025 +0200 initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..d4f585b --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "um" +version = "0.1.0" +dependencies = [ + "ux", +] + +[[package]] +name = "ux" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b59fc5417e036e53226bbebd90196825d358624fd5577432c4e486c95b1b096" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..81c914f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "um" +version = "0.1.0" +edition = "2021" + +[dependencies] +ux = "0.1.6" diff --git a/data/codex.umz b/data/codex.umz new file mode 100644 index 0000000..8b60139 Binary files /dev/null and b/data/codex.umz differ diff --git a/data/sandmark-output.txt b/data/sandmark-output.txt new file mode 100644 index 0000000..fb730c2 --- /dev/null +++ b/data/sandmark-output.txt @@ -0,0 +1,123 @@ +trying to Allocate array of size 0.. +trying to Abandon size 0 allocation.. +trying to Allocate size 11.. +trying Array Index on allocated array.. +trying Amendment of allocated array.. +checking Amendment of allocated array.. +trying Alloc(a,a) and amending it.. +comparing multiple allocations.. +pointer arithmetic.. +check old allocation.. +simple tests ok! +about to load program from some allocated array.. +success. +verifying that the array and its copy are the same... +success. +testing aliasing.. +success. +free after loadprog.. +success. +loadprog ok. + == SANDmark 19106 beginning stress test / benchmark.. == +100. 12345678.09abcdef +99. 6d58165c.2948d58d +98. 0f63b9ed.1d9c4076 +97. 8dba0fc0.64af8685 +96. 583e02ae.490775c0 +95. 0353a77b.2f02685c +94. aa25a8d7.51cb07e5 +93. e13149f5.53a9ae5d +92. abbbd460.86cf279c +91. 2c25e8d8.a71883a9 +90. dccf7b71.475e0715 +89. 49b398a7.f293a13d +88. 9116f443.2d29be37 +87. 5c79ba31.71e7e592 +86. 19537c73.0797380a +85. f46a7339.fe37b85a +84. 99c71532.729e2864 +83. f3455289.b84ced3d +82. c90c81a9.b66fcd61 +81. 087e9eef.fc1c13a6 +80. e933e2f5.3567082f +79. 25af849e.16290d7b +78. 57af9504.c76e7ded +77. 68cf6c69.6055d00c +76. 8e920fbd.02369722 +75. eb06e2de.03c46fda +74. f9c40240.f1290b2a +73. 7f484f97.bc15610b +72. 1dabb00e.61e7b75b +71. dceb40f5.207a75ca +70. c3ed44f5.db631e81 +69. b7addb67.90460bf5 +68. ae710a90.04b433ef +67. 9ca2d5f0.05d3b631 +66. 4f38abe0.4287cc05 +65. 10d8691d.a5c934f8 +64. 27c68255.52881eaa +63. a0695283.110266b7 +62. 336aa5dd.57287a9b +61. b04fe494.d741ddbd +60. 2baf3654.9e33305a +59. fd82095d.683efb19 +58. d0bac37f.badff9d7 +57. 3be33fcc.d76b127e +56. 7f964f18.8b118ee1 +55. 37aeddc8.26a8f840 +54. d71d55ff.6994c78f +53. bf175396.f960cc54 +52. f6c9d8e1.44b81fd5 +51. 6a9b4d86.fe7c66cb +50. 06bceb64.d5106aad +49. 237183b6.49c15b01 +48. 4ec10756.6936136f +47. 9d1855a7.1e929fe8 +46. a641ede3.36bff422 +45. 7bbf5ad4.dd129538 +44. 732b385e.39fadce7 +43. b7f50285.e7f54c39 +42. 42e3754c.da741dc1 +41. 5dc42265.928ea0bb +40. 623fb352.3f25bc5b +39. 491f33d9.409bca87 +38. f0943bc7.89f512be +37. 80cdbc9d.8ad93517 +36. c1a8da99.32d37f3f +35. 91a0b15c.6df2cf4e +34. 50cf7a7a.f0466dc8 +33. 02df4c13.14eb615d +32. 2963bf25.d9f06dfe +31. c493d2db.f39ce804 +30. 3b6e5a8e.5cf63bd7 +29. 4c5c2fbe.8d881c00 +28. 9b7354a6.81181438 +27. ae0fe8c6.ec436274 +26. e786b98d.f5a4111d +25. a7719df1.d989d0b6 +24. beb9ebc0.6c56750d +23. edf41fcb.e4cba003 +22. 97268c46.713025f1 +21. deb087db.1349eb6a +20. fc5221f0.3b4241bf +19. 3fa4370d.8fa16752 +18. 044af7de.87b44b11 +17. 2e86e437.c4cdbc54 +16. fd7cd8aa.63b6ca23 +15. 631ceaad.e093a9d5 +14. 01ca9732.52962532 +13. 86d8bcf5.45bdf474 +12. 8d07855b.0224e80f +11. 0f9d2bee.94d86c38 +10. 5e6a685d.26597494 +9. 24825ea1.72008775 +8. 73f9c0b5.1480e7a3 +7. a30735ec.a49b5dad +6. a7b6666b.509e5338 +5. d0e8236e.8b0e9826 +4. 4d20f3ac.a25d05a8 +3. 7c7394b2.476c1ee5 +2. f3a52453.19cc755d +1. 2c80b43d.5646302f +0. a8d1619e.5540e6cf +SANDmark complete. diff --git a/data/sandmark.umz b/data/sandmark.umz new file mode 100644 index 0000000..1bb2145 Binary files /dev/null and b/data/sandmark.umz differ diff --git a/data/um-spec.txt b/data/um-spec.txt new file mode 100644 index 0000000..f486adc --- /dev/null +++ b/data/um-spec.txt @@ -0,0 +1,259 @@ + + Order for Construction Standard Sand of Pennsylvania Co. + + Client: Cult of the Bound Variable + Object: UM-32 "Universal Machine" + ----------------------------------------------------------------- + 21 July 19106 + + Physical Specifications. + ------------------------ + + The machine shall consist of the following components: + + * An infinite supply of sandstone platters, with room on each + for thirty-two small marks, which we call "bits." + + least meaningful bit + | + v + .--------------------------------. + |VUTSRQPONMLKJIHGFEDCBA9876543210| + `--------------------------------' + ^ + | + most meaningful bit + + Figure 0. Platters + + Each bit may be the 0 bit or the 1 bit. Using the system of + "unsigned 32-bit numbers" (see patent #4,294,967,295) the + markings on these platters may also denote numbers. + + * Eight distinct general-purpose registers, capable of holding one + platter each. + + * A collection of arrays of platters, each referenced by a distinct + 32-bit identifier. One distinguished array is referenced by 0 + and stores the "program." This array will be referred to as the + '0' array. + + * A 1x1 character resolution console capable of displaying glyphs + from the "ASCII character set" (see patent #127) and performing + input and output of "unsigned 8-bit characters" (see patent + #255). + + + Behavior. + --------- + + The machine shall be initialized with a '0' array whose contents + shall be read from a "program" scroll. All registers shall be + initialized with platters of value '0'. The execution finger shall + point to the first platter of the '0' array, which has offset zero. + + When reading programs from legacy "unsigned 8-bit character" + scrolls, a series of four bytes A,B,C,D should be interpreted with + 'A' as the most magnificent byte, and 'D' as the most shoddy, with + 'B' and 'C' considered lovely and mediocre respectively. + + Once initialized, the machine begins its Spin Cycle. In each cycle + of the Universal Machine, an Operator shall be retrieved from the + platter that is indicated by the execution finger. The sections + below describe the operators that may obtain. Before this operator + is discharged, the execution finger shall be advanced to the next + platter, if any. + + Operators. + ---------- + + The Universal Machine may produce 14 Operators. The number of the + operator is described by the most meaningful four bits of the + instruction platter. + + .--------------------------------. + |VUTSRQPONMLKJIHGFEDCBA9876543210| + `--------------------------------' + ^^^^ + | + operator number + + Figure 1. Operator Description + + + Standard Operators. + ------------------- + + Each Standard Operator performs an errand using three registers, + called A, B, and C. Each register is described by a three bit + segment of the instruction platter. The register C is described by + the three least meaningful bits, the register B by the three next + more meaningful than those, and the register A by the three next + more meaningful than those. + + A C + | | + vvv vvv + .--------------------------------. + |VUTSRQPONMLKJIHGFEDCBA9876543210| + `--------------------------------' + ^^^^ ^^^ + | | + operator number B + + Figure 2. Standard Operators + + + A description of each basic Operator follows. + + Operator #0. Conditional Move. + + The register A receives the value in register B, + unless the register C contains 0. + + #1. Array Index. + + The register A receives the value stored at offset + in register C in the array identified by B. + + #2. Array Amendment. + + The array identified by A is amended at the offset + in register B to store the value in register C. + + #3. Addition. + + The register A receives the value in register B plus + the value in register C, modulo 2^32. + + #4. Multiplication. + + The register A receives the value in register B times + the value in register C, modulo 2^32. + + #5. Division. + + The register A receives the value in register B + divided by the value in register C, if any, where + each quantity is treated as an unsigned 32 bit number. + + #6. Not-And. + + Each bit in the register A receives the 1 bit if + either register B or register C has a 0 bit in that + position. Otherwise the bit in register A receives + the 0 bit. + + Other Operators. + ---------------- + + The following instructions ignore some or all of the A, B and C + registers. + + #7. Halt. + + The universal machine stops computation. + + #8. Allocation. + + A new array is created with a capacity of platters + commensurate to the value in the register C. This + new array is initialized entirely with platters + holding the value 0. A bit pattern not consisting of + exclusively the 0 bit, and that identifies no other + active allocated array, is placed in the B register. + + #9. Abandonment. + + The array identified by the register C is abandoned. + Future allocations may then reuse that identifier. + + #10. Output. + + The value in the register C is displayed on the console + immediately. Only values between and including 0 and 255 + are allowed. + + #11. Input. + + The universal machine waits for input on the console. + When input arrives, the register C is loaded with the + input, which must be between and including 0 and 255. + If the end of input has been signaled, then the + register C is endowed with a uniform value pattern + where every place is pregnant with the 1 bit. + + #12. Load Program. + + The array identified by the B register is duplicated + and the duplicate shall replace the '0' array, + regardless of size. The execution finger is placed + to indicate the platter of this array that is + described by the offset given in C, where the value + 0 denotes the first platter, 1 the second, et + cetera. + + The '0' array shall be the most sublime choice for + loading, and shall be handled with the utmost + velocity. + + Special Operators. + ------------------ + + One special operator does not describe registers in the same way. + Instead the three bits immediately less significant than the four + instruction indicator bits describe a single register A. The + remainder twenty five bits indicate a value, which is loaded + forthwith into the register A. + + A + | + vvv + .--------------------------------. + |VUTSRQPONMLKJIHGFEDCBA9876543210| + `--------------------------------' + ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | value + | + operator number + + Figure 3. Special Operators + + #13. Orthography. + + The value indicated is loaded into the register A + forthwith. + + Cost-Cutting Measures. + ---------------------- + + As per our meeting on 13 Febtober 19106, certain "impossible + behaviors" may be unimplemented in the furnished device. An + exhaustive list of these Exceptions is given below. Our contractual + agreement dictates that the machine may Fail under no other + circumstances. + + + If at the beginning of a cycle, the execution finger does not indicate + a platter that describes a valid instruction, then the machine may Fail. + + If the program decides to index or amend an array that is not + active, because it has not been allocated or it has been abandoned, + or if the offset supplied for the access lies outside the array's + capacity, then the machine may Fail. + + If the program decides to abandon the '0' array, or to abandon an array + that is not active, then the machine may Fail. + + If the program sets out to divide by a value of 0, then the machine + may Fail. + + If the program decides to load a program from an array that is not + active, then the machine may Fail. + + If the program decides to Output a value that is larger than 255, the + machine may Fail. + + If at the beginning of a machine cycle the execution finger aims + outside the capacity of the 0 array, the machine may Fail. diff --git a/data/um.um b/data/um.um new file mode 100644 index 0000000..817976d Binary files /dev/null and b/data/um.um differ diff --git a/src/bin/umdis.rs b/src/bin/umdis.rs new file mode 100644 index 0000000..e3b96b8 --- /dev/null +++ b/src/bin/umdis.rs @@ -0,0 +1,10 @@ +extern crate um; +use um::instruction::{Instruction, ParsingError}; + +fn main() { + let i = Instruction::parse(0x81234567); + match i { + Ok(x) => println!("Ins {:?}!", x.fmt()), + Err(ParsingError) => println!("OOPS") + } +} diff --git a/src/instruction.rs b/src/instruction.rs new file mode 100644 index 0000000..09c2324 --- /dev/null +++ b/src/instruction.rs @@ -0,0 +1,85 @@ + +use ux::{u3, u25}; + +pub struct ParsingError; + +#[derive(Debug)] +pub struct NormalInstruction { + pub a: u3, + pub b: u3, + pub c: u3 +} + +#[derive(Debug)] +pub struct SpecialInstruction { + pub a: u3, + pub v: u25 +} + +#[derive(Debug)] +pub enum Instruction { + ConditionalMove(NormalInstruction), + ArrayIndex(NormalInstruction), + ArrayAmend(NormalInstruction), + Add(NormalInstruction), + Multiply(NormalInstruction), + Divide(NormalInstruction), + NotAnd(NormalInstruction), + Halt(NormalInstruction), + Allocate(NormalInstruction), + Abandon(NormalInstruction), + Output(NormalInstruction), + Input(NormalInstruction), + Load(NormalInstruction), + Ortho(SpecialInstruction) +} + +const fn u3at(d: u32, pos: u8) -> u3 { + u3::new(((d >> pos) & 7) as u8) +} + +impl Instruction { + pub fn fmt(&self) -> &'static str { + match self { + Instruction::ConditionalMove(i) => "CMV", + Instruction::ArrayIndex(i) => "IDX", + Instruction::ArrayAmend(i) => "AMD", + Instruction::Add(i) => "ADD", + Instruction::Multiply(i) => "MUL", + Instruction::Divide(i) => "DIV", + Instruction::NotAnd(i) => "NAD", + Instruction::Halt(i) => "HLT", + Instruction::Allocate(i) => "ALC", + Instruction::Abandon(i) => "ABN", + Instruction::Output(i) => "OUT", + Instruction::Input(i) => "INP", + Instruction::Load(i) => "LOD", + Instruction::Ortho(i) => "ORT" + } + } + + pub const fn parse(d: u32) -> Result { + let itype = d >> 28; + let (a, b, c, v) = match itype { + 13 => (u3at(d, 25), u3::new(0), u3::new(0), u25::new(d & 0x1ffffff)), + _ => (u3at(d, 6), u3at(d, 3), u3at(d, 0), u25::new(0)) + }; + match itype { + 0 => Ok(Instruction::ConditionalMove(NormalInstruction{a: a, b: b, c: c})), + 1 => Ok(Instruction::ArrayIndex(NormalInstruction{a: a, b: b, c: c})), + 2 => Ok(Instruction::ArrayAmend(NormalInstruction{a: a, b: b, c: c})), + 3 => Ok(Instruction::Add(NormalInstruction{a: a, b: b, c: c})), + 4 => Ok(Instruction::Multiply(NormalInstruction{a: a, b: b, c: c})), + 5 => Ok(Instruction::Divide(NormalInstruction{a: a, b: b, c: c})), + 6 => Ok(Instruction::NotAnd(NormalInstruction{a: a, b: b, c: c})), + 7 => Ok(Instruction::Halt(NormalInstruction{a: a, b: b, c: c})), + 8 => Ok(Instruction::Allocate(NormalInstruction{a: a, b: b, c: c})), + 9 => Ok(Instruction::Abandon(NormalInstruction{a: a, b: b, c: c})), + 10 => Ok(Instruction::Output(NormalInstruction{a: a, b: b, c: c})), + 11 => Ok(Instruction::Input(NormalInstruction{a: a, b: b, c: c})), + 12 => Ok(Instruction::Load(NormalInstruction{a: a, b: b, c: c})), + 13 => Ok(Instruction::Ortho(SpecialInstruction{a: a, v: v})), + _ => Err(ParsingError) + } + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..ca4b15f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1 @@ +pub mod instruction;