This commit is contained in:
Richard 2025-08-22 22:06:40 +02:00
commit 69d9753fff
11 changed files with 502 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

16
Cargo.lock generated Normal file
View File

@ -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"

7
Cargo.toml Normal file
View File

@ -0,0 +1,7 @@
[package]
name = "um"
version = "0.1.0"
edition = "2021"
[dependencies]
ux = "0.1.6"

BIN
data/codex.umz Normal file

Binary file not shown.

123
data/sandmark-output.txt Normal file
View File

@ -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.

BIN
data/sandmark.umz Normal file

Binary file not shown.

259
data/um-spec.txt Normal file
View File

@ -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.

BIN
data/um.um Normal file

Binary file not shown.

10
src/bin/umdis.rs Normal file
View File

@ -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")
}
}

85
src/instruction.rs Normal file
View File

@ -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<Instruction, ParsingError> {
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)
}
}
}

1
src/lib.rs Normal file
View File

@ -0,0 +1 @@
pub mod instruction;