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.

78 lines
2.1 KiB

  1. import { R8 } from "./cpu"
  2. import { Loc, LocType } from "../ir/loc"
  3. import { Operand, AbsInsn2, insnReduce2 } from "../ir/insn"
  4. import { BinaryOp, UnaryOp } from "../ast"
  5. import type { SM83Insn } from "./insn"
  6. import { BasicBlock } from "../ir/block"
  7. export const realizeBlock = (block: BasicBlock): Array<SM83Insn> => block.insns.flatMap(realizeInsn)
  8. export const realizeInsn = (insn: AbsInsn2): Array<SM83Insn> => insnReduce2(
  9. realizeCopy,
  10. realizeLabel,
  11. realizeGoto,
  12. realizeUnary,
  13. insn,
  14. )
  15. const getSourceName = (source: Operand): string => typeof source === "number"
  16. ? source.toString()
  17. : source.asmName()
  18. export const realizeCopy = (dest: Loc, source: Operand): Array<SM83Insn> => [
  19. `LD ${dest.asmName()}, ${getSourceName(source)}`
  20. ]
  21. export const realizeLabel = (name: string): Array<SM83Insn> => [
  22. `${name}:`,
  23. ]
  24. export const realizeGoto = (name: string): Array<SM83Insn> => [
  25. `JR ${name}`,
  26. ]
  27. export const realizeUnary = (dest: Loc, op: UnaryOp | BinaryOp, source: Operand): Array<SM83Insn> => {
  28. if (!isA(dest)) {
  29. throw new Error("unexpected form for unary operation")
  30. }
  31. let output: Array<SM83Insn> = []
  32. switch (op) {
  33. case "add":
  34. return [`ADD ${getSourceName(source)}`]
  35. case "subtract":
  36. return [`SUB ${getSourceName(source)}`]
  37. case "bit_and":
  38. return [`AND ${getSourceName(source)}`]
  39. case "bit_or":
  40. return [`OR ${getSourceName(source)}`]
  41. case "bit_xor":
  42. return [`XOR ${getSourceName(source)}`]
  43. case "shift_left":
  44. for (let i = 0; i < source; ++i) {
  45. output.push("SLA A")
  46. }
  47. return output
  48. case "shift_right":
  49. for (let i = 0; i < source; ++i) {
  50. output.push("SRL A")
  51. }
  52. return output
  53. case "arith_negate":
  54. return ["CPL", "INC A"]
  55. case "bit_negate":
  56. return ["CPL"]
  57. }
  58. }
  59. const isA = (loc: Operand): boolean =>
  60. typeof loc === "object" && loc.type === LocType.REGISTER && loc.name === R8.A