From 11862865f805456d02419a8b6e1ee7f5fc9a3c79 Mon Sep 17 00:00:00 2001 From: MatCat Date: Thu, 15 Apr 2021 00:37:00 -0700 Subject: [PATCH] Support for negative and overflow, ISA work, display registers for clearing and forcing update (on SIM only for force update), memory editor, and more --- index.html | 8 ++- js/cpu.js | 102 ++++++++++++++++++++++++++++++++++---- js/defines.js | 7 +++ js/isa/alu.js | 104 +++++++++++++++++++++++++++++++++++++++ js/isa/branching.js | 24 +++++++++ js/isa/ldx.js | 21 ++++++++ js/isa/misc.js | 43 +++++++++++++--- js/isa/stx.js | 5 +- js/main.js | 74 +++++++++++++++++++++++++--- js/microcode_compiler.js | 78 +++++++++++++++++++++++++++-- 10 files changed, 436 insertions(+), 30 deletions(-) diff --git a/index.html b/index.html index 7d7569b..5601dcf 100644 --- a/index.html +++ b/index.html @@ -54,9 +54,10 @@
- 0 0x
+ 0 0x
Clock Interval: mS - Cycles Per Interval: + Cycles Per Interval:
+ CPU Frequency:
@@ -65,6 +66,9 @@
RAM : [] Lines:
+
+ 0x +
RAM (STACK):
diff --git a/js/cpu.js b/js/cpu.js index 77315d5..68cec2c 100644 --- a/js/cpu.js +++ b/js/cpu.js @@ -1,6 +1,17 @@ let intval = null; let breakpt = null; let ramlines = {value: 1}; +let iterations = 0; +let totalstart = performance.now(); +let lastiteration = 0; +let cyclecount = 0; +let cycleavg = new Array(10); +let cycleavgval = 0; +let cycleavgpos = 0; + +for (let a = 0; a < cycleavg.length; a++) { + cycleavg[a] = 0; +} function stringToRAM(rstring,ram,address) { for (let a = 0; a < rstring.length; a++) { @@ -24,7 +35,9 @@ function generateClocks_Interval(cycles_per_run=1) { } else { cpu.CLOCK(true); }*/ - + let perfStart = performance.now(); + let perfEnd = 0; + let perftotal = 0; for (let a = 0; a < cycles_per_run; a++) { cpu.CLOCK(true); clk_count++; @@ -34,9 +47,37 @@ function generateClocks_Interval(cycles_per_run=1) { if (cpu.ADDRBUS === breakpt) { btn_stopclk.disabled = true; clearInterval(intval); + updateHTML(); + perfEnd = performance.now(); + perftotal = perfEnd - perfStart; + //console.log(`Performance: ${perftotal}`); return; } } + updateHTML(); + perfEnd = performance.now(); + perftotal = perfEnd - perfStart; + iterations += 1; + let totalnow = performance.now(); + let timesince = totalnow - lastiteration; + lastiteration = totalnow; + cycleavg[cycleavgpos] = ((cycles_per_run / (timesince/1000))/1000); + cycleavgpos++; + if (cycleavgpos > cycleavg.length) cycleavgpos = 0; + cyclecount++; + if (cyclecount === 10) { + let avg = 0; + for (let a = 0; a < cycleavg.length; a++) { + avg += cycleavg[a]; + } + cycleavgval = avg/cycleavg.length; + //console.log(`[${iterations} +${timesince}ms] Performance: ${perftotal}, CPS: ${cycleavgval}KHz`); + cyclecount = 0; + } + //console.log(`[${iterations} +${timesince}ms] Performance: ${perftotal}, CPS: ${cps}`); + + + } function drawCPUInfo() { @@ -161,6 +202,12 @@ function updateHTML() { if (cpu.MC_Controls & CONTROL_RDIH) sp_gpd.style.backgroundColor = "#ff5555"; if (cpu.OUTMUX === OECONTROL_DA || cpu.OUTMUX === OECONTROL_DB || cpu.OUTMUX === OECONTROL_DC || cpu.OUTMUX === OECONTROL_DL) sp_gpd.style.backgroundColor = "#55cc55"; if (cpu.OUTMUX === OECONTROL_AD || cpu.OUTMUX === OECONTROL_BD || cpu.OUTMUX === OECONTROL_CD || cpu.OUTMUX === OECONTROL_DH) sp_gpd.style.backgroundColor = "#55ff55"; + let sp_cf = document.getElementById("clk_freq"); + sp_cf.innerText = Math.floor(cycleavgval) + "KHz"; + + let sp_ramaddr = document.getElementById("txt_ramaddr"); + let sp_ramval = document.getElementById("txt_ramval"); + sp_ramval.value = formatHex(cpu.RAM[parseInt(sp_ramaddr.value)],4); printRAM(cpu.RAM); let sp_textout = document.getElementById("TEXT_OUT"); sp_textout.innerText = printTextOut(cpu.RAM,0xd00000,0xd00000 + (80*24)); @@ -268,6 +315,19 @@ class CPU_8SA1 { if (this.MC_Controls & CONTROL_RDIH) this.GPD_In_HIGH_CLK(); if (this.MC_Controls & CONTROL_AE ) this.ALU_CLK(); + if (this.ADDRBUS === 0xff0000 && this.DATABUS > 0) { + // clear the display + for (let a = 0xd00000; a < 0xdfffff; a++) { + this.RAM[a] = 0; + } + //console.log("Display Cleared"); + } + + if (this.ADDRBUS === 0xff0001 && this.DATABUS > 0) { + // Force an update + updateHTML(); + } + } _CLOCK_LOW() { @@ -285,7 +345,7 @@ class CPU_8SA1 { ALUMUX |= (this.MC_Controls & CONTROL_ALUM0) ? 0b01 : 0; //console.log(`ALU: A=${ALU_A}, B=${ALU_B}, MUX: ${ALUMUX}`); - if (this.MC_Controls & CONTROL_ALUI) console.log("ALU Inverting B"); + //if (this.MC_Controls & CONTROL_ALUI) console.log("ALU Inverting B"); let SHIFTING = false; if (this.MC_Controls & CONTROL_ALUSL) SHIFTING = true; if (this.MC_Controls & CONTROL_ALUSR) SHIFTING = true; @@ -296,6 +356,7 @@ class CPU_8SA1 { ALU_Result = ALU_A + ALU_B; if (this.MC_Controls & CONTROL_ALUC && !SHIFTING) ALU_Result += 1; + //if (this.MC_Controls & CONTROL_ALUC && !SHIFTING) console.log("We are carrying in!"); break; } case 1: { // AND @@ -306,7 +367,7 @@ class CPU_8SA1 { } case 2: { // OR ALU_Result = ALU_A | ALU_B; - console.log(`ALU OR: A: ${ALU_A}, B: ${ALU_B}, Result: ${ALU_Result}`); + //console.log(`ALU OR: A: ${ALU_A}, B: ${ALU_B}, Result: ${ALU_Result}`); if (this.MC_Controls & CONTROL_ALUI) ALU_Result = ~ALU_Result; if (this.MC_Controls & CONTROL_ALUC && !SHIFTING) ALU_Result += 1; break; @@ -341,10 +402,10 @@ class CPU_8SA1 { if (~(((ALU_A & 0b10000000)>>7) ^ ((ALU_B & 0b10000000)>>7)) === -1) { if ((ALU_A & 0b10000000) !== (ALU_Result & 0b10000000)) { // We have an OVERFLOW - console.log("overflow"); - console.log(((ALU_A & 0b10000000)>>7)); - console.log(((ALU_B & 0b10000000)>>7)); - console.log(((ALU_Result & 0b10000000)>>7)); + //console.log("overflow"); + //console.log(((ALU_A & 0b10000000)>>7)); + //console.log(((ALU_B & 0b10000000)>>7)); + //console.log(((ALU_Result & 0b10000000)>>7)); this.SR = this.SR | 0b00000100; } } else { @@ -367,7 +428,18 @@ class CPU_8SA1 { this.DATABUS = 0; this.MCC += 1; if (this.MCC > 15) this.MCC = 0; - let mcra = ((this.IR & 0b0000001111111111) << 4) | this.MCC | ((this.SR & 0b00000011) << 14); + let lSR = 0; + if ((this.IR & 0b0000010000000000) !== 0) { + // We are going to make the ZERO line a NEGATIVE line + lSR = ((this.SR & 0b00000001) << 14); + lSR |= ((this.SR & 0b00001000) << 12); + //console.log("We are doing a NEGATIVE instead of ZERO"); + //console.log(formatBinary(lSR,16)); + //console.log(formatHex(((this.IR & 0b0000001111111111) << 4) | this.MCC | lSR,4)); + } else { + lSR = ((this.SR & 0b00000011) << 14); + } + let mcra = ((this.IR & 0b0000001111111111) << 4) | this.MCC | lSR; let MC_Controls = this.MCRAM[mcra]; if (MC_Controls & CONTROL_MCL0) this.MCC = 0; if (MC_Controls & CONTROL_MCL8) this.MCC = 8; @@ -382,8 +454,18 @@ class CPU_8SA1 { } //if (MC_Controls & CONTROL_MCL0) console.log(`Reset microcode counter to 0`); //if (MC_Controls & CONTROL_MCL8) console.log(`Reset microcode counter to 8`); - mcra = ((this.IR & 0b0000001111111111) << 4) | this.MCC | ((this.SR & 0b00000011) << 14); + if ((this.IR & 0b0000010000000000) !== 0) { + // We are going to make the ZERO line a NEGATIVE line + lSR = ((this.SR & 0b00000001) << 14); + lSR |= ((this.SR & 0b00001000) << 12); + //console.log("We are doing a NEGATIVE instead of ZERO"); + //console.log(formatBinary(lSR,16,4)); + } else { + lSR = ((this.SR & 0b00000011) << 14); + } + mcra = ((this.IR & 0b0000001111111111) << 4) | this.MCC | lSR; MC_Controls = this.MCRAM[mcra]; + //if (this.IR === 0x711) console.log(formatHex(mcra,4)); if (MC_Controls === undefined) MC_Controls = 0; //console.log(`[${mcra.toString(2)}] Control Lines: ${MC_Controls.toString(2)}`); if (MC_Controls !== this.MC_Controls) { @@ -495,7 +577,7 @@ class CPU_8SA1 { break; } case OECONTROL_TI: { - console.log(`Storing PC [${formatHex(this.PC,6)}] to SP [${formatHex(this.SP,6)}]`); + //console.log(`Storing PC [${formatHex(this.PC,6)}] to SP [${formatHex(this.SP,6)}]`); this.DATABUS = 0x7F; break; } diff --git a/js/defines.js b/js/defines.js index 93b35f6..c5154a8 100644 --- a/js/defines.js +++ b/js/defines.js @@ -10,30 +10,37 @@ const CONTROL_PCC = 0b00000000000000000000000000000001; // PC CL const CONTROL_PCI = 0b00000000000000000000000000000010; // PC Input Enable const CONTROL_SPD = 0b00000000000000000000000000000100; // SP Count Down const CONTROL_SPC = 0b00000000000000000000000000001000; // SP CLK (UP / DOWN) + const CONTROL_SPI = 0b00000000000000000000000000010000; // SP Input Enable const CONTROL_RAIL = 0b00000000000000000000000000100000; // GPA LOW Input Enable const CONTROL_RAIH = 0b00000000000000000000000001000000; // GPA HIGH Input Enable const CONTROL_RBIL = 0b00000000000000000000000010000000; // GPB LOW Input Enable + const CONTROL_RBIH = 0b00000000000000000000000100000000; // GPB HIGH Input Enable const CONTROL_RCIL = 0b00000000000000000000001000000000; // GPC LOW Input Enable const CONTROL_RCIH = 0b00000000000000000000010000000000; // GPC HIGH Input Enable const CONTROL_RDIL = 0b00000000000000000000100000000000; // GPD LOW Input Enable + const CONTROL_RDIH = 0b00000000000000000001000000000000; // GPD HIGH Input Enable const CONTROL_RRI = 0b00000000000000000010000000000000; // LOW Ram Register Input Enable const CONTROL_RHI = 0b00000000000000000100000000000000; // HIGH Ram Register Input Enable const CONTROL_ALUM0 = 0b00000000000000001000000000000000; // ALU MUX 0 + const CONTROL_ALUM1 = 0b00000000000000010000000000000000; // ALU MUX 1 const CONTROL_ALUI = 0b00000000000000100000000000000000; // ALU Invert (high side) const CONTROL_ALUC = 0b00000000000001000000000000000000; // ALU Carry Input const CONTROL_ALUSL = 0b00000000000010000000000000000000; // ALU Shift Left + const CONTROL_ALUSR = 0b00000000000100000000000000000000; // ALU Shift Right const CONTROL_OEM0 = 0b00000000001000000000000000000000; // Output Enable MUX 0 const CONTROL_OEM1 = 0b00000000010000000000000000000000; // Output Enable MUX 1 const CONTROL_OEM2 = 0b00000000100000000000000000000000; // Output Enable MUX 2 + const CONTROL_OEM3 = 0b00000001000000000000000000000000; // Output Enable MUX 3 const CONTROL_OEM4 = 0b00000010000000000000000000000000; // Output Enable MUX 4 const CONTROL_OEME = 0b00000100000000000000000000000000; // Output Enable MUX Enable const CONTROL_AE = 0b00001000000000000000000000000000; // ALU Enable + const CONTROL_RI = 0b00010000000000000000000000000000; // RAM Input Enable const CONTROL_IRI = 0b00100000000000000000000000000000; // Instruction Register Input Enable const CONTROL_MCL0 = 0b01000000000000000000000000000000; // Microcode Counter to 0 diff --git a/js/isa/alu.js b/js/isa/alu.js index 570823e..49ce8b9 100644 --- a/js/isa/alu.js +++ b/js/isa/alu.js @@ -349,3 +349,107 @@ class IS_ADD_gpd_imm extends Microcode_Instruction { } is_ADD_gpdi = new IS_ADD_gpd_imm; Instructions.push(is_ADD_gpdi); + +class IS_ADD_ABabs16 extends Microcode_Instruction { + constructor(props) { + super(props); + this.UsesCarry = true; + this.UsesZero = true; + this.Bytecode = 0x711; + this.Mnemonic = "ADD"; + this.LongName = "Addition"; + this.Aliases = new Array(); + + this.Type = InstructionTypes.Register; + this.Operands = new Array({Operand: "AB", Bitwidth: 16},{Operand: "$", Bitwidth: 16}); + this.Words = 2; + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI ); + this.AddInstruction(CONTROL_OUT_BL | CONTROL_RI | CONTROL_SPD | CONTROL_SPC); + this.AddInstruction(CONTROL_OUT_PC | CONTROL_RRI ); + this.AddInstruction(CONTROL_OUT_I2 | CONTROL_RBIL | CONTROL_PCC ); + this.AddInstruction(CONTROL_OUT_AB | CONTROL_ALU_ADD ); + this.AddInstruction(CONTROL_OUT_AO | CONTROL_RAIL ); + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI ); + this.AddInstruction(CONTROL_OUT_AL | CONTROL_RI | CONTROL_SPC ); + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI ); + this.AddInstruction(CONTROL_OUT_RO | CONTROL_RAIL ); + this.AddInstruction(CONTROL_OUT_2O | CONTROL_RBIH | CONTROL_SPD | CONTROL_SPC); + this.CloneInstruction(this.Microcode,"all"); + this.CycleCountCarry = parseInt(this.CycleCount); + this.CycleCountZero = parseInt(this.CycleCount); + this.CycleCountZC = parseInt(this.CycleCount); + this.AddInstruction(CONTROL_OUT_AB | CONTROL_ALU_ADD ); + this.AddInstruction( CONTROL_MCL0 ); + this.AddInstruction(CONTROL_OUT_AB | CONTROL_ALU_ADD , "Zero"); + this.AddInstruction( CONTROL_MCL0 , "Zero"); + this.AddInstruction(CONTROL_OUT_AB | CONTROL_ALU_ADD | CONTROL_ALUC, "Carry"); + this.AddInstruction( CONTROL_MCL0 , "Carry"); + this.AddInstruction(CONTROL_OUT_AB | CONTROL_ALU_ADD | CONTROL_ALUC, "ZC"); + this.AddInstruction( CONTROL_MCL0 , "ZC"); + +/* + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI , "Zero"); + this.AddInstruction(CONTROL_OUT_BL | CONTROL_RI | CONTROL_SPD | CONTROL_SPC, "Zero"); + this.AddInstruction(CONTROL_OUT_PC | CONTROL_RRI , "Zero"); + this.AddInstruction(CONTROL_OUT_I2 | CONTROL_RBIL | CONTROL_PCC , "Zero"); + this.AddInstruction(CONTROL_OUT_AB | CONTROL_ALU_ADD , "Zero"); + this.AddInstruction(CONTROL_OUT_AO | CONTROL_RAIL , "Zero"); + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI , "Zero"); + this.AddInstruction(CONTROL_OUT_AL | CONTROL_RI | CONTROL_SPC , "Zero"); + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI , "Zero"); + this.AddInstruction(CONTROL_OUT_RO | CONTROL_RAIL , "Zero"); + this.AddInstruction(CONTROL_OUT_2O | CONTROL_RBIH | CONTROL_SPD | CONTROL_SPC, "Zero"); + this.AddInstruction(CONTROL_OUT_AB | CONTROL_ALU_ADD , "Zero"); + this.AddInstruction(CONTROL_MCL0, "Zero"); + + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI , "Carry"); + this.AddInstruction(CONTROL_OUT_BL | CONTROL_RI | CONTROL_SPD | CONTROL_SPC, "Carry"); + this.AddInstruction(CONTROL_OUT_PC | CONTROL_RRI , "Carry"); + this.AddInstruction(CONTROL_OUT_I2 | CONTROL_RBIL | CONTROL_PCC , "Carry"); + this.AddInstruction(CONTROL_OUT_AB | CONTROL_ALU_ADD , "Carry"); + this.AddInstruction(CONTROL_OUT_AO | CONTROL_RAIL , "Carry"); + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI , "Carry"); + this.AddInstruction(CONTROL_OUT_AL | CONTROL_RI | CONTROL_SPC , "Carry"); + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI , "Carry"); + this.AddInstruction(CONTROL_OUT_RO | CONTROL_RAIL , "Carry"); + this.AddInstruction(CONTROL_OUT_2O | CONTROL_RBIH | CONTROL_SPD | CONTROL_SPC, "Carry"); + this.AddInstruction(CONTROL_OUT_AB | CONTROL_ALU_ADD | CONTROL_ALUC , "Carry"); + this.AddInstruction(CONTROL_MCL0, "Carry"); + + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI , "ZC"); + this.AddInstruction(CONTROL_OUT_BL | CONTROL_RI | CONTROL_SPD | CONTROL_SPC, "ZC"); + this.AddInstruction(CONTROL_OUT_PC | CONTROL_RRI , "ZC"); + this.AddInstruction(CONTROL_OUT_I2 | CONTROL_RBIL | CONTROL_PCC , "ZC"); + this.AddInstruction(CONTROL_OUT_AB | CONTROL_ALU_ADD , "ZC"); + this.AddInstruction(CONTROL_OUT_AO | CONTROL_RAIL , "ZC"); + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI , "ZC"); + this.AddInstruction(CONTROL_OUT_AL | CONTROL_RI | CONTROL_SPC , "ZC"); + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI , "ZC"); + this.AddInstruction(CONTROL_OUT_RO | CONTROL_RAIL , "ZC"); + this.AddInstruction(CONTROL_OUT_2O | CONTROL_RBIH | CONTROL_SPD | CONTROL_SPC, "ZC"); + this.AddInstruction(CONTROL_OUT_AB | CONTROL_ALU_ADD | CONTROL_ALUC , "ZC"); + this.AddInstruction(CONTROL_MCL0, "ZC"); +*/ + } +} +is_ADD_aab16 = new IS_ADD_ABabs16; +Instructions.push(is_ADD_aab16); + +class IS_ADD_ABabs16_2 extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x712; + this.Mnemonic = "ADD"; + this.LongName = "Addition"; + this.Aliases = new Array(); + + this.Type = InstructionTypes.Register; + this.Operands = new Array(); + this.Words = 1; + this.AddInstruction(CONTROL_OUT_SP | CONTROL_RRI ); + this.AddInstruction(CONTROL_OUT_AO | CONTROL_RBIL ); + this.AddInstruction(CONTROL_OUT_RO | CONTROL_RAIL ); + } +} +is_ADD_aab16_2 = new IS_ADD_ABabs16_2; +Instructions.push(is_ADD_aab16_2); diff --git a/js/isa/branching.js b/js/isa/branching.js index 32c86ac..b7a31db 100644 --- a/js/isa/branching.js +++ b/js/isa/branching.js @@ -432,3 +432,27 @@ class IS_RTS_abs24 extends Microcode_Instruction { } is_RTS_a24 = new IS_RTS_abs24; Instructions.push(is_RTS_a24); + +class IS_JMP_SPabs24 extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x3DF; + this.Mnemonic = "JMP"; + this.LongName = "Jump to 24 bit address stored on STACK"; + this.Aliases = new Array(); + + this.Type = InstructionTypes.RegisterAbsolute; + this.Operands = new Array({Operand: "SP", Bitwidth: 24}); + this.Words = 1; + this.Cycles = 9; + this.Microcode[2] = CONTROL_SPC; + this.Microcode[3] = CONTROL_OUT_SP | CONTROL_RRI; + this.Microcode[4] = CONTROL_OUT_I2 | CONTROL_SPC; + this.Microcode[5] = CONTROL_OUT_SP | CONTROL_RRI; + this.Microcode[6] = CONTROL_OUT_RO | CONTROL_PCI; + this.Microcode[7] = CONTROL_OUT_2O | CONTROL_RHI | CONTROL_PCC; + this.Microcode[8] = CONTROL_PCC; + } +} +is_JMP_spa24 = new IS_JMP_SPabs24; +Instructions.push(is_JMP_spa24); diff --git a/js/isa/ldx.js b/js/isa/ldx.js index 19f07a6..f1b2a9c 100644 --- a/js/isa/ldx.js +++ b/js/isa/ldx.js @@ -988,6 +988,27 @@ class IS_LDSP_abs16 extends Microcode_Instruction { is_LDSP_a = new IS_LDSP_abs16; Instructions.push(is_LDSP_a); +class IS_LDSPP_abs16 extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x05F; + this.Mnemonic = "LDSPP"; + this.LongName = "LOAD Stack Pointer Page"; + this.Aliases = new Array(); + + this.Type = InstructionTypes.Absolute16; + this.Operands = new Array({Operand: "", Bitwidth: 16}); + this.Words = 2; + this.Cycles = 4; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[2] = CONTROL_OUT_RO | CONTROL_RRI; + this.Microcode[4] = CONTROL_OUT_HS | CONTROL_PCC; + } +} +is_LDSPP_a = new IS_LDSPP_abs16; +Instructions.push(is_LDSPP_a); + + class IS_LDAL_abs24 extends Microcode_Instruction { constructor(props) { super(props); diff --git a/js/isa/misc.js b/js/isa/misc.js index 92a452a..c5e60d0 100644 --- a/js/isa/misc.js +++ b/js/isa/misc.js @@ -54,6 +54,36 @@ class IS_CTI extends Microcode_Instruction { is_CTI = new IS_CTI; Instructions.push(is_CTI); +class IS_NOPLONG extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x3fd; + this.Mnemonic = "NOPL"; + this.LongName = "NO OPERATION LONG"; + this.Aliases = new Array(); + + this.Type = InstructionTypes.SingleWord; + this.Operands = new Array(); + this.Words = 1; + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + this.AddInstruction(0); + } +} +is_NOPL = new IS_NOPLONG; +Instructions.push(is_NOPL); + class IS_RTI extends Microcode_Instruction { constructor(props) { super(props); @@ -65,14 +95,15 @@ class IS_RTI extends Microcode_Instruction { this.Type = InstructionTypes.SingleWord; this.Operands = new Array(); this.Words = 1; - this.Cycles = 6; + this.Cycles = 8; this.Microcode[0] = CONTROL_OUT_SP | CONTROL_RRI; this.Microcode[1] = CONTROL_OUT_PC | CONTROL_RI | CONTROL_SPD | CONTROL_SPC; - this.Microcode[2] = CONTROL_OUT_TI | CONTROL_PCI; - this.Microcode[3] = CONTROL_RHI; - this.Microcode[4] = CONTROL_OUT_PC | CONTROL_RRI; - this.Microcode[5] = CONTROL_OUT_RO | CONTROL_IRI | CONTROL_PCC; - + this.Microcode[2] = CONTROL_OUT_SP | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_HO | CONTROL_RI | CONTROL_SPD | CONTROL_SPC; + this.Microcode[4] = CONTROL_OUT_TI | CONTROL_PCI; + this.Microcode[5] = CONTROL_RHI; + this.Microcode[6] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[7] = CONTROL_OUT_RO | CONTROL_IRI | CONTROL_PCC; } } is_RTI = new IS_RTI; diff --git a/js/isa/stx.js b/js/isa/stx.js index 2d03bca..2ba7988 100644 --- a/js/isa/stx.js +++ b/js/isa/stx.js @@ -281,9 +281,10 @@ class IS_STAB_abs16 extends Microcode_Instruction { this.Type = InstructionTypes.Absolute16; this.Operands = new Array({Operand: "", Bitwidth: 16}); this.Words = 2; - this.Cycles = 4; + this.Cycles = 5; this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; - this.Microcode[3] = CONTROL_OUT_AB | CONTROL_RI | CONTROL_PCC; + this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RRI; + this.Microcode[4] = CONTROL_OUT_AB | CONTROL_RI | CONTROL_PCC; } } is_STAB_a = new IS_STAB_abs16; diff --git a/js/main.js b/js/main.js index 56c84f1..1aa1795 100644 --- a/js/main.js +++ b/js/main.js @@ -4,13 +4,55 @@ GenerateMicrocode(Instructions,cpu); cpu.RAM[0] = is_LDSPP_i.Bytecode; cpu.RAM[1] = 0xCF; -cpu.RAM[2] = is_LDAB_i.Bytecode; -cpu.RAM[3] = 0x0100; -cpu.RAM[4] = is_PHAB.Bytecode; -cpu.RAM[5] = is_JSR_a.Bytecode; -cpu.RAM[6] = 0x00D0; +cpu.RAM[2] = is_LDA_i.Bytecode; +cpu.RAM[3] = 1; +cpu.RAM[4] = is_STAL_a24.Bytecode; +cpu.RAM[5] = 0xFF; +cpu.RAM[6] = 0x0; +cpu.RAM[7] = is_LDAB_i.Bytecode; +cpu.RAM[8] = 0x0100; +cpu.RAM[9] = is_PHAB.Bytecode; +cpu.RAM[10] = is_JSR_a.Bytecode; +cpu.RAM[11] = 0x00D0; +cpu.RAM[12] = is_LDAB_i.Bytecode; +cpu.RAM[13] = 0x0101; +cpu.RAM[14] = is_STAL_a24.Bytecode; +cpu.RAM[15] = 0xFF; +cpu.RAM[16] = 0x1; +cpu.RAM[17] = is_ADD.Bytecode; +cpu.RAM[18] = is_NOPL.Bytecode; +cpu.RAM[19] = is_NOPL.Bytecode; +cpu.RAM[20] = is_NOPL.Bytecode; +cpu.RAM[21] = is_NOPL.Bytecode; +cpu.RAM[22] = is_NOPL.Bytecode; +cpu.RAM[23] = is_NOPL.Bytecode; +cpu.RAM[24] = is_NOPL.Bytecode; +cpu.RAM[25] = is_NOPL.Bytecode; +cpu.RAM[26] = is_NOPL.Bytecode; +cpu.RAM[27] = is_NOPL.Bytecode; +cpu.RAM[28] = is_NOPL.Bytecode; +cpu.RAM[29] = is_BCC_a.Bytecode; +cpu.RAM[30] = 17; +cpu.RAM[31] = is_JMP_a.Bytecode; +cpu.RAM[32] = 0x0; + /* + +// Experimenting with 16 bit add +cpu.RAM[2] = is_LDAB_i.Bytecode; +cpu.RAM[3] = 0x1337; +cpu.RAM[4] = is_ADD_aab16.Bytecode; +cpu.RAM[5] = 0b1111000011101001; +cpu.RAM[6] = is_ADD_aab16_2.Bytecode; +cpu.RAM[7] = is_STAB_a.Bytecode; +cpu.RAM[8] = 0x0020; +*/ + + +/* + +// Experimenting with thread interrupt cpu.RAM[2] = is_STI.Bytecode; cpu.RAM[3] = 0x80; @@ -77,6 +119,10 @@ updateHTML(); let btn_clk = document.getElementById("btn_clk"); let btn_stopclk = document.getElementById("btn_stopclk"); let btn_runtil = document.getElementById("btn_runtil"); +let btn_saveram = document.getElementById("btn_saveram"); +let txt_ramaddr = document.getElementById("txt_ramaddr"); +let txt_ramval = document.getElementById("txt_ramval"); + let brkpt = document.getElementById("addrbrk"); let clkinterval = document.getElementById("clkinterval"); let clkcycles = document.getElementById("clkcycles"); @@ -89,10 +135,12 @@ btn_clk.addEventListener('mousedown', function(evt) { cpu.CLOCK(true); clk_count++; clk_counter.innerText = clk_count; + updateHTML(); }); btn_clk.addEventListener('mouseup', function(evt) { cpu.CLOCK(false); + updateHTML(); }); @@ -107,6 +155,7 @@ btn_runtil.addEventListener('click', function(evt) { btn_stopclk.addEventListener('click', function(evt) { btn_stopclk.disabled = true; clearInterval(intval); + updateHTML(); }); btn_rst.addEventListener('click', function(evt) { @@ -136,6 +185,19 @@ btn_rst.addEventListener('click', function(evt) { for (let a = 0xd00000; a < 0xe00000; a++) { cpu.RAM[a] = 0; } + updateHTML(); + }); -window.requestAnimationFrame(drawCPUInfo); \ No newline at end of file +btn_saveram.addEventListener('click', function(evt) { + cpu.RAM[parseInt(txt_ramaddr.value)] = parseInt("0x" + txt_ramval.value); + updateHTML(); +}); + +txt_ramaddr.addEventListener('change', function(evt) { + txt_ramval.value = formatHex(cpu.RAM[parseInt(txt_ramaddr.value)],4); +}); + + +//window.requestAnimationFrame(drawCPUInfo); +updateHTML(); \ No newline at end of file diff --git a/js/microcode_compiler.js b/js/microcode_compiler.js index 082d097..0d30afe 100644 --- a/js/microcode_compiler.js +++ b/js/microcode_compiler.js @@ -206,16 +206,23 @@ function GenerateMicrocode(mcarray,cpu) { if (c === 2) offset = 0b0100000000000000; if (c === 3) offset = 0b1100000000000000; + let bytecode = mcarray[a].Bytecode & 0b1111111111; + //if (c === 0 && (bytecode === 0x311)) console.log("Doing Normals"); + //if (c === 1 && (bytecode === 0x311)) console.log("Doing Zero's"); + //if (c === 2 && (bytecode === 0x311)) console.log("Doing Carry's"); + //if (c === 3 && (bytecode === 0x311)) console.log("Doing ZC's"); + for (let b = 0; b < 16; b++) { - let bytecode = mcarray[a].Bytecode; - let mca = mcarray[a].Bytecode << 4; + let mca = bytecode << 4; mca |= b; let mcv = mcarray[a].Microcode[b]; if (mcarray[a].UsesZero && c === 1) mcv = mcarray[a].MicrocodeZero[b]; if (mcarray[a].UsesCarry && c === 2) mcv = mcarray[a].MicrocodeCarry[b]; - if (mcarray[a].UsesCarry && mcarray[a].UsesZero && c === 3) mcv = mcarray[a].MicrocodeCZ[b]; + if (mcarray[a].UsesCarry && mcarray[a].UsesZero && c === 3) mcv = mcarray[a].MicrocodeZC[b]; + if (mcarray[a].UsesCarry && !mcarray[a].UsesZero && c === 3) mcv = mcarray[a].MicrocodeCarry[b]; cpu.MCRAM[offset + mca] = mcv; - //console.log(`[${bytecode.toString(16)}] ${mca.toString(16)}: ${mcv.toString(2)}`); + mca = offset + mca; + //if (bytecode === 0x311) console.log(`[${bytecode.toString(16)}] ${mca.toString(16)}: ${mcv.toString(2)}`); } } } @@ -228,18 +235,81 @@ class Microcode_Instruction { this.LongName = ""; this.Aliases = new Array(); this.Microcode = new Array(16); + this.MicrocodeCarry = new Array(16); + this.MicrocodeZero = new Array(16); + this.MicrocodeZC = new Array(16); this.Operands = new Array(); this.UsesCarry = false; this.UsesZero = false; this.Words = 1; this.Cycles = 2; + this.CycleCount = 2; + this.CycleCountZero = 2; + this.CycleCountCarry = 2; + this.CycleCountZC = 2; this.Type = InstructionTypes.SingleWord; this.Microcode[0] = CONTROL_OUT_PC | CONTROL_RRI; this.Microcode[1] = CONTROL_OUT_RO | CONTROL_IRI | CONTROL_PCC; + this.MicrocodeCarry[0] = CONTROL_OUT_PC | CONTROL_RRI; + this.MicrocodeCarry[1] = CONTROL_OUT_RO | CONTROL_IRI | CONTROL_PCC; + this.MicrocodeZero[0] = CONTROL_OUT_PC | CONTROL_RRI; + this.MicrocodeZero[1] = CONTROL_OUT_RO | CONTROL_IRI | CONTROL_PCC; + this.MicrocodeZC[0] = CONTROL_OUT_PC | CONTROL_RRI; + this.MicrocodeZC[1] = CONTROL_OUT_RO | CONTROL_IRI | CONTROL_PCC; for (let a = 2; a < 16; a++) { this.Microcode[a] = CONTROL_MCL0; + this.MicrocodeCarry[a] = CONTROL_MCL0; + this.MicrocodeZero[a] = CONTROL_MCL0; + this.MicrocodeZC[a] = CONTROL_MCL0; + } + } + + CloneInstruction(fromtype,totype) { + // Simple function to clone instruction sets around + + if ((typeof totype === 'string' || totype instanceof String)) { + if (totype.toLowerCase() === "all") { + for (let a = 0; a < fromtype.length; a++) { + if (fromtype !== this.Microcode) this.Microcode[a] = parseInt(fromtype[a]); + if (fromtype !== this.MicrocodeZero) this.MicrocodeZero[a] = parseInt(fromtype[a]); + if (fromtype !== this.MicrocodeCarry) this.MicrocodeCarry[a] = parseInt(fromtype[a]); + if (fromtype !== this.MicrocodeZC) this.MicrocodeZC[a] = parseInt(fromtype[a]); + } + //console.log("Cloned ALL!"); + + } + } else { + if (fromtype === totype) return false; + if (fromtype.length !== totype.length) return false; + for (let a = 0; a < fromtype.length; a++) { + totype[a] = parseInt(fromtype[a]); + } + } + } + + AddInstruction(ins,type="") { + if (type.toLowerCase() === "") { + if (this.CycleCount > 15) return; // Cant find any more instructions! + this.Microcode[this.CycleCount] = ins; + this.CycleCount++; + this.Cycles = this.CycleCount; + } + if (type.toLowerCase() === "zero") { + if (this.CycleCountZero > 15) return; // Cant find any more instructions! + this.MicrocodeZero[this.CycleCountZero] = ins; + this.CycleCountZero++; + } + if (type.toLowerCase() === "carry") { + if (this.CycleCountCarry > 15) return; // Cant find any more instructions! + this.MicrocodeCarry[this.CycleCountCarry] = ins; + this.CycleCountCarry++; + } + if (type.toLowerCase() === "zc") { + if (this.CycleCountZC > 15) return; // Cant find any more instructions! + this.MicrocodeZC[this.CycleCountZC] = ins; + this.CycleCountZC++; } } }