Memory now follows the location, shows red when writing to RAM and GREEN when reading, yellow when the address bus just happens to be sitting on the address but not actively reading or writing.
This commit is contained in:
parent
3943201db1
commit
a3f5382437
@ -41,11 +41,12 @@
|
||||
</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="00" pattern="[a-fA-F\d]+" />
|
||||
<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="text" value="1" />mS
|
||||
</div>
|
||||
<div>
|
||||
<span>Text Output (0x8000-0x83ff):</span><br />
|
||||
<span id="TEXT_OUT"></span>
|
||||
<span id="TEXT_OUT" style="border: 1px solid black; min-width: 48em; min-height: 2.2em; display: inline-block;"></span>
|
||||
</div>
|
||||
<div>
|
||||
<span>RAM : [<span id="Address_BUS"></span>]</span><br /><span id="RAM"></brspan>
|
||||
@ -57,5 +58,6 @@
|
||||
<script src="js/cpu.js"></script>
|
||||
<script src="js/microcode_compiler.js"></script>
|
||||
<script src="js/main.js"></script>
|
||||
<script src="js/asm_compiler.js"></script>
|
||||
</body>
|
||||
</html>
|
113
js/asm_compiler.js
Normal file
113
js/asm_compiler.js
Normal file
@ -0,0 +1,113 @@
|
||||
class ASM_Compiler {
|
||||
constructor(assemblycode) {
|
||||
this.ASM = assemblycode.replace(/ +/g, ' ').replace(/\\t+/g, ' ').replace(/\\r+/g, '');
|
||||
this.Labels = new Array();
|
||||
this.Directives = {
|
||||
Globals: new Array()
|
||||
};
|
||||
this.Sections = new Array();
|
||||
this.CompileError = false;
|
||||
this.CompileErrorReason = "";
|
||||
}
|
||||
firstPass() {
|
||||
let codeLines = this.ASM.split("\n");
|
||||
let currentSection = "";
|
||||
console.log(`There are ${codeLines.length} lines`);
|
||||
for (let linenum = 0; linenum < codeLines.length; linenum++) {
|
||||
console.log(`Line ${linenum}: ${codeLines[linenum]}`);
|
||||
let globalDeclared = false;
|
||||
let sectionDeclared = false;
|
||||
let lineColumns = codeLines[linenum].split(" ");
|
||||
for (let colnum = 0; colnum < lineColumns.length; colnum++) {
|
||||
console.log(`Column ${colnum}: ${lineColumns[colnum]}`);
|
||||
switch (colnum) {
|
||||
case 0: { // Labels
|
||||
if (currentSection === "" && lineColumns[colnum] !== "") {
|
||||
// error, shouldn't be anything here in the directives section
|
||||
this.CompileError = true;
|
||||
this.CompileErrorReason = "Unexpected label in directives section: " + lineColumns[colnum];
|
||||
this.CompileErrorLine = linenum+1;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: { // Instructions
|
||||
if (currentSection === "" && lineColumns[colnum] === "") {
|
||||
// Error, in directive there should be SOMETHING here
|
||||
this.CompileError = true;
|
||||
this.CompileErrorReason = "Missing Directive";
|
||||
this.CompileErrorLine = linenum+1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (currentSection === "") {
|
||||
switch (lineColumns[colnum].toLowerCase()) {
|
||||
case "global": {
|
||||
if (colnum === lineColumns.length - 1) {
|
||||
this.CompileError = true;
|
||||
this.CompileErrorReason = "Missing Global Label";
|
||||
this.CompileErrorLine = linenum + 1;
|
||||
return false;
|
||||
}
|
||||
globalDeclared = true;
|
||||
break;
|
||||
}
|
||||
case "section": {
|
||||
if (colnum === lineColumns.length - 1) {
|
||||
this.CompileError = true;
|
||||
this.CompileErrorReason = "Missing section type";
|
||||
this.CompileErrorLine = linenum + 1;
|
||||
return false;
|
||||
}
|
||||
sectionDeclared = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
this.CompileError = true;
|
||||
this.CompileErrorReason = "Unknown directive: " + lineColumns[colnum];
|
||||
this.CompileErrorLine = linenum + 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
if (!FindInstructon({Instruction:lineColumns[colnum]})) {
|
||||
this.CompileError = true;
|
||||
this.CompileErrorReason = "Unknown instruction: " + lineColumns[colnum];
|
||||
this.CompileErrorLine = linenum + 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
case 2: { // Operands
|
||||
if (currentSection === "" && lineColumns[colnum] === "" && (globalDeclared === true || sectionDeclared === true)) {
|
||||
// There should be a label here!
|
||||
this.CompileError = true;
|
||||
if (globalDeclared) this.CompileErrorReason = "Missing Global Label";
|
||||
if (sectionDeclared) this.CompileErrorReason = "Missing Section type";
|
||||
this.CompileErrorLine = linenum+1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (globalDeclared) {
|
||||
let globallabel = {
|
||||
Label: lineColumns[colnum].replace(":", ""),
|
||||
Address: 0
|
||||
};
|
||||
this.Directives.Globals.push(globallabel);
|
||||
}
|
||||
if (sectionDeclared) {
|
||||
let sectionType = {
|
||||
Label: lineColumns[colnum].replace(".", ""),
|
||||
Address: 0
|
||||
};
|
||||
currentSection = sectionType;
|
||||
this.Sections.push(currentSection);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
84
js/cpu.js
84
js/cpu.js
@ -66,9 +66,9 @@ function GetMnemonic(mcarray,instruction) {
|
||||
function generateClocks(clk_cnt) {
|
||||
for (let a = 0; a < clk_cnt; a++) {
|
||||
cpu.CLOCK(true);
|
||||
updateHTML();
|
||||
clk_count++;
|
||||
clk_counter.innerText = clk_count;
|
||||
cpu.CLOCK(false);
|
||||
updateHTML();
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,17 +79,23 @@ function generateClocks_Interval() {
|
||||
cpu.CLOCK(true);
|
||||
}*/
|
||||
cpu.CLOCK(true);
|
||||
clk_count++;
|
||||
clk_counter.innerText = clk_count;
|
||||
cpu.CLOCK(false);
|
||||
|
||||
updateHTML();
|
||||
if (cpu.ADDRBUS === breakpt) clearInterval(intval);
|
||||
}
|
||||
|
||||
function drawCPUInfo() {
|
||||
updateHTML();
|
||||
window.requestAnimationFrame(drawCPUInfo);
|
||||
}
|
||||
|
||||
function RunUntilBreak(addr) {
|
||||
breakpt = addr;
|
||||
intval = setInterval(function(){
|
||||
generateClocks_Interval();
|
||||
}, 1);
|
||||
}, parseInt(clkinterval.value));
|
||||
}
|
||||
|
||||
function printTextOut(ram,startaddr,endaddr) {
|
||||
@ -101,14 +107,22 @@ function printTextOut(ram,startaddr,endaddr) {
|
||||
}
|
||||
|
||||
function printRAM(ram) {
|
||||
let startADDR = (cpu.ADDRBUS & 0xfff0) - 0x80;
|
||||
if (startADDR < 0) startADDR = 0;
|
||||
if (startADDR > 0xFEFF) startADDR = 0xFF00;
|
||||
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<br />";
|
||||
for (let a = 0; a < 16; a++) {
|
||||
ramtext += "0x" + formatHex(a*16,4) + ": ";
|
||||
for (let a = startADDR; a < (startADDR+255); a+=16) {
|
||||
ramtext += "0x" + formatHex(a,4) + ": ";
|
||||
for (let b = 0; b < 16; b++) {
|
||||
if (cpu.ADDRBUS === (a*16)+b) ramtext += '<span style="background-color: #ffff55">';
|
||||
ramtext += formatHex(ram[(a*16)+b],4) + " ";
|
||||
if (cpu.ADDRBUS === (a*16)+b) ramtext += '</span>';
|
||||
if (cpu.ADDRBUS === (a)+b) {
|
||||
let bgcolor = "#ffff55";
|
||||
if ((cpu.MC_Controls & CONTROL_OUT_RO) === CONTROL_OUT_RO) bgcolor = "#55ff55";
|
||||
if (cpu.MC_Controls & CONTROL_RI) bgcolor = "#ff5555";
|
||||
ramtext += `<span style="background-color: ${bgcolor}">`;
|
||||
}
|
||||
ramtext += formatHex(ram[(a)+b],4) + " ";
|
||||
if (cpu.ADDRBUS === (a)+b) ramtext += '</span>';
|
||||
}
|
||||
ramtext += "<br />";
|
||||
}
|
||||
@ -116,7 +130,7 @@ function printRAM(ram) {
|
||||
|
||||
let sp_stackram = document.getElementById("STACK-RAM");
|
||||
ramtext = "ADDR : 0 1 2 3 4 5 6 7 8 9 A B C D E F<br />";
|
||||
for (let a = 0xffa0; a < 0x10000; a+=16) {
|
||||
for (let a = 0xffe0; a < 0x10000; a+=16) {
|
||||
ramtext += "0x" + formatHex(a,4) + ": ";
|
||||
for (let b = 0; b < 16; b++) {
|
||||
if (cpu.ADDRBUS === (a)+b) ramtext += '<span style="background-color: #ffff55">';
|
||||
@ -283,7 +297,7 @@ class CPU_8SA1 {
|
||||
OUTMUX |= (this.MC_Controls & CONTROL_OEM0) ? 0b00001 : 0;
|
||||
|
||||
if (OUTMUX === OECONTROL_RO) {
|
||||
console.log("DATABUS = RAM");
|
||||
//console.log("DATABUS = RAM");
|
||||
this.DATABUS = this.RAM[this.ADDRBUS];
|
||||
if (this.DATABUS === undefined) this.DATABUS = 0;
|
||||
}
|
||||
@ -322,12 +336,12 @@ class CPU_8SA1 {
|
||||
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`);
|
||||
//if (MC_Controls & CONTROL_MCL0) console.log(`Reset microcode counter to 0`);
|
||||
//if (MC_Controls & CONTROL_MCL8) console.log(`Reset microcode counter to 8`);
|
||||
mcra = ((this.IR & 0b0000001111111111) << 4) | this.MCC | ((this.SR & 0b00000011) << 14);
|
||||
MC_Controls = this.MCRAM[mcra];
|
||||
if (MC_Controls === undefined) MC_Controls = 0;
|
||||
console.log(`[${mcra.toString(2)}] Control Lines: ${MC_Controls.toString(2)}`);
|
||||
//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
|
||||
@ -337,46 +351,46 @@ class CPU_8SA1 {
|
||||
OUTMUX |= (MC_Controls & CONTROL_OEM1) ? 0b00010 : 0;
|
||||
OUTMUX |= (MC_Controls & CONTROL_OEM0) ? 0b00001 : 0;
|
||||
|
||||
console.log(`OUTPUT MUX: ${OUTMUX.toString(2)}`);
|
||||
//console.log(`OUTPUT MUX: ${OUTMUX.toString(2)}`);
|
||||
switch (OUTMUX) {
|
||||
case OECONTROL_PC: {
|
||||
this.DATABUS = this.PC;
|
||||
console.log("DATABUS = PC");
|
||||
//console.log("DATABUS = PC");
|
||||
break;
|
||||
}
|
||||
case OECONTROL_SP: {
|
||||
this.DATABUS = this.SP;
|
||||
console.log("DATABUS = 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");
|
||||
//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");
|
||||
//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");
|
||||
//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");
|
||||
// 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");
|
||||
//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");
|
||||
//console.log("DATABUS HIGH = C");
|
||||
break;
|
||||
}
|
||||
case OECONTROL_DL: {
|
||||
@ -389,7 +403,7 @@ class CPU_8SA1 {
|
||||
}
|
||||
case OECONTROL_AB: {
|
||||
this.DATABUS = ((this.GPB & BITMASK_8) << 8) | (this.GPA & BITMASK_8);
|
||||
console.log("DATABUS = AB");
|
||||
//console.log("DATABUS = AB");
|
||||
break;
|
||||
}
|
||||
case OECONTROL_AC: {
|
||||
@ -437,7 +451,7 @@ class CPU_8SA1 {
|
||||
break;
|
||||
}
|
||||
case OECONTROL_AE: {
|
||||
console.log("ALU Enable");
|
||||
//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;
|
||||
@ -446,7 +460,7 @@ class CPU_8SA1 {
|
||||
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}`);
|
||||
//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;
|
||||
@ -504,17 +518,17 @@ class CPU_8SA1 {
|
||||
}
|
||||
case OECONTROL_AO: {
|
||||
this.DATABUS = (this.DATABUS & (BITMASK_8 << 8)) | this.ALUSUM;
|
||||
console.log("DATABUS = SUM");
|
||||
//console.log("DATABUS = SUM");
|
||||
break;
|
||||
}
|
||||
case OECONTROL_SR: {
|
||||
this.DATABUS = ((this.DATABUS & BITMASK_8) << 8) | (this.SR & BITMASK_8);
|
||||
console.log("DATABUS = STATUS REGISTER");
|
||||
//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)");
|
||||
//console.log("DATABUS = RAM (on CLK)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -570,32 +584,32 @@ class CPU_8SA1 {
|
||||
|
||||
GPA_In_LOW_CLK() {
|
||||
this.GPA = this.DATABUS & 0x00ff;
|
||||
console.log(`GPA = DATABUS LOW`);
|
||||
//console.log(`GPA = DATABUS LOW`);
|
||||
}
|
||||
|
||||
GPA_In_HIGH_CLK() {
|
||||
this.GPA = (this.DATABUS & 0xff00) >> 8;
|
||||
console.log(`GPA = DATABUS HIGH`);
|
||||
//console.log(`GPA = DATABUS HIGH`);
|
||||
}
|
||||
|
||||
GPB_In_LOW_CLK() {
|
||||
this.GPB = this.DATABUS & 0x00ff;
|
||||
console.log(`GPB = DATABUS LOW`);
|
||||
//console.log(`GPB = DATABUS LOW`);
|
||||
}
|
||||
|
||||
GPB_In_HIGH_CLK() {
|
||||
this.GPB = (this.DATABUS & 0xff00) >> 8;
|
||||
console.log(`GPB = DATABUS HIGH`);
|
||||
//console.log(`GPB = DATABUS HIGH`);
|
||||
}
|
||||
|
||||
GPC_In_LOW_CLK() {
|
||||
this.GPC = this.DATABUS & 0x00ff;
|
||||
console.log(`GPC = DATABUS LOW`);
|
||||
//console.log(`GPC = DATABUS LOW`);
|
||||
}
|
||||
|
||||
GPC_In_HIGH_CLK() {
|
||||
this.GPC = (this.DATABUS & 0xff00) >> 8;
|
||||
console.log(`GPC = DATABUS HIGH`);
|
||||
//console.log(`GPC = DATABUS HIGH`);
|
||||
}
|
||||
|
||||
GPD_In_LOW_CLK() {
|
||||
|
12
js/main.js
12
js/main.js
@ -36,7 +36,7 @@ cpu.RAM[4] = is_CMP.Bytecode;
|
||||
*/
|
||||
|
||||
cpu.RAM[0] = is_LDAB_i.Bytecode;
|
||||
cpu.RAM[1] = 0x0050;
|
||||
cpu.RAM[1] = 0x0100;
|
||||
cpu.RAM[2] = is_PHAB.Bytecode;
|
||||
cpu.RAM[3] = is_JSR.Bytecode;
|
||||
cpu.RAM[4] = 0x00D0;
|
||||
@ -89,12 +89,13 @@ cpu.RAM[0xFC] = is_RTS.Bytecode;
|
||||
|
||||
|
||||
|
||||
stringToRAM("Blackbeard420 is a Butt Fuckers",cpu.RAM,0x50);
|
||||
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);
|
||||
updateHTML();
|
||||
|
||||
let btn_clk = document.getElementById("btn_clk");
|
||||
let btn_runtil = document.getElementById("btn_runtil");
|
||||
let brkpt = document.getElementById("addrbrk");
|
||||
let clkinterval = document.getElementById("clkinterval");
|
||||
let btn_rst = document.getElementById("btn_rst");
|
||||
let clk_counter = document.getElementById("clk_counter");
|
||||
let clk_count = 0;
|
||||
@ -103,12 +104,10 @@ btn_clk.addEventListener('mousedown', function(evt) {
|
||||
cpu.CLOCK(true);
|
||||
clk_count++;
|
||||
clk_counter.innerText = clk_count;
|
||||
updateHTML();
|
||||
});
|
||||
|
||||
btn_clk.addEventListener('mouseup', function(evt) {
|
||||
cpu.CLOCK(false);
|
||||
updateHTML();
|
||||
});
|
||||
|
||||
btn_runtil.addEventListener('click', function(evt) {
|
||||
@ -134,5 +133,6 @@ btn_rst.addEventListener('click', function(evt) {
|
||||
|
||||
clk_count = 0;
|
||||
clk_counter.innerText = clk_count;
|
||||
updateHTML();
|
||||
});
|
||||
});
|
||||
|
||||
window.requestAnimationFrame(drawCPUInfo);
|
@ -59,6 +59,15 @@ const CONTROL_ALU_XNOR = CONTROL_OUT_AE | CONTROL_ALUM1 | CONTROL_ALUM0 | CONTRO
|
||||
|
||||
let Instructions = new Array();
|
||||
|
||||
function FindInstructon(ins) {
|
||||
for (let a = 0; a < Instructions.length; a++) {
|
||||
if (Instructions[a].Mnemonic.toLowerCase() === ins.Instruction.toLowerCase()) {
|
||||
return Instructions[a];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function GenerateMicrocode(mcarray,cpu) {
|
||||
for (let a = 0; a < mcarray.length; a++) {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user