Skip to content

Instantly share code, notes, and snippets.

@blooser
Created August 2, 2018 00:14
Show Gist options
  • Save blooser/fa596a161416499313731670cbbe1a72 to your computer and use it in GitHub Desktop.
Save blooser/fa596a161416499313731670cbbe1a72 to your computer and use it in GitHub Desktop.
Virtual machine
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include "vm.h"
void vm_init(VM *vm, int *code, int code_size, int nglobals){
vm->code = code;
vm->code_size = code_size;
vm->globals = calloc(nglobals, sizeof(int));
vm->nglobals = nglobals;
}
void vm_free(VM *vm){
free(vm->globals);
free(vm);
}
VM *vm_create(int *code, int code_size, int nglobals){
VM *vm = calloc(1, sizeof(VM));
vm_init(vm, code, code_size, nglobals);
return vm;
}
void vm_exec(VM *vm, int start){
int sp;
int ip;
int a;
int b;
a = b = 0;
int addr;
ip = start;
sp = -1;
int opcode = vm->code[ip];
while(opcode != HALT && ip < vm->code_size){
ip++;
switch(opcode){
case ADD:
b = vm->stack[sp--];
a = vm->stack[sp--];
vm->stack[++sp] = a + b;
break;
case SUB:
b = vm->stack[sp--];
a = vm->stack[sp--];
vm->stack[++sp] = a - b;
break;
case MUL:
b = vm->stack[sp--];
a = vm->stack[sp--];
vm->stack[++sp] = a * b;
break;
case AND:
b = vm->stack[sp--];
a = vm->stack[sp--];
vm->stack[++sp] = a & b;
break;
case OR:
b = vm->stack[sp--];
a = vm->stack[sp--];
vm->stack[++sp] = a | b;
break;
case XOR:
b = vm->stack[sp--];
a = vm->stack[sp--];
vm->stack[++sp] = a ^ b;
break;
case NOT:
a = vm->stack[sp--];
vm->stack[++sp] = a ? false : true;
break;
case LT:
b = vm->stack[sp--];
a = vm->stack[sp--];
vm->stack[++sp] = (a < b) ? true : false;
break;
case EQ:
b = vm->stack[sp--];
a = vm->stack[sp--];
vm->stack[++sp] = (a == b) ? true : false;
break;
case PRINT:
printf("%d\n", vm->stack[sp--]);
break;
case OUTCHAR:
printf("%c", vm->stack[sp--]);
break;
case PUSH:
vm->stack[++sp] = vm->code[ip++];
break;
case BR:
ip = vm->code[ip++];
break;
case BRF:
addr = vm->code[ip++];
if(vm->stack[sp--] == false) ip = addr;
break;
case DROP:
--sp;
break;
case GLOAD:
addr = vm->code[ip++];
vm->stack[++sp] = vm->globals[addr];
break;
case GSTORE:
addr = vm->code[ip++];
vm->globals[addr] = vm->stack[sp--];
break;
default:
printf("Invalid opcode");
exit(1);
}
opcode = vm->code[ip];
}
}
void vm_print_data(int *globals, int count){
printf("Data memory\n");
REP(i, count)
printf("%04d: %d\n", i, globals[i]);
}
#ifndef VM_H_
#define VM_H_
#ifdef __cpluplus
extern "C"{
#endif
#define MAX_STACK_SIZE 1024
#define REP(i, n) for(int i=0; i<n; i++)
typedef enum{
NOP = 0,
ADD = 1,
SUB = 2,
AND = 3,
OR = 4,
XOR = 5,
IN = 6,
NOT = 7,
SWAP = 8,
MUL = 9,
LT = 10,
EQ = 11,
PUSH = 12,
LOAD = 13,
GLOAD = 14,
STORE = 15,
GSTORE = 16,
PRINT = 17,
DROP = 18,
BR = 19,
BRF = 20,
OUTCHAR = 21,
HALT = 22
} CODES;
typedef struct{
int *code;
int code_size;
int *globals;
int nglobals;
int stack[MAX_STACK_SIZE];
} VM;
VM *vm_create(int *code, int code_size, int nglobals);
void vm_init(VM *vm, int *code, int code_size, int nglobals);
void vm_free(VM *vm);
void vm_exec(VM *vm, int start);
void vm_print_data(int *globals, int count);
#ifdef __cpluplus
}
#endif
#endif
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
#include "vm.h"
int check_if_power_of_two[] = {
PUSH, 64,
PUSH, 64,
PUSH, 1,
SUB,
AND,
PRINT,
HALT
};
int hello_world[] = {
PUSH, 10, PUSH, 33, PUSH, 100,
PUSH, 108, PUSH, 114, PUSH, 111,
PUSH, 87, PUSH, 32, PUSH, 44,
PUSH, 111, PUSH, 108, PUSH, 108,
PUSH, 101, PUSH, 72,
OUTCHAR, OUTCHAR, OUTCHAR,
OUTCHAR, OUTCHAR, OUTCHAR,
OUTCHAR, OUTCHAR, OUTCHAR,
OUTCHAR, OUTCHAR, OUTCHAR,
OUTCHAR, OUTCHAR,
HALT
};
int loop[] = {
PUSH, 15,
GSTORE, 0,
PUSH, 0,
GSTORE, 1,
GLOAD, 1,
GLOAD, 0,
LT,
BRF, 24,
GLOAD, 1,
PUSH, 1,
ADD,
GSTORE, 1,
BR, 8,
HALT
};
int main(void){
VM *vm = vm_create(check_if_power_of_two, sizeof(check_if_power_of_two), 0);
vm_exec(vm, 0);
vm_free(vm);
printf("\n");
vm = vm_create(hello_world, sizeof(hello_world), 0);
vm_exec(vm, 0);
vm_free(vm);
printf("\n");
float distance1 = (clock() / (CLOCKS_PER_SEC/1000));
vm = vm_create(loop, sizeof(loop), 2);
vm_exec(vm, 0);
vm_print_data(vm->globals, vm->nglobals);
vm_free(vm);
float distance2 = (clock() / (CLOCKS_PER_SEC/1000));
printf("Duration: %d ms\n", (distance2 - distance1));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment