diff --git a/index.html b/index.html index 57c04fa..285f007 100644 --- a/index.html +++ b/index.html @@ -2,8 +2,53 @@ MatCat's 8SA1 CPU Simulator - - + +
+ ADDRESS: +
+
+ DATA: +
+
+ PC: +
+
+ MCC: +
+
+ CO: +
+
+ SP: +
+
+ SR: +
+
+ IR: +
+
+ GPA: +
+
+ GPB: +
+
+ GPC: +
+
+ GPD: +
+
+ + 0 +
+
+ RAM:
+
+ + + \ No newline at end of file diff --git a/js/cpu.js b/js/cpu.js new file mode 100644 index 0000000..37702b6 --- /dev/null +++ b/js/cpu.js @@ -0,0 +1,525 @@ +function formatHex(value,places) { + let hexval = parseInt(value,10).toString(16).toUpperCase(); + if (hexval.length < places) { + let placecount = (places - hexval.length); + for (let a = 0; a < placecount; a++) { + hexval = "0" + hexval; + } + } + return hexval; +} + +function GetMnemonic(mcarray,instruction) { + for (let a = 0; a < mcarray.length; a++) { + if (mcarray[a] === instruction || mcarray[a].Bytecode === instruction) { + return mcarray[a].Mnemonic; + } + } +} + +function generateClocks(clk_cnt) { + for (let a = 0; a < clk_cnt; a++) { + cpu.CLOCK(true); + updateHTML(); + cpu.CLOCK(false); + updateHTML(); + } +} + +function printRAM(ram) { + let sp_ram = document.getElementById("RAM"); + let ramtext = "ADDR  :   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
"; + for (let a = 0; a < 16; a++) { + ramtext += "0x" + formatHex(a*16,4) + ": "; + for (let b = 0; b < 16; b++) { + if (cpu.ADDRBUS === (a*16)+b) ramtext += ''; + ramtext += formatHex(ram[(a*16)+b],4) + " "; + if (cpu.ADDRBUS === (a*16)+b) ramtext += ''; + } + ramtext += "
"; + } + sp_ram.innerHTML = ramtext; +} + +function updateHTML() { + let sp_addr = document.getElementById("Address_BUS"); + sp_addr.innerText = "0x" + cpu.ADDRBUS.toString(16).toUpperCase(); + let sp_data = document.getElementById("Data_BUS"); + sp_data.innerText = "0x" + cpu.DATABUS.toString(16).toUpperCase(); + let sp_pc = document.getElementById("PC_Register"); + sp_pc.innerText = "0x" + cpu.PC.toString(16).toUpperCase(); + let sp_mcc = document.getElementById("MCC_Register"); + sp_mcc.innerText = "0x" + cpu.MCC.toString(16).toUpperCase(); + let sp_co = document.getElementById("CO_Register"); + sp_co.innerText = "0b" + cpu.MC_Controls.toString(2); + let sp_sp = document.getElementById("SP_Register"); + sp_sp.innerText = "0x" + cpu.SP.toString(16).toUpperCase(); + let sp_sr = document.getElementById("SR_Register"); + sp_sr.innerText = "0b" + cpu.SR.toString(2); + let sp_ir = document.getElementById("IR_Register"); + sp_ir.innerText = "0b" + cpu.IR.toString(2) + " (" + GetMnemonic(Instructions,cpu.IR) + ")"; + let sp_gpa = document.getElementById("GPA_Register"); + sp_gpa.innerText = "0x" + cpu.GPA.toString(16).toUpperCase(); + let sp_gpb = document.getElementById("GPB_Register"); + sp_gpb.innerText = "0x" + cpu.GPB.toString(16).toUpperCase(); + let sp_gpc = document.getElementById("GPC_Register"); + sp_gpc.innerText = "0x" + cpu.GPC.toString(16).toUpperCase(); + let sp_gpd = document.getElementById("GPD_Register"); + sp_gpd.innerText = "0x" + cpu.GPD.toString(16).toUpperCase(); + printRAM(cpu.RAM); +} +// Setup a few bitmasks we can use in the code that are handy to clean inputs to registers +const BITMASK_8 = 0x00000000000000ff; +const BITMASK_16 = 0x000000000000ffff; +const BITMASK_24 = 0x0000000000ffffff; + + + +// These are the control lines that are controlled by the microcode RAM output +const CONTROL_PCC = 0b00000000000000000000000000000001; // PC CLK UP +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_RI = 0b00010000000000000000000000000000; // RAM Input Enable +const CONTROL_IRI = 0b00100000000000000000000000000000; // Instruction Register Input Enable +const CONTROL_MCL0 = 0b01000000000000000000000000000000; // Microcode Counter to 0 +const CONTROL_MCL8 = 0b10000000000000000000000000000000; // Microcode Counter to 8 + +// These are the output enable control lines, they are muxed since none of them can ever be on together +const OECONTROL_PC = 0b00000 // PC Register +const OECONTROL_SP = 0b00001 // SP Register +const OECONTROL_AL = 0b00010 // GPA to LOW +const OECONTROL_AH = 0b00011 // GPA to HIGH +const OECONTROL_BL = 0b00100 // GPB to LOW +const OECONTROL_BH = 0b00101 // GPB to HIGH +const OECONTROL_CL = 0b00110 // GPC to LOW +const OECONTROL_CH = 0b00111 // GPC to HIGH +const OECONTROL_DL = 0b01000 // GPD to LOW +const OECONTROL_DH = 0b01001 // GPD to HIGH +const OECONTROL_AB = 0b01010 // GPB to HIGH, GPA to LOW +const OECONTROL_AC = 0b01011 // GPC to HIGH, GPA to LOW +const OECONTROL_AD = 0b01100 // GPD to HIGH, GPA to LOW +const OECONTROL_BA = 0b01101 // GPA to HIGH, GPB to LOW +const OECONTROL_BC = 0b01110 // GPC to HIGH, GPB to LOW +const OECONTROL_BD = 0b01111 // GPD to HIGH, GPB to LOW +const OECONTROL_CA = 0b10000 // GPA to HIGH, GPC to LOW +const OECONTROL_CB = 0b10001 // GPB to HIGH, GPC to LOW +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_AE = 0b11100 // ALU Enable +const OECONTROL_AO = 0b11101 // ALU Output to LOW +const OECONTROL_SR = 0b11110 // Status Register to LOW +const OECONTROL_RO = 0b11111 // RAM to DATABUS Enable + + +class CPU_8SA1 { + constructor() { + this.DATABUS = 0; + this.ADDRBUS = 0; + + this.PC = 0; // Set PC register to 0 + this.SP = BITMASK_16; // Set SP register to 0xFFFF + this.SR = 0; // Set the STATUS register + + this.RR = 0; // Set lower RAM register to 0 + this.RH = 0; // Set higher RAM register to 0 + + this.GPA = 0; // Set the 4 GP registers + this.GPB = 0; + this.GPC = 0; + this.GPD = 0; + + this.MCC = 0xF; // Set the microcode counter + this.IR = 0; // Set the initial IR + this.MC_Controls = 0; // Set the control output lines + + this.ALUSUM = 0; // ALU Register to hold SUM + + this.MCRAM = new Array(2 ** 16); // Initialize the microcode RAM + + this.RAM = new Array(2 ** 24); // Initialize the main RAM array + let RAMSIZE = 2**24; + while(RAMSIZE--) this.RAM[RAMSIZE] = 0; + + this._CLK = false; + + } + + CLOCK(clk_val) { + if (clk_val && !this._CLK) { + // Clock going HIGH + this._CLK = true; + this._CLOCK_HIGH(); + } else { + if (!clk_val && this._CLK) { + // Clock going LOW + this._CLK = false; + this._CLOCK_LOW(); + } + + } + } + _CLOCK_HIGH() { + // Call anything that needs to be called on positive clock edge + if (this.MC_Controls & CONTROL_OEME) { + let 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 (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(); + if (this.MC_Controls & CONTROL_SPI ) this.SP_In_CLK(); + if (this.MC_Controls & CONTROL_RI ) this.RAM_In_CLK(); + 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 (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(); + if (this.MC_Controls & CONTROL_RBIH) this.GPB_In_HIGH_CLK(); + if (this.MC_Controls & CONTROL_RCIL) this.GPC_In_LOW_CLK(); + if (this.MC_Controls & CONTROL_RCIH) this.GPC_In_HIGH_CLK(); + if (this.MC_Controls & CONTROL_RDIL) this.GPD_In_LOW_CLK(); + if (this.MC_Controls & CONTROL_RDIH) this.GPD_In_HIGH_CLK(); + + } + + _CLOCK_LOW() { + // Call anything that needs to be called on low going clock edge + this._FetchDecode_CLK_neg(); + } + + _FetchDecode_CLK_neg() { + // We actually setup all of our fetch and decode logic during the clocks low phase + this.DATABUS = 0; + this.MCC += 1; + if (this.MCC > 15) this.MCC = 0; + let mcra = ((this.IR & 0b0000001111111111) << 4) | this.MCC | ((this.SR & 0b00000011) << 15); + let MC_Controls = this.MCRAM[mcra]; + if (MC_Controls & CONTROL_MCL0) this.MCC = 0; + if (MC_Controls & CONTROL_MCL8) this.MCC = 8; + 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) << 15); + MC_Controls = this.MCRAM[mcra]; + + console.log(`[${mcra.toString(2)}] Control Lines: ${MC_Controls.toString(2)}`); + if (MC_Controls !== this.MC_Controls) { + if (MC_Controls & CONTROL_OEME) { + // Set the DATABUS based on whatever output we are controlling + let OUTMUX = (MC_Controls & CONTROL_OEM4) ? 0b10000 : 0; + OUTMUX |= (MC_Controls & CONTROL_OEM3) ? 0b01000 : 0; + OUTMUX |= (MC_Controls & CONTROL_OEM2) ? 0b00100 : 0; + OUTMUX |= (MC_Controls & CONTROL_OEM1) ? 0b00010 : 0; + OUTMUX |= (MC_Controls & CONTROL_OEM0) ? 0b00001 : 0; + + console.log(`OUTPUT MUX: ${OUTMUX.toString(2)}`); + switch (OUTMUX) { + case OECONTROL_PC: { + this.DATABUS = this.PC; + console.log("DATABUS = PC"); + break; + } + case OECONTROL_SP: { + this.DATABUS = this.SP; + console.log("DATABUS = SP"); + break; + } + case OECONTROL_AL: { + this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.GPA & BITMASK_8); + console.log("DATABUS LOW = A"); + break; + } + case OECONTROL_AH: { + this.DATABUS = ((this.GPA & BITMASK_8) << 8) | (this.DATABUS & BITMASK_8); + console.log("DATABUS HIGH = A"); + break; + } + case OECONTROL_BL: { + this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.GPB & BITMASK_8); + console.log("DATABUS LOW = B"); + break; + } + case OECONTROL_BH: { + this.DATABUS = ((this.GPB & BITMASK_8) << 8) | (this.DATABUS & BITMASK_8); + console.log("DATABUS HIGH = B"); + break; + } + case OECONTROL_CL: { + this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.GPC & BITMASK_8); + console.log("DATABUS LOW = C"); + break; + } + case OECONTROL_CH: { + this.DATABUS = ((this.GPC & BITMASK_8) << 8) | (this.DATABUS & BITMASK_8); + console.log("DATABUS HIGH = C"); + break; + } + case OECONTROL_DL: { + this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.GPD & BITMASK_8); + break; + } + case OECONTROL_DH: { + this.DATABUS = ((this.GPD & BITMASK_8) << 8) | (this.DATABUS & BITMASK_8); + break; + } + case OECONTROL_AB: { + this.DATABUS = ((this.GPB & BITMASK_8) << 8) | (this.GPA & BITMASK_8); + console.log("DATABUS = AB"); + break; + } + case OECONTROL_AC: { + this.DATABUS = ((this.GPC & BITMASK_8) << 8) | (this.GPA & BITMASK_8); + break; + } + case OECONTROL_AD: { + this.DATABUS = ((this.GPD & BITMASK_8) << 8) | (this.GPA & BITMASK_8); + break; + } + case OECONTROL_BA: { + this.DATABUS = ((this.GPA & BITMASK_8) << 8) | (this.GPB & BITMASK_8); + break; + } + case OECONTROL_BC: { + this.DATABUS = ((this.GPC & BITMASK_8) << 8) | (this.GPB & BITMASK_8); + break; + } + case OECONTROL_BD: { + this.DATABUS = ((this.GPD & BITMASK_8) << 8) | (this.GPB & BITMASK_8); + break; + } + case OECONTROL_CA: { + this.DATABUS = ((this.GPA & BITMASK_8) << 8) | (this.GPC & BITMASK_8); + break; + } + case OECONTROL_CB: { + this.DATABUS = ((this.GPB & BITMASK_8) << 8) | (this.GPC & BITMASK_8); + break; + } + case OECONTROL_CD: { + this.DATABUS = ((this.GPD & BITMASK_8) << 8) | (this.GPC & BITMASK_8); + break; + } + case OECONTROL_DA: { + this.DATABUS = ((this.GPA & BITMASK_8) << 8) | (this.GPD & BITMASK_8); + break; + } + case OECONTROL_DB: { + this.DATABUS = ((this.GPB & BITMASK_8) << 8) | (this.GPD & BITMASK_8); + break; + } + case OECONTROL_DC: { + this.DATABUS = ((this.GPC & BITMASK_8) << 8) | (this.GPD & BITMASK_8); + break; + } + case OECONTROL_AE: { + console.log("ALU Enable"); + this.DATABUS = (this.GPB << 8) | this.GPA; + let ALU_A = this.DATABUS & BITMASK_8; + let ALU_B = (this.DATABUS & (BITMASK_8 << 8)) >> 8; + let ALU_Result = 0; + + let ALUMUX = (MC_Controls & CONTROL_ALUM1) ? 0b10 : 0; + ALUMUX |= (MC_Controls & CONTROL_ALUM0) ? 0b01 : 0; + + console.log(`ALU: A=${ALU_A}, B=${ALU_B}, MUX: ${ALUMUX}`); + if (MC_Controls & CONTROL_ALUI) console.log("ALU Inverting B"); + let SHIFTING = false; + if (MC_Controls & CONTROL_ALUSL) SHIFTING = true; + if (MC_Controls & CONTROL_ALUSR) SHIFTING = true; + + switch (ALUMUX) { + case 0: { // ADD + if (MC_Controls & CONTROL_ALUI) ALU_B = ~ALU_B; + ALU_Result = ALU_A + ALU_B; + + if (MC_Controls & CONTROL_ALUC && !SHIFTING) ALU_Result += 1; + break; + } + case 1: { // AND + ALU_Result = ALU_A & ALU_B; + if (MC_Controls & CONTROL_ALUI) ALU_Result = ~ALU_Result; + if (MC_Controls & CONTROL_ALUC && !SHIFTING) ALU_Result += 1; + break; + } + case 2: { // OR + ALU_Result = ALU_A | ALU_B; + if (MC_Controls & CONTROL_ALUI) ALU_Result = ~ALU_Result; + if (MC_Controls & CONTROL_ALUC && !SHIFTING) ALU_Result += 1; + break; + } + case 3: { // XOR + ALU_Result = ALU_A ^ ALU_B; + if (MC_Controls & CONTROL_ALUI) ALU_Result = ~ALU_Result; + if (MC_Controls & CONTROL_ALUC && !SHIFTING) ALU_Result += 1; + break; + } + } + + if (MC_Controls & CONTROL_ALUSL) ALU_Result = ALU_Result << 1; + if ((MC_Controls & CONTROL_ALUSL) && (MC_Controls & CONTROL_ALUC)) ALU_Result = ALU_Result | 0b00000001; + if (MC_Controls & CONTROL_ALUSR) ALU_Result = ALU_Result >> 1; + if ((MC_Controls & CONTROL_ALUSR) && (MC_Controls & CONTROL_ALUC)) ALU_Result = ALU_Result | 0b10000000; + + if (ALU_Result & 0b100000000) { + // We have a carry + this.SR = this.SR | 0b00000001; + } else { + this.SR = this.SR & 0b11111110; + } + + if (ALU_Result === 0) { + // We have a ZERO + this.SR = this.SR | 0b00000010; + } else { + this.SR = this.SR & 0b11111101; + } + + this.ALUSUM = ALU_Result & BITMASK_8; + break; + } + case OECONTROL_AO: { + this.DATABUS = (this.DATABUS & (BITMASK_8 << 8)) | this.ALUSUM; + console.log("DATABUS = SUM"); + break; + } + case OECONTROL_SR: { + this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.SR & BITMASK_8); + console.log("DATABUS = STATUS REGISTER"); + break; + } + case OECONTROL_RO: { + // We dont actually want to do anything here since ram outputs on CLK + console.log("DATABUS = RAM (on CLK)"); + break; + } + } + } + } + this.MC_Controls = MC_Controls; + } + + _FetchDecode_CLK_pos() { + + } + + PC_CLK() { + this.PC += 1; + if (this.PC > BITMASK_16) this.PC = 0; + } + + PC_In_CLK() { + this.PC = this.DATABUS; + } + + SP_CLK() { + if (this.MC_Controls & CONTROL_SPD) { + this.SP -= 1; + if (this.SP < 0) this.SP = BITMASK_16; + } else { + this.SP += 1; + if (this.SP > BITMASK_16) this.SP = 0; + } + } + + SP_In_CLK() { + this.SP = this.DATABUS; + } + + RAM_In_CLK() { + this.RAM[this.ADDRBUS] = this.DATABUS; + } + + IR_In_CLK() { + this.IR = this.DATABUS; + } + + RR_In_CLK() { + this.RR = this.DATABUS; + this.ADDRBUS = this.RR | this.RH << 16; + } + + RH_In_CLK() { + this.RH = this.DATABUS; + this.ADDRBUS = this.RR | this.RH << 16; + } + + GPA_In_LOW_CLK() { + this.GPA = this.DATABUS & 0x00ff; + console.log(`GPA = DATABUS LOW`); + } + + GPA_In_HIGH_CLK() { + this.GPA = (this.DATABUS & 0xff00) >> 8; + console.log(`GPA = DATABUS HIGH`); + } + + GPB_In_LOW_CLK() { + this.GPB = this.DATABUS & 0x00ff; + console.log(`GPB = DATABUS LOW`); + } + + GPB_In_HIGH_CLK() { + this.GPB = (this.DATABUS & 0xff00) >> 8; + console.log(`GPB = DATABUS HIGH`); + } + + GPC_In_LOW_CLK() { + this.GPC = this.DATABUS & 0x00ff; + console.log(`GPC = DATABUS LOW`); + } + + GPC_In_HIGH_CLK() { + this.GPC = (this.DATABUS & 0xff00) >> 8; + console.log(`GPC = DATABUS HIGH`); + } + + GPD_In_LOW_CLK() { + this.GPD = this.DATABUS & 0x00ff; + } + + GPD_In_HIGH_CLK() { + this.GPD = (this.DATABUS & 0xff00) >> 8; + } + + + PrintDebug() { + // We want to print out all the registers in a way that makes sense + } +} + diff --git a/js/main.js b/js/main.js index 31691e7..989abb4 100644 --- a/js/main.js +++ b/js/main.js @@ -1,417 +1,31 @@ -// Setup a few bitmasks we can use in the code that are handy to clean inputs to registers -const BITMASK_8 = 0x00000000000000ff; -const BITMASK_16 = 0x000000000000ffff; -const BITMASK_24 = 0x0000000000ffffff; +let cpu = new CPU_8SA1(); +GenerateMicrocode(Instructions,cpu); +cpu.RAM[0] = is_LDA_i.Bytecode; +cpu.RAM[1] = 0; +cpu.RAM[2] = is_LDB_i.Bytecode; +cpu.RAM[3] = 100; +cpu.RAM[4] = is_ADD.Bytecode; +cpu.RAM[5] = is_BCC_i.Bytecode; +cpu.RAM[6] = 4; +cpu.RAM[7] = is_LDD_i.Bytecode; +cpu.RAM[8] = 69; +cpu.RAM[9] = is_STDL_i.Bytecode; +cpu.RAM[10] = 0x69; -// These are the control lines that are controlled by the microcode RAM output -const CONTROL_PCC = 0b00000000000000000000000000000001; // PC CLK UP -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_RI = 0b00010000000000000000000000000000; // RAM Input Enable -const CONTROL_IRI = 0b00100000000000000000000000000000; // Instruction Register Input Enable -const CONTROL_MCL0 = 0b01000000000000000000000000000000; // Microcode Counter to 0 -const CONTROL_MCL8 = 0b1000000000000000000000000000000; // Microcode Counter to 8 +updateHTML(); -// These are the output enable control lines, they are muxed since none of them can ever be on together -const OECONTROL_PC = 0b00000 // PC Register -const OECONTROL_SP = 0b00001 // SP Register -const OECONTROL_AL = 0b00010 // GPA to LOW -const OECONTROL_AH = 0b00011 // GPA to HIGH -const OECONTROL_BL = 0b00100 // GPB to LOW -const OECONTROL_BH = 0b00101 // GPB to HIGH -const OECONTROL_CL = 0b00110 // GPC to LOW -const OECONTROL_CH = 0b00111 // GPC to HIGH -const OECONTROL_DL = 0b01000 // GPD to LOW -const OECONTROL_DH = 0b01001 // GPD to HIGH -const OECONTROL_AB = 0b01010 // GPB to HIGH, GPA to LOW -const OECONTROL_AC = 0b01011 // GPC to HIGH, GPA to LOW -const OECONTROL_AD = 0b01100 // GPD to HIGH, GPA to LOW -const OECONTROL_BA = 0b01101 // GPA to HIGH, GPB to LOW -const OECONTROL_BC = 0b01110 // GPC to HIGH, GPB to LOW -const OECONTROL_BD = 0b01111 // GPD to HIGH, GPB to LOW -const OECONTROL_CA = 0b10000 // GPA to HIGH, GPC to LOW -const OECONTROL_CB = 0b10001 // GPB to HIGH, GPC to LOW -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_AE = 0b11100 // ALU Enable -const OECONTROL_AO = 0b11101 // ALU Output to LOW -const OECONTROL_SR = 0b11110 // Status Register to LOW -const OECONTROL_RO = 0b11111 // RAM to DATABUS Enable +let btn_clk = document.getElementById("btn_clk"); +let clk_counter = document.getElementById("clk_counter"); +let clk_count = 0; +btn_clk.addEventListener('mousedown', function(evt) { + cpu.CLOCK(true); + clk_count++; + clk_counter.innerText = clk_count; + updateHTML(); +}); -class CPU_8SA1 { - constructor() { - this.DATABUS = 0; - this.ADDRBUS = 0; - - this.PC = 0; // Set PC register to 0 - this.SP = BITMASK_16; // Set SP register to 0xFFFF - this.SR = 0; // Set the STATUS register - - this.RR = 0; // Set lower RAM register to 0 - this.RH = 0; // Set higher RAM register to 0 - - this.GPA = 0; // Set the 4 GP registers - this.GPB = 0; - this.GPC = 0; - this.GPD = 0; - - this.MCC = 0; // Set the microcode counter - this.IR = 0; // Set the initial IR - this.MC_Controls = 0; // Set the control output lines - - this.ALUSUM = 0; // ALU Register to hold SUM - - this.MCRAM = new Array(2 ** 16); // Initialize the microcode RAM - - this.RAM = new Array(2 ** 24); // Initialize the main RAM array - - this._CLK = false; - - } - - CLOCK(clk_val) { - if (clk_val && !this._CLK) { - // Clock going HIGH - this._CLK = true; - this._CLOCK_HIGH(); - } else { - if (!clk_val && this._CLK) { - // Clock going LOW - this._CLK = false; - this._CLOCK_LOW(); - } - - } - } - _CLOCK_HIGH() { - // Call anything that needs to be called on positive clock edge - if (this.MC_Controls & CONTROL_OEME) { - let 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) this.DATABUS = this.RAM[this.ADDRBUS]; - } - - 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(); - if (this.MC_Controls & CONTROL_SPI ) this.SP_In_CLK(); - if (this.MC_Controls & CONTROL_RI ) this.RAM_In_CLK(); - 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 (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(); - if (this.MC_Controls & CONTROL_RBIH) this.GPB_In_HIGH_CLK(); - if (this.MC_Controls & CONTROL_RCIL) this.GPC_In_LOW_CLK(); - if (this.MC_Controls & CONTROL_RCIH) this.GPC_In_HIGH_CLK(); - if (this.MC_Controls & CONTROL_RDIL) this.GPD_In_LOW_CLK(); - if (this.MC_Controls & CONTROL_RDIH) this.GPD_In_HIGH_CLK(); - - } - - _CLOCK_LOW() { - // Call anything that needs to be called on low going clock edge - this._FetchDecode_CLK_neg(); - } - - _FetchDecode_CLK_neg() { - // We actually setup all of our fetch and decode logic during the clocks low phase - this.DATABUS = 0; - this.MCC += 1; - let MC_Controls = this.MCRAM[((this.IR & 0b0000001111111111) << 4) | this.MCC | ((this.SR & 0b00000011) << 14)]; - if (MC_Controls & CONTROL_MCL0) this.MCC = 0; - if (MC_Controls & CONTROL_MCL8) this.MCC = 8; - - if (MC_Controls !== this.MC_Controls) { - if (this.MC_Controls & CONTROL_OEME) { - // Set the DATABUS based on whatever output we are controlling - let 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; - - switch (OUTMUX) { - case OECONTROL_PC: { - this.DATABUS = this.PC; - break; - } - case OECONTROL_SP: { - this.DATABUS = this.SP; - break; - } - case OECONTROL_AL: { - this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.GPA & BITMASK_8); - break; - } - case OECONTROL_AH: { - this.DATABUS = ((this.GPA & BITMASK_8) << 8) | (this.DATABUS & BITMASK_8); - break; - } - case OECONTROL_BL: { - this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.GPB & BITMASK_8); - break; - } - case OECONTROL_BH: { - this.DATABUS = ((this.GPB & BITMASK_8) << 8) | (this.DATABUS & BITMASK_8); - break; - } - case OECONTROL_CL: { - this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.GPC & BITMASK_8); - break; - } - case OECONTROL_CH: { - this.DATABUS = ((this.GPC & BITMASK_8) << 8) | (this.DATABUS & BITMASK_8); - break; - } - case OECONTROL_DL: { - this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.GPD & BITMASK_8); - break; - } - case OECONTROL_DH: { - this.DATABUS = ((this.GPD & BITMASK_8) << 8) | (this.DATABUS & BITMASK_8); - break; - } - case OECONTROL_AB: { - this.DATABUS = ((this.GPB & BITMASK_8) << 8) | (this.GPA & BITMASK_8); - break; - } - case OECONTROL_AC: { - this.DATABUS = ((this.GPC & BITMASK_8) << 8) | (this.GPA & BITMASK_8); - break; - } - case OECONTROL_AD: { - this.DATABUS = ((this.GPD & BITMASK_8) << 8) | (this.GPA & BITMASK_8); - break; - } - case OECONTROL_BA: { - this.DATABUS = ((this.GPA & BITMASK_8) << 8) | (this.GPB & BITMASK_8); - break; - } - case OECONTROL_BC: { - this.DATABUS = ((this.GPC & BITMASK_8) << 8) | (this.GPB & BITMASK_8); - break; - } - case OECONTROL_BD: { - this.DATABUS = ((this.GPD & BITMASK_8) << 8) | (this.GPB & BITMASK_8); - break; - } - case OECONTROL_CA: { - this.DATABUS = ((this.GPA & BITMASK_8) << 8) | (this.GPC & BITMASK_8); - break; - } - case OECONTROL_CB: { - this.DATABUS = ((this.GPB & BITMASK_8) << 8) | (this.GPC & BITMASK_8); - break; - } - case OECONTROL_CD: { - this.DATABUS = ((this.GPD & BITMASK_8) << 8) | (this.GPC & BITMASK_8); - break; - } - case OECONTROL_DA: { - this.DATABUS = ((this.GPA & BITMASK_8) << 8) | (this.GPD & BITMASK_8); - break; - } - case OECONTROL_DB: { - this.DATABUS = ((this.GPB & BITMASK_8) << 8) | (this.GPD & BITMASK_8); - break; - } - case OECONTROL_DC: { - this.DATABUS = ((this.GPC & BITMASK_8) << 8) | (this.GPD & BITMASK_8); - break; - } - case OECONTROL_AE: { - this.DATABUS = (this.GPB >> 8) | this.GPA; - let ALU_A = this.DATABUS & BITMASK_8; - let ALU_B = (this.DATABUS & (BITMASK_8 << 8)) >> 8; - let ALU_Result = 0; - - let ALUMUX = (MC_Controls & CONTROL_ALUM1) ? 0b10 : 0; - ALUMUX |= (MC_Controls & CONTROL_ALUM0) ? 0b01 : 0; - - let SHIFTING = false; - if (MC_Controls & CONTROL_ALUSL) SHIFTING = true; - if (MC_Controls & CONTROL_ALUSR) SHIFTING = true; - - switch (ALUMUX) { - case 0: { // ADD - if (CONTROL_ALUI) ALU_B = ~ALU_B; - ALU_Result = ALU_A + ALU_B; - - if (MC_Controls & CONTROL_ALUC && !SHIFTING) ALU_Result += 1; - break; - } - case 1: { // AND - ALU_Result = ALU_A & ALU_B; - if (CONTROL_ALUI) ALU_Result = ~ALU_Result; - if (MC_Controls & CONTROL_ALUC && !SHIFTING) ALU_Result += 1; - break; - } - case 2: { // OR - ALU_Result = ALU_A | ALU_B; - if (CONTROL_ALUI) ALU_Result = ~ALU_Result; - if (MC_Controls & CONTROL_ALUC && !SHIFTING) ALU_Result += 1; - break; - } - case 3: { // XOR - ALU_Result = ALU_A ^ ALU_B; - if (CONTROL_ALUI) ALU_Result = ~ALU_Result; - if (MC_Controls & CONTROL_ALUC && !SHIFTING) ALU_Result += 1; - break; - } - } - - if (MC_Controls & CONTROL_ALUSL) ALU_Result = ALU_Result << 1; - if ((MC_Controls & CONTROL_ALUSL) && (MC_Controls & CONTROL_ALUC)) ALU_Result = ALU_Result | 0b00000001; - if (MC_Controls & CONTROL_ALUSR) ALU_Result = ALU_Result >> 1; - if ((MC_Controls & CONTROL_ALUSR) && (MC_Controls & CONTROL_ALUC)) ALU_Result = ALU_Result | 0b10000000; - - if (ALU_Result & 0b100000000) { - // We have a carry - this.SR = this.SR | 0b00000001; - } else { - this.SR = this.SR & 0b11111110; - } - - if (ALU_Result === 0) { - // We have a ZERO - this.SR = this.SR | 0b00000010; - } else { - this.SR = this.SR & 0b11111101; - } - - this.ALUSUM = ALU_Result & BITMASK_8; - break; - } - case OECONTROL_AO: { - this.DATABUS = (this.DATABUS & (BITMASK_8 << 8)) | this.ALUSUM; - break; - } - case OECONTROL_SR: { - this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.SR & BITMASK_8); - break; - } - case OECONTROL_RO: { - // We dont actually want to do anything here since ram outputs on CLK - break; - } - } - } - } - this.MC_Controls = MC_Controls; - } - - _FetchDecode_CLK_pos() { - - } - - PC_CLK() { - this.PC += 1; - if (this.PC > BITMASK_16) this.PC = 0; - } - - PC_In_CLK() { - this.PC = this.DATABUS; - } - - SP_CLK() { - if (this.MC_Controls & CONTROL_SPD) { - this.SP -= 1; - if (this.SP < 0) this.SP = BITMASK_16; - } else { - this.SP += 1; - if (this.SP > BITMASK_16) this.SP = 0; - } - } - - SP_In_CLK() { - this.SP = this.DATABUS; - } - - RAM_In_CLK() { - this.RAM[this.ADDRBUS] = this.DATABUS; - } - - IR_In_CLK() { - this.IR = this.DATABUS; - } - - RR_In_CLK() { - this.RR = this.DATABUS; - this.ADDRBUS = this.RR | this.RH << 16; - } - - RH_In_CLK() { - this.RH = this.DATABUS; - this.ADDRBUS = this.RR | this.RH << 16; - } - - GPA_In_LOW_CLK() { - this.GPA = this.DATABUS & 0x00ff; - } - - GPA_In_HIGH_CLK() { - this.GPA = (this.DATABUS & 0xff00) >> 8; - } - - GPB_In_LOW_CLK() { - this.GPB = this.DATABUS & 0x00ff; - } - - GPB_In_HIGH_CLK() { - this.GPB = (this.DATABUS & 0xff00) >> 8; - } - - GPC_In_LOW_CLK() { - this.GPC = this.DATABUS & 0x00ff; - } - - GPC_In_HIGH_CLK() { - this.GPC = (this.DATABUS & 0xff00) >> 8; - } - - GPD_In_LOW_CLK() { - this.GPD = this.DATABUS & 0x00ff; - } - - GPD_In_HIGH_CLK() { - this.GPD = (this.DATABUS & 0xff00) >> 8; - } - - - PrintDebug() { - // We want to print out all the registers in a way that makes sense - } -} \ No newline at end of file +btn_clk.addEventListener('mouseup', function(evt) { + cpu.CLOCK(false); + updateHTML(); +}); \ No newline at end of file diff --git a/js/microcode_compiler.js b/js/microcode_compiler.js index d582e32..4eaa360 100644 --- a/js/microcode_compiler.js +++ b/js/microcode_compiler.js @@ -33,6 +33,14 @@ const CONTROL_MCL8 = 0b10000000000000000000000000000000; // Micr */ 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_AE = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM3 | CONTROL_OEM2; const CONTROL_OUT_AO = CONTROL_OEME | CONTROL_OEM4 | CONTROL_OEM3 | CONTROL_OEM2 | CONTROL_OEM0; @@ -42,14 +50,29 @@ const CONTROL_ALU_ADD = CONTROL_OUT_AE; let Instructions = new Array(); -function GenerateMicrocode(mcarray) { +function GenerateMicrocode(mcarray,cpu) { for (let a = 0; a < mcarray.length; a++) { - for (let b = 0; b < 16; b++) { - let bytecode = mcarray[a].Bytecode; - let mca = mcarray[a].Bytecode << 4; - mca |= b; - let mcv = mcarray[a].Microcode[b]; - console.log(`[${bytecode.toString(16)}] ${mca.toString(16)}: ${mcv.toString(2)}`); + + + for (let c = 0; c < 3; c++) { + let offset = 0; + if (c === 1) offset = 0b0100000000000000; + if (c === 2) offset = 0b1000000000000000; + + if (c === 0) console.log(`Now populating no-conditional instructions...`); + if (c === 1) console.log(`Now populating conditional ZERO instructions...`); + if (c === 2) console.log(`Now populating conditional Carry instructions...`); + + for (let b = 0; b < 16; b++) { + let bytecode = mcarray[a].Bytecode; + let mca = mcarray[a].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]; + cpu.MCRAM[offset + mca] = mcv; + //console.log(`[${bytecode.toString(16)}] ${mca.toString(16)}: ${mcv.toString(2)}`); + } } } } @@ -58,6 +81,7 @@ function GenerateMicrocode(mcarray) { class Microcode_Instruction { constructor() { this.Bytecode = 0x000; // MAX IS 0x3ff + this.Mnemonic = "NOP"; this.Microcode = new Array(16); this.UsesCarry = false; @@ -71,11 +95,11 @@ class Microcode_Instruction { } } - class IS_LDA_imm extends Microcode_Instruction { constructor(props) { super(props); this.Bytecode = 0x000; + this.Mnemonic = "LDA"; this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RAIL | CONTROL_PCC; } @@ -87,6 +111,7 @@ class IS_LDB_imm extends Microcode_Instruction { constructor(props) { super(props); this.Bytecode = 0x001; + this.Mnemonic = "LDB"; this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RBIL | CONTROL_PCC; } @@ -98,6 +123,7 @@ class IS_LDC_imm extends Microcode_Instruction { constructor(props) { super(props); this.Bytecode = 0x002; + this.Mnemonic = "LDC"; this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RCIL | CONTROL_PCC; } @@ -109,6 +135,7 @@ class IS_LDD_imm extends Microcode_Instruction { constructor(props) { super(props); this.Bytecode = 0x003; + this.Mnemonic = "LDD"; this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RDIL | CONTROL_PCC; } @@ -116,11 +143,117 @@ class IS_LDD_imm extends Microcode_Instruction { is_LDD_i = new IS_LDD_imm; Instructions.push(is_LDD_i); +class IS_STAL_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x004; + this.Mnemonic = "STAL"; + 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_STAL_i = new IS_STAL_imm; +Instructions.push(is_STAL_i); + +class IS_STAH_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x005; + this.Mnemonic = "STAH"; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RRI | CONTROL_PCC; + this.Microcode[4] = CONTROL_OUT_AH | CONTROL_RI; + } +} +is_STAH_i = new IS_STAH_imm; +Instructions.push(is_STAH_i); + +class IS_STBL_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x006; + this.Mnemonic = "STBL"; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RRI | CONTROL_PCC; + this.Microcode[4] = CONTROL_OUT_BL | CONTROL_RI; + } +} +is_STBL_i = new IS_STBL_imm; +Instructions.push(is_STBL_i); + +class IS_STBH_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x007; + this.Mnemonic = "STBH"; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RRI | CONTROL_PCC; + this.Microcode[4] = CONTROL_OUT_BH | CONTROL_RI; + } +} +is_STBH_i = new IS_STBH_imm; +Instructions.push(is_STBH_i); + +class IS_STCL_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x008; + this.Mnemonic = "STCL"; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RRI | CONTROL_PCC; + this.Microcode[4] = CONTROL_OUT_CL | CONTROL_RI; + } +} +is_STCL_i = new IS_STCL_imm; +Instructions.push(is_STCL_i); + +class IS_STCH_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x009; + this.Mnemonic = "STCH"; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RRI | CONTROL_PCC; + this.Microcode[4] = CONTROL_OUT_CH | CONTROL_RI; + } +} +is_STCH_i = new IS_STCH_imm; +Instructions.push(is_STCH_i); + +class IS_STDL_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x00A; + this.Mnemonic = "STDL"; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RRI | CONTROL_PCC; + this.Microcode[4] = CONTROL_OUT_DL | CONTROL_RI; + } +} +is_STDL_i = new IS_STDL_imm; +Instructions.push(is_STDL_i); + +class IS_STDH_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x00B; + this.Mnemonic = "STDH"; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_RO | CONTROL_RRI | CONTROL_PCC; + this.Microcode[4] = CONTROL_OUT_DH | CONTROL_RI; + } +} +is_STDH_i = new IS_STDH_imm; +Instructions.push(is_STDH_i); + + // This is a simple ADD command which will ADD GPA and GPB putting the sum in GPA class IS_ADD extends Microcode_Instruction { constructor(props) { super(props); this.Bytecode = 0x100; + this.Mnemonic = "ADD"; this.Microcode[2] = CONTROL_ALU_ADD; this.Microcode[3] = CONTROL_RAIL | CONTROL_OUT_AO; } @@ -128,11 +261,44 @@ class IS_ADD extends Microcode_Instruction { is_ADD = new IS_ADD; Instructions.push(is_ADD); +class IS_JMP_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.Bytecode = 0x200; + this.Mnemonic = "JMP"; + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_RO | CONTROL_PCI; + } +} +is_JMP_i = new IS_JMP_imm; +Instructions.push(is_JMP_i); + +class IS_BCC_imm extends Microcode_Instruction { + constructor(props) { + super(props); + this.UsesCarry = true; + this.Bytecode = 0x201; + this.Mnemonic = "BCC"; + this.MicrocodeCarry = new Array(16); + for (let a = 0; a < 16; a++) { + this.MicrocodeCarry[a] = this.Microcode[a]; + } + this.Microcode[2] = CONTROL_OUT_PC | CONTROL_RRI; + this.Microcode[3] = CONTROL_OUT_RO | CONTROL_PCI; + this.MicrocodeCarry[2] = CONTROL_PCC; // Step over the immediate value + } +} + +is_BCC_i = new IS_BCC_imm; +Instructions.push(is_BCC_i); + class IS_NOP extends Microcode_Instruction { constructor(props) { super(props); this.Bytecode = 0x3ff; + this.Mnemonic = "NOP"; } } is_NOP = new IS_NOP; Instructions.push(is_NOP); +