shithub: spirva

ref: a0d30aba763788d63e47878756cbd4e5cc6f6798
dir: /asm.c/

View raw version
#include <u.h>
#include <libc.h>
#include "sym.h"
#include "asm.h"
#include "y.tab.h"
#include "ops.h"

#define NIL 0

Inst res;
Inst op;
Inst args[10];
int argptr = 0;

int
lstrlen(int len)
{
	int nlen = len + 1;
	return (nlen)%4 == 0 ? (nlen/4) : (nlen/4)+1;
}

void
a_init()
{
	res.type = NIL;
	op.type = NIL;
	
	for (int i = 0; i < argptr; i++) {
		if (args[i].type == STR) {
			free(args[i].str);
		}
	}
	argptr = 0;
}

void
assemble(void)
{
	u32int output[128];
	u32int* optr;
	u32int numwords = 0;
	
	int slen;
	Inst in;
	
	if (res.type == SYM) {
		numwords++;
	}
	
	if (op.type == OP) {
		numwords++;
	} else {
		fprint(2, "error: no Op to assemble!\n");
	}
	
	for (int i = 0; i < argptr; i++) {
		in = args[i];
		switch (in.type) {
		case NIL:
		case OP:
			fprint(2, "warning: strange situation!\n");
			break;
		case SYM:
		case FLOAT:
		case INT:
			numwords++;
			break;
		case STR:
			slen = strlen(in.str) + 1;
			// padded string length as words (u32int)
			numwords += slen%4 ? (slen/4 + 1) : slen/4;
		}
	}
	
	if (debug) {
		fprint(2, "%d: ", numwords);
		fprint(2, " %10s =", res.type ? res.var->name : "");
		fprint(2, " %s", op.type ? o_find(op.op) : nil);
		
		for (int i = 0; i < argptr; i++) {
			in = args[i];
			switch (in.type) {
			case NIL:
			case OP:
				fprint(2, " X");
				break;
			case SYM:
				fprint(2, " %s", in.var->name);
				break;
			case FLOAT:
				fprint(2, " %f", in.f);
				break;
			case INT:
				fprint(2, " %d", in.i);
				break;
			case STR:
				fprint(2, " \"%s\"", in.str);
				break;
			}
		}
		fprint(2, "\n");
	}
	
	optr = output;
	*optr = (u32int)(numwords<<16 | op.op);
	optr++;
	
	if (res.type == SYM) {
		*optr = (u32int)res.var->id;
		optr++;
	}
	
	for (int i = 0; i < argptr; i++) {
		in = args[i];
		switch (in.type) {
		case SYM:
			*optr = (u32int)in.var->id;
			optr++;
			break;
		case FLOAT:
			*optr = (u32int)in.f;
			optr++;
			break;
		case INT:
			*optr = (u32int)in.i;
			optr++;
			break;
		case STR:
			slen = strlen(in.str);
			memset(optr, 0, lstrlen(slen)*4);
			memcpy(optr, in.str, slen);
			optr += lstrlen(slen);
			break;
		}
	}
	
	slen = optr - output;
	write(1, output, slen*sizeof(u32int));
	
	a_init();
}

void
arg(Inst s)
{
	if (argptr >= 10) {
		sysfatal("error: too many arguments!\n");
	}
	args[argptr++] = s;
}

void
a_result(Symbol *var)
{
	res.type = SYM;
	res.var = var;
}

void
a_op(uint inop)
{
	op.type = OP;
	op.op = inop;
}

void
a_var(Symbol *sym)
{
	Inst a;
	a.type = SYM;
	a.var = sym;
	arg(a);
}

void
a_float(double f)
{
	Inst a;
	a.type = FLOAT;
	a.f = f;
	arg(a);
}

void
a_int(int i)
{
	Inst a;
	a.type = INT;
	a.i = i;
	arg(a);
}

void
a_str(char *str)
{
	Inst a;
	a.type = STR;
	a.str = str;
	arg(a);
}

void
a_keyword(char *str)
{
	Inst a;
	a.type = INT;
	a.i = k_lookup(str);
	arg(a);
}