A disasm.c => disasm.c +139 -0
@@ 0,0 1,139 @@
+#include <u.h>
+#include <libc.h>
+#include <stdio.h>
+#include "lc3.h"
+#include "util.c"
+
+int debug = 0;
+char *imagefile;
+
+void
+usage(void)
+{
+ fprint(2, "disasm -f FILE");
+}
+
+int
+printreg12(int op)
+{
+ switch(op){
+ case OP_ADD:
+ case OP_AND:
+ case OP_LD:
+ case OP_LDI:
+ case OP_LDR:
+ case OP_LEA:
+ case OP_NOT:
+ case OP_ST:
+ case OP_STI:
+ case OP_STR:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int
+printpcof9(u16int op)
+{
+ switch(op){
+ case OP_BR:
+ case OP_LD:
+ case OP_LDI:
+ case OP_LEA:
+ case OP_ST:
+ case OP_STI:
+ case OP_STR:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int
+printreg9(u16int op)
+{
+ switch(op){
+ case OP_ADD:
+ case OP_AND:
+ case OP_JMP:
+ case OP_LDR:
+ case OP_NOT:
+ return 1;
+ case OP_JSR: // dealt with in separate case
+ default:
+ return 0;
+ }
+}
+
+void
+main(int argc, char* argv[])
+{
+ int c;
+ ARGBEGIN {
+ case 'd':
+ debug++;
+ break;
+ case 'f':
+ imagefile = EARGF(usage());
+ c = readimage(imagefile);
+ if(c < 1) {
+ exits("Could not read image file");
+ }
+ c = c/2;
+ } ARGEND;
+ u16int instr = 0x0000;
+ for(int i = origin; i < origin + c; i++){
+ instr = memread(i);
+ if(instr == 0){
+ print("\tNOP\n");
+ continue;
+ }
+ u16int op = instr >> 12;
+ if(op == OP_JSR) {
+ if((instr >> 11) & 1)
+ print("\tJSR\t0x%x\n", (instr & 0x7FF));
+ else
+ print("\tJSRR\t%s\n", regname[(instr >> 6) & 0x7]);
+ continue;
+ } else if(op == OP_TRAP){
+ print("\t%s\n", trap[instr & 0xFF]);
+ continue;
+ }
+ if(op >= OP_COUNT)
+ exits("Invalid opcode");
+ print("\t%s", opcode[op]);
+ if(printreg12(op)) {
+ print("\t%s", regname[(instr >> 9) & 0x7]);
+ } else if(op == OP_BR){
+ u16int fl = (instr >> 9) & 0x7;
+ if(fl & FL_POS)
+ print("%c", 'p');
+ if(fl & FL_ZRO)
+ print("%c", 'z');
+ if(fl & FL_NEG)
+ print("%c", 'n');
+ }
+ if(printpcof9(op)){
+ if(op == OP_BR)
+ print("\t");
+ else
+ print(",");
+ print("0x%x\n", (instr & 0x1FF));
+ continue;
+ } else if(printreg9(op)) {
+ print(",%s\n", regname[(instr >> 6) & 0x7]);
+ continue;
+ }
+ if(op == OP_ADD || op == OP_AND){
+ if((instr >> 5) & 1)
+ print(",0x%x", instr & 0x1F);
+ else
+ print(",%s", regname[instr & 0x7]);
+ } else if(op == OP_STR | op == OP_LDR) {
+ print(",0x%x", instr & 0x3f);
+ }
+ print("\n");
+ }
+ exits(nil);
+}
M lc3.c => lc3.c +2 -44
@@ 3,10 3,7 @@
#include <libc.h>
#include <stdio.h>
#include "lc3.h"
-
-u16int memory[MEMORY_MAX];
-u16int reg[R_COUNT];
-
+#include "util.c"
int debug = 0;
int consctl;
@@ 17,44 14,6 @@ usage(void)
fprint(2, "lc3 -f FILE");
}
-u16int
-swap16(u16int x)
-{
- return (x << 8) | (x >> 8);
-}
-
-int
-readimage(char *file)
-{
- int c;
- int f = open(file, OREAD);
- if(f == -1) return 0;
- u16int origin;
- read(f, &origin, sizeof(origin));
- origin = swap16(origin);
- c = read(f, memory + origin, MEMORY_MAX - origin);
- c+=origin;
- memory[c]=0x00;
- while(c-- > origin)
- memory[c] = swap16(memory[c]);
- return c;
-}
-
-int
-memread(u16int addr)
-{
- return memory[addr];
-}
-
-u16int
-signextend(u16int x, u16int count)
-{
- if((x >> (count-1)) & 1) {
- x |= (0xFFFF << count);
- }
- return x;
-}
-
void
updateflags(u16int r)
{
@@ 277,8 236,7 @@ main(int argc, char* argv[])
consctl = open("/dev/consctl", OWRITE);
if(consctl == -1) exits("can't open /dev/consctl: %r\n"); // exactly one cond flag should be set at all times
reg[R_COND] = FL_ZRO;
- enum { PC_START = OFFSET };
- reg[R_PC] = PC_START;
+ reg[R_PC] = origin;
int running = 1;
while (running)
M lc3.h => lc3.h +57 -1
@@ 16,6 16,20 @@ enum
R_COUNT
};
+static const char* const regname[] =
+{
+ [R_R0] = "R0",
+ [R_R1] = "R1",
+ [R_R2] = "R2",
+ [R_R3] = "R3",
+ [R_R4] = "R4",
+ [R_R5] = "R5",
+ [R_R6] = "R6",
+ [R_R7] = "R7",
+ [R_PC] = "PC",
+ [R_COND] = "COND"
+};
+
enum
{
OP_BR = 0, // branch
@@ 33,7 47,28 @@ enum
OP_JMP, // jump
OP_RES, // reserved (unused)
OP_LEA, // load effective address
- OP_TRAP // execute trap
+ OP_TRAP, // execute trap
+ OP_COUNT
+};
+
+static const char* const opcode[] =
+{
+ [OP_BR] = "BR", // branch
+ [OP_ADD] = "ADD", // add
+ [OP_LD] = "LD", // load
+ [OP_ST] = "ST", // store
+ [OP_JSR] = "JSR", // jump register
+ [OP_AND] = "AND", // bitwise and
+ [OP_LDR] = "LDR", // load register
+ [OP_STR] = "STR", // store register
+ [OP_RTI] = "RTI", // unused
+ [OP_NOT] = "NOT", // bitwise not
+ [OP_LDI] = "LDI", // load indirect
+ [OP_STI] = "STI", // store indirect
+ [OP_JMP] = "JMP", // jump
+ [OP_RES] = "RES", // reserved (unused)
+ [OP_LEA] = "LEA", // load effective address
+ [OP_TRAP] = "TRAP" // execute trap
};
enum
@@ 43,6 78,13 @@ enum
FL_NEG = 1 << 2, // N
};
+static const char* const flag[] =
+{
+ [FL_POS] = "p",
+ [FL_ZRO] = "z",
+ [FL_NEG] = "n"
+};
+
enum
{
TRAP_GETC = 0x20,
@@ 52,3 94,17 @@ enum
TRAP_PUTSP,
TRAP_HALT
};
+
+static const char* const trap[] =
+{
+ [TRAP_GETC] = "GETC",
+ [TRAP_OUT] = "OUT",
+ [TRAP_PUTS] = "PUTS",
+ [TRAP_IN] = "IN",
+ [TRAP_PUTSP] = "PUTSP",
+ [TRAP_HALT] = "HALT"
+};
+
+u16int memory[MEMORY_MAX];
+u16int reg[R_COUNT];
+u16int origin = 0;
M mkfile => mkfile +8 -4
@@ 1,10 1,14 @@
</$objtype/mkfile
-TARG=lc3
-BIN=/$objtype/bin
-OFILES=lc3.$O
+TARG=lc3 disasm
+BIN=/$objtype/bin/lc3
HFILES=lc3.h
default:V: all
-</sys/src/cmd/mkone
+</sys/src/cmd/mkmany
+
+install:V:
+ mkdir -p $BIN
+ for (i in $TARG)
+ mk $MKFLAGS $i.install
A util.c => util.c +37 -0
@@ 0,0 1,37 @@
+u16int
+swap16(u16int x)
+{
+ return (x << 8) | (x >> 8);
+}
+
+int
+readimage(char *file)
+{
+ int c;
+ int f = open(file, OREAD);
+ if(f == -1) return 0;
+ read(f, &origin, sizeof(origin));
+ origin = swap16(origin);
+ c = read(f, memory + origin, MEMORY_MAX - origin);
+ int progsize = c;
+ c+=origin;
+ memory[c]=0x00;
+ while(c-- > origin)
+ memory[c] = swap16(memory[c]);
+ return progsize;
+}
+
+int
+memread(u16int addr)
+{
+ return memory[addr];
+}
+
+u16int
+signextend(u16int x, u16int count)
+{
+ if((x >> (count-1)) & 1) {
+ x |= (0xFFFF << count);
+ }
+ return x;
+}