--- /dev/null
+#[derive(Debug, Default, Copy, Clone)]
+pub struct MixBit {
+ pub v: u8,
+}
+
+impl MixBit {
+ // Clamps a u8 to a u6
+ // 0b0011_1111 = 64
+ fn value(&self) -> u8 {
+ return self.v & 0b0011_1111;
+ }
+
+ fn as_value(&self) -> MixBit {
+ MixBit { v: self.value() }
+ }
+}
+
+// Useful function for "packed" bits like those used for opcodes
+fn address(high: MixBit, low: MixBit) -> u16 {
+ return ((high.value() as u16) << 6) | low.value() as u16;
+}
+
+// > Each byte contains an unspecified amount of information but it must be capable of holding at
+// > least 64 distinct values.
+// > A computer word consists of five bytes and a sign. The sign portion has only two possible
+// values, + and -.
+// u8 is the smallest standard primitive, no bounds checking for now.
+#[derive(Debug, Default, Copy, Clone)]
+pub struct Word {
+ pub sign: bool,
+ pub bytes: [MixBit; 5],
+}
+
+impl Word {
+ fn new(sign: bool, bytes: [MixBit; 5]) -> Word {
+ Word { sign, bytes }
+ }
+ // The allowable fields are those that are adjacent in a computer word, and they are
+ // represented by (L:R) where L is the number of the left hand part and R is the number of the
+ // right-hand part of the field.
+ pub fn field_specification(&self, l: usize, r: usize) -> Word {
+ let mut sign = false;
+ let mut l_clamp = l;
+ if l == 0 {
+ sign = self.sign;
+ } else {
+ l_clamp = l - 1;
+ }
+ let r_clamp = r % 5;
+ let mut bytes = [MixBit::default(); 5];
+ for n in l_clamp..r_clamp {
+ bytes[n] = self.bytes[n];
+ }
+ Word { sign, bytes }
+ }
+
+ pub fn address(&self) -> i16 {
+ let magnitude = ((self.bytes[0].value() as i16) << 6) | self.bytes[1].value() as i16;
+ match self.sign {
+ true => magnitude,
+ false => -magnitude,
+ }
+ }
+}
+
+// There are nine registers in MIX.
+// We shall use a small letter "r", prefixed to the neame, to identify a MIX register.
+#[derive(Debug, Default)]
+struct Registers {
+ // Accumulator
+ rA: Word,
+ // Extension
+ rX: Word,
+ // Index registers: Should only hold 2 bytes together with a sign.
+ rI1: Word,
+ rI2: Word,
+ rI3: Word,
+ rI4: Word,
+ rI5: Word,
+ rI6: Word,
+ // Jump: holds two bytes; it behaves as if its sign is always +
+ rJ: Word,
+}
+
+// having three values: LESS, EQUAL, or GREATER
+#[derive(Debug, Default)]
+enum ComparisonIndicator {
+ Less,
+ #[default]
+ Equal,
+ Greater,
+}
+
+#[derive(Debug)]
+pub struct Machine {
+ registers: Registers,
+ // Besides its registers, MIX contains:
+ // an overflow toggle
+ overflow: bool,
+ // a comparison indicator
+ comp: ComparisonIndicator,
+ // memory: 4000 words of storage, each word with five bytes and a sign)
+ memory: [Word; 4000],
+ // and input-output devices
+ // TODO?
+}
+
+impl Machine {
+ fn default() -> Machine {
+ Machine {
+ registers: Registers::default(),
+ overflow: false,
+ comp: ComparisonIndicator::Equal,
+ memory: [Word::default(); 4000],
+ }
+ }
+}
-#[derive(Debug, Default, Copy, Clone)]
-struct MixBit {
- v: u8,
-}
-
-impl MixBit {
- // Clamps a u8 to a u6
- // 0b0011_1111 = 64
- fn value(&self) -> u8 {
- return self.v & 0b0011_1111;
- }
-
- fn as_value(&self) -> MixBit {
- MixBit { v: self.value() }
- }
-}
-
-// Useful function for "packed" bits like those used for opcodes
-fn address(high: MixBit, low: MixBit) -> u16 {
- return ((high.value() as u16) << 6) | low.value() as u16;
-}
-
-// > Each byte contains an unspecified amount of information but it must be capable of holding at
-// > least 64 distinct values.
-// > A computer word consists of five bytes and a sign. The sign portion has only two possible
-// values, + and -.
-// u8 is the smallest standard primitive, no bounds checking for now.
-#[derive(Debug, Default, Copy, Clone)]
-struct Word {
- sign: bool,
- bytes: [MixBit; 5],
-}
-
-impl Word {
- fn new(sign: bool, bytes: [MixBit; 5]) -> Word {
- Word { sign, bytes }
- }
- // The allowable fields are those that are adjacent in a computer word, and they are
- // represented by (L:R) where L is the number of the left hand part and R is the number of the
- // right-hand part of the field.
- fn field_specification(&self, l: usize, r: usize) -> Word {
- let mut sign = false;
- let mut l_clamp = l;
- if l == 0 {
- sign = self.sign;
- } else {
- l_clamp = l - 1;
- }
- let r_clamp = r % 5;
- let mut bytes = [MixBit::default(); 5];
- for n in l_clamp..r_clamp {
- bytes[n] = self.bytes[n];
- }
- Word { sign, bytes }
- }
-
- fn address(&self) -> i16 {
- let magnitude = ((self.bytes[0].value() as i16) << 6) | self.bytes[1].value() as i16;
- match self.sign {
- true => magnitude,
- false => -magnitude,
- }
- }
-}
-
-// There are nine registers in MIX.
-// We shall use a small letter "r", prefixed to the neame, to identify a MIX register.
-#[derive(Debug, Default)]
-struct Registers {
- // Accumulator
- rA: Word,
- // Extension
- rX: Word,
- // Index registers: Should only hold 2 bytes together with a sign.
- rI1: Word,
- rI2: Word,
- rI3: Word,
- rI4: Word,
- rI5: Word,
- rI6: Word,
- // Jump: holds two bytes; it behaves as if its sign is always +
- rJ: Word,
-}
-
-// having three values: LESS, EQUAL, or GREATER
-#[derive(Debug, Default)]
-enum ComparisonIndicator {
- Less,
- #[default]
- Equal,
- Greater,
-}
-
-#[derive(Debug)]
-struct Machine {
- registers: Registers,
- // Besides its registers, MIX contains:
- // an overflow toggle
- overflow: bool,
- // a comparison indicator
- comp: ComparisonIndicator,
- // memory: 4000 words of storage, each word with five bytes and a sign)
- memory: [Word; 4000],
- // and input-output devices
- // TODO?
-}
-
-impl Machine {
- fn default() -> Machine {
- Machine {
- registers: Registers::default(),
- overflow: false,
- comp: ComparisonIndicator::Equal,
- memory: [Word::default(); 4000],
- }
- }
-}
+mod machine;
+use crate::machine::*;
fn main() {
let fs = (Word {