aboutsummaryrefslogtreecommitdiffgithub
diff options
context:
space:
mode:
authorAustin Adams <git@austinjadams.com>2019-02-03 13:54:34 -0500
committerAustin Adams <git@austinjadams.com>2019-02-03 13:54:34 -0500
commit653097769b59eec970ddd0cb6ff85a39beaadcf3 (patch)
treea651b893685a296734ecd80675c8bd00b209eab2
parent3bf0d22b3fba867c0750fa4a66d1c46324dd8c7c (diff)
downloadnovice-653097769b59eec970ddd0cb6ff85a39beaadcf3.tar.gz
novice-653097769b59eec970ddd0cb6ff85a39beaadcf3.tar.xz
Show labels in disassembly
-rw-r--r--novice/simulator/cli-debugger.test.ts24
-rw-r--r--novice/simulator/cli-debugger.ts20
-rw-r--r--novice/simulator/debugger.test.ts42
-rw-r--r--novice/simulator/debugger.ts46
4 files changed, 91 insertions, 41 deletions
diff --git a/novice/simulator/cli-debugger.test.ts b/novice/simulator/cli-debugger.test.ts
index 4f20881..c1c0c31 100644
--- a/novice/simulator/cli-debugger.test.ts
+++ b/novice/simulator/cli-debugger.test.ts
@@ -314,11 +314,11 @@ describe('cli debugger', () => {
runCmd('q');
return dbg.run().then(() => {
- expect(stdoutActual).toMatch(/0x3000[^]+^==> 0x3000: 0xe002 -8190 lea r0, 2$/m);
- expect(stdoutActual).toMatch(/0x3001[^]+^ 0x3001: 0xf022 -4062 puts$/m);
- expect(stdoutActual).toMatch(/0x3002[^]+^ 0x3002: 0xf025 -4059 halt$/m);
- expect(stdoutActual).toMatch(/0x3003[^]+^ 0x3003: 0x0068 104\s*$/m);
- expect(stdoutActual).toMatch(/0x3004[^]+^ 0x3004: 0x0065 101\s*$/m);
+ expect(stdoutActual).toMatch(/0x3000[^]+^==> 0x3000: 0xe002 -8190 lea r0, 2 $/m);
+ expect(stdoutActual).toMatch(/0x3001[^]+^ 0x3001: 0xf022 -4062 puts $/m);
+ expect(stdoutActual).toMatch(/0x3002[^]+^ 0x3002: 0xf025 -4059 halt $/m);
+ expect(stdoutActual).toMatch(/0x3003[^]+^ 0x3003: 0x0068 104 $/m);
+ expect(stdoutActual).toMatch(/0x3004[^]+^ 0x3004: 0x0065 101 $/m);
});
});
@@ -342,10 +342,10 @@ describe('cli debugger', () => {
runCmd('q');
return dbg.run().then(() => {
- expect(stdoutActual).toMatch(/0x3001[^]+^0x3001: 0xf022 -4062 puts$/m);
- expect(stdoutActual).toMatch(/0x3002[^]+^0x3002: 0xf025 -4059 halt$/m);
- expect(stdoutActual).toMatch(/0x3003[^]+^0x3003: 0x0068 104\s*$/m);
- expect(stdoutActual).toMatch(/0x3004[^]+^0x3004: 0x0065 101\s*$/m);
+ expect(stdoutActual).toMatch(/0x3001[^]+^0x3001: 0xf022 -4062 puts $/m);
+ expect(stdoutActual).toMatch(/0x3002[^]+^0x3002: 0xf025 -4059 halt $/m);
+ expect(stdoutActual).toMatch(/0x3003[^]+^0x3003: 0x0068 104 $/m);
+ expect(stdoutActual).toMatch(/0x3004[^]+^0x3004: 0x0065 101 $/m);
});
});
@@ -369,8 +369,8 @@ describe('cli debugger', () => {
runCmd('q');
return dbg.run().then(() => {
- expect(stdoutActual).toMatch(/0x3001[^]+^0x3001: 0xf022 -4062 puts$/m);
- expect(stdoutActual).toMatch(/0x3002[^]+^0x3002: 0xf025 -4059 halt$/m);
+ expect(stdoutActual).toMatch(/0x3001[^]+^0x3001: 0xf022 -4062 puts $/m);
+ expect(stdoutActual).toMatch(/0x3002[^]+^0x3002: 0xf025 -4059 halt $/m);
});
});
@@ -394,7 +394,7 @@ describe('cli debugger', () => {
runCmd('q');
return dbg.run().then(() => {
- expect(stdoutActual).toMatch(/0x3001[^]+^0x3001: 0xf022 -4062 puts$/m);
+ expect(stdoutActual).toMatch(/0x3001[^]+^0x3001: 0xf022 -4062 puts $/m);
});
});
diff --git a/novice/simulator/cli-debugger.ts b/novice/simulator/cli-debugger.ts
index b14bf34..cf46e7b 100644
--- a/novice/simulator/cli-debugger.ts
+++ b/novice/simulator/cli-debugger.ts
@@ -231,14 +231,28 @@ class CliDebugger extends Debugger {
private printMemRegion(actualPc: number, fromPc: number, toPc: number): void {
const padDecTo = Math.floor(Math.log10(Math.pow(2, this.isa.mem.word - 1) - 1)) + 2;
const hasPc = fromPc <= actualPc && actualPc <= toPc;
+ const disassembled = this.disassembleRegion(fromPc, toPc);
- for (const spot of this.disassembleRegion(fromPc, toPc)) {
- const [pc, word, sext, disassembled] = spot;
+ let longestInstr = 0;
+ for (const spot of disassembled) {
+ const instrLen = spot[3] ? spot[3].length : 0;
+ longestInstr = Math.max(longestInstr, instrLen);
+ }
+
+ if (longestInstr > 0) {
+ // Add two spaces for between instructions and labels, but
+ // only if we actually disassembled some instructions
+ longestInstr += 2;
+ }
+
+ for (const spot of disassembled) {
+ const [pc, word, sext, instr, labels] = spot;
this.stdout.write(`${!hasPc ? '' : pc === actualPc ? '==> ' : ' '}` +
`${this.fmtAddr(pc)}: ` +
`${this.fmtWord(word)} ` +
`${padStr(sext.toString(10), padDecTo, ' ', true)} ` +
- `${disassembled || ''}\n`);
+ `${padStr(instr || '', longestInstr, ' ', true)}` +
+ `${labels.join(' ')}\n`);
}
}
diff --git a/novice/simulator/debugger.test.ts b/novice/simulator/debugger.test.ts
index 3e60f54..13261a3 100644
--- a/novice/simulator/debugger.test.ts
+++ b/novice/simulator/debugger.test.ts
@@ -74,6 +74,14 @@ describe('debugger', () => {
dbg.store(0x3007, 0xf025); // done halt
dbg.store(0x3008, 0x0021); // bang .fill '!'
dbg.store(0x3009, 0xd000); // .fill 0xd000
+
+ Object.assign(dbg.getSymbTable(), {
+ loop: 0x3003,
+ // Don't include this so the branch has to have an integer
+ // operand in the disassembly
+ //done: 0x3007,
+ bang: 0x3008,
+ });
});
it('errors on negative breakpoint', () => {
@@ -134,28 +142,28 @@ describe('debugger', () => {
it('disassembles the whole dang thing', () => {
expect(dbg.disassembleRegion(0x2ffe, 0x300b)).toEqual([
- [0x2ffe, 0x0000, 0, "nop"],
- [0x2fff, 0x0000, 0, "nop"],
- [0x3000, 0x2007, 8199, "ld r0, 7"],
- [0x3001, 0x54a0, 21664, "and r2, r2, 0"],
- [0x3002, 0x14a3, 5283, "add r2, r2, 3"],
- [0x3003, 0x0c03, 3075, "brnz 3"],
- [0x3004, 0xf021, -4063, "out"],
- [0x3005, 0x14bf, 5311, "add r2, r2, -1"],
- [0x3006, 0x0ffc, 4092, "brnzp -4"],
- [0x3007, 0xf025, -4059, "halt"],
- [0x3008, 0x0021, 33, null],
- [0x3009, 0xd000, -12288, null],
- [0x300a, 0x0000, 0, "nop"],
- [0x300b, 0x0000, 0, "nop"],
+ [0x2ffe, 0x0000, 0, 'nop', []],
+ [0x2fff, 0x0000, 0, 'nop', []],
+ [0x3000, 0x2007, 8199, 'ld r0, bang', []],
+ [0x3001, 0x54a0, 21664, 'and r2, r2, 0', []],
+ [0x3002, 0x14a3, 5283, 'add r2, r2, 3', []],
+ [0x3003, 0x0c03, 3075, 'brnz 3', ['loop']],
+ [0x3004, 0xf021, -4063, 'out', []],
+ [0x3005, 0x14bf, 5311, 'add r2, r2, -1', []],
+ [0x3006, 0x0ffc, 4092, 'brnzp loop', []],
+ [0x3007, 0xf025, -4059, 'halt', []],
+ [0x3008, 0x0021, 33, null, ['bang']],
+ [0x3009, 0xd000, -12288, null, []],
+ [0x300a, 0x0000, 0, 'nop', []],
+ [0x300b, 0x0000, 0, 'nop', []],
]);
});
it('disassembles reversed operands', () => {
expect(dbg.disassembleRegion(0x3004, 0x3002)).toEqual([
- [0x3002, 0x14a3, 5283, "add r2, r2, 3"],
- [0x3003, 0x0c03, 3075, "brnz 3"],
- [0x3004, 0xf021, -4063, "out"],
+ [0x3002, 0x14a3, 5283, 'add r2, r2, 3', []],
+ [0x3003, 0x0c03, 3075, 'brnz 3', ['loop']],
+ [0x3004, 0xf021, -4063, 'out', []],
]);
});
});
diff --git a/novice/simulator/debugger.ts b/novice/simulator/debugger.ts
index a8558c6..b947d2e 100644
--- a/novice/simulator/debugger.ts
+++ b/novice/simulator/debugger.ts
@@ -60,10 +60,10 @@ class Debugger extends Simulator {
}
public disassembleAt(pc: number): string|null {
- return this.disassemble(this.load(pc));
+ return this.disassemble(pc, this.load(pc));
}
- public disassemble(ir: number): string|null {
+ public disassemble(pc: number, ir: number): string|null {
let spec: InstructionSpec|null;
let fields: Fields|null;
@@ -77,10 +77,10 @@ class Debugger extends Simulator {
return null;
}
- return this.reassemble(spec, fields);
+ return this.reassemble(pc, spec, fields);
}
- public reassemble(spec: InstructionSpec, fields: Fields): string {
+ public reassemble(pc: number, spec: InstructionSpec, fields: Fields): string {
const operands: string[] = [];
for (const field of spec.fields) {
@@ -90,8 +90,18 @@ class Debugger extends Simulator {
break;
case 'imm':
- // TODO: labels
- operands.push(fields.imms[field.name].toString());
+ let labels: string[] = [];
+ if (field.label) {
+ const targetPc = pc + this.isa.pc.increment +
+ fields.imms[field.name];
+ labels = this.labelsForAddr(targetPc);
+ }
+
+ if (labels.length > 0) {
+ operands.push(labels[0]);
+ } else {
+ operands.push(fields.imms[field.name].toString());
+ }
break;
case 'reg':
@@ -110,7 +120,8 @@ class Debugger extends Simulator {
}
public disassembleRegion(fromPc: number, toPc: number):
- [number, number, number, string|null][] {
+ // pc, unsigned, signed, instruction, labels
+ [number, number, number, string|null, string[]][] {
this.validateAddr(fromPc);
this.validateAddr(toPc);
@@ -118,17 +129,34 @@ class Debugger extends Simulator {
[fromPc, toPc] = [toPc, fromPc];
}
- const result: [number, number, number, string|null][] = [];
+ const result: [number, number, number, string|null, string[]][] = [];
for (let pc = fromPc; pc <= toPc; pc += this.isa.pc.increment) {
const word = this.load(pc);
const sext = sextTo(word, this.isa.mem.word);
- result.push([pc, word, sext, this.disassemble(word)]);
+ const labels = this.labelsForAddr(pc);
+ result.push([pc, word, sext, this.disassemble(pc, word), labels]);
}
return result;
}
+ private labelsForAddr(pc: number): string[] {
+ // TODO: replace with something less grossly inefficient
+ const results: string[] = [];
+
+ for (const label in this.symbTable) {
+ if (this.symbTable[label] === pc) {
+ results.push(label);
+ }
+ }
+
+ // Make sure order is deterministic
+ results.sort();
+
+ return results;
+ }
+
private validateAddr(addr: number): void {
// TODO: check if NaN or infinity or whatever