Refactoring of the display and some 24 bit instructions

This commit is contained in:
MatCat 2021-04-09 01:39:21 -07:00
parent a572229c87
commit a76e01aca1
6 changed files with 394 additions and 150 deletions

View File

@ -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
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

View File

@ -3,56 +3,66 @@
<title>MatCat's 8SA1 CPU Emulator</title>
</head>
<body style="font-family: monospace; font-size: 1.5em;">
<div style="display: flex;">
<div>
<input type="button" id ="btn_rst" value="RESET" />
<span style="font-size: 0.7em;">Display (0xD00000-0xDFFFFF):</span><br />
<span style="font-size: 0.75em; display: inline-block; padding: 30px; background: rgb(213,206,166); background: -moz-radial-gradient(center, ellipse cover, rgba(213,206,166,1) 0%, rgba(201,193,144,1) 47%, rgba(183,173,112,1) 100%); background: -webkit-radial-gradient(center, ellipse cover, rgba(213,206,166,1) 0%,rgba(201,193,144,1) 47%,rgba(183,173,112,1) 100%); background: radial-gradient(ellipse at center, rgba(213,206,166,1) 0%,rgba(201,193,144,1) 47%,rgba(183,173,112,1) 100%); filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#d5cea6', endColorstr='#b7ad70',GradientType=1 );">
<span id="TEXT_OUT" style="border: 1px solid black; width: 44em; height: 28em; display: inline-block; color: #ddd; padding: 2px; background-color: #222;">MatCat 8SA1 Computer<br /></span></span>
</div>
<div>
<span>DATA: </span><span id="Data_BUS"></span>
<div style="font-size: 0.8em; margin-left: 10px; margin-top: 30px;">
<div>
<input type="button" id ="btn_rst" value="RESET" />
</div>
<div>
<span>DATA: </span><span id="Data_BUS"></span>
</div>
<div>
<span>PC&nbsp;&nbsp;: </span><span id="PC_Register"></span>
</div>
<div>
<span>MCC : </span><span id="MCC_Register"></span>
</div>
<div>
<span>CO&nbsp;&nbsp;: </span><span id="CO_Register"></span>
</div>
<div>
<span>SP&nbsp;&nbsp;: </span><span id="SP_Register"></span>
</div>
<div>
<span>SR&nbsp;&nbsp;: </span><span id="SR_Register"></span>
</div>
<div>
<span>IR&nbsp;&nbsp;: </span><span id="IR_Register"></span>
</div>
<div>
<span>IR2&nbsp;: </span><span id="IR2_Register"></span>
</div>
<div>
<span>GPA : </span><span id="GPA_Register"></span>
</div>
<div>
<span>GPB : </span><span id="GPB_Register"></span>
</div>
<div>
<span>GPC : </span><span id="GPC_Register"></span>
</div>
<div>
<span>GPD : </span><span id="GPD_Register"></span>
</div>
<div>
<input type="button" id ="btn_clk" value="CLOCK" />
<span id="clk_counter">0</span><input type="button" id ="btn_runtil" value="BREAK AT:" /> 0x<input id="addrbrk" type="text" value="07" pattern="[a-fA-F\d]+" /> <input type="button" id ="btn_stopclk" value="STOP CLOCK" disabled /><br />
<span>Clock Interval: </span><input id="clkinterval" type="number" value="1" size="4" min="1" max="999999" />mS
<span>Cycles Per Interval: </span><input id="clkcycles" type="number" value="25" size="4" min="1" max="999999" />
</div>
</div>
<div>
<span>PC&nbsp;&nbsp;: </span><span id="PC_Register"></span>
</div>
<div>
<span>MCC : </span><span id="MCC_Register"></span>
</div>
<div>
<span>CO&nbsp;&nbsp;: </span><span id="CO_Register"></span>
</div>
<div>
<span>SP&nbsp;&nbsp;: </span><span id="SP_Register"></span>
</div>
<div>
<span>SR&nbsp;&nbsp;: </span><span id="SR_Register"></span>
</div>
<div>
<span>IR&nbsp;&nbsp;: </span><span id="IR_Register"></span>
</div>
<div>
<span>GPA : </span><span id="GPA_Register"></span>
</div>
<div>
<span>GPB : </span><span id="GPB_Register"></span>
</div>
<div>
<span>GPC : </span><span id="GPC_Register"></span>
</div>
<div>
<span>GPD : </span><span id="GPD_Register"></span>
</div>
<div>
<input type="button" id ="btn_clk" value="CLOCK" />
<span id="clk_counter">0</span><input type="button" id ="btn_runtil" value="BREAK AT:" /> 0x<input id="addrbrk" type="text" value="05" pattern="[a-fA-F\d]+" />
<span>Clock Interval: </span><input id="clkinterval" type="number" value="1" size="4" min="1" max="999999" />mS
<span>Cycles Per Interval: </span><input id="clkcycles" type="number" value="1" size="4" min="1" max="999999" />
</div>
<div>
<span>Text Output (0x8000-0x83ff):</span><br />
<span id="TEXT_OUT" style="border: 1px solid black; min-width: 48em; min-height: 2.2em; display: inline-block;"></span>
</div>
<div>
<div style="font-size: 0.9em;">
<span>RAM : [<span id="Address_BUS"></span>] <span>Lines: </span><input id="ramlines" type="number" value="4" size="4" min="1" max="1024" /></span><br /><span id="RAM"></span>
</div>
<div>
<div style="font-size: 0.9em;">
<span>RAM (STACK): </span><br /><span id="STACK-RAM"></span>
</div>

View File

@ -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&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;&nbsp;&nbsp;&nbsp;D&nbsp;&nbsp;&nbsp;&nbsp;E&nbsp;&nbsp;&nbsp;&nbsp;F<br />";
for (let a = 0xffe0; a < 0x10000; a+=16) {
ramtext += "0x" + formatHex(a,4) + ": ";
ramtext = "ADDR&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;A&nbsp;&nbsp;&nbsp;&nbsp;B&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;&nbsp;&nbsp;&nbsp;D&nbsp;&nbsp;&nbsp;&nbsp;E&nbsp;&nbsp;&nbsp;&nbsp;F<br />";
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 += '<span style="background-color: #ffff55">';
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;
}

View File

@ -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("");

View File

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

View File

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