#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 int fp; int debug = 0; 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; struct stack callStack; callStack.size = 1000; callStack.currentFrame = 0; for (int i = 0; i < stack.size; ++i) { struct stackFrame *frame = malloc(sizeof(struct stackFrame)); frame->fp = malloc(sizeof(int) * stack.size); frame->sp = malloc(sizeof(int) * stack.size); frame->bp = NULL; stack.frames[i] = frame; } for (int i = 0; i < callStack.size; ++i) { struct stackFrame *frame = malloc(sizeof(struct stackFrame)); frame->fp = malloc(sizeof(int) * stack.size); frame->sp = malloc(sizeof(int) * stack.size); frame->bp = NULL; callStack.frames[i] = frame; } struct stackFrame *currentFrame = NULL; //struct stackFrame *currentCallFrame = NULL; unsigned int tmp; int intInput; char charInput; for (int i = 0; i < program->size; ++i) { unsigned int instruction = program->program[i]; if (i >= program->size) { printf("Error: Jump out of program memory\n"); goto end; } switch (instruction >> 24) { case HALT: goto end; case PUSHC: if (debug == 1) printf("PUSHC %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); push(&stack, SIGN_EXTEND(IMMEDIATE(instruction))); break; case ADD: if (debug == 1) printf("ADD\n"); push(&stack, pop(&stack) + pop(&stack)); break; case SUB: tmp = pop(&stack); if (debug == 1) printf("SUB\n"); if (debug == 1) printf("tmp: %d\n", tmp); push(&stack, pop(&stack) - tmp); break; case MUL: if (debug == 1) printf("MUL\n"); push(&stack, pop(&stack) * pop(&stack)); break; case DIV: tmp = pop(&stack); if (debug == 1) printf("DIV\n"); if (debug == 1) printf("tmp: %d\n", tmp); push(&stack, pop(&stack) / tmp); break; case MOD: tmp = pop(&stack); if (debug == 1) printf("MOD\n"); if (debug == 1) printf("tmp: %d\n", tmp); push(&stack, pop(&stack) % tmp); break; case RDINT: scanf("%i", &intInput); if (debug == 1) printf("RDINT %d\n", intInput); push(&stack, intInput); break; case WRINT: if (debug == 1) printf("WRINT\n"); printf("%i", pop(&stack)); break; case RDCHR: scanf("%c", &charInput); if (debug == 1) printf("RDCHR %c\n", charInput); push(&stack, charInput); break; case WRCHR: if (debug == 1) printf("WRCHR\n"); printf("%c", pop(&stack)); break; case PUSHG: if (debug == 1) printf("PUSHG %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); currentFrame = stack.frames[stack.currentFrame]; currentFrame->bp = currentFrame->sp; *currentFrame->sp++ = getSDA(SIGN_EXTEND(IMMEDIATE(instruction)), sda); break; case POPG: if (debug == 1) printf("POPG %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); currentFrame = stack.frames[stack.currentFrame]; currentFrame->bp = currentFrame->sp; setSDA(SIGN_EXTEND(IMMEDIATE(instruction)), pop(&stack), sda); break; case ASF: if (debug == 1) printf("ASF %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); 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: if (debug == 1) printf("RSF\n"); stack.currentFrame = pop(&stack); currentFrame = stack.frames[stack.currentFrame]; currentFrame->bp = NULL; break; case PUSHL: printf("PUSHL %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); currentFrame = stack.frames[stack.currentFrame]; currentFrame->bp = currentFrame->sp; int x = SIGN_EXTEND(IMMEDIATE(instruction)); push(&stack, currentFrame->fp[x]); break; case POPL: if (debug == 1) printf("POPL %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); currentFrame = stack.frames[stack.currentFrame]; currentFrame->fp[SIGN_EXTEND(IMMEDIATE(instruction))] = pop(&stack); break; case EQ: if (debug == 1) printf("EQ\n"); if (pop(&stack) == pop(&stack)) { push(&stack, 1); } else { push(&stack, 0); } break; case NE: if (debug == 1) printf("NE\n"); if (pop(&stack) != pop(&stack)) { push(&stack, 1); } else { push(&stack, 0); } break; case LT: if (debug == 1) printf("LT\n"); tmp = pop(&stack); if (pop(&stack) < tmp) { push(&stack, 1); } else { push(&stack, 0); } break; case LE: if (debug == 1) printf("LE\n"); tmp = pop(&stack); if (pop(&stack) <= tmp) { push(&stack, 1); } else { push(&stack, 0); } break; case GT: if (debug == 1) printf("GT\n"); if (debug == 1) printf("peek(1): %d\n", peek(&stack, 1)); if (debug == 1) printf("peek(2): %d\n", peek(&stack, 2)); if (debug == 1) printf("peek(1) > peek(2): %d\n", peek(&stack, 2) > peek(&stack, 1)); tmp = pop(&stack); if (pop(&stack) > tmp) { push(&stack, 1); } else { push(&stack, 0); } break; case GE: if (debug == 1) printf("GE\n"); tmp = pop(&stack); if (pop(&stack) >= tmp) { push(&stack, 1); } else { push(&stack, 0); } break; case JMP: if (debug == 1) printf("JMP %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); int j = SIGN_EXTEND(IMMEDIATE(program->program[i])); if (debug == 1) printf("JMP %d\n", j); if (j-- >= program->size) { printf("Error: Jump out of program memory\n"); goto end; } i = j; break; case BRF: // branch on false if (debug == 1) printf("BRF %d\nStack: %d\n", SIGN_EXTEND(IMMEDIATE(instruction)), pop(&stack)); if (pop(&stack) == 0) { int j = SIGN_EXTEND(IMMEDIATE(program->program[i])); if (j-- >= program->size) { printf("Error: BRF out of program memory\n"); goto end; } i = j; } break; case BRT: if (debug == 1) printf("BRT %d\n", SIGN_EXTEND(IMMEDIATE(instruction))); if (pop(&stack) == 1) { int j = SIGN_EXTEND(IMMEDIATE(program->program[i])); if (j-- >= program->size) { printf("Error: BRT out of program memory\n"); goto end; } i = j; } break; case CALL: tmp = SIGN_EXTEND(IMMEDIATE(program->program[i])); if (j-- >= program->size) { printf("Error: Call out of program memory\n"); goto end; } push(&callStack, i + 1); i = tmp; break; case RET: if (debug == 1) printf("RET\n"); tmp = pop(&callStack); if (tmp-- >= program->size) { printf("Error: Return out of program memory\n"); goto end; } i = tmp; break; case DROP: tmp = SIGN_EXTEND(IMMEDIATE(instruction)); if (debug == 1) printf("DROP %d\n", tmp); for (int b = 0; b < tmp; ++b) { 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 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; if (debug == 1) printProgram(program); execute(program, (struct sda *) &sda); printf("Ninja Virtual Machine stopped\n"); } else { printf("Error: no code file specified\n"); return 1; } return 0; }