#include #include #include #include #define CORE_SIZE 0x10000 #define UART (0xFF0000) #define PROGRAM \ LABEL(start) \ LOD(L(Q32)) \ STO(L(C)) \ LABEL(loop) \ LOD(L(C)) \ STO(UART) \ ADD(L(Q1)) \ STO(L(C)) \ SUB(L(Q127)) \ JNZ(L(loop)) \ JMP(L(start)) \ LABEL(C) \ DW(0) \ LABEL(Q32) DW(32) \ LABEL(Q1) DW(1) \ LABEL(Q127) DW(127) #define OPCODES \ _(ADD), _(ILL1), _(SUB), _(ILL3), \ _(AND), _(IOR), _(XOR), _(SHR), \ _(LOD), _(ILL9), _(STO), _(ILLB), \ _(JMP), _(JNZ), _(JNC), _(ILLF) #define _(x) OP_##x enum { OPCODES }; #undef _ #define ADD(x) DW((OP_ADD<<28)|(x)) #define SUB(x) DW((OP_SUB<<28)|(x)) #define IOR(x) DW((OP_IOR<<28)|(x)) #define XOR(x) DW((OP_XOR<<28)|(x)) #define AND(x) DW((OP_AND<<28)|(x)) #define LOD(x) DW((OP_LOD<<28)|(x)) #define STO(x) DW((OP_STO<<28)|(x)) #define JMP(x) DW((OP_JMP<<28)|(x)) #define JNZ(x) DW((OP_JNZ<<28)|(x)) #define DW(x) uint32_t :24; #define LABEL(x) uint8_t x; struct reloc { PROGRAM }; #undef DW #undef LABEL #define LABEL(x) #define DW(x) x, #define L(x) ((uint32_t)((offsetof(struct reloc,x) + 3)/4)) uint32_t core[CORE_SIZE] = { PROGRAM }; #undef DW #undef LABEL uint32_t memr (uint32_t p) { if (p < CORE_SIZE) { return core[p]; } else if (p == UART) { return (unsigned)getchar(); } else { fprintf (stderr, "\nBUS FAULT while reading from 0x%lx; the party is over.\n", (unsigned long)p); abort(); } } void memw (uint32_t p, uint32_t v) { if (p < CORE_SIZE) { core[p] = v; } else if (p == UART) { putchar (v & 0xFF); fflush (stdout); } else { fprintf (stderr, "\nBUS FAULT while writing; the party is over.\n"); abort(); } } void emu (void) { uint32_t pc = 0; uint64_t ac = 0; #define MEM ((uint64_t)memr(arg)) #define A ((ac & 0xFFFFFFFFUL)) #define CF ((ac >> 32)&1) #define PC (pc-1) for (;;) { uint32_t insn = memr(pc++); uint32_t arg = insn & 0xFFFFFFF; unsigned op = (insn >> 28) & 0xF; switch (op & 0xF) { case OP_ADD: ac = A + memr(arg); break; case OP_SUB: ac = (uint64_t)A - (uint64_t)memr(arg); break; case OP_AND: ac = A & memr(arg); break; case OP_IOR: ac = A | memr(arg); break; case OP_XOR: ac = A ^ memr(arg); break; case OP_SHR: ac = A >> 1; break; case OP_JMP: if (PC == arg) goto halt; pc = arg; break; case OP_JNZ: if (A) pc = arg; break; case OP_JNC: if (!CF) pc = arg; break; case OP_LOD: ac = memr(arg); break; case OP_STO: memw(arg, A); break; } } halt:; } int main (void) { emu (); return 0; }