wm: 5552

ref: 574330802775a8417de895c924bf454807295150
dir: /5552a.c/

View raw version
#include "port.h"
#include "5552.h"

char*
readin(char *in, int len)
{
	memset(in, 1, len);
	for(int i = 0 ; i < len || in+i ; i++)
		read(1, in+i, 1);

	return in;
}

void
asmtobin(char *in)
{
	int tmp = 0, len;
	char *buf;

	len = strlen(in);
	for(int i = 0 ; i < len && in[i] ; i++)
	{
		if(in[i] == '\t')
			continue;
		else if(in[i] == '\n' || in[i] == '\0')
		{
			buf[tmp++] = '\0';
			tmp = 0;
			tobin(buf);
		}
		buf[tmp++] = in[i];
	}
}

void
tobin(char *line)
{
	int *inst, *arg1, *arg2;

	match(line, inst, arg1, arg2);
}

int
matchinst(char *s)
{
	int inst = -1;

	if(!strcmp(s, "DRD"))
		inst = DRD;
	if(!strcmp(s, "DWR"))
		inst = DWR;

	if(!strcmp(s, "NOT"))
		inst = NOT;
	if(!strcmp(s, "AND"))
		inst = AND;
	if(!strcmp(s, "NOR"))
		inst = NOR;
	if(!strcmp(s, "XOR"))
		inst = XOR;

	if(!strcmp(s, "ADD"))
		inst = ADD;
	if(!strcmp(s, "SUB"))
		inst = SUB;

	if(!strcmp(s, "INC"))
		inst = INC;
	if(!strcmp(s, "DEC"))
		inst = DEC;

	if(!strcmp(s, "MUL"))
		inst = MUL;
	if(!strcmp(s, "DIV"))
		inst = DIV;

	if(!strcmp(s, "SHR"))
		inst = SHR;
	if(!strcmp(s, "SHL"))
		inst = SHL;

	if(!strcmp(s, "JMP"))
		inst = JMP;

	if(inst == -1)
		sysfatal("No instruction found for %s", s);

	return inst;
}

void
addlabel(char *name)
{
	for(int i = 0 ; i < lc ; i++)
	{
		if(!strcmp(labels[i].name, name))
			sysfatal("duplicate label %s\t
			"prev pc: %x\t"
			"curr pc: %x", name, labels[i].pc, pc);
	}
	
	labels[lc].name = name;
	labels[lc].pc = pc;

	lc++;
}

void
matchline(char *line)
{
	int len, spaces[2], scount = 0;

	len = strlen(line);
	for(int i = 0 ; i < len ; i++)
	{
		if(line[i] == ' ')
		{
			if(scount < 2)
				spaces[scount++] = i;
			else
			{
				fprint(2, "Too many spaces in the line:\n"
				"\t%s\n\t", line);
				for(int j = 0 ; j < i ; j++)
					fprint(2, " ");

				fprint(2, "^\n");
				sysfatal("Too many spaces.");
			}
			
		}
		else if(line[i] == ':' && line[i+1] == '\n' && scount == 0)
		{
			addlabel(line);
			return;
		}
	}

	for(int i = 0 ; i < scount ; i++)
		line[spaces[i]] = '\0';

	program[pc].inst = matchinst(line);
	if(scount == 1)
		program[pc].arg1 = atoi(line+spaces[0]);
	else if(scount == 2)
		program[pc].arg2 = atoi(line+spaces[1]);
	pc++
}

void
lint(void)
{
	int res, totalres[2] = {0, 0};

	for(int i = 0 ; i < pc ; i++)
	{
		res = lintop(program[i]);
		if(res & WARN)
			totalres[WARN]++;
		if(res & ERR)
			totalres[ERR]++;
	}
	if(totalres[WARN] || totalres[ERR])
		fprint(2, "%d warnnings and %d errors detected\n",
		totalres[WARN], totalres[ERR]);
}

int
lintop(int linenumber)
{
	Op op = program[linenumber];
	for(int i ; i < sizeof(instructions) / sizeof(Inst) ; i++)
	{
		if(op.inst == instructions[i].inst)
			return instructions[i].lint(op.mode, op.arg1, op.arg2);
	}
}

void
asm(int flags)
{
	asm2bin(input);
	if(flags & SFLAG)
	{
		for(int i = 0 ; i < pc ; i++)
		{
			write(0, program[i].inst, sizeof(Word));
			write(0, program[i].mode, sizeof(Word));
			write(0, program[i].arg1, sizeof(Word));
			write(0, program[i].arg2, sizeof(Word));
		}
	}
}

int main(int argc, char* argv[])
{
	unsigned int inst, a, b, c;
	char string[32], op[4];
	while(scanf("%s %[^\n;]%*c", op, string) > 0)
	{
		sscanf(string, "%u %u %u", &a, &b, &c);
		if(!strcmp(op, "DIE"))
			inst = DIE;
		if(!strcmp(op, "OUT"))
			inst = OUT;
		if(!strcmp(op, "NOT"))
			inst = NOT;
		if(!strcmp(op, "AND"))
			inst = AND;
		if(!strcmp(op, "NOR"))
			inst = NOR;
		if(!strcmp(op, "XOR"))
			inst = XOR;
		if(!strcmp(op, "SUB"))
			inst = SUB;
		if(!strcmp(op, "ADD"))
			inst = ADD;
		if(!strcmp(op, "SHR"))
			inst = SHR;
		if(!strcmp(op, "SHL"))
			inst = SHL;
		if(!strcmp(op, "PUT"))
			inst = PUT;
		if(!strcmp(op, "MOV"))
			inst = MOV;
		if(!strcmp(op, "LDM"))
			inst = LDM;
		if(!strcmp(op, "NTH"))
			inst = NTH;

		switch(inst)
		{
			/* no args */
			case DIE:
					printf("%u\n", inst);
					break;
			/* one arg */
			case NOT:
			case OUT:
					printf("%u %u\n", inst, a);
					break;
			/* two args */
			case PUT:
			case MOV:
			case LDM:
				printf("%u %u %u\n", inst, a, b);
				break;
			/* three args */
			case AND:
			case NOR:
			case XOR:
			case SUB:
			case SHL:
			case SHR:
			case ADD:
			case NTH:
				printf("%u %u %u %u\n", inst, a, b, c);
				break;
			/* should this ever happen? */
			default:
				fprintf(stderr, "unkown instr.\n");
				return -1;
			
		}
	}
	return 0;
}