Refactor (CPU): Move more logic into `stepCPU()` in preparation for implementing single-stepping
This commit is contained in:
parent
3ac1276bfe
commit
aa6cbc3e6d
62
cpu.js
62
cpu.js
|
|
@ -4,24 +4,19 @@ const display = require('./display.js');
|
|||
|
||||
// STATE
|
||||
const CPU = {
|
||||
// Core state
|
||||
running: false,
|
||||
IP: INITIAL_IP_ADDRESS,
|
||||
FLAGS: 0, // A bit field! 0000 = NZOC
|
||||
Acc: 0,
|
||||
memory: null,
|
||||
|
||||
currentInstruction: {
|
||||
opcode: null,
|
||||
operand: null,
|
||||
mnemonic: null,
|
||||
},
|
||||
|
||||
// Functions that update core state
|
||||
/** @param {Uint8Array} data */
|
||||
loadMemory: (data) => {
|
||||
if (data.length > 256) { throw new Error("Out of memory error (program too long)"); }
|
||||
CPU.memory = data;
|
||||
},
|
||||
|
||||
setFlagNegative: () => { CPU.FLAGS |= 8 },
|
||||
setFlagZero: () => { CPU.FLAGS |= 4 },
|
||||
setFlagOverflow: () => { CPU.FLAGS |= 2 },
|
||||
|
|
@ -30,7 +25,6 @@ const CPU = {
|
|||
unsetFlagZero: () => { CPU.FLAGS &= ~4 },
|
||||
unsetFlagOverflow: () => { CPU.FLAGS &= ~2 },
|
||||
unsetFlagCarry: () => { CPU.FLAGS &= ~1 },
|
||||
|
||||
updateFlagZero: () => {
|
||||
if (CPU.Acc === 0) {
|
||||
CPU.setFlagZero();
|
||||
|
|
@ -38,9 +32,17 @@ const CPU = {
|
|||
CPU.unsetFlagZero();
|
||||
}
|
||||
},
|
||||
|
||||
updateFlagNegative: () => {
|
||||
CPU.Acc & 128 ? CPU.setFlagNegative : CPU.unsetFlagNegative },
|
||||
CPU.Acc & 128 ? CPU.setFlagNegative : CPU.unsetFlagNegative
|
||||
},
|
||||
|
||||
// Debug info
|
||||
currentInstruction: {
|
||||
opcode: null,
|
||||
operand: null,
|
||||
mnemonic: null,
|
||||
},
|
||||
cycleCounter: 0,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -266,17 +268,33 @@ const opcodes2mnemonics = {
|
|||
**/
|
||||
function startCPU(code) {
|
||||
CPU.loadMemory(code);
|
||||
CPU.cycleCounter = 0;
|
||||
CPU.running = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute just the next instruction in memory
|
||||
**/
|
||||
function stepCPU() {
|
||||
CPU.currentInstruction.opcode = CPU.memory[CPU.IP];
|
||||
CPU.currentInstruction.operand = CPU.memory[CPU.IP+1];
|
||||
let executeInstruction = opcodes2mnemonics[CPU.currentInstruction.opcode];
|
||||
executeInstruction(CPU.currentInstruction.operand);
|
||||
async function stepCPU(debug = false) {
|
||||
if (CYCLE_LIMIT) { // Temporary limit as a lazy way to halt infinite loops
|
||||
if (CPU.cycleCounter > CYCLE_LIMIT) {
|
||||
console.warn('HALTING - reached cycle limit');
|
||||
CPU.running = false;
|
||||
}
|
||||
}
|
||||
if (CPU.running) {
|
||||
if (CPU.IP >= CPU.memory.length) {
|
||||
console.error('HALTING - IP greater than memory size');
|
||||
CPU.running = false;
|
||||
} else {
|
||||
CPU.currentInstruction.opcode = CPU.memory[CPU.IP];
|
||||
CPU.currentInstruction.operand = CPU.memory[CPU.IP+1];
|
||||
let executeInstruction = opcodes2mnemonics[CPU.currentInstruction.opcode];
|
||||
executeInstruction(CPU.currentInstruction.operand);
|
||||
CPU.cycleCounter += 1;
|
||||
}
|
||||
}
|
||||
await logCPUState(debug);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -285,18 +303,8 @@ function stepCPU() {
|
|||
**/
|
||||
exports.runProgram = async (code, debug = false) => {
|
||||
startCPU(code);
|
||||
let step = 0;
|
||||
while (true) {
|
||||
step = step + 1;
|
||||
// Temporary limit as a lazy way to halt infinite loops:
|
||||
if (CYCLE_LIMIT && (step > CYCLE_LIMIT)) {
|
||||
console.log('SIMULATION HALTING - reached cycle limit');
|
||||
break;
|
||||
}
|
||||
if (!CPU.running) break;
|
||||
if (CPU.IP >= CPU.memory.length) break;
|
||||
stepCPU();
|
||||
await logCPUState(debug);
|
||||
while (CPU.running) {
|
||||
stepCPU(debug);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue