From 66854d4a5b1b980652fe19692896e9ce8a17318c Mon Sep 17 00:00:00 2001 From: glenda Date: Wed, 14 Sep 2022 19:47:38 +0000 Subject: [PATCH] Actually assembling to runnable bytecode! --- asm.c | 98 +++++++++++++++++++++++++++++++++++++++++++++---- tests/hello.asm | 11 ++++++ 2 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 tests/hello.asm diff --git a/asm.c b/asm.c index 5661cc8..6e0191c 100644 --- a/asm.c +++ b/asm.c @@ -2,6 +2,7 @@ #include #include #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; iargc - 1; + int p = unmapped[i] - orig; + int last = mem[p]->argc - 1; + int offset = 0; int found = 0; for(int j = 0; jarg[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); } diff --git a/tests/hello.asm b/tests/hello.asm new file mode 100644 index 0000000..c0aedfd --- /dev/null +++ b/tests/hello.asm @@ -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 -- 2.45.2