/* sim2.c - Add skip and jump instructions to the SIM1 computer */ /* Last modified on 2014 */ /* usage "sim2 < test.sim2", 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 (plus JMP) 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 */ #define JMP 6 /* jump (branch) to address */ #define SKIPSET 7 /* skip instructions */ /* SIM2 skip operation codes with format 7n0r where r is a general */ /* register and n is as follows: */ #define SKIP 0 /* unconditional skip */ #define SKEQ 1 /* skip if acc equals 0 */ #define SKNE 2 /* skip if acc not equal to 0 */ #define SKGT 3 /* skip if acc greater than 0 */ #define SKGE 4 /* skip if acc greater or equal to 0 */ #define SKLT 5 /* skip if acc less than 0 */ #define SKLE 6 /* skip if acc less than or equal to 0 */ /* 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 */ void skipop(); /* process skip operation codes */ /* 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; case JMP: /* jump instruction */ ip = digit234; break; case SKIPSET: /* skip instructions */ skipop(); 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 */ /* process "skip" instructions with format 7n00 where */ /* n equals digit2 */ void skipop() { if (digit3 != 0 || digit4 != 0) { printf("Illegal skip instruction, instruction %i \n", inst); trace(); exit(1); } switch ( digit2 ) { case SKIP: /* unconditional skip */ ip = ip + 1; break; case SKEQ: /* skip if acc equals 0 */ if (acc == 0) ip = ip + 1; break; case SKNE: /* skip if acc not equal 0 */ if (acc != 0) ip = ip + 1; break; case SKGT: /* skip if acc greater than 0 */ if (acc > 0 && acc < 5000) ip = ip + 1; break; case SKGE: /* skip if acc greater or equal to 0 */ if (acc >= 0 && acc < 5000) ip = ip + 1; break; case SKLT: /* skip if acc less than 0 */ if (acc >= 5000) ip = ip + 1; break; case SKLE: /* skip if acc less than or equal to 0 */ if (acc >= 5000 || acc == 0) ip = ip + 1; break; default: printf("Illegal skip code, instruction %i \n", inst); exit(1); } /* end of "7n00" switch */ ip = ip % MEMSIZE; /* wrap if ip > 999 */ return; /* finished processing legal skip instruction */ } /* end of skipop() */ /* 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 ignorred\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() */