|
|
@ -1,4 +1,4 @@ |
|
|
|
import type { SSA } from "./ir" |
|
|
|
import type { SSA, SSABinary, SSACopy, SSAUnary } from "./ir" |
|
|
|
|
|
|
|
const reg8 = ["B", "C", "D", "E"] as const |
|
|
|
|
|
|
@ -62,42 +62,130 @@ export const convertASM = (ir: Array): Array => { |
|
|
|
const state = new ASMState() |
|
|
|
|
|
|
|
ir.forEach(ssa => convertASM_SSA(state, ssa)) |
|
|
|
|
|
|
|
for (let sym of Object.keys(state.syms)) { |
|
|
|
if (sym.startsWith("temp")) { |
|
|
|
continue |
|
|
|
} |
|
|
|
|
|
|
|
state.insns.push( |
|
|
|
`LD A, ${state.syms[sym]}`, |
|
|
|
`LD (${sym}), A` |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
for (let sym of Object.keys(state.stack_offsets)) { |
|
|
|
if (sym.startsWith("temp")) { |
|
|
|
continue |
|
|
|
} |
|
|
|
|
|
|
|
state.insns.push( |
|
|
|
`LD HL, SP + (${state.cur_offset - state.stack_offsets[sym]})`, |
|
|
|
`LD A, (HL)`, |
|
|
|
`LD (${sym}), A` |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
if (state.cur_offset !== 0) { |
|
|
|
state.insns.push(`ADD SP, ${state.cur_offset}`) |
|
|
|
} |
|
|
|
|
|
|
|
return state.insns |
|
|
|
} |
|
|
|
|
|
|
|
// TODO: Track liveness
|
|
|
|
const convertASM_SSA = (state: ASMState, ssa: SSA): void => { |
|
|
|
const dest = state.alloc_sym_loc(ssa.dest) |
|
|
|
|
|
|
|
if ("source1" in ssa) { // Binary
|
|
|
|
convertASM_SSA_Binary(state, ssa) |
|
|
|
} else if ("op" in ssa) { // Unary
|
|
|
|
convertASM_SSA_Unary(state, ssa) |
|
|
|
} else { // Copy
|
|
|
|
let source = "" |
|
|
|
if (typeof ssa.source == "number") { |
|
|
|
source = ssa.source.toString() |
|
|
|
convertASM_SSA_Copy(state, ssa) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
export const convertASM_SSA_Binary = (state: ASMState, ssa: SSABinary): void => { |
|
|
|
const dest = state.alloc_sym_loc(ssa.dest) |
|
|
|
} |
|
|
|
|
|
|
|
export const convertASM_SSA_Unary = (state: ASMState, ssa: SSAUnary): void => { |
|
|
|
const dest = state.alloc_sym_loc(ssa.dest) |
|
|
|
|
|
|
|
if (typeof ssa.source == "number") { |
|
|
|
state.insns.push(`LD A, ${ssa.source}`) |
|
|
|
} else { |
|
|
|
const loc = state.get_sym_loc(ssa.source) |
|
|
|
|
|
|
|
if (loc === null) { |
|
|
|
state.insns.push(`LD A, (${ssa.source})`) |
|
|
|
} else if (typeof loc === "string") { |
|
|
|
state.insns.push(`LD A, ${loc}`) |
|
|
|
} else { |
|
|
|
const loc = state.get_sym_loc(ssa.source) |
|
|
|
|
|
|
|
if (loc === null) { |
|
|
|
state.insns.push(`LD A, (${ssa.source})`) |
|
|
|
source = "A" |
|
|
|
} else if (typeof loc === "string") { |
|
|
|
source = loc |
|
|
|
} else { |
|
|
|
state.insns.push( |
|
|
|
`LD HL, SP + (${loc})`, |
|
|
|
`LD A, (HL)` |
|
|
|
) |
|
|
|
source = "A" |
|
|
|
} |
|
|
|
state.insns.push( |
|
|
|
`LD HL, SP + (${loc})`, |
|
|
|
`LD A, (HL)` |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
switch (ssa.op) { |
|
|
|
case 'arith_negate': |
|
|
|
state.insns.push( |
|
|
|
`CPL`, |
|
|
|
`INC A`, |
|
|
|
) |
|
|
|
break |
|
|
|
|
|
|
|
case 'bit_negate': |
|
|
|
state.insns.push( |
|
|
|
`CPL` |
|
|
|
) |
|
|
|
break |
|
|
|
|
|
|
|
if (typeof dest === "string") { |
|
|
|
state.insns.push(`LD ${dest}, ${source}`) |
|
|
|
default: |
|
|
|
throw new Error(`unsupported unary op \`'${ssa.op}`) |
|
|
|
} |
|
|
|
|
|
|
|
if (typeof dest === "string") { |
|
|
|
state.insns.push(`LD ${dest}, A`) |
|
|
|
} else { |
|
|
|
state.insns.push( |
|
|
|
`LD HL, SP + (${dest})`, |
|
|
|
`LD (HL), A` |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export const convertASM_SSA_Copy = (state: ASMState, ssa: SSACopy): void => { |
|
|
|
const dest = state.alloc_sym_loc(ssa.dest) |
|
|
|
|
|
|
|
let source = "" |
|
|
|
if (typeof ssa.source == "number") { |
|
|
|
source = ssa.source.toString() |
|
|
|
} else { |
|
|
|
const loc = state.get_sym_loc(ssa.source) |
|
|
|
|
|
|
|
if (loc === null) { |
|
|
|
state.insns.push(`LD A, (${ssa.source})`) |
|
|
|
source = "A" |
|
|
|
} else if (typeof loc === "string") { |
|
|
|
source = loc |
|
|
|
} else { |
|
|
|
state.insns.push( |
|
|
|
`LD HL, SP + (${dest})`, |
|
|
|
`LD (HL), ${source}` |
|
|
|
`LD HL, SP + (${loc})`, |
|
|
|
`LD A, (HL)` |
|
|
|
) |
|
|
|
source = "A" |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (typeof dest === "string") { |
|
|
|
state.insns.push(`LD ${dest}, ${source}`) |
|
|
|
} else { |
|
|
|
state.insns.push( |
|
|
|
`LD HL, SP + (${dest})`, |
|
|
|
`LD (HL), ${source}` |
|
|
|
) |
|
|
|
} |
|
|
|
} |