~grimmware/lc3

66854d4a5b1b980652fe19692896e9ce8a17318c — glenda 1 year, 10 months ago bdc92f3
Actually assembling to runnable bytecode!
2 files changed, 101 insertions(+), 8 deletions(-)

M asm.c
A tests/hello.asm
M asm.c => asm.c +90 -8
@@ 2,6 2,7 @@
#include <libc.h>
#include <stdio.h>
#include "lc3.h"
#include "util.c"
#define MAXLINE 256
#define MAXTOKEN 32
#define MAXSYMBOL 128


@@ 27,7 28,7 @@ Symbol symtab[MAXSYMBOL];

// FIXME: Make these dynamic;
Inst *mem[MEMORY];
Inst *unmapped[MEMORY];
u16int unmapped[MEMORY];

int debug = 0;
int unmappedcount = 0;


@@ 36,6 37,7 @@ int memc = 0;
int lineno = 1;
u16int orig, pc = 0x3000;
char *asmfile;
char *outfile;


void


@@ 225,7 227,7 @@ validate(Inst *in)
			if(in->arg[1][0] == 'x'){
				in->p_arg[1] = hexnparse(9, in->arg[1]);
			} else {
				unmapped[unmappedcount++] = in;
				unmapped[unmappedcount++] = pc;
			}
			break;
		}


@@ 237,7 239,7 @@ validate(Inst *in)
			if(in->arg[0][0] == 'x'){
				in->p_arg[0] = hexnparse(9, in->arg[0]);
			} else {
				unmapped[unmappedcount++] = in;
				unmapped[unmappedcount++] = pc;
			}
			break;
		case OP_JSR:


@@ 246,7 248,7 @@ validate(Inst *in)
				if(in->arg[0][0] == 'x'){
					in->p_arg[0] = hexnparse(11, in->arg[0]);
				} else {
					unmapped[unmappedcount++] = in;
					unmapped[unmappedcount++] = pc;
				}
			} else { // JSRR
				goto Reg;


@@ 385,18 387,89 @@ void
maplabels(void)
{
	for(int i = 0; i<unmappedcount; i++){
		int last = unmapped[i]->argc - 1;
		int p = unmapped[i] - orig;
		int last = mem[p]->argc - 1;
		int offset = 0;
		int found = 0;
		for(int j = 0; j<symcount; j++){
			if(!strcmp(symtab[j].label, unmapped[i]->arg[last])){
				unmapped[i]->p_arg[last] = symtab[j].addr;
			if(!strcmp(symtab[j].label, mem[p]->arg[last])){
				// JSR has 11 bits available for PCoffset, the rest have 9
				u16int bits = (mem[p]->op == OP_JSR) ? 11 : 9;
				u16int mask = (mem[p]->op == OP_JSR) ? 0x07FF : 0x01FF;
				u16int packed_offset;
				offset = symtab[j].addr - (p + orig + 1);
				if(offset < 0){
					packed_offset = offset * -1;
					packed_offset = ~packed_offset;
					packed_offset++;
				}
				mem[p]->p_arg[last] = packed_offset & mask;
				/* FIXME: test this
				if(offset != signextend(mem[p]->p_arg[last], bits))
					syntaxerr(smprint("Memory offset %x for label %s is too big to fit the argument for opcode %s", offset, symtab[j].label, opcode[mem[p]->op]));
				*/
				found++;
				break;
			}
		}
		if(!found)
			syntaxerr(smprint("Label %s does not exist!", unmapped[i]->arg[last]));
			syntaxerr(smprint("Label %s does not exist!", mem[p]->arg[last]));
	}
}

long
writeinst(Inst *i, FILE *f)
{
	u16int code = 0;
	code |= i->op << 12;
	switch(i->op){
	case OP_ADD:
	case OP_AND:
		code |= i->p_arg[0] << 9;
		code |= i->p_arg[1] << 6;
		code |= i->mode << 5;
		code |= i->p_arg[2];
		break;
	case OP_BR:
		code |= i->mode << 9;
		code |= i->p_arg[0];
		break;
	case OP_JMP:
		code |= i->p_arg[0] << 6;
		break;
	case OP_JSR:
		code |= i->mode << 11;
		if(i->mode)
			code |= i->p_arg[0];
		else
			code |= i->p_arg[0] << 6;
		break;
	case OP_LD:
	case OP_LDI:
	case OP_LEA:
	case OP_ST:
	case OP_STI:
		code |= i->p_arg[0] << 9;
		code |= i->p_arg[1];
		break;
	case OP_LDR:
	case OP_STR:
		code |= i->p_arg[0] << 9;
		code |= i->p_arg[1] << 6;
		code |= i->p_arg[2];
		break;
	case OP_NOT:
		code |= i->p_arg[0] << 9;
		code |= i->p_arg[1] << 6;
		code |= 0x1f;
		break;
	case OP_TRAP:
		code |= i->p_arg[0];
	case OP_RTI:
		break;
	}
	code = swap16(code);
	return fwrite(&code, 2, 1, f);
}

void


@@ 410,9 483,14 @@ main(int argc, char* argv[])
		break;
	case 'f':
		asmfile = EARGF(usage());
		break;
	case 'o':
		outfile = EARGF(usage());
		break;
	} ARGEND;

	in = fopen(asmfile, "r");
	out = fopen(outfile, "w+");
	parse(in);
	if(debug){
		print("Symbol table:\n");


@@ 435,5 513,9 @@ main(int argc, char* argv[])
			print("\n");
		}
	}
	u16int o = swap16(orig);
	fwrite(&o, 2, 1, out);
	for(int i = 0; i < memc; i++)
		writeinst(mem[i], out);
	exits(nil);
}

A tests/hello.asm => tests/hello.asm +11 -0
@@ 0,0 1,11 @@
	.ORIG	x3000
	ADD	R2,R2,x6	; we need 6 loops to get to 'h'
	NOT	R2,R2		; we want to be able to subtract this number so we'll 2's complements it
	ADD	R2,R2,x1
LOOPH	ADD	R0,R0,xf
	ADD	R1,R1,x1
	ADD	R3,R1,R2	; compare if we're at 6 loops yet
	BRn	LOOPH
	ADD	R0,R0,xe
	TRAP	x21
	.END