type reg = | Zero (* Toujours à zéro *) | V0 (* Valeurs de retours *) | V1 (* .................. *) | A0 (* Premiers arguments des fonctions *) | A1 (* ................................ *) | A2 (* ................................ *) | A3 (* ................................ *) | T0 (* Registres temporaires *) | T1 (* ..................... *) | T2 (* ..................... *) | T3 (* ..................... *) | T4 (* ..................... *) | T5 (* ..................... *) | T6 (* ..................... *) | T7 (* ..................... *) | T8 (* ..................... *) | T9 (* ..................... *) | S0 (* Registres sauvegardés *) | S1 (* ..................... *) | S2 (* ..................... *) | S3 (* ..................... *) | S4 (* ..................... *) | S5 (* ..................... *) | S6 (* ..................... *) | S7 (* ..................... *) | GP (* Global pointer *) | SP (* Stack pointer *) | FP (* Frame pointer *) | RA (* Adresse de retour *) type label = string type loc = | Lbl of label | Mem of reg * int type instr = | Label of label | Li of reg * int | La of reg * loc | Sw of reg * loc | Lw of reg * loc | Sb of reg * loc | Lb of reg * loc | Move of reg * reg | Neg of reg * reg | Addi of reg * reg * int | Add of reg * reg * reg | Mul of reg * reg * reg | Syscall | B of label | Beqz of reg * label | Jal of label | Jr of reg 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_float = 2 let print_double = 3 let print_str = 4 let read_int = 5 let read_float = 6 let read_double = 7 let read_str = 8 let sbrk = 9 let exit = 10 end let fmt_reg = function | Zero -> "$zero" | V0 -> "$v0" | V1 -> "$v1" | A0 -> "$a0" | A1 -> "$a1" | A2 -> "$a2" | A3 -> "$a3" | T0 -> "$t0" | T1 -> "$t1" | T2 -> "$t2" | T3 -> "$t3" | T4 -> "$t4" | T5 -> "$t5" | T6 -> "$t6" | T7 -> "$t7" | T8 -> "$t8" | T9 -> "$t9" | S0 -> "$s0" | S1 -> "$s1" | S2 -> "$s2" | S3 -> "$s3" | S4 -> "$s4" | S5 -> "$s5" | S6 -> "$s6" | S7 -> "$s7" | GP -> "$gp" | SP -> "$sp" | FP -> "$fp" | RA -> "$ra" ;; let fmt_loc = function | Lbl l -> l | Mem (r, o) -> Printf.sprintf "%d(%s)" o (fmt_reg r) ;; let fmt_instr = function | Label _ -> "" | _ as i -> Printf.sprintf " " ^ (match i with | Label l -> Printf.sprintf "%s:" l | Li (r, i) -> Printf.sprintf "li %s, %d" (fmt_reg r) i | La (r, a) -> Printf.sprintf "la %s, %s" (fmt_reg r) (fmt_loc a) | Sw (r, a) -> Printf.sprintf "sw %s, %s" (fmt_reg r) (fmt_loc a) | Lw (r, a) -> Printf.sprintf "lw %s, %s" (fmt_reg r) (fmt_loc a) | Sb (r, a) -> Printf.sprintf "sb %s, %s" (fmt_reg r) (fmt_loc a) | Lb (r, a) -> Printf.sprintf "lb %s, %s" (fmt_reg r) (fmt_loc a) | Move (rd, rs) -> Printf.sprintf "move %s, %s" (fmt_reg rd) (fmt_reg rs) | Neg (r, a) -> Printf.sprintf "neg %s, %s" (fmt_reg r) (fmt_reg a) | Addi (rd, rs, i) -> Printf.sprintf "addi %s, %s, %d" (fmt_reg rd) (fmt_reg rs) i | Add (rd, rs, rt) -> Printf.sprintf "add %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Mul (rd, rs, rt) -> Printf.sprintf "mul %s, %s, %s" (fmt_reg rd) (fmt_reg rs) (fmt_reg rt) | Syscall -> Printf.sprintf "syscall" | B l -> Printf.sprintf "b %s" l | Beqz (r, l) -> Printf.sprintf "beqz %s, %s" (fmt_reg r) l | Jal l -> Printf.sprintf "jal %s" l | Jr r -> Printf.sprintf "jr %s" (fmt_reg r)) ;; let fmt_dir = function | Asciiz s -> Printf.sprintf ".asciiz \"%s\"" s ;; let emit oc asm = Printf.fprintf oc ".text\n.globl main\nmain:\n"; List.iter (fun i -> Printf.fprintf oc "%s\n" (fmt_instr i)) asm.text; Printf.fprintf oc "%s\n%s\n%s\n%s\n" (fmt_instr (Move (A0, V0))) (fmt_instr (Li (V0, 1))) (fmt_instr Syscall) (fmt_instr (Jr RA)); Printf.fprintf oc "\n.data\n"; List.iter (fun (l, d) -> Printf.fprintf oc "%s: %s\n" l (fmt_dir d)) asm.data ;;