Start a new simulator sketch with a better architecture + using a Uint8Array for memory

This commit is contained in:
n loewen 2023-07-26 11:41:11 +01:00
parent 3eaced0e5d
commit a17b7f4ba9
1 changed files with 130 additions and 0 deletions

View File

@ -0,0 +1,130 @@
// 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();