/* file: stm.c * * Code for the simulated toy machine (STM), * a simulated architecture supporting variable-length partitions. * * The original STM CODE is from Professor Ernie Davis with permission. ***************************************************/ #include "stm.h" /*************************************************** * externs ***************************************************/ extern void exec_trap(); /* trap handling is OS-dependent */ /*************************************************** * Global Variables for STM ***************************************************/ int debug = 0, /* Level of debugging */ error = 0, /* Error flag */ terminate = 0; /* Termination flag */ int mem[RAMSIZE], /* Core memory */ regs[NUMREGS], /* Number of registers */ base, /* Base register */ limit; /* limit register */ char codes[16][4] = /* Abbreviations for opcodes */ { "LOA", "STO", "CPR", "LOI", "STI", "ADD", "SUB", "MUL", "DIV", "ICR", "DCR", "GTR", "JMP", "IFZ", "JMI", "TRP" }; /*************************************************** * Convert a relative address to a physical address. * Check that it lies within bounds * Note: This is considered part of the "hardware" of the virtual machine. * You may not change it in any of the projects. ***************************************************/ int phys_address(int reladd) { if ((reladd >= 0) && (reladd < limit)) return(reladd+base); else { error = 1; printf("Error: Address out of bounds\n"); return(0); } } /*************************************************** * Display STM instruction for level-2 debugging ***************************************************/ void show_inst(op, ra, ad, rb, rc, rd) int op, ra, ad, rb, rc, rd; { //printf("Process %i %s instruction 0x%X : %3s", // procindex, procname, regs[0], codes[op]); printf("Instruction 0x%X : %3s", regs[0], codes[op]); switch(op) { case 0: case 1: case 13: printf(" R%i Address 0x%X", ra, ad); break; case 12: printf(" Address 0x%X", ad); break; case 2: case 3: case 4: printf(" R%i R%i", ra, rb); break; case 5: case 6: case 7: case 11: printf(" R%i R%i R%i", ra, rb, rc); break; case 8: printf(" R%i R%i R%i R%i", ra, rb, rc, rd); break; case 9: case 10: case 14: printf(" R%i ", ra); break; } printf("\n"); } /*************************************************** * Decompose an STM instruction into its components ***************************************************/ void get_inst(inst, pop, pra, pad, prb, prc, prd) int inst, *pop, *pra, *pad, *prb, *prc, *prd; { *pop = inst % 16; inst = inst / 16; *pra = inst % 16; inst = inst / 16; *pad = inst % RAMSIZE; *prb = inst % 16; inst = inst / 16; *prc = inst % 16; inst = inst / 16; *prd = inst % 16; if (debug == 2) show_inst(*pop, *pra, *pad, *prb, *prc, *prd); } /*************************************************** /* Execute an STM instruction. * This is what does the actual work of carrying out the STM code ***************************************************/ int exec_inst(op, ra, ad, rb, rc, rd) int op, ra, ad, rb, rc, rd; { int regrep = 0; /* Flag for repeated registers */ int trap = 0; switch (op) { case 0: regs[ra] = mem[phys_address(ad)]; break; case 1: mem[phys_address(ad)] = regs[ra]; break; case 2: regs[ra] = regs[rb]; break; case 3: regs[ra] = mem[phys_address(regs[rb])]; break; case 4: mem[phys_address(regs[ra])] = regs[rb]; break; case 5: regs[rc] = regs[ra] + regs[rb]; break; case 6: regs[rc] = regs[ra] - regs[rb]; break; case 7: regs[rc] = regs[ra] * regs[rb]; break; case 8: if (regs[rb] == 0) { printf("Arithmetic error: Divide by zero\n"); error = 1; } else { regs[rc] = regs[ra] / regs[rb]; regs[rd] = regs[ra] % regs[rb]; } break; case 9: regs[ra]++; break; case 10: regs[ra]--; break; case 11: regs[rc] = (regs[ra] > regs[rb]); break; case 12: regs[0] = ad; break; case 13: if (regs[ra] == 0) regs[0] = ad; break; case 14: regs[0] = regs[ra]; break; case 15: trap = 1; break; } return(trap); } /*************************************************** * fetch and execute an instruction of STM code ***************************************************/ void exec_stm() { int opcode, rega, ad, regb, regc, regd; /* Components of STML instruction */ int trap; /* flag that code executes a trap */ int padd; /* physical address */ int i; padd=phys_address(regs[0]); if (debug == 2) { printf("Registers: "); for (i=0; i<16; i++) printf(" %3i", regs[i]); printf("\n"); printf("address 0x%X instruction 0x%X\n", regs[0], mem[padd]); } get_inst(mem[padd], &opcode, ®a, &ad, ®b, ®c, ®d); /* fetch instruction */ if (!error) { regs[0]++; /* increment PC */ if (regs[0] >= limit) error=1; else { trap = exec_inst(opcode, rega, ad, regb, regc, regd); /*execute*/ if (trap) exec_trap(); /* handle trap */ /* NOTE: exec_trap() is part of SOS */ } } } // This to specify the hardware of stm (please use our versioning convention void version() { /* an optional argument can give more info */ printf("This is STM Version 0\n"); }