| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,65 @@ |
| 1 |
+#include <array> |
|
| 2 |
+#include <cstdint> |
|
| 3 |
+#include <cstdio> |
|
| 4 |
+#include <cstdlib> |
|
| 5 |
+#include <fstream> |
|
| 6 |
+#include <iostream> |
|
| 7 |
+#include <vector> |
|
| 8 |
+ |
|
| 9 |
+void um(std::istream & scroll, std::istream & i, std::ostream & o) |
|
| 10 |
+{
|
|
| 11 |
+ std::unitbuf(o); |
|
| 12 |
+ using Chr = std::uint8_t; |
|
| 13 |
+ using Plt = std::uint32_t; |
|
| 14 |
+ auto reg = std::array<Plt, 8>(); |
|
| 15 |
+ auto arr = std::vector<std::vector<Plt>>(1); |
|
| 16 |
+ auto fng = Plt(0); |
|
| 17 |
+ auto hlt = false; |
|
| 18 |
+ auto alloc = [&](Plt c) { arr.emplace_back(c); return(Plt)arr.size()-1; };
|
|
| 19 |
+ auto aband = [&](Plt c) { arr[c] = decltype(arr)::value_type(); };
|
|
| 20 |
+ #define PACK(IND) ((Plt)(Chr)ch[IND] << 8*(3-IND)) |
|
| 21 |
+ for (char ch[4]; scroll.read(ch, 4);) |
|
| 22 |
+ arr[0].push_back(PACK(0) | PACK(1) | PACK(2) | PACK(3)); |
|
| 23 |
+ #undef PACK |
|
| 24 |
+ while (!hlt) |
|
| 25 |
+ {
|
|
| 26 |
+ #define UNPACK(POS, SIZ) ((plt >> POS) & ((Plt(1) << SIZ) - 1)) |
|
| 27 |
+ auto plt = arr[0][fng++]; |
|
| 28 |
+ auto num = UNPACK(28, 4); |
|
| 29 |
+ auto val = UNPACK( 0, 25); |
|
| 30 |
+ auto & a = reg[UNPACK( 6, 3)]; |
|
| 31 |
+ auto & b = reg[UNPACK( 3, 3)]; |
|
| 32 |
+ auto & c = reg[UNPACK( 0, 3)]; |
|
| 33 |
+ auto & d = reg[UNPACK(25, 3)]; |
|
| 34 |
+ #undef UNPACK |
|
| 35 |
+ switch (num) |
|
| 36 |
+ {
|
|
| 37 |
+ case 0: a = c ? b : a; break; // CMOVE |
|
| 38 |
+ case 1: a = arr[b][c]; break; // LOAD |
|
| 39 |
+ case 2: arr[a][b] = c; break; // STOR |
|
| 40 |
+ case 3: a = b + c; break; // ADD |
|
| 41 |
+ case 4: a = b * c; break; // MUL |
|
| 42 |
+ case 5: a = b / c; break; // DIV |
|
| 43 |
+ case 6: a = ~(b & c); break; // NAND |
|
| 44 |
+ case 7: hlt = true; break; // HALT |
|
| 45 |
+ case 8: b = alloc(c); break; // ALLOC |
|
| 46 |
+ case 9: aband(c); break; // ABAND |
|
| 47 |
+ case 10: o.put(c); break; // PUT |
|
| 48 |
+ case 11: c = i.get(); break; // GET |
|
| 49 |
+ case 12: arr[0] = arr[b]; fng = c; break; // EXEC |
|
| 50 |
+ case 13: d = val; break; // VALUE |
|
| 51 |
+ } |
|
| 52 |
+ } |
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+int main(int argc, char * argv[]) |
|
| 56 |
+{
|
|
| 57 |
+ if (argc != 2) |
|
| 58 |
+ return std::fputs("Usage: um <scroll>\n", stderr), EXIT_FAILURE;
|
|
| 59 |
+ auto scroll = std::ifstream(argv[1], std::ios::binary); |
|
| 60 |
+ if (scroll.fail()) |
|
| 61 |
+ return std::perror("Failed to read scroll"), EXIT_FAILURE;
|
|
| 62 |
+ if (scroll.peek(), scroll.eof()) |
|
| 63 |
+ return std::fputs("Empty scroll\n", stderr), EXIT_FAILURE;
|
|
| 64 |
+ um(scroll, std::cin, std::cout); |
|
| 65 |
+} |