diff --git a/examples/printstring.asm b/examples/printstring.asm index 57abfcb..f3e41db 100644 --- a/examples/printstring.asm +++ b/examples/printstring.asm @@ -5,7 +5,7 @@ ; The routine takes a simple argument on the stack with the address of the string. ; The routine will use the DISPLAY variable set in .data ; -; Version: 0.2.0 +; Version: 0.2.1 GLOBAL START GLOBAL PRINTSTRING @@ -13,32 +13,33 @@ SECTION .text START: LDAB MYSTRING ; Put string address into AB PHAB ; and push to the stack - JSR PRINTSTRING ; Call PRINTSTRING routine + PJSR PRINTSTRING ; Call PRINTSTRING routine SECTION .printstring PRINTSTRING: PLAB - PLCD - PHAB ; Get the address of the string ^^^ - LDAB $DISPLAY ; Set the output address + PHAB ; Get the address of the string + LDA $DISPLAY ; Set the output address + PHA + LDAB $DISPLAY+1 ; Set the output address PHAB PRINTLOOP: LDAB CD - CMP %A,%B + CMP A,B BEQ RETURN ; If we pull a 0, or null then we are done STAL [SP] - ADD %C,$1 ; Increment our string location by 1 + ADD C,$1 ; Increment our string location by 1 BCS ROLLOVER ; If it rolls over we need to go handle high byte PLAB - ADD %A,$1 ; Icrement our output by 1 + ADD A,$1 ; Icrement our output by 1 PHAB JMP PRINTLOOP ; Loop back and keep reading in the string -ROLLOVER: ADD %D, $1 +ROLLOVER: ADD D, $1 PLAB - ADD %B, $1 + ADD B, $1 PHAB JMP PRINTLOOP ; Loop back and keep reading in the string RETURN: PLAB ; To return we need to clean up our stack use first - RTS + PRTS SECTION .data -DISPLAY equ 8000h -MYSTRING DB "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc maximus erat mollis, fermentum quam at, blandit turpis. Pellentesque arcu tortor, smoke weed guam sagittis ac, posuere ut ipsum. Nulla facilisi. Mauris eget urna id sem porttitor consequat ultrices porttitor magna. Quisque condimentum porta viverra. Suspendisse ac condimentum ante. Duis accumsan augue urna, at ultricies nunc accumsan eget. Nullam eleifend.", 0 \ No newline at end of file +DISPLAY equ D00000h +MYSTRING DB "Welcome to the MatCat 8SA1 Computer Simulator!\n\nThis is a full hardware simulation of the computer to allow for easy development testing. It is currently a heavy work in progress as it is very early alpha, so check back often for new features!\n\n\nThis demo can be seen in the examples folder on the git page at: \nhttps://mygit.space/MatCat.OpenSource/8SA1Sim", 0 \ No newline at end of file diff --git a/index.html b/index.html index 143a3f0..e816597 100644 --- a/index.html +++ b/index.html @@ -3,56 +3,66 @@ MatCat's 8SA1 CPU Emulator +
- + Display (0xD00000-0xDFFFFF):
+ + MatCat 8SA1 Computer
-
- DATA: +
+
+ +
+
+ DATA: +
+
+ PC  : +
+
+ MCC : +
+
+ CO  : +
+
+ SP  : +
+
+ SR  : +
+
+ IR  : +
+
+ IR2 : +
+
+ GPA : +
+
+ GPB : +
+
+ GPC : +
+
+ GPD : +
+
+ + 0 0x
+ Clock Interval: mS + Cycles Per Interval: +
+
-
- PC  :
-
- MCC : -
-
- CO  : -
-
- SP  : -
-
- SR  : -
-
- IR  : -
-
- GPA : -
-
- GPB : -
-
- GPC : -
-
- GPD : -
-
- - 0 0x - Clock Interval: mS - Cycles Per Interval: -
-
- Text Output (0x8000-0x83ff):
- -
-
+ +
RAM : [] Lines:
-
+
RAM (STACK):
diff --git a/js/cpu.js b/js/cpu.js index 1330648..dbdad0b 100644 --- a/js/cpu.js +++ b/js/cpu.js @@ -32,6 +32,7 @@ function generateClocks_Interval(cycles_per_run=1) { cpu.CLOCK(false); if (cpu.ADDRBUS === breakpt) { + btn_stopclk.disabled = true; clearInterval(intval); return; } @@ -53,9 +54,13 @@ function RunUntilBreak(addr,cycles = 1) { function printTextOut(ram,startaddr,endaddr) { let outString = ""; for (let a = startaddr; a <= endaddr; a++) { - if (ram[a] === 0) return outString; // kill on null - outString += String.fromCharCode(ram[a]); + if (ram[a] === 0) { + outString += " "; + } else { + outString += String.fromCharCode(ram[a]); + } } + return outString; } function printRAM(ram) { @@ -82,9 +87,9 @@ function printRAM(ram) { sp_ram.innerHTML = ramtext; let sp_stackram = document.getElementById("STACK-RAM"); - ramtext = "ADDR  :   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
"; - for (let a = 0xffe0; a < 0x10000; a+=16) { - ramtext += "0x" + formatHex(a,4) + ": "; + ramtext = "ADDR    :   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
"; + for (let a = (0xffe0 | cpu.SPP << 16); a < ((0xffe0 | cpu.SPP << 16)+0x20); a+=16) { + ramtext += "0x" + formatHex(a,6) + ": "; for (let b = 0; b < 16; b++) { if (cpu.ADDRBUS === (a)+b) ramtext += ''; ramtext += formatHex(ram[(a)+b],4) + " "; @@ -103,8 +108,8 @@ function updateHTML() { let sp_pc = document.getElementById("PC_Register"); sp_pc.innerText = "0x" + formatHex(cpu.PC,4); sp_pc.style.backgroundColor = "transparent"; - if (cpu.MC_Controls & CONTROL_PCI) sp_pc.style.backgroundColor = "#ff5555"; if (cpu.MC_Controls & CONTROL_PCC) sp_pc.style.backgroundColor = "#55ff55"; + if (cpu.MC_Controls & CONTROL_PCI) sp_pc.style.backgroundColor = "#ff5555"; let sp_mcc = document.getElementById("MCC_Register"); sp_mcc.innerText = "0x" + cpu.MCC.toString(16).toUpperCase(); let sp_co = document.getElementById("CO_Register"); @@ -114,13 +119,18 @@ function updateHTML() { if (cpu.MC_Controls & CONTROL_SPI) sp_sp.style.backgroundColor = "#ff5555"; if (cpu.MC_Controls & CONTROL_SPC) sp_sp.style.backgroundColor = "#55ff55"; if (cpu.MC_Controls & CONTROL_SPD) sp_sp.style.backgroundColor = "#7777ff"; - sp_sp.innerText = "0x" + formatHex(cpu.SP,4); + sp_sp.innerText = "0x" + formatHex(cpu.SP | cpu.SPP << 16,6); let sp_sr = document.getElementById("SR_Register"); sp_sr.innerHTML = "0b" + formatBinary(cpu.SR,8,4,["","","","","","Negative","Zero","Carry"]); let sp_ir = document.getElementById("IR_Register"); - sp_ir.innerText = "0b" + formatBinary(cpu.IR,16,4) + " (" + GetMnemonic(Instructions,cpu.IR) + ")"; + sp_ir.innerText = `[0x${formatHex(cpu.IR,4)}] 0b` + formatBinary(cpu.IR,16,4) + " (" + GetMnemonic(Instructions,cpu.IR) + ")"; sp_ir.style.backgroundColor = "transparent"; if (cpu.MC_Controls & CONTROL_IRI) sp_ir.style.backgroundColor = "#ff5555"; + let sp_ir2 = document.getElementById("IR2_Register"); + sp_ir2.innerText = `[0x${formatHex(cpu.IR2,4)}] 0b` + formatBinary(cpu.IR2,16,4); + sp_ir2.style.backgroundColor = "transparent"; + if (cpu.OUTMUX === OECONTROL_I2) sp_ir2.style.backgroundColor = "#ff5555"; + if (cpu.OUTMUX === OECONTROL_2O) sp_ir2.style.backgroundColor = "#55ff55"; let sp_gpa = document.getElementById("GPA_Register"); sp_gpa.innerText = "0x" + formatHex(cpu.GPA,2); sp_gpa.style.backgroundColor = "transparent"; @@ -151,7 +161,7 @@ function updateHTML() { if (cpu.OUTMUX === OECONTROL_AD || cpu.OUTMUX === OECONTROL_BD || cpu.OUTMUX === OECONTROL_CD || cpu.OUTMUX === OECONTROL_DH) sp_gpd.style.backgroundColor = "#55ff55"; printRAM(cpu.RAM); let sp_textout = document.getElementById("TEXT_OUT"); - sp_textout.innerText = printTextOut(cpu.RAM,0x8000,0x83ff); + sp_textout.innerText = printTextOut(cpu.RAM,0xd00000,0xd00000 + (80*24)); } @@ -162,6 +172,7 @@ class CPU_8SA1 { this.PC = 0; // Set PC register to 0 this.SP = BITMASK_16; // Set SP register to 0xFFFF + this.SPP = BITMASK_8; this.SR = 0; // Set the STATUS register this.RR = 0; // Set lower RAM register to 0 @@ -174,6 +185,7 @@ class CPU_8SA1 { this.MCC = 0xF; // Set the microcode counter this.IR = 0; // Set the initial IR + this.IR2 = 0; // IR2 is used for 3 word instructions this.MC_Controls = 0; // Set the control output lines this.ALUSUM = 0; // ALU Register to hold SUM @@ -197,6 +209,7 @@ class CPU_8SA1 { if (!clk_val && this._CLK) { // Clock going LOW this._CLK = false; + this.DATABUS = 0; this._CLOCK_LOW(); } @@ -204,20 +217,31 @@ class CPU_8SA1 { } _CLOCK_HIGH() { // Call anything that needs to be called on positive clock edge + let OUTMUX = false; if (this.MC_Controls & CONTROL_OEME) { - let OUTMUX = (this.MC_Controls & CONTROL_OEM4) ? 0b10000 : 0; + OUTMUX = (this.MC_Controls & CONTROL_OEM4) ? 0b10000 : 0; OUTMUX |= (this.MC_Controls & CONTROL_OEM3) ? 0b01000 : 0; OUTMUX |= (this.MC_Controls & CONTROL_OEM2) ? 0b00100 : 0; OUTMUX |= (this.MC_Controls & CONTROL_OEM1) ? 0b00010 : 0; OUTMUX |= (this.MC_Controls & CONTROL_OEM0) ? 0b00001 : 0; if (OUTMUX === OECONTROL_RO) { - //console.log("DATABUS = RAM"); this.DATABUS = this.RAM[this.ADDRBUS]; if (this.DATABUS === undefined) this.DATABUS = 0; } + if (OUTMUX === OECONTROL_I2) { + this.DATABUS = this.RAM[this.ADDRBUS]; + if (this.DATABUS === undefined) this.DATABUS = 0; + this.IR2 = this.DATABUS; + } + if (OUTMUX === OECONTROL_HS) { + this.DATABUS = this.RAM[this.ADDRBUS]; + if (this.DATABUS === undefined) this.DATABUS = 0; + this.SPP = this.DATABUS & BITMASK_8; + } } + if (this.MC_Controls & CONTROL_PCC ) this.PC_CLK(); if (this.MC_Controls & CONTROL_PCI ) this.PC_In_CLK(); if (this.MC_Controls & CONTROL_SPC ) this.SP_CLK(); @@ -226,6 +250,7 @@ class CPU_8SA1 { if (this.MC_Controls & CONTROL_IRI ) this.IR_In_CLK(); if (this.MC_Controls & CONTROL_RRI ) this.RR_In_CLK(); if (this.MC_Controls & CONTROL_RHI ) this.RH_In_CLK(); + if ((OUTMUX === OECONTROL_SP) && (this.MC_Controls & CONTROL_RRI)) this.ADDRBUS = (this.ADDRBUS & BITMASK_16) | (this.SPP << 16); if (this.MC_Controls & CONTROL_RAIL) this.GPA_In_LOW_CLK(); if (this.MC_Controls & CONTROL_RAIH) this.GPA_In_HIGH_CLK(); if (this.MC_Controls & CONTROL_RBIL) this.GPB_In_LOW_CLK(); @@ -341,7 +366,7 @@ class CPU_8SA1 { } case OECONTROL_SP: { this.DATABUS = this.SP; - //console.log("DATABUS = SP"); + if (OECONTROL_SP && (MC_Controls & CONTROL_RRI)) this.ADDRBUS = (this.ADDRBUS & BITMASK_16) | (this.SPP << 16); break; } case OECONTROL_AL: { @@ -431,6 +456,22 @@ class CPU_8SA1 { this.DATABUS = ((this.GPC & BITMASK_8) << 8) | (this.GPD & BITMASK_8); break; } + case OECONTROL_I2: { + if (OECONTROL_I2 && (MC_Controls & CONTROL_SPC)) this.ADDRBUS = (this.ADDRBUS & BITMASK_16) | (this.SPP << 16); + break; + } + case OECONTROL_2O: { + this.DATABUS = this.IR2; + break; + } + case OECONTROL_HO: { + this.DATABUS = this.RH; + break; + } + case OECONTROL_HS: { + // this is done @ clock + break; + } case OECONTROL_AO: { this.DATABUS = (this.DATABUS & (BITMASK_8 << 8)) | this.ALUSUM; //console.log("DATABUS = SUM"); @@ -493,7 +534,7 @@ class CPU_8SA1 { } RH_In_CLK() { - this.RH = this.DATABUS; + this.RH = (this.DATABUS & BITMASK_8); this.ADDRBUS = this.RR | this.RH << 16; } diff --git a/js/defines.js b/js/defines.js index 68cf393..4ec2c29 100644 --- a/js/defines.js +++ b/js/defines.js @@ -62,10 +62,46 @@ const OECONTROL_CD = 0b10010 // GPD to HIGH, GPC to LOW const OECONTROL_DA = 0b10011 // GPA to HIGH, GPD to LOW const OECONTROL_DB = 0b10100 // GPB to HIGH, GPD to LOW const OECONTROL_DC = 0b10101 // GPC to HIGH, GPD to LOW +const OECONTROL_I2 = 0b11000 // RAM Out, IR2 In +const OECONTROL_2O = 0b11001 // IR2 Out +const OECONTROL_HO = 0b11010 // HIGH Ram to DATABUS LOW +const OECONTROL_HS = 0b11011 // Stack Page Byte out to ADDRBUS HIGH (disables RH out) const OECONTROL_AO = 0b11101 // ALU Output to LOW const OECONTROL_SR = 0b11110 // Status Register to LOW const OECONTROL_RO = 0b11111 // RAM to DATABUS Enable +const CONTROL_OUT_PC = CONTROL_OEME; +const CONTROL_OUT_SP = CONTROL_OEME | CONTROL_OEM0; +const CONTROL_OUT_AL = CONTROL_OEME | CONTROL_OEM1; +const CONTROL_OUT_AH = CONTROL_OEME | CONTROL_OEM1 | CONTROL_OEM0; +const CONTROL_OUT_BL = CONTROL_OEME | CONTROL_OEM2; +const CONTROL_OUT_BH = CONTROL_OEME | CONTROL_OEM2 | CONTROL_OEM0; +const CONTROL_OUT_CL = CONTROL_OEME | CONTROL_OEM2 | CONTROL_OEM1; +const CONTROL_OUT_CH = CONTROL_OEME | CONTROL_OEM2 | CONTROL_OEM1 | CONTROL_OEM0; +const CONTROL_OUT_DL = CONTROL_OEME | CONTROL_OEM3; +const CONTROL_OUT_DH = CONTROL_OEME | CONTROL_OEM3 | CONTROL_OEM0; +const CONTROL_OUT_AB = CONTROL_OEME | CONTROL_OEM3 | CONTROL_OEM1; +const CONTROL_OUT_CA = CONTROL_OEME | CONTROL_OEM4; +const CONTROL_OUT_CD = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM1; +const CONTROL_OUT_DA = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM1 | CONTROL_OEM0; +const CONTROL_OUT_I2 = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM3; +const CONTROL_OUT_2O = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM3 | CONTROL_OEM0; +const CONTROL_OUT_HO = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM3 | CONTROL_OEM1; +const CONTROL_OUT_HS = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM3 | CONTROL_OEM1 | CONTROL_OEM0; +const CONTROL_OUT_AE = CONTROL_AE; +const CONTROL_OUT_AO = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM3 | CONTROL_OEM2 | CONTROL_OEM0; +const CONTROL_OUT_RO = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM3 | CONTROL_OEM2 | CONTROL_OEM1 | CONTROL_OEM0; + +const CONTROL_ALU_ADD = CONTROL_OUT_AE; +const CONTROL_ALU_SUB = CONTROL_OUT_AE | CONTROL_ALUI | CONTROL_ALUC; +const CONTROL_ALU_NOT = CONTROL_OUT_AE | CONTROL_ALUI; +const CONTROL_ALU_AND = CONTROL_OUT_AE | CONTROL_ALUM0; +const CONTROL_ALU_NAND = CONTROL_OUT_AE | CONTROL_ALUM0 | CONTROL_ALUI; +const CONTROL_ALU_OR = CONTROL_OUT_AE | CONTROL_ALUM1; +const CONTROL_ALU_NOR = CONTROL_OUT_AE | CONTROL_ALUM1 | CONTROL_ALUI; +const CONTROL_ALU_XOR = CONTROL_OUT_AE | CONTROL_ALUM1 | CONTROL_ALUM0; +const CONTROL_ALU_XNOR = CONTROL_OUT_AE | CONTROL_ALUM1 | CONTROL_ALUM0 | CONTROL_ALUI; + function reverseString(str) { return str.split("").reverse().join(""); diff --git a/js/main.js b/js/main.js index 60a934c..0f3dcc3 100644 --- a/js/main.js +++ b/js/main.js @@ -1,52 +1,63 @@ let cpu = new CPU_8SA1(); 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_PJSR.Bytecode; +cpu.RAM[6] = 0x00D0; +cpu.RAM[0x80000] = is_RTS.Bytecode; -cpu.RAM[0] = is_LDAB_i.Bytecode; -cpu.RAM[1] = 0x0100; -cpu.RAM[2] = is_PHAB.Bytecode; -cpu.RAM[3] = is_JSR.Bytecode; -cpu.RAM[4] = 0x00D0; - +let v_printloop = 0xd9; +let v_rollover = 0xe8; +let v_return = 0xf0; +let v_displayh = 0xd0; +let v_displayl = 0x0; cpu.RAM[0xD0] = is_PLAB.Bytecode; cpu.RAM[0xD1] = is_PLCD.Bytecode; cpu.RAM[0xD2] = is_PHAB.Bytecode; -cpu.RAM[0xD3] = is_LDAB_i.Bytecode; -cpu.RAM[0xD4] = 0x8000; -cpu.RAM[0xD5] = is_PHAB.Bytecode; -cpu.RAM[0xD6] = is_LDAB_GPCD.Bytecode; // printloop -cpu.RAM[0xD7] = is_CMP.Bytecode; -cpu.RAM[0xD8] = is_BEQ_i.Bytecode; -cpu.RAM[0xD9] = 0x00ED; -cpu.RAM[0xDA] = is_STAL_spin.Bytecode; -cpu.RAM[0xDB] = is_ADD_gpci.Bytecode -cpu.RAM[0xDC] = 1; -cpu.RAM[0xDD] = is_BCS_i.Bytecode; -cpu.RAM[0xDE] = 0x00E5; -cpu.RAM[0xDF] = is_PLAB.Bytecode; -cpu.RAM[0xE0] = is_ADD_gpai.Bytecode; -cpu.RAM[0xE1] = 1; -cpu.RAM[0xE2] = is_PHAB.Bytecode; -cpu.RAM[0xE3] = is_JMP_i.Bytecode; -cpu.RAM[0xE4] = 0x00D6; -cpu.RAM[0xE5] = is_ADD_gpdi.Bytecode; // rollover -cpu.RAM[0xE6] = 1; -cpu.RAM[0xE7] = is_PLAB.Bytecode; -cpu.RAM[0xE8] = is_ADD_gpbi.Bytecode; +cpu.RAM[0xD3] = is_LDA_i.Bytecode; +cpu.RAM[0xD4] = v_displayh; +cpu.RAM[0xD5] = is_PHA.Bytecode; +cpu.RAM[0xD6] = is_LDAB_i.Bytecode; +cpu.RAM[0xD7] = v_displayl; +cpu.RAM[0xD8] = is_PHAB.Bytecode; +cpu.RAM[0xD9] = is_LDAB_GPCD.Bytecode; // printloop +cpu.RAM[0xDA] = is_CMP.Bytecode; +cpu.RAM[0xDB] = is_BEQ_i.Bytecode; +cpu.RAM[0xDC] = v_return; +cpu.RAM[0xDD] = is_STAL_spin.Bytecode; +cpu.RAM[0xDE] = is_ADD_gpci.Bytecode +cpu.RAM[0xDF] = 1; +cpu.RAM[0xE0] = is_BCS_i.Bytecode; +cpu.RAM[0xE1] = v_rollover; +cpu.RAM[0xE2] = is_PLAB.Bytecode; +cpu.RAM[0xE3] = is_ADD_gpai.Bytecode; +cpu.RAM[0xE4] = 1; +cpu.RAM[0xE5] = is_PHAB.Bytecode; +cpu.RAM[0xE6] = is_JMP_i.Bytecode; +cpu.RAM[0xE7] = v_printloop; +cpu.RAM[0xE8] = is_ADD_gpdi.Bytecode; // rollover cpu.RAM[0xE9] = 1; -cpu.RAM[0xEA] = is_PHAB.Bytecode; -cpu.RAM[0xEB] = is_JMP_i.Bytecode; -cpu.RAM[0xEC] = 0x00D6; -cpu.RAM[0xED] = is_PLAB.Bytecode; // return -cpu.RAM[0xEE] = is_RTS.Bytecode; +cpu.RAM[0xEA] = is_PLAB.Bytecode; +cpu.RAM[0xEB] = is_ADD_gpbi.Bytecode; +cpu.RAM[0xEC] = 1; +cpu.RAM[0xED] = is_PHAB.Bytecode; +cpu.RAM[0xEE] = is_JMP_i.Bytecode; +cpu.RAM[0xEF] = v_printloop; +cpu.RAM[0xF0] = is_PLAB.Bytecode; // return +cpu.RAM[0xF1] = is_PRTS.Bytecode; -stringToRAM("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc maximus erat mollis, fermentum quam at, blandit turpis. Pellentesque arcu tortor, smoke weed guam sagittis ac, posuere ut ipsum. Nulla facilisi. Mauris eget urna id sem porttitor consequat ultrices porttitor magna. Quisque condimentum porta viverra. Suspendisse ac condimentum ante. Duis accumsan augue urna, at ultricies nunc accumsan eget. Nullam eleifend.",cpu.RAM,0x100); +stringToRAM("Welcome to the MatCat 8SA1 Computer Simulator!\n\nThis is a full hardware simulation of the computer to allow for easy development testing. It is currently a heavy work in progress as it is very early alpha, so check back often for new features!\n\n\nThis demo can be seen in the examples folder on the git page at: \nhttps://mygit.space/MatCat.OpenSource/8SA1Sim",cpu.RAM,0x100); //stringToRAM("Blackbeard420 is a Butt Fuckers",cpu.RAM,0x100); updateHTML(); let btn_clk = document.getElementById("btn_clk"); +let btn_stopclk = document.getElementById("btn_stopclk"); let btn_runtil = document.getElementById("btn_runtil"); let brkpt = document.getElementById("addrbrk"); let clkinterval = document.getElementById("clkinterval"); @@ -71,13 +82,23 @@ btn_runtil.addEventListener('click', function(evt) { let addr = parseInt("0x" + brkpt.value); let cpi = parseInt(clkcycles.value); console.log(`Running ${cpi} cycles per interval`); + btn_stopclk.disabled = false; RunUntilBreak(addr,cpi); }); +btn_stopclk.addEventListener('click', function(evt) { + btn_stopclk.disabled = true; + clearInterval(intval); +}); + btn_rst.addEventListener('click', function(evt) { + btn_stopclk.disabled = true; + clearInterval(intval); + cpu.PC = 0; cpu.MCC = 0xf; cpu.IR = 0; + cpu.IR2 = 0; cpu.DATABUS = 0; cpu.ADDRBUS = 0; cpu.MC_Controls = 0; @@ -89,9 +110,14 @@ btn_rst.addEventListener('click', function(evt) { cpu.GPD = 0; cpu.SR = 0; cpu.SP = BITMASK_16; + cpu.SPP = BITMASK_8; clk_count = 0; clk_counter.innerText = clk_count; + + for (let a = 0xd00000; a < 0xe00000; a++) { + cpu.RAM[a] = 0; + } }); window.requestAnimationFrame(drawCPUInfo); \ No newline at end of file diff --git a/js/microcode_compiler.js b/js/microcode_compiler.js index ef5f212..8c97c4d 100644 --- a/js/microcode_compiler.js +++ b/js/microcode_compiler.js @@ -31,33 +31,6 @@ const CONTROL_IRI = 0b00100000000000000000000000000000; // Instr const CONTROL_MCL0 = 0b01000000000000000000000000000000; // Microcode Counter to 0 const CONTROL_MCL8 = 0b10000000000000000000000000000000; // Microcode Counter to 8 */ -const CONTROL_OUT_PC = CONTROL_OEME; -const CONTROL_OUT_SP = CONTROL_OEME | CONTROL_OEM0; -const CONTROL_OUT_AL = CONTROL_OEME | CONTROL_OEM1; -const CONTROL_OUT_AH = CONTROL_OEME | CONTROL_OEM1 | CONTROL_OEM0; -const CONTROL_OUT_BL = CONTROL_OEME | CONTROL_OEM2; -const CONTROL_OUT_BH = CONTROL_OEME | CONTROL_OEM2 | CONTROL_OEM0; -const CONTROL_OUT_CL = CONTROL_OEME | CONTROL_OEM2 | CONTROL_OEM1; -const CONTROL_OUT_CH = CONTROL_OEME | CONTROL_OEM2 | CONTROL_OEM1 | CONTROL_OEM0; -const CONTROL_OUT_DL = CONTROL_OEME | CONTROL_OEM3; -const CONTROL_OUT_DH = CONTROL_OEME | CONTROL_OEM3 | CONTROL_OEM0; -const CONTROL_OUT_AB = CONTROL_OEME | CONTROL_OEM3 | CONTROL_OEM1; -const CONTROL_OUT_CA = CONTROL_OEME | CONTROL_OEM4; -const CONTROL_OUT_CD = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM1; -const CONTROL_OUT_DA = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM1 | CONTROL_OEM0; -const CONTROL_OUT_AE = CONTROL_AE; -const CONTROL_OUT_AO = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM3 | CONTROL_OEM2 | CONTROL_OEM0; -const CONTROL_OUT_RO = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM3 | CONTROL_OEM2 | CONTROL_OEM1 | CONTROL_OEM0; - -const CONTROL_ALU_ADD = CONTROL_OUT_AE; -const CONTROL_ALU_SUB = CONTROL_OUT_AE | CONTROL_ALUI | CONTROL_ALUC; -const CONTROL_ALU_NOT = CONTROL_OUT_AE | CONTROL_ALUI; -const CONTROL_ALU_AND = CONTROL_OUT_AE | CONTROL_ALUM0; -const CONTROL_ALU_NAND = CONTROL_OUT_AE | CONTROL_ALUM0 | CONTROL_ALUI; -const CONTROL_ALU_OR = CONTROL_OUT_AE | CONTROL_ALUM1; -const CONTROL_ALU_NOR = CONTROL_OUT_AE | CONTROL_ALUM1 | CONTROL_ALUI; -const CONTROL_ALU_XOR = CONTROL_OUT_AE | CONTROL_ALUM1 | CONTROL_ALUM0; -const CONTROL_ALU_XNOR = CONTROL_OUT_AE | CONTROL_ALUM1 | CONTROL_ALUM0 | CONTROL_ALUI; let Instructions = new Array(); @@ -91,8 +64,19 @@ const InstructionTypes = { toString() { return this.Name; } + }, + RegisterImmediate: { + Name: `Register Immediate`, + toString() { + return this.Name; + } + }, + RegisterAbsolute: { + Name: `Register Absolute`, + toString() { + return this.Name; + } } - }; function IsRegister(reg) { @@ -516,7 +500,7 @@ is_LDAB_a = new IS_LDAB_abs; Instructions.push(is_LDAB_a); -class IS_STAL_imm extends Microcode_Instruction { +class IS_STAL_imm24 extends Microcode_Instruction { constructor(props) { super(props); this.Bytecode = 0x030; @@ -525,15 +509,22 @@ class IS_STAL_imm extends Microcode_Instruction { this.Aliases = new Array(); this.Type = InstructionTypes.Immediate; - this.Operands = new Array({Operand: "$", Bitwidth: 8}); - this.Words = 2; - this.Cycles = 5; - this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; - this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RRI | CONTROL_PCC; - this.Microcode[4] = CONTROL_OUT_AL | CONTROL_RI; + this.Operands = new Array({Operand: "$", Bitwidth: 24}); + this.Words = 3; + this.Cycles = 11; + this.Microcode[2] = CONTROL_OUT_SP | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_HO | CONTROL_RI; + this.Microcode[4] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[5] = CONTROL_OUT_I2 | CONTROL_PCC; + this.Microcode[6] = CONTROL_OUT_2O | CONTROL_RHI | CONTROL_PCC; + this.Microcode[7] = CONTROL_RRI; + this.Microcode[8] = CONTROL_OUT_AL | CONTROL_RI; + this.Microcode[9] = CONTROL_OUT_SP | CONTROL_RRI; + this.Microcode[10] = CONTROL_OUT_RO | CONTROL_RHI; + } } -is_STAL_i = new IS_STAL_imm; +is_STAL_i = new IS_STAL_imm24; Instructions.push(is_STAL_i); class IS_STAH_imm extends Microcode_Instruction { @@ -704,7 +695,7 @@ class IS_STAB_sp extends Microcode_Instruction { this.LongName = "STORE Register A and B"; this.Aliases = new Array(); - this.Type = InstructionTypes.Register; + this.Type = InstructionTypes.RegisterAbsolute; this.Operands = new Array({Operand: "SP", Bitwidth: 16}); this.Words = 1; this.Cycles = 6; @@ -717,12 +708,12 @@ class IS_STAB_sp extends Microcode_Instruction { is_STAB_sp = new IS_STAB_sp; Instructions.push(is_STAB_sp); -class IS_STAL_sp_ind extends Microcode_Instruction { +class IS_PSTAL_sp_ind extends Microcode_Instruction { constructor(props) { super(props); this.Bytecode = 0x03A; - this.Mnemonic = "STAL"; - this.LongName = "STORE Register A to LOW Byte"; + this.Mnemonic = "PSTAL"; + this.LongName = "Page STORE Register A to LOW Byte"; this.Aliases = new Array(); this.Type = InstructionTypes.Indirect; @@ -735,7 +726,55 @@ class IS_STAL_sp_ind extends Microcode_Instruction { this.Microcode[5] = CONTROL_OUT_AL | CONTROL_RI; } } -is_STAL_spin = new IS_STAL_sp_ind; +is_PSTAL_spin = new IS_PSTAL_sp_ind; +Instructions.push(is_PSTAL_spin); + +class IS_PSTAL_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x03B; + this.Mnemonic = "PSTAL"; + this.LongName = "Page STORE Register A to LOW Byte"; + this.Aliases = new Array(); + + this.Type = InstructionTypes.Immediate; + this.Operands = new Array({Operand: "$", Bitwidth: 8}); + this.Words = 2; + this.Cycles = 5; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RRI | CONTROL_PCC; + this.Microcode[4] = CONTROL_OUT_AL | CONTROL_RI; + } +} +is_PSTAL_i = new IS_PSTAL_imm; +Instructions.push(is_PSTAL_i); + +class IS_STAL_sp_ind24 extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x03C; + this.Mnemonic = "STAL"; + this.LongName = "STORE Register A to LOW Byte"; + this.Aliases = new Array(); + + this.Type = InstructionTypes.Indirect; + this.Operands = new Array({Operand: "[SP]", Bitwidth: 16}); + this.Words = 1; + this.Cycles = 12; + this.Microcode[2] = CONTROL_OUT_SP | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_HO | CONTROL_RI | CONTROL_SPC; + this.Microcode[4] = CONTROL_SPC; + this.Microcode[5] = CONTROL_OUT_SP | CONTROL_RRI; + this.Microcode[6] = CONTROL_OUT_RO | CONTROL_RHI | CONTROL_SPD | CONTROL_SPC; + this.Microcode[7] = CONTROL_OUT_SP | CONTROL_RRI; + this.Microcode[8] = CONTROL_OUT_RO | CONTROL_RRI | CONTROL_SPD | CONTROL_SPC; + this.Microcode[9] = CONTROL_OUT_AL | CONTROL_RI; + this.Microcode[10] = CONTROL_OUT_SP | CONTROL_RRI; + this.Microcode[11] = CONTROL_OUT_RO | CONTROL_RHI; + //this.Microcode[12] = 0; + } +} +is_STAL_spin = new IS_STAL_sp_ind24; Instructions.push(is_STAL_spin); @@ -1694,6 +1733,32 @@ class IS_JSR extends Microcode_Instruction { this.LongName = "JUMP to Subroutine"; this.Aliases = new Array(); + this.Type = InstructionTypes.Immediate; + this.Operands = new Array({Operand: "$", Bitwidth: 24}); + this.Words = 3; + this.Cycles = 11; + this.Microcode[2] = CONTROL_OUT_SP | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_PC | CONTROL_RI | CONTROL_SPD | CONTROL_SPC; + this.Microcode[4] = CONTROL_OUT_SP | CONTROL_RRI; + this.Microcode[5] = CONTROL_OUT_HO | CONTROL_RI | CONTROL_SPD | CONTROL_SPC; + this.Microcode[6] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[7] = CONTROL_OUT_I2 | CONTROL_PCC; + this.Microcode[8] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[9] = CONTROL_OUT_RO | CONTROL_PCI; + this.Microcode[10] = CONTROL_OUT_2O | CONTROL_RHI; + } +} +is_JSR = new IS_JSR; +Instructions.push(is_JSR); + +class IS_PJSR extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x206; + this.Mnemonic = "PJSR"; + this.LongName = "Page JUMP to Subroutine"; + this.Aliases = new Array(); + this.Type = InstructionTypes.Immediate; this.Operands = new Array({Operand: "$", Bitwidth: 16}); this.Words = 2; @@ -1705,17 +1770,41 @@ class IS_JSR extends Microcode_Instruction { } } -is_JSR = new IS_JSR; -Instructions.push(is_JSR); +is_PJSR = new IS_PJSR; +Instructions.push(is_PJSR); class IS_RTS extends Microcode_Instruction { constructor(props) { super(props); - this.Bytecode = 0x206; + this.Bytecode = 0x207; this.Mnemonic = "RTS"; this.LongName = "RETURN from Subroutine"; this.Aliases = new Array(); + this.Type = InstructionTypes.SingleWord; + this.Operands = new Array(); + 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_RTS = new IS_RTS; +Instructions.push(is_RTS); + +class IS_PRTS extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x208; + this.Mnemonic = "PRTS"; + this.LongName = "Page RETURN from Subroutine"; + this.Aliases = new Array(); + this.Type = InstructionTypes.SingleWord; this.Operands = new Array(); this.Words = 1; @@ -1726,8 +1815,49 @@ class IS_RTS extends Microcode_Instruction { this.Microcode[5] = CONTROL_PCC; } } -is_RTS = new IS_RTS; -Instructions.push(is_RTS); +is_PRTS = new IS_PRTS; +Instructions.push(is_PRTS); + +class IS_JMP_imm24 extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x209; + this.Mnemonic = "JMP"; + this.LongName = "JUMP to address"; + this.Aliases = new Array(); + + this.Type = InstructionTypes.Immediate; + this.Operands = new Array({Operand: "$", Bitwidth: 24}); + this.Words = 3; + this.Cycles = 7; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_I2 | CONTROL_PCC; + this.Microcode[4] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[5] = CONTROL_OUT_RO | CONTROL_PCI; + this.Microcode[6] = CONTROL_OUT_2O | CONTROL_RHI; + } +} +is_JMP_i24 = new IS_JMP_imm24; +Instructions.push(is_JMP_i24); + +class IS_LDSPP_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x20A; + this.Mnemonic = "LDSPP"; + this.LongName = "LOAD Stack Pointer Page"; + this.Aliases = new Array(); + + this.Type = InstructionTypes.Register; + this.Operands = new Array({Operand: "$", Bitwidth: 8}); + this.Words = 2; + this.Cycles = 4; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_HS | CONTROL_PCC; + } +} +is_LDSPP_i = new IS_LDSPP_imm; +Instructions.push(is_LDSPP_i);