cardiograph-computer/sketches/simulator-sketch-v2.js

130 lines
3.2 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// STATE
const CPU = {
running: false,
IP: 0,
CF: 0,
Acc: 0,
memory: null,
loadMemory: (data) => { // data: Uint8Array
// TODO: check length of data
CPU.memory = data;
},
}
// FUNCTIONS THAT MODIFY STATE
const Instructions = {
end: () => {
console.log('END');
CPU.running = false;
},
store_lit: (lit) => {
console.log('STO lit#');
CPU.memory[lit] = CPU.acc;
logTableTitled(CPU.memory, 'Current memory');
CPU.IP = CPU.IP += 2;
},
store_addr: (addr) => {
console.log('STO addr');
CPU.memory[CPU.memory[addr]] = CPU.acc;
logTableTitled(CPU.memory, 'Memory');
CPU.IP = CPU.IP += 2;
},
load_lit: (lit) => {
console.log('LDA lit#');
CPU.acc = lit;
CPU.IP = CPU.IP += 2;
},
load_addr: (addr) => {
console.log('LDA addr');
console.log('mem at addr: ', CPU.memory[addr]);
CPU.acc = CPU.memory[addr];
CPU.IP = CPU.IP += 2;
},
}
const instructionLookupTable = {
0: (arg) => Instructions.end(arg),
1: (arg) => Instructions.store_lit(arg),
2: (arg) => Instructions.store_addr(arg),
3: (arg) => Instructions.load_lit(arg),
4: (arg) => Instructions.load_addr(arg),
};
function stepCPU() {
console.group("Step CPU");
let opcode = CPU.memory[CPU.IP];
let argument = CPU.memory[CPU.IP+1];
console.log(`OP: ${opcode} ARG: ${argument}`);
let instruction = instructionLookupTable[opcode];
instruction(argument);
logCPUState();
console.groupEnd("Step CPU");
}
function runCPU() {
const initialMemory = JSON.parse(JSON.stringify(CPU.memory)); // Hack to make a copy-by-value -- https://stackoverflow.com/questions/18829099/copy-a-variables-value-into-another
console.log();
console.log("————————————————————————————————————————");
let time = new Date();
console.log( `Running at ${time.toLocaleTimeString('en-US')}` );
console.log("————————————————————————————————————————");
logCPUState();
CPU.running = true;
for (let i = 0; i < 255; i++) { // FIXME: temporary limit as a lazy way to halt infinite loops
if (!CPU.running) break;
if (CPU.IP >= CPU.memory.length) break;
stepCPU();
};
}
// FUNCTIONS THAT PULL INFO FROM STATE TO DISPLAY
function logCPUState() {
console.log();
console.group('CPU state');
console.log( `Acc: ${CPU.acc} IP: ${CPU.IP} CF: ${CPU.CF}  ${CPU.running ? "running" : "halted" }` );
console.log();
console.groupEnd('CPU state');
};
// FUNCTIONS FOR DISPLAYING DATA
function num2hex(num) { num.toString(16) };
function hex2num(hex) { parseInt(hex, 16) };
logTableTitled = (memory, tableTitle) => {
console.log();
console.group(tableTitle);
console.table(memory);
console.groupEnd(tableTitle);
};
// RUN IT !
const test_lda_sto = new Uint8Array([
3, 17, // LDA lit ... acc = 17
1, 14, // STO lit ... @14 = acc = 17
3, 16, // LDA lit ... acc = 16
1, 15, // STO lit ... @15 = acc = 16
2, 15, // STO addr ... @[@15] = acc = 16 ... mem[mem[addr]] <- Acc
4, 0, // LDA addr ... acc = @00 = 03
0, 0, // END
0, 0, // DATA
]);
CPU.loadMemory(test_lda_sto);
runCPU();