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);
+