Skip to content

Instantly share code, notes, and snippets.

@itsbth
Created November 19, 2011 20:44
Show Gist options
  • Select an option

  • Save itsbth/1379332 to your computer and use it in GitHub Desktop.

Select an option

Save itsbth/1379332 to your computer and use it in GitHub Desktop.
Uploaded by UploadToGist for Sublime Text 2
#include "vm.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
struct _vm_state {
int regi[8];
double regf[8];
unsigned int code_len;
unsigned int *code;
unsigned int data_len;
int *data;
unsigned int iptr;
unsigned int sptr;
vm_interrupt_handler interrupt_table[VM_INTERRUPT_TABLE_SIZE];
};
#include "instr_names.c"
void *vm_decode_rm(vm_state s, unsigned int rm, bool write);
void print_rm(char *target, unsigned int rm) {
unsigned int val = rm & VM_DATA_MASK;
char tmp[64];
if (rm & VM_REG_MASK) {
sprintf(tmp, "VM_REG(0x%x)", val);
} else if (rm & VM_CODE_MASK) {
sprintf(tmp, "VM_CODE(0x%x)", val);
} else {
sprintf(tmp, "0x%x", val);
}
strcat(target, tmp);
}
char *print_instr(vm_state s, unsigned int iptr) {
static char line[256];
memset(line, 0, 256);
strcat(line, instr_names[s->code[iptr]]);
strcat(line, " ");
print_rm(line, s->code[iptr+1]);
strcat(line, ", ");
print_rm(line, s->code[iptr+2]);
return line;
}
void _panic(vm_state s, bool pred, char *pred_str, char *file, int line) {
if (pred) return;
fprintf(stderr, "ASSERTION FAILED:\n");
fprintf(stderr, " `%s`\n", pred_str);
fprintf(stderr, " in %s:%d\n", file, line);
fprintf(stderr, " ---\n");
fprintf(stderr, " s->iptr = 0x%x\n", s->iptr);
fprintf(stderr, " ---\n");
if (s->iptr >= 3) fprintf(stderr, " %s\n", print_instr(s, s->iptr-3));
fprintf(stderr, "->%s<-\n", print_instr(s, s->iptr));
if (s->iptr+3 < s->code_len) fprintf(stderr, " %s\n", print_instr(s, s->iptr+3));
exit(1);
}
#define panic(state, pred) _panic(state, pred, #pred, __FILE__, __LINE__)
vm_state vm_create_state(unsigned int *code, unsigned int code_len, unsigned int data_len) {
vm_state s = malloc(sizeof(struct _vm_state));
memset(s, 0, sizeof(struct _vm_state));
s->code = code; // TODO: Create a copy?
s->code_len = code_len;
s->data_len = data_len;
s->data = malloc(sizeof(int) * data_len);
s->iptr = 0;
return s;
}
void *vm_decode_rm(vm_state s, unsigned int rm, bool write) {
unsigned int data_val = rm & VM_DATA_MASK;
if (rm & VM_REG_MASK) {
panic(s, data_val < 16);
return &s->regi[data_val];
}
if (rm & VM_CODE_MASK) {
panic(s, data_val < s->code_len);
return &s->code[data_val];
}
//if (rm & VM_CONST_MASK && !write) {
// return
//}
panic(s, data_val < s->data_len);
return s->data + data_val;
}
int vm_get_int(vm_state s, unsigned int ptr) {
int *ret = vm_decode_rm(s, ptr, false);
return *ret;
}
void vm_set_int(vm_state s, unsigned int ptr, int val) {
int *ret = vm_decode_rm(s, ptr, true);
*ret = val;
}
double vm_get_double(vm_state s, unsigned int ptr) {
double *ret = vm_decode_rm(s, ptr, false);
return *ret;
}
void vm_set_double(vm_state s, unsigned int ptr, double val) {
double *ret = vm_decode_rm(s, ptr, false);
*ret = val;
}
bool vm_set_data(vm_state s, unsigned int ptr, char *data, unsigned int data_len) {
if (ptr + data_len > s->data_len)
return false;
memcpy(s->data + ptr, data, data_len);
return true;
}
unsigned int vm_get_data(vm_state s, unsigned int ptr, char *dest, unsigned int dest_len) {
if(ptr + dest_len > s->data_len)
dest_len = s->data_len - ptr;
memcpy(dest, s->data + ptr, dest_len);
return dest_len;
}
void vm_register_interrupt(vm_state s, unsigned int itr, vm_interrupt_handler handler) {
panic(s, itr < VM_INTERRUPT_TABLE_SIZE && handler != NULL);
s->interrupt_table[itr] = handler;
}
void vm_run_interrupt(vm_state s, unsigned int itr) {
fprintf(stderr, "Interrupt: %x\n", itr);
panic(s, itr < VM_INTERRUPT_TABLE_SIZE && s->interrupt_table[itr] != NULL);
s->interrupt_table[itr](s);
}
void vm_run_instruction(vm_state s) {
unsigned int instr = s->code[s->iptr],
*rm1 = vm_decode_rm(s, s->code[s->iptr+1], false),
*rm2 = vm_decode_rm(s, s->code[s->iptr+2], false);
//#ifdef VERBOSE
fprintf(stderr, "%x: %s [%u, %u]\n", s->iptr, print_instr(s, s->iptr), *rm1, *rm2);
//#endif // VERBOSE
switch (instr) {
case INSTR_NOP:
break;
case INSTR_INT:
vm_run_interrupt(s, *rm1);
break;
case INSTR_MOV:
*rm1 = *rm2;
break;
case INSTR_ADDI:
*rm1 = *rm1 + *rm2;
break;
default:
panic(s, true && "unknown opcode");
}
s->iptr += 3;
//NO_INCR:
return;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment