148 lines
4.8 KiB
OCaml
148 lines
4.8 KiB
OCaml
|
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
|