This repository has been archived by the owner on Nov 3, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
vm.c
95 lines (81 loc) · 1.95 KB
/
vm.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/* elemental vm
copyright (c) 2012 darkf
MIT licensed */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* memset */
#include "vm.h"
#include "op.h"
#include "cpu.h"
/* mini instruction assembler for early testing */
unsigned long op_emit(vm_t *vm, long op, operand_t *a, operand_t *b, unsigned long ptr)
{
vm->mem[ptr++] = op;
if(a != NULL)
if(b != NULL)
vm->mem[ptr++] = (a->type << 4) | b->type;
else
vm->mem[ptr++] = (a->type << 4);
if(a != NULL) {
/* 32-bit big endian encoded over four bytes */
vm->mem[ptr++] = (a->data >> 24) & 0xff;
vm->mem[ptr++] = (a->data >> 16) & 0xff;
vm->mem[ptr++] = (a->data >> 8) & 0xff;
vm->mem[ptr++] = (a->data >> 0) & 0xff;
}
if(b != NULL) {
/* 32-bit big endian encoded over four bytes */
vm->mem[ptr++] = (b->data >> 24) & 0xff;
vm->mem[ptr++] = (b->data >> 16) & 0xff;
vm->mem[ptr++] = (b->data >> 8) & 0xff;
vm->mem[ptr++] = (b->data >> 0) & 0xff;
}
return ptr;
}
void load_program(vm_t *vm, unsigned long ptr)
{
operand_t a, b, c, d, e;
vm->reg[IP] = ptr;
long_to_register(&a, 0); /* reg 0 */
long_to_literal(&b, 1);
long_to_literal(&c, 0xfffffff);
/*
mov $1, 1
loop: add $0xfffffff, 0
blt loop
halt
*/
ptr = op_emit(vm, OP_MOV32, &a, &b, ptr);
long_to_literal(&e, ptr);
ptr = op_emit(vm, OP_ADD, &a, &c, ptr);
ptr = op_emit(vm, OP_BLT, &e, NULL, ptr);
op_emit(vm, OP_HALT, NULL, NULL, ptr);
}
int vm_init(vm_t *vm)
{
long base;
vm->mem = malloc(MEM_LENGTH);
memset(vm->mem, 0, MEM_LENGTH);
memset(vm->reg, 0, sizeof(vm->reg));
base = 0x00300000; /* end of VRAM */
vm->reg[SP] = base;
base += STACK_SIZE;
vm->base_addr = base;
return 1;
}
int vm_quit(vm_t *vm)
{
free(vm->mem);
return 1;
}
int vm_begin(vm_t *vm)
{
load_program(vm, vm->base_addr);
/* run the program */
cpu_run(vm);
/* pure debug code here -- check if the
program worked */
printf("register 0 = %ld\n", vm->reg[0]);
printf("register 1 = %ld\n", vm->reg[1]);
return 0;
}