Skip to content

Instantly share code, notes, and snippets.

@aaronryank
Last active October 4, 2017 01:35
Show Gist options
  • Save aaronryank/3c0c7f43d92a95b0049b0add73509766 to your computer and use it in GitHub Desktop.
Save aaronryank/3c0c7f43d92a95b0049b0add73509766 to your computer and use it in GitHub Desktop.
bitwise interpreter - now with working functions
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
enum { TYPE_NEG = -1, TYPE_REG = 0, TYPE_FRAME_REG = 1, TYPE_LITERAL = 2, TYPE_LABEL = 3, TYPE_REF = 4, TYPE_ARG = 5 };
int exec_cmd(char *, char *, char *, char *);
int type(char *);
void frame(int);
int _atoi(char *);
void name_function(int,char*);
int call(int,char *,char *,char *);
int32_t _register(char *);
int32_t registers[1000];
int32_t frame_registers[100][1000];
int32_t labels[1000];
int cur_frame;
int line, func;
struct {
char *name;
char code[1000][500];
int lines, fline;
int labels[100];
int32_t func_registers[1000];
} functions[200];
int function_depth[200];
int function_count, cur_fdepth;
#define CUR_FUNC function_depth[cur_fdepth]
#define FLINE functions[CUR_FUNC].fline
#define FUNC_REGISTERS functions[CUR_FUNC].func_registers
int main(int argc, char **argv)
{
FILE *in = (argc >= 2) ? fopen(argv[1],"r") : stdin;
if (!in) {
fprintf(stderr,"Invalid source file!");
return -1;
}
int fline = 0, cur_func = 0;
char s[1000][500] = {0};
char t[500] = {0};
while (fgets(t,499,in)) {
if (strchr(t,'.') == t && strchr(t,':') == t+strlen(t)-2) { // -2 due to newline
func = 1;
fline = 0;
name_function(cur_func,t);
continue;
}
if (t[strlen(t)-1] == '\n')
t[strlen(t)-1] = 0;
if (func) {
strcpy(functions[cur_func].code[fline],t);
fline++;
}
else {
strcpy(s[line],t);
line++;
}
if (strstr(t,"RET") == t) {
func = 0;
functions[cur_func].lines = fline - 1;
cur_func++;
}
}
function_count = cur_func;
int lines = line;
line = 0;
while (line < lines) {
char *t = strdup(s[line]);
char *cmd = strtok(t," ");
char *arg1 = strtok(NULL," ");
char *arg2 = strtok(NULL," ");
char *arg3 = strtok(NULL," ");
//printf("%s %s %s %s\n",cmd,arg1,arg2,arg3);
exec_cmd(cmd,arg1,arg2,arg3);
free(t);
line++;
}
}
int _register(char *index)
{
if (index[0] == '&')
return _atoi(index);
else if (index[0] == '*')
return frame_registers[cur_frame][_atoi(index)];
else if (index[0] == '@' && !func)
return labels[_atoi(index)];
else if (index[0] == '@' && func)
return functions[CUR_FUNC].labels[_atoi(index)];
else if (index[0] == '#')
return registers[registers[_atoi(index)]];
else if (index[0] == '$')
return FUNC_REGISTERS[_atoi(index)];
else
return registers[atoi(index)];
}
int exec_cmd(char *cmd, char *arg1, char *arg2, char *arg3)
{
int result = 0, unrecognized = 0;
if (!cmd || !strlen(cmd))
return -1;
if (!strcmp(cmd,"xor") || !strcmp(cmd,"XOR"))
result = _register(arg1) ^ _register(arg2);
else if (!strcmp(cmd,"and") || !strcmp(cmd,"AND"))
result = _register(arg1) & _register(arg2);
else if (!strcmp(cmd,"sl") || !strcmp(cmd,"SL"))
result = _register(arg1) << _register(arg2);
else if (!strcmp(cmd,"sr") || !strcmp(cmd,"SR"))
result = _register(arg1) >> _register(arg2);
else if (!strcmp(cmd,"mov") || !strcmp(cmd,"MOV")) {
if (_register(arg3)) {
if (type(arg1) == TYPE_REG)
registers[atoi(arg1)] = _register(arg2);
else if (type(arg1) == TYPE_FRAME_REG)
frame_registers[cur_frame][_atoi(arg1)] = _register(arg2);
else if (type(arg1) == TYPE_REF)
registers[registers[_atoi(arg1)]] = _register(arg2);
}
return 0;
}
else if (!strcmp(cmd,"jmp") || !strcmp(cmd,"JMP")) {
if (_register(arg2)) {
int nl = (func ? FLINE : line);
if (type(arg1) == TYPE_LABEL)
nl = _register(arg1);
else {
nl += _register(arg1);
if (!_register(arg1))
exit(EXIT_SUCCESS);
}
//printf(">>> jumping to line %d of %s %d\n",nl,func?"function":"code",func?CUR_FUNC:0);
if (func)
FLINE = nl;
else
line = nl;
}
}
else if (!strcmp(cmd,"label") || !strcmp(cmd,"LABEL")) {
if (func)
functions[CUR_FUNC].labels[_register(arg1)] = FLINE;
else
labels[_register(arg1)] = line;
}
else if (!strcmp(cmd,"not") || !strcmp(cmd,"NOT")) {
result = ~_register(arg1);
arg3 = strdup(arg2);
}
else if (!strcmp(cmd,"lsr") || !strcmp(cmd,"LSR"))
result = (int) ((unsigned int) _register(arg1) >> _register(arg2)); // https://stackoverflow.com/a/5253269/6850771
else if (!strcmp(cmd,"lor") || !strcmp(cmd,"LOR"))
result = _register(arg1) || _register(arg2);
else if (!strcmp(cmd,"land") || !strcmp(cmd,"LAND"))
result = _register(arg1) && _register(arg2);
else if (!strcmp(cmd,"in") || !strcmp(cmd,"IN")) {
if (_register(arg2)) {
int x = getchar();
if (type(arg1) == TYPE_FRAME_REG)
frame_registers[cur_frame][_atoi(arg1)] = x;
else if (type(arg1) == TYPE_REG)
registers[atoi(arg1)] = x;
else if (type(arg1) == TYPE_REF)
registers[registers[_atoi(arg1)]] = x;
else if (type(arg1) == TYPE_ARG)
FUNC_REGISTERS[_atoi(arg1)] = x;
result = x != -1;
}
}
else if (!strcmp(cmd,"out") || !strcmp(cmd,"OUT")) {
if (_register(arg2))
result = putchar(_register(arg1));
}
else if (!strcmp(cmd,"outi") || !strcmp(cmd,"OUTI")) {
if (_register(arg2))
result = printf("%d ",_register(arg1));
}
else if (!strcmp(cmd,"frame") || !strcmp(cmd,"FRAME"))
frame(1);
else if (!strcmp(cmd,"deframe") || !strcmp(cmd,"DEFRAME"))
frame(-1);
else if (!strcmp(cmd,"ret") || !strcmp(cmd,"RET"))
return 0;
else if (!strcmp(cmd,"__lnot") || !strcmp(cmd,"__LNOT")) {
result = !_register(arg1);
arg3 = strdup(arg2);
}
else {
int i, called;
for (i = called = 0; i < function_count; i++) {
if (!strcmp(cmd,functions[i].name)) {
result = call(i,arg1,arg2,arg3);
called = 1;
}
}
if (!arg2)
arg2 = strdup(arg1);
if (!arg3)
arg3 = strdup(arg2);
if (!called)
unrecognized = 1;
}
if (!arg1)
arg1 = strdup("-1");
else if (!arg2)
arg2 = strdup("-1");
else if (!arg3)
arg3 = strdup("-1");
if (!strcmp(cmd,"jmp") || !strcmp(cmd,"JMP") || !strcmp(cmd,"label") || !strcmp(cmd,"LABEL") || !strcmp(cmd,"frame") || !strcmp(cmd,"FRAME") || !strcmp(cmd,"deframe") || !strcmp(cmd,"DEFRAME") || unrecognized)
;
else if (type(arg3) == TYPE_REG)
registers[atoi(arg3)] = result;
else if (type(arg3) == TYPE_FRAME_REG)
frame_registers[cur_frame][_atoi(arg3)] = result;
else if (type(arg3) == TYPE_REF)
registers[registers[_atoi(arg3)]] = result;
else if (type(arg3) == TYPE_ARG)
FUNC_REGISTERS[_atoi(arg3)] = result;
return 0;
}
void frame(int x)
{
if (x == 1)
cur_frame++;
else if (x == -1) {
memset(&frame_registers[cur_frame],0,sizeof(int)*1000);
cur_frame--;
}
}
// declaration: .foobar:\n
// actual name: foobar
void name_function(int idx, char *decl)
{
functions[idx].name = strdup(decl);
char *tmp = strdup(decl);
strcpy(tmp,decl+1);
memset(functions[idx].name,0,strlen(decl)*sizeof(char));
strncpy(functions[idx].name,tmp,strlen(tmp)-2);
free(tmp);
}
int call(int cmd, char *arg1, char *arg2, char *arg3)
{
func = 1;
function_depth[cur_fdepth+1] = cmd;
functions[function_depth[cur_fdepth+1]].func_registers[0] = cmd;
functions[function_depth[cur_fdepth+1]].func_registers[1] = _register(arg1);
functions[function_depth[cur_fdepth+1]].func_registers[2] = _register(arg2);
frame(1);
cur_fdepth++;
char *_cmd, *_arg1, *_arg2, *_arg3, *t;
for (FLINE = 0; FLINE <= functions[cmd].lines; FLINE++) {
t = strdup(functions[cmd].code[FLINE]);
_cmd = strtok(t," ");
_arg1 = strtok(NULL," ");
_arg2 = strtok(NULL," ");
_arg3 = strtok(NULL," ");
//printf("executing line %d of function %d: %s %s %s %s\n",FLINE,cmd,_cmd,_arg1,_arg2,_arg3);
exec_cmd(_cmd,_arg1,_arg2,_arg3);
if (!strcmp(_cmd,"ret") || !strcmp(_cmd,"RET"))
break;
free(t);
}
int retval = _register(_arg1);
memset(&FUNC_REGISTERS,0,sizeof(int)*1000);
free(t);
frame(-1);
func = CUR_FUNC = 0;
cur_fdepth--;
return retval;
}
int type(char *val)
{
if (*val == '-')
return -1;
else if (isdigit(*val))
return 0;
else if (*val == '*')
return 1;
else if (*val == '&')
return 2;
else if (*val == '@')
return 3;
else if (*val == '#')
return 4;
else if (*val == '$')
return 5;
return -2;
}
int _atoi(char *str)
{
char *num = strdup(str);
strcpy(num,&str[1]);
return atoi(num);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment