Files
IPS_G-assignment/Fasto/Mips.fs
2022-05-18 10:46:19 +02:00

128 lines
5.7 KiB
Forth

(* Types and utilities for the abstract syntax of MIPS. *)
module Mips
open AbSyn
type reg = RN of int | RS of string
type imm = int
type addr = string
type Instruction =
LABEL of addr (* Angiver en label, man fx kan hoppe til *)
| COMMENT of string (* Placerer en kommentar i assemblerkoden *)
| LA of reg*addr (* LA($rd,addr): $rd = addr (label) *)
| LUI of reg*imm (* LUI($rd,imm): $rd = (imm << 16) *)
| LW of reg*reg*imm (* LW($rd,$rs,imm): $rd = Mem[$rs + imm] *)
| LB of reg*reg*imm (* LB($rd,$rs,imm): $rd = Mem[$rs + imm] *)
| SW of reg*reg*imm (* SW($rw,$rm,imm): Mem[$rm + imm] = $rw *)
| SB of reg*reg*imm (* SB($rb,$rm,imm): Mem[$rm + imm] = $rb *)
(* Aritmetiske instruktioner *)
| ADD of reg*reg*reg (* ADD($rd,$rs,$rt): $rd = $rs + $rt. *)
| ADDI of reg*reg*imm (* ADDI($rd,$rs,imm): $rd = $rs + imm *)
| SUB of reg*reg*reg (* SUB($rd,$rs,$rt): $rd = $rs - $rt. *)
| MUL of reg*reg*reg (* MUL($rd,$rs,$rt): $rd = $rs * $rt, no overflow. *)
| DIV of reg*reg*reg (* DIV($rd,$rs,$rt): $rd = quotient($rd / $rs), no overflow. *)
(* Bitvise operatorer *)
| AND of reg*reg*reg (* AND($rd,$rs,$rt): $rd = $rs & $rt *)
| ANDI of reg*reg*imm (* ANDI($rd,$rs,imm): $rd = $rs & imm *)
| OR of reg*reg*reg (* OR($rd,$rs,$rt): $rd = $rs | $rt *)
| ORI of reg*reg*imm (* ORI($rd,$rs,imm): $rd = $rs | imm *)
| XOR of reg*reg*reg (* XOR($rd,$rs,$rt): $rd = $rs ^ $rt *)
| XORI of reg*reg*imm (* XORI($rd,$rs,imm): $rd = $rs ^ imm *)
(* Bit-shifting *)
| SLL of reg*reg*imm (* SLL($rd,$rs,imm): $rd = $rs << imm *)
| SRA of reg*reg*imm (* SRA($rd,$rs,imm): $rd = $rs >> imm *)
(* Instruktioner til sammenligning *)
| SLT of reg*reg*reg (* SLT($rd,$rs,$rt): $rd = $rs < $rt *)
| SLTI of reg*reg*imm (* SLTI($rd,$rs,imm): $rd = $rs < imm *)
| BEQ of reg*reg*addr (* BEQ($rs,$rt,addr): if ($rs == $rd) goto(addr) *)
| BNE of reg*reg*addr (* BNE($rs,$rt,addr): if ($rs != $rd) goto(addr) *)
| BGEZ of reg*addr (* BGEZ($rs,addr): if ($rs >= $0) goto(addr) *)
| J of addr (* J(addr): goto(addr) *)
| JR of reg * reg list (* JR($rd,regs): goto($rd) *)
| JAL of addr* reg list (* JAL(addr,regs): $RA = $PC; goto(addr) *)
| NOP
| SYSCALL (* Udfører det systemkald som er nævnt i $2 *)
(* Angiver direktiverne .globl, .text, .data, .space, ascii, .asciiz, .align *)
| GLOBL of addr
| TEXT of addr
| DATA of addr
| SPACE of int
| ASCII of string
| ASCIIZ of string
| ALIGN of int
(* Diverse pseudo-instruktioner *)
let MOVE (rd,rs) = ORI (rd, rs, 0) (* MOVE($rd,$rs): $rd = $rs *)
let LI (rd,imm) = ORI (rd, RN 0, imm) (* LI($rd,imm): $rd = imm *)
let SUBI (rd, rs, imm) = ADDI (rd, rs, -imm)
type Prog = Instruction list
(* Pretty-print a list of MIPS instructions in the
format accepted by the MARS MIPS simulator. *)
let rec ppMipsProg instructions =
String.concat "\n" (List.map ppMips instructions)
(* Pretty-print a single MIPS instruction for .asm output *)
and ppMips inst =
match inst with
| LABEL l -> l + ":"
| COMMENT s -> "# " + s
| LA (rt,l) -> "\tla\t" + ppReg rt + ", " + l
| LUI (rt,v) -> "\tlui\t" + ppReg rt + ", " + imm2str v
| LW (rd,rs,v) -> "\tlw\t" + ppReg rd + ", " + imm2str v + "(" + ppReg rs + ")"
| LB (rd,rs,v) -> "\tlb\t" + ppReg rd + ", " + imm2str v + "(" + ppReg rs + ")"
| SW (rd,rs,v) -> "\tsw\t" + ppReg rd + ", " + imm2str v + "(" + ppReg rs + ")"
| SB (rd,rs,v) -> "\tsb\t" + ppReg rd + ", " + imm2str v + "(" + ppReg rs + ")"
| ADD (rd,rs,rt) -> "\tadd\t" + ppReg rd + ", " + ppReg rs + ", " + ppReg rt
| ADDI (rd,rs,v) -> "\taddi\t" + ppReg rd + ", " + ppReg rs + ", " + imm2str v
| SUB (rd,rs,rt) -> "\tsub\t" + ppReg rd + ", " + ppReg rs + ", " + ppReg rt
| MUL (rd,rs,rt) -> "\tmul\t" + ppReg rd + ", " + ppReg rs + ", " + ppReg rt
| DIV (rd,rs,rt) -> "\tdiv\t" + ppReg rd + ", " + ppReg rs + ", " + ppReg rt
| AND (rd,rs,rt) -> "\tand\t" + ppReg rd + ", " + ppReg rs + ", " + ppReg rt
| ANDI (rd,rs,v) -> "\tandi\t" + ppReg rd + ", " + ppReg rs + ", " + imm2str v
| OR (rd,rs,rt) -> "\tor\t" + ppReg rd + ", " + ppReg rs + ", " + ppReg rt
| ORI (rd,rs,v) -> "\tori\t" + ppReg rd + ", " + ppReg rs + ", " + imm2str v
| XOR (rd,rs,rt) -> "\txor\t" + ppReg rd + ", " + ppReg rs + ", " + ppReg rt
| XORI (rd,rs,v) -> "\txori\t" + ppReg rd + ", " + ppReg rs + ", " + imm2str v
| SLL (rd,rt,v) -> "\tsll\t" + ppReg rd + ", " + ppReg rt + ", " + imm2str v
| SRA (rd,rt,v) -> "\tsra\t" + ppReg rd + ", " + ppReg rt + ", " + imm2str v
| SLT (rd,rs,rt) -> "\tslt\t" + ppReg rd + ", " + ppReg rs + ", " + ppReg rt
| SLTI (rd,rs,v) -> "\tslti\t" + ppReg rd + ", " + ppReg rs + ", " + imm2str v
| BEQ (rs,rt,l) -> "\tbeq\t" + ppReg rs + ", " + ppReg rt + ", " + l
| BNE (rs,rt,l) -> "\tbne\t" + ppReg rs + ", " + ppReg rt + ", " + l
| BGEZ (rs,l) -> "\tbgez\t" + ppReg rs + ", " + l
| J l -> "\tj\t" + l
| JAL (l,argRegs) -> "\tjal\t" + l
| JR (r,resRegs) -> "\tjr\t" + ppReg r
| NOP -> "\tnop"
| SYSCALL -> "\tsyscall"
| GLOBL s -> "\t.globl\t" + s
| TEXT s -> "\t.text\t" + s
| DATA s -> "\t.data\t" + s
| SPACE s -> "\t.space\t" + string s
| ASCII s -> "\t.ascii\t\"" + toCString s + "\""
| ASCIIZ s -> "\t.asciiz\t\"" + toCString s + "\""
| ALIGN s -> "\t.align\t" + string s
and ppReg r =
match r with
| RN n -> "$" + string n
| RS s -> s
and imm2str (i:imm) = string i (* maybe add some sanity checks here *)