diff --git a/cpu.js b/cpu.js index abe7cb3..832f580 100644 --- a/cpu.js +++ b/cpu.js @@ -10,7 +10,7 @@ const { const { num2hex, - num2bin_4bit, + bool2bit, } = require('./logging.js'); const display = require('./display.js'); @@ -19,8 +19,8 @@ const CPU = { // Core state running: false, IP: INITIAL_IP_ADDRESS, - FLAGS: 0, // A bit field! 0000 = ONZC - FlagNames: ['C', 'Z', 'N', 'O'], + FLAGS: {'C': false, 'Z': false, 'N': false, 'O': false}, + FLAGNUMS2NAMES: {0: 'C', 1: 'Z', 2: 'N', 3: 'O'}, Acc: 0, memory: null, @@ -38,24 +38,8 @@ const CPU = { CPU.previousIP = CPU.IP; CPU.IP = address; }, - setFlagOverflow: () => { CPU.FLAGS |= 4 }, - setFlagNegative: () => { CPU.FLAGS |= 4 }, - setFlagZero: () => { CPU.FLAGS |= 2 }, - setFlagCarry: () => { CPU.FLAGS |= 1 }, - unsetFlagOverflow: () => { CPU.FLAGS &= ~8 }, - unsetFlagNegative: () => { CPU.FLAGS &= ~4 }, - unsetFlagZero: () => { CPU.FLAGS &= ~2 }, - unsetFlagCarry: () => { CPU.FLAGS &= ~1 }, - updateFlagZero: () => { - if (CPU.Acc === 0) { - CPU.setFlagZero(); - } else { - CPU.unsetFlagZero(); - } - }, - updateFlagNegative: () => { - CPU.Acc & 128 ? CPU.setFlagNegative : CPU.unsetFlagNegative - }, + updateFlagZero: () => { CPU.FLAGS.Z = CPU.Acc === 0; }, + updateFlagNegative: () => { CPU.Acc & 128 ? CPU.FLAGS.N = true : CPU.FLAGS.N = false }, // Debug info previousIP: 0, @@ -110,19 +94,22 @@ const Instructions = { // Calculate sum let sum = CPU.Acc + lit; if (sum > 255) { - CPU.setFlagCarry(); + CPU.FLAGS.C = true; sum = (sum % 255) - 1; } else { - CPU.unsetFlagCarry(); + CPU.FLAGS.C = false; } // Calculate overflow flag status let bitSixCarry = 0; if ((CPU.Acc & 64) && (lit & 64)) { bitSixCarry = 1; } - let overflow = bitSixCarry ^ (CPU.FLAGS & 8); + // let overflow = bitSixCarry ^ (CPU.FLAGS & 8); + // FIXME FIXME FIXME + // I'm on a plane and can't remember how this works + let overflow = 0; if (overflow) { - CPU.setFlagOverflow(); + CPU.FLAGS.O = true; } else { - CPU.unsetFlagOverflow(); + CPU.FLAGS.O = false; } CPU.Acc = sum; CPU.updateFlagNegative(); @@ -135,19 +122,22 @@ const Instructions = { // Calculate sum let sum = CPU.Acc + CPU.memory[addr]; if (sum > 255) { - CPU.setFlagCarry(); + CPU.FLAGS.C = true; sum = (sum % 255) - 1; } else { - CPU.unsetFlagCarry(); + CPU.FLAGS.C = false; } // Calculate overflow flag status let bitSixCarry = 0; if ((CPU.Acc & 64) && (addr & 64)) { bitSixCarry = 1; } - let overflow = bitSixCarry ^ (CPU.FLAGS & 8); + // let overflow = bitSixCarry ^ (CPU.FLAGS & 8); + // FIXME FIXME FIXME + // I'm on a plane and can't remember how this works + let overflow = 0; if (overflow) { - CPU.setFlagOverflow(); + CPU.FLAGS.O = true; } else { - CPU.unsetFlagOverflow(); + CPU.FLAGS.O = false; } CPU.Acc = sum; CPU.updateFlagNegative(); @@ -160,19 +150,22 @@ const Instructions = { // Calculate sum let sum = CPU.Acc - lit; if (sum < 0) { - CPU.setFlagCarry(); + CPU.FLAGS.C = true; sum = sum + 256; } else { - CPU.unsetFlagCarry(); + CPU.FLAGS.C = false; } // Calculate overflow flag status let bitSixCarry = 0; if ((CPU.Acc & 64) && (lit & 64)) { bitSixCarry = 1; } - let overflow = bitSixCarry ^ (CPU.FLAGS & 8); + // let overflow = bitSixCarry ^ (CPU.FLAGS & 8); + // FIXME FIXME FIXME + // I'm on a plane and can't remember how this works + let overflow = 0; if (overflow) { - CPU.setFlagOverflow(); + CPU.FLAGS.O = true; } else { - CPU.unsetFlagOverflow(); + CPU.FLAGS.O = false; } CPU.Acc = sum; CPU.updateFlagNegative(); @@ -185,19 +178,22 @@ const Instructions = { // Calculate sum let sum = CPU.Acc - CPU.memory[addr]; if (sum < 0) { - CPU.setFlagCarry(); + CPU.FLAGS.C = true; sum = sum + 256; } else { - CPU.unsetFlagCarry(); + CPU.FLAGS.C = false; } // Calculate overflow flag status let bitSixCarry = 0; if ((CPU.Acc & 64) && (addr & 64)) { bitSixCarry = 1; } - let overflow = bitSixCarry ^ (CPU.FLAGS & 8); + // let overflow = bitSixCarry ^ (CPU.FLAGS & 8); + // FIXME FIXME FIXME + // I'm on a plane and can't remember how this works + let overflow = 0; if (overflow) { - CPU.setFlagOverflow(); + CPU.FLAGS.O = true; } else { - CPU.unsetFlagOverflow(); + CPU.FLAGS.O = false; } CPU.Acc = sum; CPU.updateFlagNegative(); @@ -234,26 +230,24 @@ const Instructions = { }, flag_toggle: (flagNum) => { - CPU.currentInstruction.mnemonic = `FTG; ${CPU.FlagNames[flagNum]}`; - let mask = null; - if (flagNum === 0) { mask = 1; } - if (flagNum === 1) { mask = 2; } - if (flagNum === 2) { mask = 8; } - if (flagNum === 3) { mask = 16; } - if (mask === null) { throw new Error('Invalid flag number'); } - CPU.FLAGS = CPU.FLAGS ^= mask; + if (flagNum === null) { + console.error('Invalid flag number'); + process.exit(); + } + const flagName = CPU.FLAGNUMS2NAMES[flagNum]; + CPU.currentInstruction.mnemonic = `FTG ${flagName}`; + CPU.FLAGS[flagName] = !CPU.FLAGS[flagName]; CPU.incrementIP(2); }, flag_hop: (flagNum) => { - CPU.currentInstruction.mnemonic = `FTG; ${CPU.FlagNames[flagNum]}; IP+2: ${CPU.memory[CPU.IP+2]}, IP+3: ${CPU.memory[CPU.IP+3]}`; - let mask = null; - if (flagNum === 0) { mask = 1; } - if (flagNum === 1) { mask = 2; } - if (flagNum === 2) { mask = 8; } - if (flagNum === 3) { mask = 16; } - if (mask === null) { throw new Error('Invalid flag number'); } - if (CPU.FLAGS & mask) { + if (flagNum === null) { + console.error('Invalid flag number'); + process.exit(); + } + const flagName = CPU.FLAGNUMS2NAMES[flagNum]; + CPU.currentInstruction.mnemonic = `FHP ${flagName}; IP+2: ${CPU.memory[CPU.IP+2]}, IP+3: ${CPU.memory[CPU.IP+3]}`; + if (CPU.FLAGS[CPU.FLAGNUMS2NAMES[flagNum]]) { CPU.incrementIP(4); } else { CPU.incrementIP(2); @@ -373,7 +367,11 @@ exports.runProgram = // Animate the output by pausing between steps const loop = setInterval(async () => { stepCPU(debugInfo, debug, prettyPrint); - if (!CPU.running) process.exit(); + if (!CPU.running) { + logCPUState(debugInfo, debug, prettyPrint); + console.log('Halted'); + process.exit(); + } }, clockSpeed); } }; @@ -412,12 +410,12 @@ function logCPUState(debugInfo, debug = false, prettyPrintDisplay = false) { console.log(); if (debugInfo) { console.log(`Line ${debugInfo.lineNumber}: ${debugInfo.source}`); - console.log(); + console.log(); } console.log('Mnemonic:', CPU.currentInstruction.mnemonic); console.log(`Machine: $${num2hex(CPU.currentInstruction.opcode)} $${num2hex(CPU.currentInstruction.operand)}`); console.log(); - console.log(`IP: $${num2hex(CPU.IP)} Acc: $${num2hex(CPU.Acc)} ONZC: ${num2bin_4bit(CPU.FLAGS)}`); + console.log(`IP: $${num2hex(CPU.IP)} Acc: $${num2hex(CPU.Acc)} ONZC ${bool2bit(CPU.FLAGS.O)}${bool2bit(CPU.FLAGS.N)}${bool2bit(CPU.FLAGS.Z)}${bool2bit(CPU.FLAGS.C)}`); console.log(`KEY: $${num2hex(CPU.memory[KEYPAD_ADDR])}  ${CPU.running ? "running" : "halted" }`); console.log(); console.log(); diff --git a/logging.js b/logging.js index a662a71..39ee03e 100644 --- a/logging.js +++ b/logging.js @@ -72,6 +72,12 @@ const num2bin_4bit = (num) => (num >>> 0).toString(2).padStart(4, "0"); */ const bin2num = (bin) => parseInt(bin, 2) +/** + * @param {Boolean} bool + * @returns {0|1} + **/ +const bool2bit = (bool) => bool ? 1 : 0; + module.exports = { "logMemory": logMemory, @@ -81,4 +87,5 @@ module.exports = { "num2bin": num2bin, "num2bin_4bit": num2bin_4bit, "bin2num": bin2num, + "bool2bit": bool2bit, } \ No newline at end of file