Implementation of the UM-32 "Universal Machine" as described by the Cult of the Bound Variable

move operations to lib

tjh 2677baf0 92e16e4c

+105 -103
+102
src/lib.rs
··· 1 + pub type Platter = u32; 2 + pub type Parameter = u8; 3 + 4 + #[derive(Clone, Copy, Debug, PartialEq, Eq)] 5 + pub enum Operation { 6 + ConditionalMove { 7 + a: Parameter, 8 + b: Parameter, 9 + c: Parameter, 10 + }, 11 + ArrayIndex { 12 + a: Parameter, 13 + b: Parameter, 14 + c: Parameter, 15 + }, 16 + ArrayAmendment { 17 + a: Parameter, 18 + b: Parameter, 19 + c: Parameter, 20 + }, 21 + Addition { 22 + a: Parameter, 23 + b: Parameter, 24 + c: Parameter, 25 + }, 26 + Multiplication { 27 + a: Parameter, 28 + b: Parameter, 29 + c: Parameter, 30 + }, 31 + Division { 32 + a: Parameter, 33 + b: Parameter, 34 + c: Parameter, 35 + }, 36 + NotAnd { 37 + a: Parameter, 38 + b: Parameter, 39 + c: Parameter, 40 + }, 41 + Halt, 42 + Allocation { 43 + b: Parameter, 44 + c: Parameter, 45 + }, 46 + Abandonment { 47 + c: Parameter, 48 + }, 49 + Output { 50 + c: Parameter, 51 + }, 52 + Input { 53 + c: Parameter, 54 + }, 55 + LoadProgram { 56 + b: Parameter, 57 + c: Parameter, 58 + }, 59 + Orthography { 60 + a: Parameter, 61 + value: u32, 62 + }, 63 + IllegalInstruction, 64 + } 65 + 66 + impl From<Platter> for Operation { 67 + #[inline] 68 + fn from(value: Platter) -> Self { 69 + let a = ((value >> 6) & 0x07) as Parameter; 70 + let b = ((value >> 3) & 0x07) as Parameter; 71 + let c = ((value >> 0) & 0x07) as Parameter; 72 + 73 + match value & 0xf0000000 { 74 + 0x00000000 => Self::ConditionalMove { a, b, c }, 75 + 0x10000000 => Self::ArrayIndex { a, b, c }, 76 + 0x20000000 => Self::ArrayAmendment { a, b, c }, 77 + 0x30000000 => Self::Addition { a, b, c }, 78 + 0x40000000 => Self::Multiplication { a, b, c }, 79 + 0x50000000 => Self::Division { a, b, c }, 80 + 0x60000000 => Self::NotAnd { a, b, c }, 81 + 0x70000000 => Self::Halt, 82 + 0x80000000 => Self::Allocation { b, c }, 83 + 0x90000000 => Self::Abandonment { c }, 84 + 0xa0000000 => Self::Output { c }, 85 + 0xb0000000 => Self::Input { c }, 86 + 0xc0000000 => Self::LoadProgram { b, c }, 87 + 0xd0000000 => { 88 + let a = ((value >> 25) & 0x07) as Parameter; 89 + let value = value & 0x01ffffff; 90 + Self::Orthography { a, value } 91 + } 92 + _ => Self::IllegalInstruction, 93 + } 94 + } 95 + } 96 + 97 + #[inline] 98 + pub fn decode_ops(ops: &[Platter]) -> Vec<Operation> { 99 + ops.iter() 100 + .map(|&encoded| Operation::from(encoded)) 101 + .collect() 102 + }
+3 -103
src/main.rs
··· 2 2 use smallvec::SmallVec; 3 3 #[cfg(feature = "timing")] 4 4 use std::time::Instant; 5 + use um::{Operation, Parameter, Platter}; 5 6 6 7 #[cfg(feature = "smallvec")] 7 8 const SMALLVEC_SIZE: usize = 24; ··· 19 20 .run(); 20 21 } 21 22 22 - type Platter = u32; 23 - type Parameter = u8; 24 - 25 - #[derive(Clone, Copy, Debug, PartialEq, Eq)] 26 - enum Operation { 27 - ConditionalMove { 28 - a: Parameter, 29 - b: Parameter, 30 - c: Parameter, 31 - }, 32 - ArrayIndex { 33 - a: Parameter, 34 - b: Parameter, 35 - c: Parameter, 36 - }, 37 - ArrayAmendment { 38 - a: Parameter, 39 - b: Parameter, 40 - c: Parameter, 41 - }, 42 - Addition { 43 - a: Parameter, 44 - b: Parameter, 45 - c: Parameter, 46 - }, 47 - Multiplication { 48 - a: Parameter, 49 - b: Parameter, 50 - c: Parameter, 51 - }, 52 - Division { 53 - a: Parameter, 54 - b: Parameter, 55 - c: Parameter, 56 - }, 57 - NotAnd { 58 - a: Parameter, 59 - b: Parameter, 60 - c: Parameter, 61 - }, 62 - Halt, 63 - Allocation { 64 - b: Parameter, 65 - c: Parameter, 66 - }, 67 - Abandonment { 68 - c: Parameter, 69 - }, 70 - Output { 71 - c: Parameter, 72 - }, 73 - Input { 74 - c: Parameter, 75 - }, 76 - LoadProgram { 77 - b: Parameter, 78 - c: Parameter, 79 - }, 80 - Orthography { 81 - a: Parameter, 82 - value: u32, 83 - }, 84 - IllegalInstruction, 85 - } 86 - 87 - impl From<Platter> for Operation { 88 - fn from(value: Platter) -> Self { 89 - let a = ((value >> 6) & 0x07) as Parameter; 90 - let b = ((value >> 3) & 0x07) as Parameter; 91 - let c = ((value >> 0) & 0x07) as Parameter; 92 - 93 - match value & 0xf0000000 { 94 - 0x00000000 => Self::ConditionalMove { a, b, c }, 95 - 0x10000000 => Self::ArrayIndex { a, b, c }, 96 - 0x20000000 => Self::ArrayAmendment { a, b, c }, 97 - 0x30000000 => Self::Addition { a, b, c }, 98 - 0x40000000 => Self::Multiplication { a, b, c }, 99 - 0x50000000 => Self::Division { a, b, c }, 100 - 0x60000000 => Self::NotAnd { a, b, c }, 101 - 0x70000000 => Self::Halt, 102 - 0x80000000 => Self::Allocation { b, c }, 103 - 0x90000000 => Self::Abandonment { c }, 104 - 0xa0000000 => Self::Output { c }, 105 - 0xb0000000 => Self::Input { c }, 106 - 0xc0000000 => Self::LoadProgram { b, c }, 107 - 0xd0000000 => { 108 - let a = ((value >> 25) & 0x07) as Parameter; 109 - let value = value & 0x01ffffff; 110 - Self::Orthography { a, value } 111 - } 112 - _ => Self::IllegalInstruction, 113 - } 114 - } 115 - } 116 - 117 - fn decode_ops(ops: &[Platter]) -> Vec<Operation> { 118 - ops.iter() 119 - .map(|&encoded| Operation::from(encoded)) 120 - .collect() 121 - } 122 - 123 23 #[derive(Default)] 124 24 pub struct Um { 125 25 program_counter: Platter, ··· 138 38 impl Um { 139 39 /// Initialise a Universal Machine with the specified program scroll. 140 40 pub fn new(program: Vec<Platter>) -> Self { 141 - let ops = decode_ops(&program); 41 + let ops = um::decode_ops(&program); 142 42 Self { 143 43 memory: vec![program.into()], 144 44 ops, ··· 343 243 // is no point copying array[0] to array[0]. 344 244 if block != 0 { 345 245 let duplicated = self.duplicate_memory(block); 346 - let ops = decode_ops(&duplicated); 246 + let ops = um::decode_ops(&duplicated); 347 247 self.ops = ops; 348 248 } 349 249