diff options
Diffstat (limited to 'src/mips.ml')
-rw-r--r-- | src/mips.ml | 186 |
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 "@." + + |