import { R8 } from "./cpu" import { Loc, LocType } from "../ir/loc" import { Operand, AbsInsn2, insnReduce2 } from "../ir/insn" import { BinaryOp, UnaryOp } from "../ast" import type { SM83Insn } from "./insn" import { BasicBlock } from "../ir/block" export const realizeBlock = (block: BasicBlock): Array => block.insns.flatMap(realizeInsn) export const realizeInsn = (insn: AbsInsn2): Array => insnReduce2( realizeCopy, realizeLabel, realizeGoto, realizeUnary, insn, ) const getSourceName = (source: Operand): string => typeof source === "number" ? source.toString() : source.asmName() export const realizeCopy = (dest: Loc, source: Operand): Array => [ `LD ${dest.asmName()}, ${getSourceName(source)}` ] export const realizeLabel = (name: string): Array => [ `${name}:`, ] export const realizeGoto = (name: string): Array => [ `JR ${name}`, ] export const realizeUnary = (dest: Loc, op: UnaryOp | BinaryOp, source: Operand): Array => { if (!isA(dest)) { throw new Error("unexpected form for unary operation") } let output: Array = [] switch (op) { case "add": return [`ADD ${getSourceName(source)}`] case "subtract": return [`SUB ${getSourceName(source)}`] case "bit_and": return [`AND ${getSourceName(source)}`] case "bit_or": return [`OR ${getSourceName(source)}`] case "bit_xor": return [`XOR ${getSourceName(source)}`] case "shift_left": for (let i = 0; i < source; ++i) { output.push("SLA A") } return output case "shift_right": for (let i = 0; i < source; ++i) { output.push("SRL A") } return output case "arith_negate": return ["CPL", "INC A"] case "bit_negate": return ["CPL"] } } const isA = (loc: Operand): boolean => typeof loc === "object" && loc.type === LocType.REGISTER && loc.name === R8.A