A "high-level" language for the Gameboy
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

77 lines
2.0 KiB

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"
export const realizeBlock = (block: Array<AbsInsn2>): Array<SM83Insn> => block.flatMap(realizeInsn)
export const realizeInsn = (insn: AbsInsn2): Array<SM83Insn> => 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<SM83Insn> => [
`LD ${dest.asmName()}, ${getSourceName(source)}`
]
export const realizeLabel = (name: string): Array<SM83Insn> => [
`${name}:`,
]
export const realizeGoto = (name: string): Array<SM83Insn> => [
`JR ${name}`,
]
export const realizeUnary = (dest: Loc, op: UnaryOp | BinaryOp, source: Operand): Array<SM83Insn> => {
if (!isA(dest)) {
throw new Error("unexpected form for unary operation")
}
let output: Array<SM83Insn> = []
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