main.rs 6.8 KB

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