Implementation of the UM-32 "Universal Machine" as described by the Cult of the Bound Variable
1// Copyright (C) 2025 Thom Hayward.
2//
3// This program is free software: you can redistribute it and/or modify it under
4// the terms of the GNU General Public License as published by the Free Software
5// Foundation, version 3.
6//
7// This program is distributed in the hope that it will be useful, but WITHOUT
8// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
10// details.
11//
12// You should have received a copy of the GNU General Public License along with
13// this program. If not, see <https://www.gnu.org/licenses/>.
14//
15/// A reference to a register of the UM-32.
16#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
17pub enum Register {
18 #[default]
19 R0,
20 R1,
21 R2,
22 R3,
23 R4,
24 R5,
25 R6,
26 R7,
27}
28
29impl std::fmt::Display for Register {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 write!(f, "r{}", *self as u8)
32 }
33}
34
35impl Register {
36 /// Encodes the register as the 'a' parameter of an encoded
37 /// instruction (bits 6..=8).
38 pub fn encode_a(self) -> u32 {
39 ((self as u32) & 0x7) << 6
40 }
41
42 /// Encodes the register as the 'b' parameter of an encoded
43 /// instruction (bits 3..=5).
44 pub fn encode_b(self) -> u32 {
45 ((self as u32) & 0x7) << 3
46 }
47
48 /// Encodes the register as the 'c' parameter of an encoded
49 /// instruction (bits 0..=2).
50 pub fn encode_c(self) -> u32 {
51 (self as u32) & 0x7
52 }
53
54 /// Encodes the register as the 'a' parameter of an `Orthography`
55 /// operation.
56 ///
57 /// This is *only* valid for `Orthography` operations.
58 pub fn encode_a_ortho(self) -> u32 {
59 ((self as u32) & 0x7) << 25
60 }
61
62 pub fn from_u8(index: u8) -> Self {
63 match index {
64 0 => Register::R0,
65 1 => Register::R1,
66 2 => Register::R2,
67 3 => Register::R3,
68 4 => Register::R4,
69 5 => Register::R5,
70 6 => Register::R6,
71 7 => Register::R7,
72 _ => unreachable!(),
73 }
74 }
75}
76
77/// A set of registers.
78#[derive(Debug, Default)]
79pub struct Page([u32; 8]);
80
81impl std::ops::Index<Register> for Page {
82 type Output = u32;
83 #[inline(always)]
84 fn index(&self, index: Register) -> &Self::Output {
85 &self.0[index as usize]
86 }
87}
88
89impl std::ops::IndexMut<Register> for Page {
90 #[inline(always)]
91 fn index_mut(&mut self, index: Register) -> &mut Self::Output {
92 &mut self.0[index as usize]
93 }
94}
95
96impl From<[u32; 8]> for Page {
97 fn from(value: [u32; 8]) -> Self {
98 Self(value)
99 }
100}