Start a new simulator sketch with a better architecture + using a Uint8Array for memory
This commit is contained in:
parent
3eaced0e5d
commit
a17b7f4ba9
|
|
@ -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();
|
||||
Loading…
Reference in New Issue