minic/mips.ml

148 lines
4.8 KiB
OCaml
Raw Permalink Normal View History

2022-01-27 16:31:58 +01:00
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