ec2-18-117-152-251.us-east-2.compute.amazonaws.com | ToothyWiki | Rachael | RecentChanges | Login | Webcomic
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#define OPCODE_MASK (1 << 31 | 1 << 30 | 1 << 29 | 1 << 28 )
#define A_MASK (1 << 8 | 1 << 7 | 1 << 6 )
#define B_MASK (1 << 5 | 1 << 4 | 1 << 3 )
#define C_MASK (1 << 2 | 1 << 1 | 1 << 0 )
#define ORTHOGRAPHY_A_MASK (1 << 27 | 1 << 26 | 1 << 25 )
enum eOpcode
{
CONDITIONALMOVE,
ARRAYINDEX,
ARRAYAMEND,
ADD,
MULTIPLY,
DIVIDE,
NAND,
HALT,
ALLOC,
FREE,
OUTPUT,
INPUT,
LOADPROGRAM,
ORTHOGRAPHY
};
typedef struct
{
unsigned int * anArray;
unsigned int nSize;
} t_array;
/*helper function to read the input file from a file handle into an
unsigned int array*/
unsigned int * fileReadInToArray(FILE * fpInput)
{
char c;
unsigned int ii;
unsigned int * anArray = NULL;
struct stat st;
fstat(fileno(fpInput), &st);
int nSize = st.st_size / 4; /*divide char count by 4 to get int32 count*/
anArray = malloc(nSize * sizeof(*anArray));
for (ii = 0; ii < nSize - 1; ii++)
{
anArray[ii] = (unsigned char)getc(fpInput) << 24 | (unsigned
char)getc(fpInput) << 16 | (unsigned char)getc(fpInput) << 8 |
(unsigned char)getc(fpInput);
}
return anArray;
}
int main(int argc, char ** argv)
{
unsigned int registers[8] = {0,0,0,0,0,0,0,0};
FILE * fpInput = fopen(argv[1], "rb");
unsigned int * pc = NULL;
unsigned int nOp;
unsigned int nRegisterA, nRegisterB, nRegisterC;
unsigned int nTemp, nInstructionNumber = 0;
unsigned int * anZero = fileReadInToArray(fpInput);
if (anZero) pc = anZero;
for (; ; )
{
pc = &(anZero[nInstructionNumber++]);
nOp = *pc >> 28;
nRegisterA = (*pc & A_MASK) >> 6;
nRegisterB = (*pc & B_MASK) >> 3;
nRegisterC = (*pc & C_MASK);
switch (nOp)
{
case CONDITIONALMOVE:
if (registers[nRegisterC] != 0) registers[nRegisterA] = registers[nRegisterB];
break;
case ARRAYINDEX:
if (registers[nRegisterB] == 0)
{
registers[nRegisterA] = anZero[registers[nRegisterC]];
}
else
{
registers[nRegisterA] = (((t_array *)registers[nRegisterB])->anArray)[registers[nRegisterC]];
}
break;
case ARRAYAMEND:
if (registers[nRegisterA] == 0)
{
anZero[registers[nRegisterB]] = registers[nRegisterC];
}
else
{
(((t_array *)registers[nRegisterA])->anArray)[registers[nRegisterB]] = registers[nRegisterC];
}
break;
case ADD:
registers[nRegisterA] = registers[nRegisterB] + registers[nRegisterC];
break;
case MULTIPLY:
registers[nRegisterA] = registers[nRegisterB] * registers[nRegisterC];
break;
case DIVIDE:
if (0 == registers[nRegisterC])
{
printf("Error: divide by zero");
return -1;
}
registers[nRegisterA] = (unsigned int) registers[nRegisterB] / (unsigned int) registers[nRegisterC];
break;
case NAND:
registers[nRegisterA] = ~registers[nRegisterB] | ~registers[nRegisterC];
break;
case HALT:
return 0; /*break not needed*/
case ALLOC:
{
t_array * pNewArray = malloc(sizeof(t_array));
pNewArray->anArray = calloc(registers[nRegisterC], sizeof(unsigned int));
pNewArray->nSize = registers[nRegisterC];
registers[nRegisterB] = (unsigned int)pNewArray ;
break;
}
case FREE:
free(((t_array *)registers[nRegisterC])->anArray);
free((t_array *)registers[nRegisterC]);
break;
case OUTPUT:
if (registers[nRegisterC] >= 0 && registers[nRegisterC] <= 255) putchar(registers[nRegisterC]);
break;
case INPUT:
nTemp = getchar();
if (nTemp >= 0 && nTemp <= 255) registers[nRegisterC] = nTemp;
else if (nTemp == EOF) registers[nRegisterC] = ~0;
/*todo error otherwise*/
break;
case LOADPROGRAM:
if (registers[nRegisterB] != 0)
{
unsigned int nNewSize = ((t_array *)registers[nRegisterB])->nSize;
free(anZero);
anZero = calloc(nNewSize, sizeof(*anZero));
for (nTemp=0;nTemp<nNewSize;nTemp++)
{
anZero[nTemp] = (((t_array*)registers[nRegisterB])->anArray)[nTemp];
}
}
nInstructionNumber = registers[nRegisterC];
continue; /*in for loop */
/* break not needed*/
case ORTHOGRAPHY:
nRegisterA = (*pc & ORTHOGRAPHY_A_MASK) >> 25;
registers[nRegisterA] = *pc & ~ORTHOGRAPHY_A_MASK & ~OPCODE_MASK;
break;
default:
/*todo error*/
break;
}
}
}