~grimmware/lc3

bc221626a7ce87b4546e2f1b03cae94ff67422b5 — glenda 1 year, 2 months ago 66854d4
Fixed up label mapping for positive offsets
Implemented all directives
Implemented shorthand for traps
Wrote a "hello world" that does all of the memory filling directives
4 files changed, 108 insertions(+), 21 deletions(-)

M asm.c
M lc3.c
M lc3.h
M tests/hello.asm
M asm.c => asm.c +87 -14
@@ 7,7 7,8 @@
#define MAXTOKEN 32
#define MAXSYMBOL 128
#define MAXARGS 3
#define MEMORY 32
// FIXME make program growth dynamic
#define MEMORY 128

typedef struct Inst Inst;
struct Inst {


@@ 125,6 126,16 @@ matchopcode(char* t)
	return -1;
}

int
matchtrapcode(char* t)
{
	for(int i = TRAP_GETC; i < TRAP_COUNT; i++){
		if(!strcmp(t, trap[i]))
			return i;
	}
	return -1;
}

void
parseargs(char* t, Inst* in)
{


@@ 142,14 153,11 @@ parseargs(char* t, Inst* in)
	// FIXME should probably find some way to indicate larger arity errors here?
}

u16int
hexnparse(int b, char *s)
u16int 
hexnparselit(int b, char *s)
{
	u16int n;
	long m;
	if(s[0] != 'x')
		syntaxerr(smprint("Not a hex value, must indicate base with a leading `x`: %s", s));
	s++;
	m = strtol(s, 0, 16);
	n = (u16int) m;
	if(n != m || n >= (1 << b))


@@ 157,12 165,24 @@ hexnparse(int b, char *s)
	return n;
}


u16int
hexnparse(int b, char *s)
{
	if(s[0] != 'x')
		syntaxerr(smprint("Not a hex value, must indicate base with a leading `x`: %s", s));
	s++;
	return hexnparselit(b, s);
}


void
validate(Inst *in)
{
	int arity;
	int p;
	// Validate arity

	switch(in->op){
	case OP_ADD:
	case OP_AND:


@@ 182,6 202,7 @@ validate(Inst *in)
	case OP_JMP:
	case OP_JSR:
	case OP_TRAP:
	case OP_DATA:
		arity = 1;
		break;
	case OP_RTI:


@@ 257,6 278,9 @@ validate(Inst *in)
		case OP_TRAP:
			in->p_arg[0] = hexnparse(8, in->arg[0]);
			break;
		case OP_DATA:
			in->p_arg[0] = hexnparse(16, in->arg[0]);
			break;
		default:
		Reg:
			// They're all registers


@@ 298,6 322,10 @@ parseline(char *l)
			if(c == 0) return 0;
 			l += c;
			if(strcmp(t,".END") == 0) {
				inst = newinst(OP_TRAP);
				inst->p_arg[0] = TRAP_HALT;
				inst->argc++;
				pc++;
				return -1; // We're done parsing!
			} else if(strcmp(t,".ORIG") == 0){
				//FIXME: only supporting hex for now


@@ 315,12 343,43 @@ parseline(char *l)
				if(debug)
					print("updated origin to %x\n", orig);
				return 0;
			} else if(strcmp(t,".FILL") == 0) {
				l++;
				inst = newinst(OP_DATA);
				gettoken(&t, l);
				parseargs(t, inst);
				goto validate;
			} else if(strcmp(t,".BLKW") == 0) {
				l++;
				gettoken(&t, l);
				for(int i = 0; i<hexnparse(16, t); i++){
					inst = newinst(OP_DATA);
					inst->arg[0] = "x0";
					inst->argc = 1;
					validate(inst);
					pc++;
				}
				return 1;
			} else if(strcmp(t,".STRINGZ") == 0) {
				// FIXME very hex
				l+=2;
				gettoken(&t, l);
				for(int i = 0; i<=strlen(t); i+=2){
					u16int p = 0;
					p |= t[i];
					if(t[i] != 0)
						p|= t[i+1] << 8;
					inst = newinst(OP_DATA);
					inst->p_arg[0] = hexnparselit(16, (char *) &p);
					inst->argc++;
					pc++;
				}
				return 1;
			} else if(strcmp(t,"NOP") == 0) {
				inst = newinst(OP_BR);
				inst->arg[0] = "x0";
				inst->argc++;
				goto validate;
				return 1;
			} else if(strcmp(t,"RET") == 0) {
				inst = newinst(OP_JMP);
				inst->arg[0] = "R7";


@@ 347,9 406,17 @@ parseline(char *l)
				pos++;
			} else {
				int op = matchopcode(t);
				if(op == -1){
					op = matchtrapcode(t);
					if(op == -1)
						syntaxerr(smprint("Invalid instruction `%s`", t));
					inst = newinst(OP_TRAP);
					inst->argc++;
					inst->p_arg[0] = op;
					pc++;
					return 1;
				}
				pos++;
				if(op == -1)
					syntaxerr(smprint("Invalid instruction `%s`", t));
				l++;
				inst = newinst(op);
			}


@@ 369,7 436,7 @@ parseline(char *l)
			return 1;
		}
	}
	fprint(2, "Should not get here\n");
	syntaxerr("Should not get here\n");
	return -1;
}



@@ 402,12 469,12 @@ maplabels(void)
					packed_offset = offset * -1;
					packed_offset = ~packed_offset;
					packed_offset++;
				} else {
					packed_offset = offset;
				}
				mem[p]->p_arg[last] = packed_offset & mask;
				/* FIXME: test this
				if(offset != signextend(mem[p]->p_arg[last], bits))
				if(packed_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;
			}


@@ 423,6 490,9 @@ writeinst(Inst *i, FILE *f)
	u16int code = 0;
	code |= i->op << 12;
	switch(i->op){
	case OP_DATA:
		code = i->p_arg[0];
		break;
	case OP_ADD:
	case OP_AND:
		code |= i->p_arg[0] << 9;


@@ 515,7 585,10 @@ main(int argc, char* argv[])
	}
	u16int o = swap16(orig);
	fwrite(&o, 2, 1, out);
	for(int i = 0; i < memc; i++)
	for(int i = 0; i < memc; i++){
		writeinst(mem[i], out);
	}
	//fflush(out);
	//fclose(out);
	exits(nil);
}

M lc3.c => lc3.c +0 -5
@@ 243,11 243,6 @@ main(int argc, char* argv[])
	{
		// fetch instruction
		u16int instr = memread(reg[R_PC]++);
		// FIXME: this cond might not be correct
		if(instr==0x00) {
			running = 0;
			break;
		}
		u16int op = instr >> 12;
		if(debug) print("%x\n", instr);
		switch(op){

M lc3.h => lc3.h +5 -2
@@ 1,5 1,6 @@
#define OFFSET 0x3000
#define MEMORY_MAX (1 << 16)
#define OP_DATA 65535

enum
{


@@ 68,7 69,8 @@ static const char* const opcode[] =
	[OP_JMP]	= "JMP",	// jump
	[OP_RES]	= "RES",	// reserved (unused)
	[OP_LEA]	= "LEA",	// load effective address
	[OP_TRAP]	= "TRAP"	// execute trap
	[OP_TRAP]	= "TRAP",	// execute trap
	[OP_DATA]	= "DATA"	// Dummy op for raw data
};

enum


@@ 92,7 94,8 @@ enum
	TRAP_PUTS,
	TRAP_IN,
	TRAP_PUTSP,
	TRAP_HALT
	TRAP_HALT,
	TRAP_COUNT
};

static const char* const trap[] =

M tests/hello.asm => tests/hello.asm +16 -0
@@ 1,4 1,5 @@
	.ORIG	x3000
	NOP
	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


@@ 8,4 9,19 @@ LOOPH	ADD	R0,R0,xf
	BRn	LOOPH
	ADD	R0,R0,xe
	TRAP	x21
E	.FILL	x65
L	.FILL	x6c
O	.FILL	x6f
	LD	R0,E
	TRAP	x21
	LD	R0,L
	TRAP	x21
	TRAP	x21
	LD	R0,O
	TRAP	x21
	.BLKW	x5
	LEA	R0,WRLD
	PUTSP
	HALT
WRLD	.STRINGZ	x20776f726c64210a
	.END