297 lines
9.2 KiB
JavaScript
297 lines
9.2 KiB
JavaScript
"use strict";
|
|
|
|
// CPU register and disassembler display
|
|
(globalThis.CPUWindow = class CPUWindow extends Toolkit.Window {
|
|
|
|
// Static initializer
|
|
static initializer() {
|
|
|
|
// System register IDs
|
|
this.ADTRE = 25;
|
|
this.CHCW = 24;
|
|
this.ECR = 4;
|
|
this.EIPC = 0;
|
|
this.EIPSW = 1;
|
|
this.FEPC = 2;
|
|
this.FEPSW = 3;
|
|
this.PC = -1;
|
|
this.PIR = 6;
|
|
this.PSW = 5;
|
|
this.TKCW = 7;
|
|
|
|
// Program register names
|
|
this.PROGRAM = {
|
|
[ 2]: "hp",
|
|
[ 3]: "sp",
|
|
[ 4]: "gp",
|
|
[ 5]: "tp",
|
|
[31]: "lp"
|
|
};
|
|
|
|
}
|
|
|
|
// Object constructor
|
|
constructor(debug, options) {
|
|
super(debug.gui, options);
|
|
|
|
// Configure instance fields
|
|
this.address = 0xFFFFFFF0;
|
|
this.debug = debug;
|
|
|
|
// Configure properties
|
|
this.setProperty("sim", "");
|
|
|
|
// Configure elements
|
|
|
|
this.initDisassembler();
|
|
this.initSystemRegisters();
|
|
this.initProgramRegisters();
|
|
this.initWindow();
|
|
|
|
// Layout components
|
|
|
|
// Disassembler on the left
|
|
this.mainWrap.add(this.dasmWrap);
|
|
|
|
// Registers on the right
|
|
this.regs = this.newPanel({
|
|
layout: "grid",
|
|
rows : "max-content max-content auto"
|
|
});
|
|
this.regs.element.setAttribute("name", "wrap-registers");
|
|
|
|
// Splitter between disassembler and registers
|
|
this.mainSplit = this.newSplitter({
|
|
component : this.regs,
|
|
orientation: "vertical",
|
|
edge : "right",
|
|
name : "{cpu.mainSplit}"
|
|
});
|
|
this.mainSplit.element.setAttribute("name", "split-main");
|
|
this.mainSplit.element.style.width = "3px";
|
|
this.mainSplit.element.style.minWidth = "3px";
|
|
this.mainSplit.element.style.cursor = "ew-resize";
|
|
this.mainWrap.add(this.mainSplit);
|
|
|
|
// Registers on the right
|
|
this.mainWrap.add(this.regs);
|
|
|
|
// System registers on top
|
|
this.regs.add(this.sysWrap);
|
|
|
|
// Splitter between system registers and program registers
|
|
this.regsSplit = this.regs.add(this.newSplitter({
|
|
component : this.sysWrap,
|
|
orientation: "horizontal",
|
|
edge : "top",
|
|
name : "{cpu.regsSplit}"
|
|
}));
|
|
this.regsSplit.element.style.height = "3px";
|
|
this.regsSplit.element.style.minHeight = "3px";
|
|
this.regsSplit.element.style.cursor = "ns-resize";
|
|
|
|
// Program registers on the bottom
|
|
this.regs.add(this.proWrap);
|
|
}
|
|
|
|
// Initialize disassembler pane
|
|
initDisassembler() {
|
|
|
|
// Wrapping element to hide overflowing scrollbar
|
|
this.dasmWrap = this.newPanel({
|
|
layout : "grid",
|
|
overflowX: "hidden",
|
|
overflowY: "hidden"
|
|
});
|
|
this.dasmWrap.element.setAttribute("name", "wrap-disassembler");
|
|
|
|
// Main element
|
|
this.dasm = this.dasmWrap.add(this.newPanel({
|
|
focusable: true,
|
|
name : "{cpu.disassembler}",
|
|
overflowX: "auto",
|
|
overflowY: "hidden"
|
|
}));
|
|
this.dasm.element.setAttribute("name", "disassembler");
|
|
}
|
|
|
|
// Initialize program registers pane
|
|
initProgramRegisters() {
|
|
|
|
// Wrapping element to hide overflowing scrollbar
|
|
this.proWrap = this.newPanel({
|
|
layout : "grid",
|
|
overflow: "hidden"
|
|
});
|
|
this.proWrap.element.setAttribute("name", "wrap-program-registers");
|
|
this.proWrap.element.style.flexGrow = "1";
|
|
|
|
// Main element
|
|
this.proRegs = this.proWrap.add(this.newPanel({
|
|
overflowX: "auto",
|
|
overflowY: "scroll"
|
|
}));
|
|
this.proRegs.element.setAttribute("name", "program-registers");
|
|
|
|
// List of registers
|
|
this.proRegs.registers = {};
|
|
for (let x = 0; x <= 31; x++)
|
|
this.addRegister(false, x, CPUWindow.PROGRAM[x] || "r" + x);
|
|
|
|
}
|
|
|
|
// Initialize system registers pane
|
|
initSystemRegisters() {
|
|
|
|
// Wrapping element to hide overflowing scrollbar
|
|
this.sysWrap = this.newPanel({
|
|
layout : "grid",
|
|
overflow: "hidden"
|
|
});
|
|
this.sysWrap.element.setAttribute("name", "wrap-system-registers");
|
|
|
|
// Main element
|
|
this.sysRegs = this.sysWrap.add(this.newPanel({
|
|
overflowX: "auto",
|
|
overflowY: "scroll"
|
|
}));
|
|
this.sysRegs.element.setAttribute("name", "system-registers");
|
|
|
|
// List of registers
|
|
this.sysRegs.registers = {};
|
|
this.addRegister(true, CPUWindow.PC , "PC" );
|
|
this.addRegister(true, CPUWindow.PSW , "PSW" );
|
|
this.addRegister(true, CPUWindow.ADTRE, "ADTRE");
|
|
this.addRegister(true, CPUWindow.CHCW , "CHCW" );
|
|
this.addRegister(true, CPUWindow.ECR , "ECR" );
|
|
this.addRegister(true, CPUWindow.EIPC , "EIPC" );
|
|
this.addRegister(true, CPUWindow.EIPSW, "EIPSW");
|
|
this.addRegister(true, CPUWindow.FEPC , "FEPC" );
|
|
this.addRegister(true, CPUWindow.FEPSW, "FEPSW");
|
|
this.addRegister(true, CPUWindow.PIR , "PIR" );
|
|
this.addRegister(true, CPUWindow.TKCW , "TKCW" );
|
|
this.addRegister(true, 29 , "29" );
|
|
this.addRegister(true, 30 , "30" );
|
|
this.addRegister(true, 31 , "31" );
|
|
this.sysRegs.registers[CPUWindow.PSW].setExpanded(true);
|
|
}
|
|
|
|
// Initialize window and client
|
|
initWindow() {
|
|
|
|
// Configure element
|
|
this.element.setAttribute("window", "cpu");
|
|
|
|
// Configure body
|
|
this.body.element.setAttribute("filter", "");
|
|
|
|
// Configure client
|
|
this.client.setLayout("grid", {
|
|
columns: "auto"
|
|
});
|
|
this.client.addResizeListener(b=>this.onresize(b));
|
|
|
|
// Configure main wrapper
|
|
this.mainWrap = this.client.add(this.newPanel({
|
|
layout : "grid",
|
|
columns: "auto max-content max-content"
|
|
}));
|
|
this.mainWrap.element.setAttribute("name", "wrap-main");
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////// Public Methods //////////////////////////////
|
|
|
|
// The window is being displayed for the first time
|
|
firstShow() {
|
|
super.firstShow();
|
|
this.center();
|
|
this.mainSplit.measure();
|
|
this.regsSplit.measure();
|
|
this.refresh();
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////// Package Methods /////////////////////////////
|
|
|
|
// Update the display with current emulation data
|
|
refresh(clientHeight, lineHeight, registers) {
|
|
if (!this.isVisible())
|
|
return;
|
|
if (registers) {
|
|
this.getRegisters({ registers });
|
|
return;
|
|
}
|
|
this.debug.core.postMessage({
|
|
command: "GetRegisters",
|
|
debug : "CPU",
|
|
sim : this.debug.sim
|
|
});
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////// Message Methods /////////////////////////////
|
|
|
|
// Message received
|
|
message(msg) {
|
|
switch (msg.command) {
|
|
case "GetRegisters": this.getRegisters(msg); break;
|
|
case "SetRegister" : this.setRegister (msg); break;
|
|
}
|
|
}
|
|
|
|
// Retrieved all register values
|
|
getRegisters(msg) {
|
|
this.sysRegs.registers[CPUWindow.PC ]
|
|
.setValue(msg.pc, msg.pcFrom, msg.pcTo);
|
|
this.sysRegs.registers[CPUWindow.PSW ].setValue(msg.psw );
|
|
this.sysRegs.registers[CPUWindow.ADTRE].setValue(msg.adtre);
|
|
this.sysRegs.registers[CPUWindow.CHCW ].setValue(msg.chcw );
|
|
this.sysRegs.registers[CPUWindow.ECR ].setValue(msg.ecr );
|
|
this.sysRegs.registers[CPUWindow.EIPC ].setValue(msg.eipc );
|
|
this.sysRegs.registers[CPUWindow.EIPSW].setValue(msg.eipsw);
|
|
this.sysRegs.registers[CPUWindow.FEPC ].setValue(msg.fepc );
|
|
this.sysRegs.registers[CPUWindow.FEPSW].setValue(msg.fepsw);
|
|
this.sysRegs.registers[CPUWindow.PIR ].setValue(msg.pir );
|
|
this.sysRegs.registers[CPUWindow.TKCW ].setValue(msg.tkcw );
|
|
this.sysRegs.registers[29 ].setValue(msg.sr29 );
|
|
this.sysRegs.registers[30 ].setValue(msg.sr30 );
|
|
this.sysRegs.registers[31 ].setValue(msg.sr31 );
|
|
for (let x = 0; x <= 31; x++)
|
|
this.proRegs.registers[x].setValue(msg.program[x]);
|
|
}
|
|
|
|
// Modified a register value
|
|
setRegister(msg) {
|
|
(msg.type == "program" ? this.proRegs : this.sysRegs)
|
|
.registers[msg.id].setValue(msg.value);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////// Private Methods /////////////////////////////
|
|
|
|
// Insert a register control to a register list
|
|
addRegister(system, id, name) {
|
|
let list = system ? this.sysRegs : this.proRegs;
|
|
let reg = new CPUWindow.Register(this.debug, list, system, id, name);
|
|
list.registers[id] = reg;
|
|
list.add(reg);
|
|
if (reg.expands)
|
|
list.add(reg.expansion);
|
|
}
|
|
|
|
// Resize event handler
|
|
onresize(bounds) {
|
|
if (!this.isVisible())
|
|
return;
|
|
//this.regs.setHeight(bounds.height);
|
|
this.mainSplit.measure();
|
|
this.regsSplit.measure();
|
|
}
|
|
|
|
}).initializer();
|