// g++ -o um -O3 -Xlinker -pagezero_size -Xlinker 4000000 umdir.cpp
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <sys/mman.h>
class Machine
{
std::vector<unsigned int> data;
public:
Machine(char *fname);
int Run();
};
Machine::Machine(char *fname):data()
{
std::cout << "Loading..." << std::endl;
FILE * f = fopen(fname, "r");
int c1;
while ((c1 = fgetc(f)) != EOF)
{
int c2, c3, c4;
c2 = fgetc(f);
c3 = fgetc(f);
c4 = fgetc(f);
unsigned int instr = ((unsigned int)c1 << 24) + ((unsigned int)c2 << 16) + ((unsigned int)c3 << 8) + (unsigned int)c4;
data.push_back(instr);
}
std::cout << "Loaded" << std::endl;
}
#define regA registers[(instruction >> 6) & 7]
#define regB registers[(instruction >> 3) & 7]
#define regC registers[instruction & 7]
#define Next instruction = *finger++; goto *ops[instruction >> 28];
int Machine::Run()
{
void* ops[] = {&&op_0, &&op_1, &&op_2, &&op_3, &&op_4, &&op_5, &&op_6, &&op_7, &&op_8, &&op_9, &&op_10, &&op_11, &&op_12, &&op_13};
unsigned int * finger = 0;
unsigned int registers[8];
memset(registers, 0, 8*sizeof(unsigned int));
unsigned int zsize = data.size();
unsigned int zactual = 4096*(1 + 4*zsize/4096);
if (mmap(0, zactual, PROT_READ | PROT_WRITE, MAP_ANON | MAP_FIXED | MAP_PRIVATE, -1, 0) == (unsigned int*)-1)
{
printf("Whoops!\n");
return 0;
}
for (unsigned int i = 0; i < zsize; ++i)
*(unsigned int*)(4*i)=data[i];
unsigned int instruction;
unsigned int * tmp;
unsigned int sz;
Next;
op_0:
if (regC != 0) regA = regB;
Next;
op_1:
regA = ((unsigned int*)(regB))[regC];
Next;
op_2:
((unsigned int*)(regA))[regB] = regC;
Next;
op_3:
regA = regB + regC;
Next;
op_4:
regA = regB * regC;
Next;
op_5:
regA = regB / regC;
Next;
op_6:
regA = ~(regB & regC);
Next;
op_7:
return 0;
op_8:
sz = regC;
tmp = (unsigned int*) calloc(1+sz,4);
*tmp++ = sz;
regB = (unsigned int)tmp;
Next;
op_9:
free((unsigned int*)(regC) - 1);
Next;
op_10:
putchar(regC);
Next;
op_11:
regC = getchar();
if (regC == EOF) clearerr(stdin);
Next;
op_12:
tmp = (unsigned int*)(regB);
if (tmp)
{
sz = tmp[-1];
if (sz > zsize)
{
zsize = sz;
zactual = 4096*(1 + 4*zsize/4096);
mmap(0, zactual, PROT_READ | PROT_WRITE, MAP_ANON | MAP_FIXED | MAP_PRIVATE, -1, 0);
}
memcpy(0, tmp, sz*4);
}
finger = (unsigned int*)(4 * regC);
Next;
op_13:
registers[(instruction >> 25) & 7] = (instruction & ((1 << 25) - 1));
Next;
}
int main(int argc, char **argv)
{
if (argc != 2)
{
std::cout << "Usage: um inputfile\n";
return 1;
}
Machine(argv[1]).Run();
return 0;
}