summaryrefslogtreecommitdiff
path: root/src/mips.ml
diff options
context:
space:
mode:
Diffstat (limited to 'src/mips.ml')
-rw-r--r--src/mips.ml186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/mips.ml b/src/mips.ml
new file mode 100644
index 0000000..f2ef3db
--- /dev/null
+++ b/src/mips.ml
@@ -0,0 +1,186 @@
+
+type register =
+ | ZERO | A0 | A1 | A2 | V0 | T0 | T1 | T2 | S0 | RA | SP | FP
+
+type address =
+ | Alab of string
+ | Areg of int * register
+
+type operand =
+ | Oimm of int
+ | Oreg of register
+
+type arith = Add | Sub | Mul | Div | Rem
+
+type condition = Eq | Ne | Le | Lt | Ge | Gt
+
+type label = string
+
+type instruction =
+ | Move of register * register
+ | Li of register * int
+ | Li32 of register * int32
+ | La of register * label
+ | Lw of register * address
+ | Sw of register * address
+ | Lb of register * address
+ | Sb of register * address
+ | Arith of arith * register * register * operand
+ | Neg of register * register
+ | Set of condition * register * register * operand
+ | B of label
+ | Beq of register * register * label
+ | Beqz of register * label
+ | Bnez of register * label
+ | J of string
+ | Jal of string
+ | Jr of register
+ | Jalr of register
+ | Syscall
+ | Label of string
+ | Inline of string
+
+type word = Wint of int | Waddr of string
+
+type data =
+ | Asciiz of string * string
+ | Word of string * word list
+ | Space of string * int
+ | Align of int
+
+type code =
+ | Clist of instruction list
+ | Capp of code * code
+
+let nop = Clist []
+
+let mips l = Clist l
+
+let inline s = Clist [Inline s]
+
+let (++) c1 c2 = Capp (c1, c2)
+
+type program = {
+ text : code;
+ data : data list;
+}
+
+open Format
+
+let print_register fmt = function
+ | ZERO -> pp_print_string fmt "$0"
+ | A0 -> pp_print_string fmt "$a0"
+ | A1 -> pp_print_string fmt "$a1"
+ | A2 -> pp_print_string fmt "$a2"
+ | V0 -> pp_print_string fmt "$v0"
+ | T0 -> pp_print_string fmt "$t0"
+ | T1 -> pp_print_string fmt "$t1"
+ | T2 -> pp_print_string fmt "$t2"
+ | S0 -> pp_print_string fmt "$s0"
+ | RA -> pp_print_string fmt "$ra"
+ | SP -> pp_print_string fmt "$sp"
+ | FP -> pp_print_string fmt "$fp"
+
+let print_arith fmt = function
+ | Add -> pp_print_string fmt "add"
+ | Sub -> pp_print_string fmt "sub"
+ | Mul -> pp_print_string fmt "mul"
+ | Div -> pp_print_string fmt "div"
+ | Rem -> pp_print_string fmt "rem"
+
+let print_condition fmt = function
+ | Eq -> pp_print_string fmt "seq"
+ | Ne -> pp_print_string fmt "sne"
+ | Lt -> pp_print_string fmt "slt"
+ | Le -> pp_print_string fmt "sle"
+ | Gt -> pp_print_string fmt "sgt"
+ | Ge -> pp_print_string fmt "sge"
+
+let print_address fmt = function
+ | Alab s -> pp_print_string fmt s
+ | Areg (ofs, r) -> fprintf fmt "%d(%a)" ofs print_register r
+
+let print_operand fmt = function
+ | Oimm i -> pp_print_int fmt i
+ | Oreg r -> print_register fmt r
+
+let print_instruction fmt = function
+ | Move (dst, src) ->
+ fprintf fmt "\tmove %a, %a\n" print_register dst print_register src
+ | Li (r, i) ->
+ fprintf fmt "\tli %a, %d\n" print_register r i
+ | Li32 (r, i) ->
+ fprintf fmt "\tli %a, %ld\n" print_register r i
+ | La (r, s) ->
+ fprintf fmt "\tla %a, %s\n" print_register r s
+ | Lw (r, a) ->
+ fprintf fmt "\tlw %a, %a\n" print_register r print_address a
+ | Sw (r, a) ->
+ fprintf fmt "\tsw %a, %a\n" print_register r print_address a
+ | Lb (r, a) ->
+ fprintf fmt "\tlb %a, %a\n" print_register r print_address a
+ | Sb (r, a) ->
+ fprintf fmt "\tsb %a, %a\n" print_register r print_address a
+ | Arith (a, dst, src, op) ->
+ fprintf fmt "\t%a %a, %a, %a\n"
+ print_arith a print_register dst print_register src print_operand op
+ | Neg (dst, src) ->
+ fprintf fmt "\tneg %a, %a\n" print_register dst print_register src
+ | Set (cond, dst, src, op) ->
+ fprintf fmt "\t%a %a, %a, %a\n"
+ print_condition cond print_register dst print_register src
+ print_operand op
+ | B l ->
+ fprintf fmt "\tb %s\n" l
+ | Beq (r1, r2, l) ->
+ fprintf fmt "\tbeq %a, %a, %s\n" print_register r1 print_register r2 l
+ | Beqz (r, l) ->
+ fprintf fmt "\tbeqz %a, %s\n" print_register r l
+ | Bnez (r, l) ->
+ fprintf fmt "\tbnez %a, %s\n" print_register r l
+ | J s ->
+ fprintf fmt "\tj %s\n" s
+ | Jal s ->
+ fprintf fmt "\tjal %s\n" s
+ | Jalr r ->
+ fprintf fmt "\tjalr %a\n" print_register r
+ | Jr r ->
+ fprintf fmt "\tjr %a\n" print_register r
+ | Syscall ->
+ fprintf fmt "\tsyscall\n"
+ | Label s ->
+ fprintf fmt "%s:\n" s
+ | Inline s ->
+ fprintf fmt "%s" s
+
+let rec print_code fmt = function
+ | Clist l -> List.iter (print_instruction fmt) l
+ | Capp (c1, c2) -> print_code fmt c1; print_code fmt c2
+
+let print_word fmt = function
+ | Wint n -> pp_print_int fmt n
+ | Waddr s -> pp_print_string fmt s
+
+let rec print_list print fmt = function
+ | [] -> ()
+ | [x] -> print fmt x
+ | x :: r -> fprintf fmt "%a, %a" print x (print_list print) r
+
+let print_data fmt = function
+ | Asciiz (l, s) ->
+ fprintf fmt "%s:\n\t.asciiz %S\n" l s
+ | Word (l, n) ->
+ fprintf fmt "%s:\n\t.word %a\n" l (print_list print_word) n
+ | Space (l, n) ->
+ fprintf fmt "%s:\n\t.space %d\n" l n
+ | Align n ->
+ fprintf fmt "\t.align %d\n" n
+
+let print_program fmt p =
+ fprintf fmt "\t.text\n";
+ print_code fmt p.text;
+ fprintf fmt "\t.data\n";
+ List.iter (print_data fmt) p.data;
+ fprintf fmt "@."
+
+