main.rs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. use std::collections::HashMap;
  2. use std::fmt;
  3. use std::fs;
  4. use text_io::read;
  5. struct UMState {
  6. pc: usize, // program counter
  7. regs: [u32; 8], // register contents
  8. arrmap: HashMap<u32, usize>, // active arrays
  9. mem: Vec<Vec<u32>> // memory contents (array of arrays)
  10. }
  11. enum UMOp {
  12. ConditionalMove(u8, u8, u8),
  13. ArrayIndex(u8, u8, u8),
  14. ArrayAmend(u8, u8, u8),
  15. Add(u8, u8, u8),
  16. Mult(u8, u8, u8),
  17. Div(u8, u8, u8),
  18. NotAnd(u8, u8, u8),
  19. Halt,
  20. Allocate(u8, u8),
  21. Abandon(u8),
  22. Output(u8),
  23. Input(u8),
  24. Load(u8, u8),
  25. Value(u8, u32),
  26. }
  27. fn reg(i:u8) -> &'static str {
  28. match i {
  29. 0 => "A",
  30. 1 => "B",
  31. 2 => "C",
  32. 3 => "D",
  33. 4 => "E",
  34. 5 => "F",
  35. 6 => "G",
  36. 7 => "H",
  37. _ => panic!("Bad register! {}",i)
  38. }
  39. }
  40. impl fmt::Display for UMOp {
  41. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  42. let repr = match self {
  43. UMOp::ConditionalMove(a, b, c) =>
  44. format!("Conditional #{} <- {} ? #{} : #{}",
  45. reg(*a),
  46. reg(*c),
  47. reg(*b),
  48. reg(*a)),
  49. UMOp::ArrayIndex(a, b, c) =>
  50. format!("ArrIndex #{} <- #{}[#{}]",
  51. reg(*a),
  52. reg(*b),
  53. reg(*c)),
  54. UMOp::ArrayAmend(a, b, c) =>
  55. format!("ArrAmend #{}[#{}] <- #{}",
  56. reg(*a),
  57. reg(*b),
  58. reg(*c)),
  59. UMOp::Add(a, b, c) =>
  60. format!("Add #{} <- #{} + #{}",
  61. reg(*a),
  62. reg(*b),
  63. reg(*c)),
  64. UMOp::Mult(a, b, c) =>
  65. format!("Mult #{} <- #{} * #{}",
  66. reg(*a),
  67. reg(*b),
  68. reg(*c)),
  69. UMOp::Div(a, b, c) =>
  70. format!("Div #{} <- #{} / #{}",
  71. reg(*a),
  72. reg(*b),
  73. reg(*c)),
  74. UMOp::NotAnd(a, b, c) =>
  75. format!("NotAnd #{} <- #{} !&& #{}",
  76. reg(*a),
  77. reg(*b),
  78. reg(*c)),
  79. UMOp::Halt =>
  80. format!("Halt!"),
  81. UMOp::Allocate(b, c) =>
  82. format!("Alloc #{} <- [#{}]",
  83. reg(*b),
  84. reg(*c)),
  85. UMOp::Abandon(c) =>
  86. format!("Abandon @#{}",
  87. reg(*c)),
  88. UMOp::Output(c) =>
  89. format!("Output #{}",
  90. reg(*c)),
  91. UMOp::Input(c) =>
  92. format!("Input #{} <-",
  93. reg(*c)),
  94. UMOp::Load(b, c) =>
  95. format!("Load <- #{}[#{}]",
  96. reg(*b),
  97. reg(*c)),
  98. UMOp::Value(a, val) =>
  99. format!("Value <- #{} <- $#{}",
  100. reg(*a),
  101. val),
  102. };
  103. write!(f, "{}", repr)
  104. }
  105. }
  106. fn num_extract(masks_map: &HashMap<&str, (u32,u32)>,
  107. num: u32, mask_name: &str) -> u32 {
  108. let masktup = masks_map.get(mask_name).unwrap();
  109. (num & masktup.0) >> masktup.1
  110. }
  111. fn parse_instr(masks_map: &HashMap<&str, (u32,u32)>,
  112. instr: u32) -> UMOp {
  113. let opcode = num_extract(masks_map, instr, "op_mask");
  114. let rega = num_extract(masks_map, instr, "rega_mask") as u8;
  115. let regb = num_extract(masks_map, instr, "regb_mask") as u8;
  116. let regc = num_extract(masks_map, instr, "regc_mask") as u8;
  117. let alta = num_extract(masks_map, instr, "alta_mask") as u8;
  118. let val = num_extract(masks_map, instr, "val_mask");
  119. match opcode {
  120. 0 => UMOp::ConditionalMove(rega, regb, regc),
  121. 1 => UMOp::ArrayIndex(rega, regb, regc),
  122. 2 => UMOp::ArrayAmend(rega, regb, regc),
  123. 3 => UMOp::Add(rega, regb, regc),
  124. 4 => UMOp::Mult(rega, regb, regc),
  125. 5 => UMOp::Div(rega, regb, regc),
  126. 6 => UMOp::NotAnd(rega, regb, regc),
  127. 7 => UMOp::Halt,
  128. 8 => UMOp::Allocate(regb, regc),
  129. 9 => UMOp::Abandon(regc),
  130. 10 => UMOp::Output(regc),
  131. 11 => UMOp::Input(regc),
  132. 12 => UMOp::Load(regb, regc),
  133. 13 => UMOp::Value(alta, val),
  134. _ => panic!("Bad Instruction! ({})", instr)
  135. }
  136. }
  137. fn um_step(um: &mut UMState, op: UMOp) {
  138. match op {
  139. UMOp::ConditionalMove(a, b, c) => {
  140. if um.regs[c as usize] != 0 {
  141. um.regs[a as usize] = um.regs[b as usize]
  142. }
  143. },
  144. UMOp::ArrayIndex(a, b, c) => {
  145. um.regs[a as usize] = um.mem[um.regs[b as usize] as usize][um.regs[c as usize] as usize]
  146. },
  147. UMOp::ArrayAmend(a, b, c) => {
  148. um.mem[um.regs[a as usize] as usize][um.regs[b as usize] as usize] = um.regs[c as usize]
  149. },
  150. UMOp::Add(a, b, c) => {
  151. um.regs[a as usize] = um.regs[b as usize].wrapping_add(um.regs[c as usize])
  152. },
  153. UMOp::Mult(a, b, c) => {
  154. um.regs[a as usize] = um.regs[b as usize].wrapping_mul(um.regs[c as usize])
  155. },
  156. UMOp::Div(a, b, c) => {
  157. um.regs[a as usize] = um.regs[b as usize] / um.regs[c as usize]
  158. },
  159. UMOp::NotAnd(a, b, c) => {
  160. um.regs[a as usize] = ! (um.regs[b as usize] & um.regs[c as usize])
  161. },
  162. UMOp::Halt => {
  163. println!("\n\n end of program");
  164. panic!("Halt reached")
  165. },
  166. UMOp::Allocate(b, c) => {
  167. let new_arr = vec![0u32; um.regs[c as usize] as usize];
  168. let new_arr_add = um.mem.len() as u32;
  169. um.mem.push(new_arr);
  170. um.arrmap.insert(new_arr_add, new_arr_add as usize);
  171. um.regs[b as usize] = new_arr_add;
  172. },
  173. UMOp::Abandon(c) => {
  174. let i = um.arrmap[&um.regs[c as usize]];
  175. um.arrmap.remove(&um.regs[c as usize]);
  176. um.mem[i] = vec![0u32; 0];
  177. },
  178. UMOp::Output(c) => {
  179. print!("{}", um.regs[c as usize] as u8 as char)
  180. },
  181. UMOp::Input(c) => {
  182. let input: String = read!();
  183. um.regs[c as usize] = input.chars().nth(0).unwrap() as u32 as u8 as u32;
  184. if um.regs[c as usize] == 4 {
  185. um.regs[c as usize] = 255
  186. }
  187. },
  188. UMOp::Load(b, c) => {
  189. let new_arr = um.mem[um.arrmap[&um.regs[b as usize]]].clone();
  190. let new_arr_add = um.mem.len() as u32;
  191. um.mem.push(new_arr);
  192. um.arrmap.remove(&0);
  193. um.arrmap.insert(0,new_arr_add as usize);
  194. um.pc = um.regs[c as usize] as usize;
  195. },
  196. UMOp::Value(a, val) => {
  197. um.regs[a as usize] = val
  198. }
  199. }
  200. }
  201. fn um_run(masks: HashMap<&str, (u32,u32)>,
  202. um: &mut UMState) {
  203. loop {
  204. let instr = um.mem[0][um.pc];
  205. let full_op = parse_instr(&masks, instr);
  206. //println!("{}", full_op);
  207. um.pc = um.pc+1;
  208. um_step(um, full_op);
  209. }
  210. }
  211. fn main() {
  212. let mut masks_map: HashMap<&str, (u32,u32)> = HashMap::new();
  213. masks_map.insert("op_mask", (0b11110000000000000000000000000000, 28));
  214. masks_map.insert("rega_mask", (0b00000000000000000000000111000000, 6));
  215. masks_map.insert("regb_mask", (0b00000000000000000000000000111000, 3));
  216. masks_map.insert("regc_mask", (0b00000000000000000000000000000111, 0));
  217. masks_map.insert("alta_mask", (0b00001110000000000000000000000000, 25));
  218. masks_map.insert("val_mask", (0b00000001111111111111111111111111, 0));
  219. let codex8 = &fs::read("data/sandmark.umz").unwrap();
  220. let mut codex = vec![0u32; codex8.len() / 4];
  221. for i in 0..codex.len() {
  222. codex[i] = u32::from_be_bytes([
  223. codex8[i*4],
  224. codex8[i*4+1],
  225. codex8[i*4+2],
  226. codex8[i*4+3] ]);
  227. }
  228. let mut arrmap: HashMap<u32,usize> = HashMap::new();
  229. arrmap.insert(0,0);
  230. let mut um = UMState {
  231. pc: 0,
  232. arrmap: arrmap,
  233. regs: [0,0,0,0,0,0,0,0],
  234. mem: vec![codex]
  235. };
  236. um_run(masks_map, &mut um);
  237. }