summaryrefslogblamecommitdiff
path: root/src/mips.mli
blob: f1e39d64942fe7bb59605945c818a0a88c444d83 (plain) (tree)
1
2
3
4
5
6
 
                                           
 

                                         
 






                                          
 
                                                             
 
 






                                                                     
 






                                                                     

                

              
 

                                                                    

                                                       

















                                                                    





                 


































































































































































































                                                                            
 



































                                                                                                                                     
(* Bibliothèque pour produire du code MIPS

   2008 Jean-Christophe Filliâtre (CNRS)
   - version initiale

   2013 Kim Nguyen (Université Paris Sud)
   - sous-types text et data
   - types fantômes pour oreg et oi
   - plus d'opérations et de directives
   - manipulation de la pile
   - ocamldoc
*)

(** {0 Bibliothèque pour l'écriture de programmes MIPS } *)


(** Le module {!Mips} permet l'écriture de code MIPS dans du code
    OCaml, sans utiliser un préprocesseur.  Un exemple complet est
    donné {{:#1_Exemple}ci-dessous, dans la section exemple}. *)

type 'a asm
(** type abstrait pour représenter du code assembleur. Le paramètre
    ['a] est utilisé comme type fantôme. *)

type text = [ `text ] asm
(** type représentant du code assembleur se trouvant dans la zone de
    texte *)

type data = [ `data ] asm
(** type représentant du code assembleur se trouvant dans la zone de
    données *)

type program = {
  text : text;
  data : data;
}
(** un programme est constitué d'une zone de texte et d'une zone de
    donnée *)

val print_program : Format.formatter -> program -> unit
  (** [print_program fmt p] imprime le code du programme [p] dans le
      formatter [fmt] *)

val print_in_file: file:string -> program -> unit

type register
(** Type abstrait pour les registres *)

val v0 : register
val v1 : register
val a0 : register
val a1 : register
val a2 : register
val a3 : register
val t0 : register
val t1 : register
val t2 : register
val t3 : register
val t4 : register
val t5 : register
val t6 : register
val t7 : register
val t8 : register
val t9 : register
val s0 : register
val s1 : register
val ra : register
val sp : register
val fp : register
val gp : register
val zero : register
(** Constantes représentant les registres manipulables. [zero] est
    cablé à 0 *)


type label = string
(** Les étiquettes d'addresses sont des chaines de caractères *)

type 'a operand
val oreg : register operand
val oi : int operand
val oi32 : int32 operand

(** type abstrait pour représenter la dernière opérande d'une
    expression arithmétique ainsi que 3 constantes (soit un registre,
    soit un entier, soit un entier 32 bits)
*)



(** {1 Opérations arithmétiques } *)


val li : register -> int -> text
val li32 : register -> int32 -> text
(** Chargement des constantes entières *)

val abs : register -> register -> text
(** [abs r1 r2] stocke dans r1 la valeur absolue de r2 *)

val neg : register -> register -> text
(** [neg r1 r2] stocke dans r1 l'opposé de r2 *)

val add : register -> register -> 'a operand -> 'a -> text
val sub : register -> register -> 'a operand -> 'a -> text
val mul : register -> register -> 'a operand -> 'a -> text
val rem : register -> register -> 'a operand -> 'a -> text
val div : register -> register -> 'a operand -> 'a -> text

(** Les 5 opérations arithmétique de base: [add rdst rsrc1 ospec o]
   stocke dans rdst le résultat de l'opération entre rsrc1 et o. La
   constant ospec spécifie si o est un immédiat, immédiat sur 32 bits
   ou un registre.
   Exemple:

   [add v0 v1 oreg v2]

   [div v0 v1 oi 424]

   [sub t0 a0 oi32 2147483647l]
 *)

(** {1 Opérations logiques } *)

val and_ : register -> register -> register -> text
val or_ : register -> register -> register -> text
val not_ : register -> register -> text
val clz : register -> register -> text
(** Opérations de manipulation de bits. "et" bit à bit, "ou" bit à
    bit, "not" bit à bit et clz (count leading zero) *)


(** {1 Comparaisons } *)

val seq : register -> register -> register -> text
val sge : register -> register -> register -> text
val sgt : register -> register -> register -> text
val sle : register -> register -> register -> text
val slt : register -> register -> register -> text
val sne : register -> register -> register -> text
  (** conditionnelles [sop ra rb rc] met [ra] à 1 si [rb op rc] et à 0
      dans le cas contraire (eq : ==, ge : >=, gt : >, le : <=, lt : <=,
      ne : !=) *)

(** {1 Sauts } *)

val b : label -> text
(** saut inconditionnel *)

val beq : register -> register -> label -> text
val bne : register -> register -> label -> text
val bge : register -> register -> label -> text
val bgt : register -> register -> label -> text
val ble : register -> register -> label -> text
val blt : register -> register -> label -> text
(** [bop ra rb label] branche vers le label [label] si [ra op rb] *)

val beqz : register -> label -> text
val bnez : register -> label -> text
val bgez : register -> label -> text
val bgtz : register -> label -> text
val blez : register ->  label -> text
val bltz : register ->  label -> text
(** [bopz ra rb label] branche vers le label [label] si [ra op 0] *)


val jr : register -> text
(** [jr r] Continue l'exécution à l'adresse spécifiée dans le registre
    [r] *)
val jal : label -> text
(** [jal l] Continue l'exécution à l'adresse spécifiée par le label [l],
    sauve l'adresse de retour dans $ra.
*)
val jalr : register -> text
(** [jalr r] Continue l'exécution à l'adresse spécifiée par le
    registre [r], sauve l'adresse de retour dans $ra.
*)

(** {1 Lecture / écriture en mémoire } *)

type 'a address
(** type abstrait pour représenter des adresses *)

val alab : label address
val areg : (int * register) address
(** Les adresses sont soit données par un label, soit par une paire
    décalage, registre *)

val la : register -> 'a address -> 'a -> text
(** [la reg alab "foo"] charge dans [reg] l'adresse du label "foo"
    [la reg1 areg (x, reg2)] charge dans [reg1] l'adresse contenue dans
    [reg2] décallée de [x] octets
 *)

val lbu : register -> 'a address -> 'a -> text
(** charge l'octet à l'adresse donnée sans extension de signe (valeur
    entre 0 et 255) *)
val lw : register -> 'a address -> 'a -> text
(** charge l'entier 32bits à l'adresse donnée *)
val sb : register -> 'a address -> 'a -> text
(** écrit les 8 bits de poid faible du registre donnée à l'adresse
    donnée *)
val sw : register -> 'a address -> 'a -> text
(** écrit le contenu du registre à l'adresse donnée *)
val move : register -> register -> text

(** {1 Divers } *)

val nop : [> ] asm
(** l'instruction vide. Peut se trouver dans du text ou du data *)

val label : label ->  [> ] asm
(** un label. Peut se retrouver dans du text ou du data *)

val syscall : text
(** l'instruction syscall *)

val comment : string -> [> ] asm
(** place un commentaire dans le code généré. Peut se retrouver dans
    du text ou du data *)

val align : int ->  [> ] asm
(** [align n] aligne le code suivant l'instruction sur 2^n octets *)

val asciiz : string -> data
(** place une constante chaîne de carctères (terminées par 0) dans a
    zone data *)

val dword : int list -> data
(** place une liste de mots mémoires dans la zone data *)

val address : label list -> data
(** place une liste d'adresses (dénotées par des labels) dans la zone
    data *)

val ( ++ ) : ([< `text|`data ] asm as 'a)-> 'a -> 'a
(** concatène deux bouts de codes (soit text avec text, soit data avec
    data) *)

(** {1 Manipulation de la pile} *)

val push : register -> text
(** [push r] place le contenu de [r] au sommet de la pile.
    Rappel : $sp pointe sur l'adresse de la dernière case occupée *)

val pop : register -> text
(** [pop r] place le mot en sommet de pile dans [r] et dépile *)

val popn: int -> text
(** [popn n] dépile [n] octets *)

val peek : register -> text
(** [peek r] place le mot en sommet de pile dans [r] sans dépiler *)

(** {1 Exemple } *)

(** Le programme ci-dessous, donné à gauche en pur MIPS et à droite en
    OCaml, charge deux constantes, effectue quelques opérations
    arithétiques et affiche le résultat à l'écran

    {[
        .text                                                |  { text =
        main:                                                |        label "main"
         #charge 42 dans $a0 et 23 dans $a1                  |    ++  comment "charge 42 dans $a0 et 23 dans $a1"
         li $a0,  42                                         |    ++  li  a0 42
         li $a1,  23                                         |    ++  li  a1 23
         mul $a0, $a0, $a1                                   |    ++  mul a0 a0 oreg a1 (* on utilise oreg pour dire que la dernière
                                                             |                             operande est un registre *)
         #place le contenu de $a0 sur la pile                |    ++  comment "place le contenu de $a0 sur la pile"
         sub $sp, $sp, 4                                     |    ++  sub sp sp oi 4
         sw  $a0,  0($sp)                                    |    ++  sw a0 areg (0, sp)
                                                             |
         #appelle une routine d'affichage                    |    ++  comment "appelle la routine d'affichage"
         jal print_int                                       |    ++  jal "print_int"
                                                             |
         #termine                                            |    ++  comment "termine"
         li $v0, 10                                          |    ++  li v0 10
         syscall                                             |    ++  syscall
                                                             |
      print_int:                                             |    ++  label "print_int"
         lw $a0,  0($sp)                                     |    ++  lw a0 areg (0, sp)
         add $sp, $sp, 4                                     |    ++  add sp sp oi 4
         li $v0, 1                                           |    ++  li v0 1
         syscall                                             |    ++  syscall
         #affiche un retour chariot                          |    ++  comment "affiche un retour chariot"
         la $a0, newline                                     |    ++  la a0 alab "newline"
         li $v0, 4                                           |    ++  li v0  4
         syscall                                             |    ++  syscall
         jr $ra                                              |    ++  jr ra  ; (* fin du label text *)
                                                             |
        .data                                                |    data =
       newline:                                              |        label "newline"
        .asciiz  "\n"                                        |    ++  asciiz "\n" ;
                                                             |  } (* fin du record *)
    ]}
*)