From b33a6c3055399136feefd6f11d36b28e5e7f50b2 Mon Sep 17 00:00:00 2001 From: Guy Perfect Date: Mon, 20 Sep 2021 14:32:09 +0000 Subject: [PATCH] HALT fix, QoL tweaks --- app/App.js | 2 +- app/Debugger.js | 4 +-- app/windows/CPUWindow.js | 2 +- app/windows/Disassembler.js | 6 ++-- app/windows/MemoryWindow.js | 37 ++++++++++++++++------ core/cpu.c | 62 ++++++++++++++++++++++++++++++------- core/vb.c | 32 ++----------------- 7 files changed, 89 insertions(+), 56 deletions(-) diff --git a/app/App.js b/app/App.js index d4730d0..5f7cd5c 100644 --- a/app/App.js +++ b/app/App.js @@ -121,7 +121,7 @@ globalThis.App = class App { // ROM buffer has been configured setROM(msg) { let dbg = this.debuggers[msg.sim]; - dbg.refresh(); + dbg.refresh(true); } diff --git a/app/Debugger.js b/app/Debugger.js index beea995..2b917b7 100644 --- a/app/Debugger.js +++ b/app/Debugger.js @@ -46,8 +46,8 @@ globalThis.Debugger = class Debugger { } // Reload all output - refresh() { - this.cpu .refresh(); + refresh(seekToPC) { + this.cpu .refresh(seekToPC); this.memory.refresh(); } diff --git a/app/windows/CPUWindow.js b/app/windows/CPUWindow.js index 67a8ac6..b959edd 100644 --- a/app/windows/CPUWindow.js +++ b/app/windows/CPUWindow.js @@ -234,7 +234,7 @@ case "ReadBuffer" : this.readBuffer (msg); break; case "SetRegister" : this.setRegister (msg); break; case "RunNext": case "SingleStep": - this.refresh(true); break; + this.debug.refresh(true); break; } } diff --git a/app/windows/Disassembler.js b/app/windows/Disassembler.js index 997be3a..8693e27 100644 --- a/app/windows/Disassembler.js +++ b/app/windows/Disassembler.js @@ -345,8 +345,10 @@ let reg2 = this.PROREGNAMES[bits >> 21 & 31]; let reg1 = this.PROREGNAMES[bits >> 16 & 31]; let disp = this.signExtend(bits & 0xFFFF, 16); - disp = disp == 0 ? "" : (disp < 0 ? "-" : "") + "0x" + - Math.abs(disp).toString(16).toUpperCase(); + disp = disp == 0 ? "" : (disp < -255 || disp > 255) ? "0x" + + ("000" + (disp & 0xFFFF).toString(16).toUpperCase()).slice(-4) : + (disp < 0 ? "-" : "") + "0x" + + Math.abs(disp).toString(16).toUpperCase(); switch (inst.opcode) { case 0b110000: // LD.B case 0b110001: // LD.H diff --git a/app/windows/MemoryWindow.js b/app/windows/MemoryWindow.js index 5db7ce6..dba4387 100644 --- a/app/windows/MemoryWindow.js +++ b/app/windows/MemoryWindow.js @@ -99,8 +99,8 @@ globalThis.MemoryWindow = class MemoryWindow extends Toolkit.Window { // Message received message(msg) { switch (msg.command) { - case "ReadBuffer": this.readBuffer(msg); break; - case "Write" : this.debug.refresh(); break; + case "ReadBuffer": this.readBuffer(msg) ; break; + case "Write" : this.debug.refresh(false); break; } } @@ -380,6 +380,7 @@ MemoryWindow.Row = class Row extends Toolkit.Panel { // Configure element this.element.setAttribute("role", "row"); + this.element.addEventListener("pointerdown", e=>this.onpointerdown(e)); // Address label this.addr = this.add(parent.newLabel({ text: "\u00a0" })); @@ -418,6 +419,31 @@ MemoryWindow.Row = class Row extends Toolkit.Panel { return (this.wnd.address + this.offset & 0xFFFFFFFF) >>> 0; } + // Pointer down event handler + onpointerdown(e) { + + // Error checking + if (e.button != 0) + return; + + // Check whether the click is within the columns of cells + let next = this.cells[0].getBounds(); + if (e.x < next.left) + return; + + // Compute which cell was clicked + for (let x = 0; x < 16; x++) { + let cur = next; + if (x < 15) { + next = this.cells[x + 1].getBounds(); + if (e.x < (cur.right + next.left) / 2) + return this.wnd.setSelected(this.cells[x].address()); + } else if (e.x < cur.right) + return this.wnd.setSelected(this.cells[x].address()); + } + + } + }; // One cell of output @@ -435,7 +461,6 @@ MemoryWindow.Cell = class Cell extends Toolkit.Label { // Configure element this.element.setAttribute("role", "gridcell"); this.element.setAttribute("name", "byte"); - this.element.addEventListener("pointerdown", e=>this.onpointerdown(e)); parent.add(this); } @@ -473,10 +498,4 @@ MemoryWindow.Cell = class Cell extends Toolkit.Label { return (this.wnd.address + this.offset & 0xFFFFFFFF) >>> 0; } - // Pointer down event handler - onpointerdown(e) { - if (e.button == 0) - this.wnd.setSelected(this.address()); - } - }; diff --git a/core/cpu.c b/core/cpu.c index 5b11b3d..3add6d5 100644 --- a/core/cpu.c +++ b/core/cpu.c @@ -979,7 +979,7 @@ static void cpuDIVU(VB *emu, VB_INSTRUCTION *inst) { static void cpuHALT(VB *emu, VB_INSTRUCTION *inst) { emu->cpu.state = CPU_HALTED; inst->size = 0; - /* TODO: Find out how many clocks this takes */ + /* emu->cpu.clocks = ? */ } /* Input Byte */ @@ -1491,8 +1491,8 @@ static int cpuExecute(VB *emu) { /* Post-instruction tasks */ if (emu->cpu.causeCode == 0 && !emu->cpu.busWait) { - /* Advance to next instruction if not processing a bit string */ - if (!emu->cpu.substring) + /* Advance to next instruction */ + if (emu->cpu.state != CPU_HALTED && !emu->cpu.substring) emu->cpu.pc += inst->size; /* Check for interrupts */ @@ -1505,11 +1505,10 @@ static int cpuExecute(VB *emu) { emu->cpu.substring = 0; } - /* Switch to fetch mode if not halting and execution has completed */ + /* Switch to fetch mode */ else if (emu->cpu.state != CPU_HALTED && !emu->cpu.busWait && !emu->cpu.substring) { emu->cpu.state = CPU_FETCH; - emu->cpu.fetch = 0; } return 0; @@ -1518,6 +1517,7 @@ static int cpuExecute(VB *emu) { /* Enter an exception state */ static int cpuException(VB *emu) { uint16_t causeCode = emu->cpu.causeCode; + int irq = causeCode < 0xFF00; /* Fatal exception */ if (emu->cpu.psw.np) { @@ -1587,7 +1587,7 @@ static int cpuException(VB *emu) { else { emu->cpu.ecr.eicc = causeCode; emu->cpu.eipsw = vbGetSystemRegister(emu, VB_PSW); - emu->cpu.eipc = emu->cpu.pc; + emu->cpu.eipc = emu->cpu.pc + (irq ? 2 : 0); emu->cpu.eipcFrom = emu->cpu.pcFrom; emu->cpu.eipcTo = emu->cpu.pcTo; emu->cpu.psw.ep = 1; @@ -1596,7 +1596,7 @@ static int cpuException(VB *emu) { } /* Interrupt */ - if (causeCode < 0xFF00) + if (irq) emu->cpu.psw.i += emu->cpu.psw.i == 15 ? 0 : 1; /* Update state */ @@ -1690,10 +1690,11 @@ static int cpuEmulate(VB *emu, uint32_t clocks) { /* Processing by operations state */ switch (emu->cpu.state) { - case CPU_FETCH : if (cpuFetch (emu)) return 1; break; - case CPU_EXECUTE : if (cpuExecute (emu)) return 1; break; - case CPU_EXCEPTION: if (cpuException(emu)) return 1; break; - case CPU_HALTED : if (cpuCheckIRQs(emu)) return 0; break; + case CPU_EXCEPTION: if ( cpuException(emu)) return 1; break; + case CPU_EXECUTE : if ( cpuExecute (emu)) return 1; break; + case CPU_FATAL : return 0; break; + case CPU_FETCH : if ( cpuFetch (emu)) return 1; break; + case CPU_HALTED : if (!cpuCheckIRQs(emu)) return 0; break; } } while (clocks > 0); @@ -1702,6 +1703,45 @@ static int cpuEmulate(VB *emu, uint32_t clocks) { return 0; } +/* Simulate a hardware reset */ +static void cpuReset(VB *emu) { + int x; /* Iterator */ + + /* Registers */ + vbSetProgramCounter(emu, 0xFFFFFFF0); + vbSetSystemRegister(emu, VB_ECR, 0x0000FFF0); + vbSetSystemRegister(emu, VB_PSW, 0x00008000); + + /* Cache */ + vbSetSystemRegister(emu, VB_CHCW, 0x00000000); + + /* Other state */ + emu->cpu.busWait = 0; + emu->cpu.state = CPU_FETCH; + emu->cpu.substring = 0; + for (x = 0; x < 5; x++) + emu->cpu.irq[x] = 0; + + /* Other registers (the hardware does not do this) */ + for (x = 0; x < 32; x++) + emu->cpu.program[x] = 0x00000000; + emu->cpu.adtre = 0x00000000; + emu->cpu.eipc = 0x00000000; + emu->cpu.eipsw = 0x00000000; + emu->cpu.fepc = 0x00000000; + emu->cpu.fepsw = 0x00000000; + emu->cpu.sr29 = 0x00000000; + emu->cpu.sr31 = 0x00000000; + + /* History tracking */ + emu->cpu.eipcFrom = 0xFFFFFFF0; + emu->cpu.eipcTo = 0xFFFFFFF0; + emu->cpu.fepcFrom = 0xFFFFFFF0; + emu->cpu.fepcTo = 0xFFFFFFF0; + emu->cpu.pcFrom = 0xFFFFFFF0; + emu->cpu.pcTo = 0xFFFFFFF0; +} + /* Determine the number of clocks before a break condititon could occur */ static uint32_t cpuUntil(VB *emu, uint32_t clocks) { diff --git a/core/vb.c b/core/vb.c index 0eea7eb..d8eae4d 100644 --- a/core/vb.c +++ b/core/vb.c @@ -197,36 +197,8 @@ int32_t vbRead(VB *emu, uint32_t address, int type, int debug) { void vbReset(VB *emu) { uint32_t x; /* Iterator */ - /* CPU registers */ - vbSetProgramCounter(emu, 0xFFFFFFF0); - vbSetSystemRegister(emu, VB_ECR, 0x0000FFF0); - vbSetSystemRegister(emu, VB_PSW, 0x00008000); - - /* Extra CPU registers (the hardware does not do this) */ - for (x = 0; x < 32; x++) - emu->cpu.program[x] = 0x00000000; - emu->cpu.adtre = 0x00000000; - emu->cpu.eipc = 0x00000000; - emu->cpu.eipsw = 0x00000000; - emu->cpu.fepc = 0x00000000; - emu->cpu.fepsw = 0x00000000; - emu->cpu.sr29 = 0x00000000; - emu->cpu.sr31 = 0x00000000; - - /* History tracking */ - emu->cpu.eipcFrom = 0xFFFFFFF0; - emu->cpu.eipcTo = 0xFFFFFFF0; - emu->cpu.fepcFrom = 0xFFFFFFF0; - emu->cpu.fepcTo = 0xFFFFFFF0; - emu->cpu.pcFrom = 0xFFFFFFF0; - emu->cpu.pcTo = 0xFFFFFFF0; - - /* Other CPU state */ - emu->cpu.busWait = 0; - emu->cpu.state = CPU_FETCH; - emu->cpu.substring = 0; - for (x = 0; x < 5; x++) - emu->cpu.irq[x] = 0; + /* Subsystem components */ + cpuReset(emu); /* WRAM (the hardware does not do this) */ for (x = 0; x < 0x10000; x++)