import bit from "./bit"; import { memory } from "./memory"; import { Ram } from "./ram"; import { Word, emptyWord, wordFromNumber, wordFromString } from "./word"; export function machine(ram: Ram) { const programCounterRegister = memory(wordFromNumber(1, ram.addressLength)) const startAddress = ram.read(emptyWord(ram.addressLength)).subword(ram.wordSize - ram.addressLength, ram.addressLength) const addressRegister = memory(startAddress) const instructionCounterSize = Math.ceil(Math.log2(Math.floor(ram.wordSize / 2))) const instructionCounterRegister = memory(emptyWord(instructionCounterSize)) function programCounter() { return programCounterRegister } function instructionCounter() { return instructionCounterRegister } function tick() { const currentInstruction = ram.read(programCounterRegister.value()).subword(instructionCounterRegister.value().toNumber() * 2, 2) if (currentInstruction.equals(wordFromString("00"))) { const firstOperand = ram.read(addressRegister.value()) const secondOperand = ram.read(addressRegister.value().plus(wordFromNumber(1)).sum) const result = firstOperand.plus(secondOperand).sum as Word ram.write(result as Word, addressRegister.value().plus(wordFromString("10")).sum) incrementInstruction() } else if (currentInstruction.equals(wordFromString("01"))) { addressRegister.set(ram.read(addressRegister.value())) incrementInstruction() } else if (currentInstruction.equals(wordFromString("10"))) { const current = ram.read(addressRegister.value()) const jumpAddress = ram.read(addressRegister.value().plus(wordFromNumber(1)).sum).subword(ram.wordSize - ram.addressLength, ram.addressLength) if (current.toNumber() !== 0) { programCounterRegister.set(jumpAddress) instructionCounterRegister.set(emptyWord(instructionCounterSize)) } else { incrementInstruction() } } else if (currentInstruction.equals(wordFromString("11"))) { const nextValue = addressRegister.value().plus(wordFromNumber(1)).sum addressRegister.set(nextValue) incrementInstruction() } } function incrementInstruction() { const nextInstructionIndex = instructionCounterRegister.value().plus(wordFromNumber(1, instructionCounterSize)) instructionCounterRegister.set(nextInstructionIndex.sum) if (nextInstructionIndex.carry.equals(bit(1))) { const nextProgramCounterAddress = programCounterRegister.value().plus(wordFromNumber(1, ram.addressLength)) programCounterRegister.set(nextProgramCounterAddress.sum) } } return { programCounter, addressRegister, instructionCounter, tick, ram } }