two-bit/machine.ts

74 lines
3.0 KiB
TypeScript

import bit from "./bit";
import { memory } from "./memory";
import { Ram } from "./ram";
import { Word, emptyWord, wordFromNumber, wordFromString } from "./word";
export function machine<Width extends number>(ram: Ram<Width>) {
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<number>
ram.write(result as Word<Width>, 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
}
}