@@ 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);
}
@@ 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