8SA1Sim/js/microcode_compiler.js

246 lines
8.2 KiB
JavaScript

/*
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
*/
/*
Free Instructions:
0x000
0x001
0x003
0x005
0x007
0x009
*/
let Instructions = new Array();
const InstructionTypes = {
SingleWord: {
Name: `Singe Word`,
toString() {
return this.Name;
}
},
RTS16: {
Name: `JSR 16 Return`,
toString() {
return this.Name;
}
},
RTS24: {
Name: `JSR 24 Return`,
toString() {
return this.Name;
}
},
Immediate8: {
Name: `8 bit Immediate`,
toString() {
return this.Name;
}
},
Immediate16: {
Name: `16 bit Immediate`,
toString() {
return this.Name;
}
},
Immediate24: {
Name: `24 bit Immediate`,
toString() {
return this.Name;
}
},
Indirect16: {
Name: `16 bit Indirect`,
toString() {
return this.Name;
}
},
Indirect24: {
Name: `24 bit Indirect`,
toString() {
return this.Name;
}
},
Absolute16: {
Name: `16 bit Absolute`,
toString() {
return this.Name;
}
},
Absolute24: {
Name: `24 bit Absolute`,
toString() {
return this.Name;
}
},
Register: {
Name: `Register`,
toString() {
return this.Name;
}
},
RegisterImmediate: {
Name: `Register Immediate`,
toString() {
return this.Name;
}
},
RegisterAbsolute: {
Name: `Register Absolute`,
toString() {
return this.Name;
}
},
RegisterIndirect: {
Name: `Register Indirect`,
toString() {
return this.Name;
}
}
};
function IsRegister(reg) {
reg = reg.toLowerCase().replace("%","").replace("[","").replace("]","");
switch (reg) {
case "a":
case "b":
case "c":
case "d":
case "pc":
case "sp":
case "ab":
case "ac":
case "ad":
case "ba":
case "bc":
case "bd":
case "ca":
case "cb":
case "cd":
case "da":
case "db":
case "dc":
return true;
break;
}
return false;
}
function ValidateInstruction(line) {
let linearr = line.split(" ");
let label = false;
let type = false;
if (linearr[0] !== "") label = linearr[0];
if (linearr.length > 2) {
let operands = linearr[2].split(",");
if (operands.length > 0) {
if (operands.length === 1) {
if (operands[0].substring(0,1) === '$') type = InstructionTypes.Immediate;
if (operands[0].substring(0,1) === '[') type = InstructionTypes.Indirect;
if (IsRegister(operands[0])) type = InstructionTypes.Register;
if (type === false) type = InstructionTypes.Absolute;
} else {
// more then one operand
}
}
}
console.log(linearr[1]);
let foundinstruction = FindInstructon({Instruction: linearr[1]}, type);
return foundinstruction;
}
function FindInstructon(ins,type = false) {
for (let a = 0; a < Instructions.length; a++) {
if (Instructions[a].Mnemonic.toLowerCase() === ins.Instruction.toLowerCase()) {
if (type) {
if (Instructions[a].Type === type) return Instructions[a];
} else {
return Instructions[a];
}
}
}
return false;
}
function GenerateMicrocode(mcarray,cpu) {
for (let a = 0; a < mcarray.length; a++) {
for (let c = 0; c < 3; c++) {
let offset = 0;
if (c === 1) offset = 0b1000000000000000;
if (c === 2) offset = 0b0100000000000000;
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)}`);
}
}
}
}
class Microcode_Instruction {
constructor() {
this.Bytecode = 0x000; // MAX IS 0x3ff
this.Mnemonic = "NOP";
this.LongName = "";
this.Aliases = new Array();
this.Microcode = new Array(16);
this.Operands = new Array();
this.UsesCarry = false;
this.UsesZero = false;
this.Words = 1;
this.Cycles = 2;
this.Type = InstructionTypes.SingleWord;
this.Microcode[0] = CONTROL_OUT_PC | CONTROL_RRI;
this.Microcode[1] = CONTROL_OUT_RO | CONTROL_IRI | CONTROL_PCC;
for (let a = 2; a < 16; a++) {
this.Microcode[a] = CONTROL_MCL0;
}
}
}