#include #include #include "instruktion.c" #include "code.c" #include "stack.c" #include "program.c" #include "codeReader.c" #include "SDA.c" // Program struct program *program; // SDA unsigned fp; void version(void) { printf("Ninja Virtual Machine version %i (compiled %s, %s)\n", 0, __DATE__, __TIME__); } void help(void) { printf("Usage: ./njvm [options] \n\t--debug\tstart virtual machine in debug mode\n\t--version\tshow version and exit\n\t--help\t\tshow this help and exit\n"); } void execute(struct program *program, struct sda *sda) { struct stack stack; stack.size = 1000; stack.currentFrame = 0; for (int i = 0; i < stack.size; ++i) { struct stackFrame *frame = malloc(sizeof(struct stackFrame)); frame->fp = malloc(sizeof(unsigned int) * stack.size); frame->sp = malloc(sizeof(unsigned int) * stack.size); frame->bp = NULL; stack.frames[i] = frame; } struct stackFrame *currentFrame = NULL; unsigned int tmp; int intInput; char charInput; for (int i = 0; i < program->size; ++i) { unsigned int instruction = program->program[i]; switch (instruction >> 24) { case HALT: goto end; case PUSHC: push(&stack, SIGN_EXTEND(IMMEDIATE(instruction))); break; case ADD: push(&stack, pop(&stack) + pop(&stack)); break; case SUB: tmp = pop(&stack); push(&stack, pop(&stack) - tmp); break; case MUL: push(&stack, pop(&stack) * pop(&stack)); break; case DIV: tmp = pop(&stack); push(&stack, pop(&stack) / tmp); break; case MOD: tmp = pop(&stack); push(&stack, pop(&stack) % tmp); break; case RDINT: scanf("%i", &intInput); push(&stack, intInput); break; case WRINT: printf("%i", pop(&stack)); break; case RDCHR: scanf("%c", &charInput); push(&stack, charInput); break; case WRCHR: printf("%c", pop(&stack)); break; case PUSHG: currentFrame = stack.frames[stack.currentFrame]; currentFrame->bp = currentFrame->sp; *currentFrame->sp++ = getSDA(SIGN_EXTEND(IMMEDIATE(instruction)), sda); break; case POPG: currentFrame = stack.frames[stack.currentFrame]; currentFrame->bp = currentFrame->sp; setSDA(SIGN_EXTEND(IMMEDIATE(instruction)), pop(&stack), sda); break; case ASF: currentFrame = stack.frames[stack.currentFrame]; push(&stack, *currentFrame->sp); *currentFrame->sp = stack.currentFrame; currentFrame->bp = currentFrame->sp; stack.currentFrame += SIGN_EXTEND(IMMEDIATE(instruction)); break; case RSF: stack.currentFrame = pop(&stack); currentFrame = stack.frames[stack.currentFrame]; currentFrame->bp = NULL; break; case PUSHL: currentFrame = stack.frames[stack.currentFrame]; push(&stack, currentFrame->fp[SIGN_EXTEND(IMMEDIATE(instruction))]); break; case POPL: currentFrame = stack.frames[stack.currentFrame]; currentFrame->fp[SIGN_EXTEND(IMMEDIATE(instruction))] = pop(&stack); break; } } end: return; } // run prog2.bin void tests(void) { printf("Test started\n"); struct sda *sda = malloc(sizeof(struct sda)); unsigned int s[1000]; sda->size = 1000; sda->sda = s; fromFile("prog2.bin", program); execute(program, (struct sda *) &sda); printf("Test finished\n"); } int main(int argc, char *argv[]) { // Initialize the Stack struct stack stack; int size = SIZE; stack.size = size; stack.currentFrame = 0; // Initialize ProgrammSpeicher int psize = SIZE; unsigned int p[1000]; program = malloc(sizeof(struct program)); program->size = psize; program->program = p; // Initialize runtime variables int debug = 0; int run = 0; int sizeSDA; if (argc > 1) { for (int i = 1; i < argc; ++i) { if (strcmp(argv[i], "--debug") == 0) { debug = 1; } else if (strcmp(argv[i], "--version") == 0) { version(); return 0; } else if (strcmp(argv[i], "--help") == 0) { help(); return 0; } else { sizeSDA = fromFile(argv[i], program); run = 1; } } } /* * Debug mode */ if (debug) { tests(); } /* * Run program */ if (run) { printf("Ninja Virtual Machine started\n"); struct sda *sda = malloc(sizeof(struct sda)); unsigned int s[sizeSDA]; sda->size = sizeSDA; sda->sda = s; printProgram(program); execute(program, (struct sda *) &sda); if (debug == 1) printSDA(sda); printf("Ninja Virtual Machine stopped\n"); } else { printf("Error: no code file specified\n"); return 1; } return 0; }