aboutsummaryrefslogtreecommitdiffgithub
diff options
context:
space:
mode:
authorAustin Adams <git@austinjadams.com>2019-02-03 23:47:40 -0500
committerAustin Adams <git@austinjadams.com>2019-02-03 23:47:40 -0500
commitf1c3f91ddf6e2a6d36efbfa9774ee1e290e43347 (patch)
tree7671c763d53a5927c22128119cb661a95833f192
parent54bff2c53cc9db4c8cf421c1a3fa4487450ac36d (diff)
downloadnovice-f1c3f91ddf6e2a6d36efbfa9774ee1e290e43347.tar.gz
novice-f1c3f91ddf6e2a6d36efbfa9774ee1e290e43347.tar.xz
Use register aliases in debugger
-rw-r--r--novice/simulator/cli-debugger.test.ts26
-rw-r--r--novice/simulator/cli-debugger.ts14
-rw-r--r--novice/simulator/debugger.ts24
3 files changed, 56 insertions, 8 deletions
diff --git a/novice/simulator/cli-debugger.test.ts b/novice/simulator/cli-debugger.test.ts
index e2b50af..c96e556 100644
--- a/novice/simulator/cli-debugger.test.ts
+++ b/novice/simulator/cli-debugger.test.ts
@@ -445,4 +445,30 @@ describe('cli debugger', () => {
});
});
});
+
+ describe('lc2200 debugging', () => {
+ beforeEach(() => {
+ dbg = new CliDebugger(getIsa('lc2200'), stdin, stdout);
+ });
+
+ it('displays register aliases properly', () => {
+ runCmd('q');
+
+ return dbg.run().then(() => {
+ // @ts-ignore
+ expect(mockInterface.question.mock.calls.length).toEqual(1);
+ // @ts-ignore
+ expect(mockInterface.question.mock.calls[0][0]).toEqual('(novice) ');
+ expect(stdoutActual).toMatch('==> 0x00000000');
+ expect(stdoutActual).toMatch(/^[^]*\$zero:[^]+\$at:[^]+$/m);
+ expect(stdoutActual).toMatch(/^[^]*\$v0:[^]+\$a0:[^]+$/m);
+ expect(stdoutActual).toMatch(/^[^]*\$a1:[^]+\$a2:[^]+$/m);
+ expect(stdoutActual).toMatch(/^[^]*\$t0:[^]+\$t1:[^]+$/m);
+ expect(stdoutActual).toMatch(/^[^]*\$t2:[^]+\$s0:[^]+$/m);
+ expect(stdoutActual).toMatch(/^[^]*\$s1:[^]+\$s2:[^]+$/m);
+ expect(stdoutActual).toMatch(/^[^]*\$k0:[^]+\$sp:[^]+$/m);
+ expect(stdoutActual).toMatch(/^[^]*\$fp:[^]+\$ra:[^]+$/m);
+ });
+ });
+ });
});
diff --git a/novice/simulator/cli-debugger.ts b/novice/simulator/cli-debugger.ts
index c23384a..6a8e8d5 100644
--- a/novice/simulator/cli-debugger.ts
+++ b/novice/simulator/cli-debugger.ts
@@ -289,13 +289,21 @@ class CliDebugger extends Debugger {
if (reg.kind === 'reg-range') {
const nibbles = Math.ceil(reg.bits / 4);
const rowSize = Math.ceil(16 / nibbles);
- const maxLen = Math.floor(Math.log10(reg.count)) + 2;
const base = (reg.bits <= 4) ? 2 : 16;
const prefix = (reg.bits === 1) ? '' : (base === 2) ? '0b' : '0x';
+ let maxRegnameLen = -1;
for (let i = 0; i < reg.count; i++) {
- // TODO: aliases
- const regname = padStr(`${reg.prefix}${i}`, maxLen, ' ');
+ const regname = reg.prefix + (this.lookupRegAlias(reg.prefix, i) || i);
+ const len = regname.length;
+ if (len > maxRegnameLen) {
+ maxRegnameLen = len;
+ }
+ }
+
+ for (let i = 0; i < reg.count; i++) {
+ const regno = this.lookupRegAlias(reg.prefix, i) || i;
+ const regname = padStr(`${reg.prefix}${regno}`, maxRegnameLen, ' ');
const regval = forceUnsigned(this.regs.range[reg.prefix][i],
this.isa.mem.word);
const padded = padStr(regval.toString(base),
diff --git a/novice/simulator/debugger.ts b/novice/simulator/debugger.ts
index b947d2e..9932eec 100644
--- a/novice/simulator/debugger.ts
+++ b/novice/simulator/debugger.ts
@@ -1,4 +1,5 @@
-import { Fields, InstructionSpec, IO, Isa, SymbTable } from '../isa';
+import { Fields, getRegAliases, InstructionSpec, IO, Isa,
+ SymbTable } from '../isa';
import { maskTo, maxUnsignedVal, sextTo } from '../util';
import { Simulator } from './simulator';
@@ -105,11 +106,10 @@ class Debugger extends Simulator {
break;
case 'reg':
- // TODO: use reg aliases if available
const regid = fields.regs[field.name];
- const str = (typeof regid === 'string')
- ? regid
- : regid.join('');
+ const str = (typeof regid === 'string') ? regid :
+ regid[0] + (this.lookupRegAlias(...regid) || regid[1]);
+
operands.push(str);
}
}
@@ -141,6 +141,20 @@ class Debugger extends Simulator {
return result;
}
+ protected lookupRegAlias(prefix: string, regno: number): string|null {
+ const aliases = getRegAliases(this.isa, prefix);
+ // Choose the lexicographically first matching alias (so it's
+ // deterministic)
+ let minAlias: string|null = null;
+ // TODO: ~O(1) instead please
+ for (const alias in aliases) {
+ if (aliases[alias] === regno && (!minAlias || alias < minAlias)) {
+ minAlias = alias;
+ }
+ }
+ return minAlias;
+ }
+
private labelsForAddr(pc: number): string[] {
// TODO: replace with something less grossly inefficient
const results: string[] = [];