[Home]Rachael/ICFP

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;
           }
         
       }


}



ec2-18-117-152-251.us-east-2.compute.amazonaws.com | ToothyWiki | Rachael | RecentChanges | Login | Webcomic
This page is read-only | View other revisions | Recently used referrers
Last edited January 30, 2007 3:37 pm (viewing revision 4, which is the newest) (diff)
Search: