188 lines
5.9 KiB
JavaScript
188 lines
5.9 KiB
JavaScript
import { Disassembler } from /**/"./Disassembler.js";
|
|
import { Memory } from /**/"./Memory.js";
|
|
import { RegisterList } from /**/"./RegisterList.js";
|
|
|
|
|
|
|
|
class Debugger {
|
|
|
|
///////////////////////// Initialization Methods //////////////////////////
|
|
|
|
constructor(app, index, sim) {
|
|
|
|
// Configure instance fields
|
|
this.app = app;
|
|
this.index = index;
|
|
this.sim = sim;
|
|
|
|
// Configure components
|
|
this.disassembler = new Disassembler(this);
|
|
this.memory = new Memory (this);
|
|
this.programRegisters = new RegisterList(this, false);
|
|
this.systemRegisters = new RegisterList(this, true );
|
|
|
|
// Configure windows
|
|
this.initCPUWindow ();
|
|
this.initMemoryWindow();
|
|
}
|
|
|
|
// Set up the CPU window
|
|
initCPUWindow() {
|
|
let app = this.app;
|
|
|
|
// Produce the window
|
|
let wnd = this.cpuWindow = new app.Toolkit.Window(app, {
|
|
width : 400,
|
|
height : 300,
|
|
className : "tk tk-window tk-cpu" + (this.index==0?"":" two"),
|
|
closeToolTip: "common.close",
|
|
title : "cpu._",
|
|
visible : false
|
|
});
|
|
wnd.setSubstitution("sim", this.index == 1 ? " 2" : "");
|
|
wnd.addEventListener("close", ()=>wnd.setVisible(false));
|
|
app.desktop.add(wnd);
|
|
|
|
// Visibility override
|
|
let that = this;
|
|
let setVisible = wnd.setVisible;
|
|
wnd.setVisible = function(visible) {
|
|
that.disassembler .setSubscribed(visible);
|
|
that.systemRegisters .setSubscribed(visible);
|
|
that.programRegisters.setSubscribed(visible);
|
|
setVisible.apply(wnd, arguments);
|
|
};
|
|
|
|
// Auto-seek the initial view
|
|
let onSeek = ()=>this.disassembler.seek(this.disassembler.pc, true);
|
|
Toolkit.addResizeListener(this.disassembler.element, onSeek);
|
|
wnd.addEventListener("firstshow", ()=>{
|
|
app.desktop.center(wnd);
|
|
Toolkit.removeResizeListener(this.disassembler.element, onSeek);
|
|
});
|
|
|
|
// Window splitters
|
|
let sptMain = new Toolkit.SplitPane(this.app, {
|
|
className: "tk tk-splitpane tk-main",
|
|
edge : Toolkit.SplitPane.RIGHT
|
|
});
|
|
let sptRegs = new Toolkit.SplitPane(this.app, {
|
|
className: "tk tk-splitpane tk-registers",
|
|
edge : Toolkit.SplitPane.TOP
|
|
});
|
|
|
|
// Configure window splitter initial size
|
|
let resize = new ResizeObserver(()=>{
|
|
|
|
// Measure register lists
|
|
let sys = this.systemRegisters .getPreferredSize();
|
|
let pro = this.programRegisters.getPreferredSize();
|
|
let height = Math.ceil(Math.max(sys.height, pro.height));
|
|
let width = Math.ceil(Math.max(sys.width , pro.width )) +
|
|
this.systemRegisters.vertical.getBounds().width;
|
|
|
|
// Configure splitters
|
|
if (sptMain.getValue() != width)
|
|
sptMain.setValue(width);
|
|
if (sptRegs.getValue() != height)
|
|
sptRegs.setValue(height);
|
|
});
|
|
resize.observe(this.programRegisters.view.element);
|
|
resize.observe(this.systemRegisters .view.element);
|
|
|
|
// Stop monitoring splitter size when something receives focus
|
|
let onFocus = e=>{
|
|
resize.disconnect();
|
|
wnd.removeEventListener("focus", onFocus, true);
|
|
};
|
|
sptMain.addEventListener("focus", onFocus, true);
|
|
|
|
// Configure window layout
|
|
sptMain.setView(0, this.disassembler);
|
|
sptMain.setView(1, sptRegs);
|
|
sptRegs.setView(0, this.systemRegisters);
|
|
sptRegs.setView(1, this.programRegisters);
|
|
wnd.append(sptMain);
|
|
}
|
|
|
|
// Set up the Memory window
|
|
initMemoryWindow() {
|
|
let app = this.app;
|
|
|
|
// Produce the window
|
|
let wnd = this.memoryWindow = new app.Toolkit.Window(app, {
|
|
width : 400,
|
|
height : 300,
|
|
className : "tk tk-window" + (this.index == 0 ? "" : " two"),
|
|
closeToolTip: "common.close",
|
|
title : "memory._",
|
|
visible : false
|
|
});
|
|
wnd.setSubstitution("sim", this.index == 1 ? " 2" : "");
|
|
wnd.addEventListener("close" , ()=>wnd.setVisible(false));
|
|
wnd.addEventListener("firstshow", ()=>app.desktop.center(wnd));
|
|
app.desktop.add(wnd);
|
|
|
|
// Visibility override
|
|
let that = this;
|
|
let setVisible = wnd.setVisible;
|
|
wnd.setVisible = function(visible) {
|
|
that.memory.setSubscribed(visible);
|
|
setVisible.apply(wnd, arguments);
|
|
};
|
|
|
|
// Configure window layout
|
|
wnd.append(this.memory);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////// Package Methods /////////////////////////////
|
|
|
|
// Retrieve the disassembler configuraiton
|
|
getDasmConfig() {
|
|
return this.disassembler.getConfig();
|
|
}
|
|
|
|
// Attempt to run until the next instruction
|
|
runNext() {
|
|
this.app.runNext(this.index);
|
|
}
|
|
|
|
// Update the disassembler configuration
|
|
setDasmConfig(config) {
|
|
this.disassembler .setConfig(config);
|
|
this.memory .dasmChanged();
|
|
this.programRegisters.dasmChanged();
|
|
this.systemRegisters .dasmChanged();
|
|
}
|
|
|
|
// Specify whether dual sims mode is active
|
|
setDualSims(dualSims) {
|
|
|
|
// Update substitutions for sim 1
|
|
if (this.index == 0) {
|
|
let sub = dualSims ? " 1" : "";
|
|
this.cpuWindow .setSubstitution("sim", sub);
|
|
this.memoryWindow.setSubstitution("sim", sub);
|
|
}
|
|
|
|
// Hide windows for sim 2
|
|
else if (!dualSims) {
|
|
this.cpuWindow .close(false);
|
|
this.memoryWindow.close(false);
|
|
}
|
|
|
|
}
|
|
|
|
// Execute one instruction
|
|
singleStep() {
|
|
this.app.singleStep(this.index);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export { Debugger };
|