/* sim1.c - Implements the six instructions for the SIM1 computer */ /* Last modified on 2014 */ /* usage "sim1 < test.sim1", up to 100 cycles with trace */ #include /* printf() function available */ #include /* exit() function declared */ #define MEMSIZE 1000 /* 1000 words of memory */ #define WORDSIZE 4 /* each word is 4 digits */ #define WORDLIMIT 9999 /* change this if you change WORDSIZE */ #define MAXCNT 100 /* limit execution of 100 instructions */ /* SIM1 operation codes with format naaa where */ /* aaa is a 3-digit address and n is as follows: */ #define HALT 0 /* halt processor */ #define LD 1 /* load accumulator instruction */ #define ST 2 /* store accumulator instruction */ #define ADD 3 /* add (to accumulator) */ #define SUB 4 /* subtract (from accumulator) */ #define LDA 5 /* load address */ /* function declarations */ void panic(char *pmessage); /* found impossible condition, C code broken */ void trace(); /* output a trace line */ void readcode(); /* input a machine language program */ void fetch(); /* fetch a machine language instruction */ void execute(); /* execute a machine language instruction */ /* external variables (declared outside any function, available to all) */ int memory[MEMSIZE]; int ip, acc, inst, cnt; int digit1, digit2, digit3, digit4, digit234; /* Start of main program (where execution begins) */ int main() { int i; /* local variable known only in main() */ /* Initialize memory and processor registers */ for (i = 0; i < MEMSIZE; i++) { memory[i]=0; } ip = 0; /* instruction pointer contains address of next instruction */ acc = 0; /* accumulator is where all arithmetic happens */ cnt = 0; /* number of instructions executed so far */ readcode(); /* input a SIM2 machine language program */ /* Main loop - fetch next instruction, decode, and execute */ while (cnt++ < MAXCNT) { /* limit execution to MAXCNT instructions */ fetch(); execute(); } /* end of while loop */ /* Normal exit is via HALT instruction, only reach here if cnt >= MAXCNT */ printf("Processor executed more than %d instructions\n", MAXCNT); trace(); exit(1); } /* end of main */ /* Fetch instruction from memory and update program counter */ void fetch() { inst = memory[ip]; /* get instruction from memory */ trace(); ip = ip + 1; /* increment instruction pointer */ ip = ip % MEMSIZE; /* wrap to 000 if ip > 999 */ /* Break apart the machine language instruction into digits */ digit4 = inst%10; /* if inst = 5678, digit4 = 8 */ digit3 = (inst/10)%10; /* digit3 = 7 */ digit2 = (inst/100)%10; /* digit2 = 6 */ digit1 = (inst/1000); /* digit1 = 5 */ digit234 = inst%1000; /* and digit234 = 678 */ } /* end of fetch */ /* Process opcodes 0 to 7 with switch statement */ void execute() { int temp; switch ( digit1 ) { case HALT: /* HALT instruction */ printf("Processor executed HALT instruction\n"); trace(); exit(0); case LD: /* load accumulator */ acc = memory[digit234]; break; case ST: /* store accumulator */ memory[digit234] = acc; break; case ADD: /* add to accumulator */ acc = acc + memory[digit234]; acc = acc % (WORDLIMIT + 1); /* wrap if regs[0] > 9999 */ break; case SUB: /* subtract from acc */ temp = (WORDLIMIT+1) - memory[digit234]; /* negate */ acc = acc + temp; /* and add */ acc = acc % (WORDLIMIT+1); /* wrap if acc > 9999 */ break; case LDA: /* load address */ acc = digit234; break; default: /* should never get here */ printf("Illegal operation code, instruction %i \n", inst); trace(); exit(1); } /* end of switch ( digit1 ) */ return; } /* end of execute */ /* function to input a machine language program */ void readcode() { #define MAXLINE 80 int addr, value, items; char line[MAXLINE]; while (1) { if ( (fgets(line, sizeof(line), stdin) ) <= 0) { /* read until EOF */ printf("End of file encountered, exiting\n"); exit(1); } printf("%s", line); /* print all lines */ if (line[0] == '#') { /* ignore comment */ continue; } items = sscanf(line, "%d %d" , &addr, &value); /* up to two ints */ switch (items) { case 0: /* illegal line, print and ignore */ printf("illegal input ignored\n"); continue; case 1: /* one number is starting address */ if ( (addr < 000) || (addr > 999) ) { printf("illegal starting address %d, exiting\n", addr); exit(1); } else { ip = addr; /* so initialize ip and return */ printf("Starting execution of SIM program at address %3.3d\n", ip); return; } case 2: /* two numbers, address and value */ if ( (addr < 000) || (addr > 999) ) { printf("illegal memory address %d, exiting\n", addr); exit(1); } if ( (value < 000) || (value > 9999) ) { printf("illegal memory value %d, exiting\n", value); exit(1); } memory[addr]=value; /* place value in memory */ } /* end switch */ } /* end of while */ } /* end of readcode() */ /* display a single line of trace output */ void trace() { printf("cnt = %d, ip = %3.3d, inst = %4.4d, acc = %4.4d\n", cnt, ip, inst, acc); } /* end of trace() */ /* panic - impossible condition (fire the programmer) */ void panic(char *pmessage) { trace(); printf("PANIC - %s, exiting\n", pmessage); exit(2); } /* end of panic() */