"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 (!registers) { 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();