-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathroboarchvm.c
143 lines (132 loc) · 3.62 KB
/
roboarchvm.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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // for memcpy which is essential for copy
#define DEBUGMODE
#define TRUE 1
#define FALSE 0
unsigned int memsize = 65536;
unsigned char * mem = 0;
int inputap = 0;
int inputbp = 0;
int outputp = 0;
//gets the pointers
void getp(const int op, const int a, const int b, const int c){
if(op & 1) inputap = ((int *)mem)[a];
else inputap = a;
if(op & 2) inputbp = ((int *)mem)[b];
else inputbp = b;
if(op & 4) outputp = ((int *)mem)[c];
else outputp = c;
}
void doop(const int op){
switch((unsigned int) op >> 3){
case 0://copy
memcpy(((int*)mem) + outputp, ((int*)mem) + inputap, ((int *)mem)[inputbp]*4);
break;
case 1: //add
#ifdef DEBUGMODE
{
int t = ((int*)mem)[inputap] + ((int*)mem)[inputbp];
printf("writing %i to 0x%x\n",t, mem[outputp]);
((int*)mem)[outputp] = t;
}
#else
((int*)mem)[outputp] = ((int*)mem)[inputap] + ((int*)mem)[inputbp];
#endif
break;
case 2: //sub
((int*)mem)[outputp] = ((int*)mem)[inputap] - ((int*)mem)[inputbp];
break;
case 3: //mult
((int*)mem)[outputp] = ((int*)mem)[inputap] * ((int*)mem)[inputbp];
break;
case 4: //div
((int*)mem)[outputp] = ((int*)mem)[inputap] / ((int*)mem)[inputbp];
break;
case 5: //mod
((int*)mem)[outputp] = ((int*)mem)[inputap] % ((int*)mem)[inputbp];
break;
case 6: //and
((int*)mem)[outputp] = ((int*)mem)[inputap] & ((int*)mem)[inputbp];
break;
case 7: //or
((int*)mem)[outputp] = ((int*)mem)[inputap] | ((int*)mem)[inputbp];
break;
case 8: //xor
((int*)mem)[outputp] = ((int*)mem)[inputap] ^ ((int*)mem)[inputbp];
break;
case 9: //not
((int*)mem)[outputp] = ~((int*)mem)[inputap];
break;
case 10://bnot
((int*)mem)[outputp] = !((int*)mem)[inputap];
break;
case 11://sl
((int*)mem)[outputp] = ((int*)mem)[inputap] << ((int*)mem)[inputbp];
break;
case 12://sr
((int*)mem)[outputp] = ((unsigned int*)mem)[inputap] >> ((int*)mem)[inputbp]; //the unsigned tricks c into logical shift?
break;
case 13://sa
((int*)mem)[outputp] = ((int*)mem)[inputap] >> ((int*)mem)[inputbp];
break;
case 14://tg
((int*)mem)[outputp] = (((int*)mem)[inputap] > ((int*)mem)[inputbp]);
break;
case 15://te
((int*)mem)[outputp] = (((int*)mem)[inputap] == ((int*)mem)[inputbp]);
break;
default: break;//noop
}
}
void executionloop(void){
int ip;
for(;(ip = ((int*)mem)[0]); ((int*)mem)[0]+=4){
int op = ((int*)mem)[ip];
int a = ((int*)mem)[ip+1];
int b = ((int*)mem)[ip+2];
int c = ((int*)mem)[ip+3];
#ifdef DEBUGMODE
printf("%i with opcode %i or %i, %i, %i, %i\n", ip, op, op >> 3, a, b, c);
#endif
getp(op, a, b, c);
doop(op);
}
}
int main(int argc, char ** argv){
//grab input file
char * filename = argc > 1 ? argv[1] : "./program.bin";
FILE *f = fopen(filename, "rb");
if(!f){
printf("File %s not found\n", filename);
return TRUE;
}
fseek(f, 0, SEEK_END);
int filesize = ftell(f);
rewind(f);
memsize = (filesize + memsize-1) & ~(memsize -1);
if(argc > 2){
int presize = atoi(argv[2]);
if(presize < filesize) printf("Memsize %i too small for a %i file, setting to %i\n", presize, filesize, memsize);
else memsize = presize;
}
mem = malloc(memsize);
fread(mem, 1, filesize, f);
if(f)fclose(f); f = 0;
memset(mem + filesize, 0, memsize - filesize);
executionloop();
//dump output
if(argc > 3) f = fopen(argv[3], "wb");
if(f){
//find end of mem
int i;
for(i = (memsize-1)/4; i >= 0 && !((int*)mem)[i]; i--);
i++;
if(i){
printf("dumping %i bytes to file %s\n", i*4, argv[3]);
fwrite(mem, i*4, 1, f);
} else printf("no bytes to write\n");
}
if(mem) free(mem); mem = 0;
return FALSE;
}