diff --git a/cpu.js b/cpu.js index e985f8c..a2725d3 100644 --- a/cpu.js +++ b/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); }; }