aboutsummaryrefslogtreecommitdiffgithub
path: root/novice/simulator/debugger.ts
diff options
context:
space:
mode:
Diffstat (limited to 'novice/simulator/debugger.ts')
-rw-r--r--novice/simulator/debugger.ts103
1 files changed, 76 insertions, 27 deletions
diff --git a/novice/simulator/debugger.ts b/novice/simulator/debugger.ts
index f53e0e4..28b6a4f 100644
--- a/novice/simulator/debugger.ts
+++ b/novice/simulator/debugger.ts
@@ -2,15 +2,18 @@ import { Fields, getRegAliases, InstructionSpec, IO, Isa,
SymbTable } from '../isa';
import { maskTo, maxUnsignedVal, sextTo } from '../util';
import { Simulator } from './simulator';
+import { Symbols } from './symbols';
type RegAliasLut = {[prefix: string]: (string|null)[]};
+type InvSymbTable = {[addr: number]: string[]};
-class Debugger extends Simulator {
+class Debugger extends Simulator implements Symbols {
protected nextBreakpoint: number;
// Map of address -> breakpoint number
protected breakpoints: {[addr: number]: number};
protected interrupt: boolean;
protected symbTable: SymbTable;
+ protected invSymbTable: InvSymbTable;
protected regAliasLut: RegAliasLut;
public constructor(isa: Isa, io: IO, maxExec: number) {
@@ -20,36 +23,12 @@ class Debugger extends Simulator {
this.breakpoints = {};
this.interrupt = false;
this.symbTable = {};
+ this.invSymbTable = {};
this.regAliasLut = this.genRegAliasLut(isa);
}
- private genRegAliasLut(isa: Isa): RegAliasLut {
- const lut: RegAliasLut = {};
-
- for (const reg of isa.regs) {
- if (reg.kind === 'reg-range') {
- lut[reg.prefix] = new Array(reg.count).fill(null);
-
- if (reg.aliases) {
- for (const alias in reg.aliases) {
- const regno = reg.aliases[alias];
- const current = lut[reg.prefix][regno];
- // Make sure we behave deterministically: If we
- // have a collision, choose the
- // lexicographically smaller alias
- if (!current || current > alias) {
- lut[reg.prefix][regno] = alias;
- }
- }
- }
- }
- }
-
- return lut;
- }
-
public getSymbTable(): SymbTable {
- return this.symbTable;
+ return Object.assign({}, this.symbTable);
}
// continue
@@ -179,10 +158,80 @@ class Debugger extends Simulator {
return result;
}
+ public hasSymbol(symb: string): boolean {
+ return symb in this.symbTable;
+ }
+
+ public setSymbol(symb: string, addr: number): void {
+ if (this.hasSymbol(symb)) {
+ const oldAddr = this.symbTable[symb];
+ // update inverted
+ const symbols = this.invSymbTable[oldAddr];
+ symbols.splice(symbols.indexOf(symb), 1);
+ }
+
+ this.symbTable[symb] = addr;
+
+ if (!(addr in this.invSymbTable)) {
+ this.invSymbTable[addr] = [];
+ }
+
+ this.invSymbTable[addr].push(symb);
+ // Determinism!
+ this.invSymbTable[addr].sort();
+ }
+
+ public setSymbols(symbtable: SymbTable): void {
+ for (const symb in symbtable) {
+ this.setSymbol(symb, symbtable[symb]);
+ }
+ }
+
+ public getSymbolAddr(symb: string): number {
+ if (!(symb in this.symbTable)) {
+ throw new Error(`no such symbol \`${symb}'`);
+ }
+
+ return this.symbTable[symb];
+ }
+
+ public getAddrSymbols(addr: number): string[] {
+ if (!(addr in this.invSymbTable)) {
+ return [];
+ }
+
+ return this.invSymbTable[addr];
+ }
+
protected lookupRegAlias(prefix: string, regno: number): string|null {
return this.regAliasLut[prefix][regno];
}
+ private genRegAliasLut(isa: Isa): RegAliasLut {
+ const lut: RegAliasLut = {};
+
+ for (const reg of isa.regs) {
+ if (reg.kind === 'reg-range') {
+ lut[reg.prefix] = new Array(reg.count).fill(null);
+
+ if (reg.aliases) {
+ for (const alias in reg.aliases) {
+ const regno = reg.aliases[alias];
+ const current = lut[reg.prefix][regno];
+ // Make sure we behave deterministically: If we
+ // have a collision, choose the
+ // lexicographically smaller alias
+ if (!current || current > alias) {
+ lut[reg.prefix][regno] = alias;
+ }
+ }
+ }
+ }
+ }
+
+ return lut;
+ }
+
private labelsForAddr(pc: number): string[] {
// TODO: replace with something less grossly inefficient
const results: string[] = [];