--- /dev/null
+use crate::*;
+
+#[derive(Debug)]
+pub struct Operator {
+ instruction: Word,
+ operator: fn(Word, &mut Machine) -> (),
+}
+
+impl Operator {
+ pub fn call(&self, machine: &mut Machine) -> () {
+ (self.operator)(self.instruction, machine)
+ }
+}
+
+fn lda(w: Word, m: &mut Machine) {
+ m.registers.a = m.memory[w.address() as usize].as_field_spec(w.field_spec());
+}
+
+fn noop(w: Word, m: &mut Machine) {}
+
+pub fn op_table(instruction: Word) -> Operator {
+ match instruction.bytes[4].value() {
+ 8 => Operator {
+ instruction,
+ operator: lda,
+ },
+ _ => Operator {
+ instruction,
+ operator: noop,
+ },
+ }
+}
impl MixBit {
// Clamps a u8 to a u6
// 0b0011_1111 = 64
- fn value(&self) -> u8 {
+ pub fn value(&self) -> u8 {
return self.v & 0b0011_1111;
}
pub bytes: [MixBit; 5],
}
+// Multiple return type for dealing with 8L+R fields from Words
+#[derive(Debug)]
+pub struct FieldSpec {
+ l: usize,
+ r: usize,
+}
+
impl Word {
fn new(sign: bool, bytes: [MixBit; 5]) -> Word {
Word { sign, bytes }
}
+
+ // The word is being used as an instruction.
+ // By definition, the 4th bit of the word is the field specification as 8L + R.
+ pub fn field_spec(&self) -> FieldSpec {
+ FieldSpec {
+ // divide by 8
+ l: (self.bytes[3].value() >> 3) as usize,
+ r: (self.bytes[3].value() % 8) as usize,
+ }
+ }
+
// 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 {
+ pub fn as_field_spec(&self, fs: FieldSpec) -> Word {
+ let mut sign = true;
+ let mut l_clamp = fs.l;
+ if fs.l == 0 {
sign = self.sign;
} else {
- l_clamp = l - 1;
+ l_clamp = l_clamp - 1;
}
- let r_clamp = r % 5;
+ let r_clamp = (fs.r - 1) % 5;
let mut bytes = [MixBit::default(); 5];
- for n in l_clamp..r_clamp {
+ for n in l_clamp..=r_clamp {
bytes[n] = self.bytes[n];
}
Word { sign, bytes }
}
+ // TODO implement / respect index word (self.bytes[2] should be index)
pub fn address(&self) -> i16 {
let magnitude = ((self.bytes[0].value() as i16) << 6) | self.bytes[1].value() as i16;
match self.sign {
// 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 {
+pub struct Registers {
// Accumulator
- rA: Word,
+ pub a: Word,
// Extension
- rX: Word,
+ pub x: Word,
// Index registers: Should only hold 2 bytes together with a sign.
- rI1: Word,
- rI2: Word,
- rI3: Word,
- rI4: Word,
- rI5: Word,
- rI6: Word,
+ pub i: [Word; 6],
// Jump: holds two bytes; it behaves as if its sign is always +
- rJ: Word,
+ pub j: Word,
}
// having three values: LESS, EQUAL, or GREATER
#[derive(Debug)]
pub struct Machine {
- registers: Registers,
+ pub 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],
+ pub memory: [Word; 4000],
// and input-output devices
// TODO?
}
impl Machine {
- fn default() -> Machine {
+ pub fn default() -> Machine {
Machine {
registers: Registers::default(),
overflow: false,
+mod instruction;
mod machine;
+use crate::instruction::*;
use crate::machine::*;
fn main() {
- let fs = (Word {
+ let mut m = Machine::default();
+ m.memory[0] = Word {
+ sign: false,
+ bytes: [
+ MixBit { v: 2 },
+ MixBit { v: 16 },
+ MixBit { v: 3 },
+ MixBit { v: 5 },
+ MixBit { v: 4 },
+ ],
+ };
+ let i = Word {
sign: true,
- bytes: [MixBit { v: 63 }; 5],
- })
- .field_specification(1, 2);
- println!("{:?}", fs.address());
+ bytes: [
+ MixBit { v: 0 },
+ MixBit { v: 0 },
+ MixBit { v: 0 },
+ MixBit { v: 29 },
+ MixBit { v: 8 },
+ ],
+ };
+ println!("{:?}", i.field_spec());
+ let o = op_table(i);
+ o.call(&mut m);
+ println!("{:?}", m.registers.a);
+ println!("{:?}", m.memory[0]);
}