246 lines
8.2 KiB
JavaScript
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|