type reg = | Zero | SP | RA | FP | V0 | F0 | F1 | F2 | A0 | A1 | T0 | T1 (* | FF *) type label = string type loc = | Lbl of label | Mem of reg * int type instr = | Label of label | Li of reg * int | Lis of reg * float | La of reg * loc | Sw of reg * loc | Lw of reg * loc | Ls of reg * loc | Sb of reg * loc | Lb of reg * loc | Move of reg * reg | Addi of reg * reg * int | Add of reg * reg * reg | Sub of reg * reg * reg | Div of reg * reg * reg | Mflo of reg | Mfhi of reg | Xor of reg * reg * reg | Or of reg * reg * reg | Nor of reg * reg * reg | And of reg * reg * reg | Mul of reg * reg * reg | Seq of reg * reg * reg | Sne of reg * reg * reg | Sge of reg * reg * reg | Sgt of reg * reg * reg | Sle of reg * reg * reg | Slt of reg * reg * reg | Adds of reg * reg * reg | Subs of reg * reg * reg | Muls of reg * reg * reg | Divs of reg * reg * reg | Andi of reg * reg * int | Not of reg * reg | Syscall | B of label | Beqz of reg * label | Jal of label | Jr of reg | J of label type directive = | Asciiz of string type decl = label * directive type asm = { text: instr list ; data: decl list } module Syscall = struct let print_int = 1 let print_str = 4 let read_int = 5 let read_str = 8 let sbrk = 9 end let ps = Printf.sprintf (* alias raccourci *) let fmt_reg = function | Zero -> "$zero" | SP -> "$sp" | FP -> "$fp" | RA -> "$ra" | V0 -> "$v0" | F0 -> "$f0" | F1 -> "$f1" | F2 -> "$f2" | A0 -> "$a0" | A1 -> "$a1" | T0 -> "$t0" | T1 -> "$t1" (* | FF -> "0x00ff" *) let fmt_loc = function | Lbl (l) -> l | Mem (r, o) -> ps "%d(%s)" o (fmt_reg r) let fmt_instr = function | Label (l) -> ps "%s:" l | Li (r, i) -> ps " li %s, %d" (fmt_reg r) i | Lis (r, i) -> ps " li.s %s, %f" (fmt_reg r) i | La (r, a) -> ps " la %s, %s" (fmt_reg r) (fmt_loc a) | Sw (r, a) -> ps " sw %s, %s" (fmt_reg r) (fmt_loc a) | Lw (r, a) -> ps " lw %s, %s" (fmt_reg r) (fmt_loc a) | Ls (r, a) -> ps " l.s %s, %s" (fmt_reg r) (fmt_loc a) | Sb (r, a) -> ps " sb %s, %s" (fmt_reg r) (fmt_loc a) | Lb (r, a) -> ps " lb %s, %s" (fmt_reg r) (fmt_loc a) | Move (rd, rs) -> ps " move %s, %s" (fmt_reg rd) (fmt_reg rs) | Addi (rd, rs, i) -> ps " addi %s, %s, %d" (fmt_reg rd) (fmt_reg rs) i | Add (rd, rs, rt) -> ps " add %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Sub (rd, rs, rt) -> ps " sub %s, %s, %s" (fmt_reg rd)(fmt_reg rt) (fmt_reg rs) | Div (rd, rs, rt) -> ps " div %s, %s, %s" (fmt_reg rd) (fmt_reg rt) (fmt_reg rs) | Mflo rd -> ps " mflo %s" (fmt_reg rd) | Mfhi rd -> ps " mfhi %s" (fmt_reg rd) | Xor (rd, rs, rt) -> ps " xor %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Or (rd, rs, rt) -> ps " or %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Nor (rd, rs, rt) -> ps " nor %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | And (rd, rs, rt) -> ps " and %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Mul (rd, rs, rt) -> ps " mul %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Seq (rd, rs, rt) -> ps " seq %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Sne (rd, rs, rt) -> ps " sne %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Sge (rd, rt, rs) -> ps " sge %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Sgt (rd, rt, rs) -> ps " sgt %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Sle (rd, rt, rs) -> ps " sle %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Slt (rd, rt, rs) -> ps " slt %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Adds (rd, rt, rs) -> ps " add.s %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Subs (rd, rt, rs) -> ps " sub.s %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Muls (rd, rt, rs) -> ps " mul.s %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Divs (rd, rt, rs) -> ps " div.s %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Andi (rd, rs, i) -> ps " and %s, %s, %d" (fmt_reg rd) (fmt_reg rs) i | Not (rd, rs) -> ps " not %s, %s" (fmt_reg rd) (fmt_reg rs) | Syscall -> ps " syscall" | B (l) -> ps " b %s" l | Beqz (r, l) -> ps " beqz %s, %s" (fmt_reg r) l | Jal (l) -> ps " jal %s" l | Jr (r) -> ps " jr %s" (fmt_reg r) | J (l) -> ps " j %s" l let fmt_dir = function | Asciiz (s) -> ps ".asciiz \"%s\"" s let print_asm oc asm = Printf.fprintf oc ".text\n.globl main\n" ; List.iter (fun i -> Printf.fprintf oc "%s\n" (fmt_instr i)) asm.text ; Printf.fprintf oc "\n.data\n" ; List.iter (fun (l, d) -> Printf.fprintf oc "%s: %s\n" l (fmt_dir d)) asm.data