A MiniC++ (C++ subset) compiler for a course.

mips.mli 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. (* Bibliothèque pour produire du code MIPS
  2. 2008 Jean-Christophe Filliâtre (CNRS)
  3. - version initiale
  4. 2013 Kim Nguyen (Université Paris Sud)
  5. - sous-types text et data
  6. - types fantômes pour oreg et oi
  7. - plus d'opérations et de directives
  8. - manipulation de la pile
  9. - ocamldoc
  10. *)
  11. (** {0 Bibliothèque pour l'écriture de programmes MIPS } *)
  12. (** Le module {!Mips} permet l'écriture de code MIPS dans du code
  13. OCaml, sans utiliser un préprocesseur. Un exemple complet est
  14. donné {{:#1_Exemple}ci-dessous, dans la section exemple}. *)
  15. type 'a asm
  16. (** type abstrait pour représenter du code assembleur. Le paramètre
  17. ['a] est utilisé comme type fantôme. *)
  18. type text = [ `text ] asm
  19. (** type représentant du code assembleur se trouvant dans la zone de
  20. texte *)
  21. type data = [ `data ] asm
  22. (** type représentant du code assembleur se trouvant dans la zone de
  23. données *)
  24. type program = {
  25. text : text;
  26. data : data;
  27. }
  28. (** un programme est constitué d'une zone de texte et d'une zone de
  29. donnée *)
  30. val print_program : Format.formatter -> program -> unit
  31. (** [print_program fmt p] imprime le code du programme [p] dans le
  32. formatter [fmt] *)
  33. val print_in_file: file:string -> program -> unit
  34. type register
  35. (** Type abstrait pour les registres *)
  36. val v0 : register
  37. val v1 : register
  38. val a0 : register
  39. val a1 : register
  40. val a2 : register
  41. val a3 : register
  42. val t0 : register
  43. val t1 : register
  44. val t2 : register
  45. val t3 : register
  46. val s0 : register
  47. val s1 : register
  48. val ra : register
  49. val sp : register
  50. val fp : register
  51. val gp : register
  52. val zero : register
  53. (** Constantes représentant les registres manipulables. [zero] est
  54. cablé à 0 *)
  55. type label = string
  56. (** Les étiquettes d'addresses sont des chaines de caractères *)
  57. type 'a operand
  58. val oreg : register operand
  59. val oi : int operand
  60. val oi32 : int32 operand
  61. (** type abstrait pour représenter la dernière opérande d'une
  62. expression arithmétique ainsi que 3 constantes (soit un registre,
  63. soit un entier, soit un entier 32 bits)
  64. *)
  65. (** {1 Opérations arithmétiques } *)
  66. val li : register -> int -> text
  67. val li32 : register -> int32 -> text
  68. (** Chargement des constantes entières *)
  69. val abs : register -> register -> text
  70. (** [abs r1 r2] stocke dans r1 la valeur absolue de r2 *)
  71. val neg : register -> register -> text
  72. (** [neg r1 r2] stocke dans r1 l'opposé de r2 *)
  73. val add : register -> register -> 'a operand -> 'a -> text
  74. val sub : register -> register -> 'a operand -> 'a -> text
  75. val mul : register -> register -> 'a operand -> 'a -> text
  76. val rem : register -> register -> 'a operand -> 'a -> text
  77. val div : register -> register -> 'a operand -> 'a -> text
  78. (** Les 5 opérations arithmétique de base: [add rdst rsrc1 ospec o]
  79. stocke dans rdst le résultat de l'opération entre rsrc1 et o. La
  80. constant ospec spécifie si o est un immédiat, immédiat sur 32 bits
  81. ou un registre.
  82. Exemple:
  83. [add v0 v1 oreg v2]
  84. [div v0 v1 oi 424]
  85. [sub t0 a0 oi32 2147483647l]
  86. *)
  87. (** {1 Opérations logiques } *)
  88. val and_ : register -> register -> register -> text
  89. val or_ : register -> register -> register -> text
  90. val not_ : register -> register -> text
  91. val clz : register -> register -> text
  92. (** Opérations de manipulation de bits. "et" bit à bit, "ou" bit à
  93. bit, "not" bit à bit et clz (count leading zero) *)
  94. (** {1 Comparaisons } *)
  95. val seq : register -> register -> register -> text
  96. val sge : register -> register -> register -> text
  97. val sgt : register -> register -> register -> text
  98. val sle : register -> register -> register -> text
  99. val slt : register -> register -> register -> text
  100. val sne : register -> register -> register -> text
  101. (** conditionnelles [sop ra rb rc] met [ra] à 1 si [rb op rc] et à 0
  102. dans le cas contraire (eq : ==, ge : >=, gt : >, le : <=, lt : <=,
  103. ne : !=) *)
  104. (** {1 Sauts } *)
  105. val b : label -> text
  106. (** saut inconditionnel *)
  107. val beq : register -> register -> label -> text
  108. val bne : register -> register -> label -> text
  109. val bge : register -> register -> label -> text
  110. val bgt : register -> register -> label -> text
  111. val ble : register -> register -> label -> text
  112. val blt : register -> register -> label -> text
  113. (** [bop ra rb label] branche vers le label [label] si [ra op rb] *)
  114. val beqz : register -> label -> text
  115. val bnez : register -> label -> text
  116. val bgez : register -> label -> text
  117. val bgtz : register -> label -> text
  118. val blez : register -> label -> text
  119. val bltz : register -> label -> text
  120. (** [bopz ra rb label] branche vers le label [label] si [ra op 0] *)
  121. val jr : register -> text
  122. (** [jr r] Continue l'exécution à l'adresse spécifiée dans le registre
  123. [r] *)
  124. val jal : label -> text
  125. (** [jal l] Continue l'exécution à l'adresse spécifiée par le label [l],
  126. sauve l'adresse de retour dans $ra.
  127. *)
  128. val jalr : register -> text
  129. (** [jalr r] Continue l'exécution à l'adresse spécifiée par le
  130. registre [r], sauve l'adresse de retour dans $ra.
  131. *)
  132. (** {1 Lecture / écriture en mémoire } *)
  133. type 'a address
  134. (** type abstrait pour représenter des adresses *)
  135. val alab : label address
  136. val areg : (int * register) address
  137. (** Les adresses sont soit données par un label, soit par une paire
  138. décalage, registre *)
  139. val la : register -> 'a address -> 'a -> text
  140. (** [la reg alab "foo"] charge dans [reg] l'adresse du label "foo"
  141. [la reg1 areg (x, reg2)] charge dans [reg1] l'adresse contenue dans
  142. [reg2] décallée de [x] octets
  143. *)
  144. val lbu : register -> 'a address -> 'a -> text
  145. (** charge l'octet à l'adresse donnée sans extension de signe (valeur
  146. entre 0 et 255) *)
  147. val lw : register -> 'a address -> 'a -> text
  148. (** charge l'entier 32bits à l'adresse donnée *)
  149. val sb : register -> 'a address -> 'a -> text
  150. (** écrit les 8 bits de poid faible du registre donnée à l'adresse
  151. donnée *)
  152. val sw : register -> 'a address -> 'a -> text
  153. (** écrit le contenu du registre à l'adresse donnée *)
  154. val move : register -> register -> text
  155. (** {1 Divers } *)
  156. val nop : [> ] asm
  157. (** l'instruction vide. Peut se trouver dans du text ou du data *)
  158. val label : label -> [> ] asm
  159. (** un label. Peut se retrouver dans du text ou du data *)
  160. val syscall : text
  161. (** l'instruction syscall *)
  162. val comment : string -> [> ] asm
  163. (** place un commentaire dans le code généré. Peut se retrouver dans
  164. du text ou du data *)
  165. val align : int -> [> ] asm
  166. (** [align n] aligne le code suivant l'instruction sur 2^n octets *)
  167. val asciiz : string -> data
  168. (** place une constante chaîne de carctères (terminées par 0) dans a
  169. zone data *)
  170. val dword : int list -> data
  171. (** place une liste de mots mémoires dans la zone data *)
  172. val address : label list -> data
  173. (** place une liste d'adresses (dénotées par des labels) dans la zone
  174. data *)
  175. val ( ++ ) : ([< `text|`data ] asm as 'a)-> 'a -> 'a
  176. (** concatène deux bouts de codes (soit text avec text, soit data avec
  177. data) *)
  178. (** {1 Manipulation de la pile} *)
  179. val push : register -> text
  180. (** [push r] place le contenu de [r] au sommet de la pile.
  181. Rappel : $sp pointe sur l'adresse de la dernière case occupée *)
  182. val pop : register -> text
  183. (** [pop r] place le mot en sommet de pile dans [r] et dépile *)
  184. val popn: int -> text
  185. (** [popn n] dépile [n] octets *)
  186. val peek : register -> text
  187. (** [peek r] place le mot en sommet de pile dans [r] sans dépiler *)
  188. (** {1 Exemple } *)
  189. (** Le programme ci-dessous, donné à gauche en pur MIPS et à droite en
  190. OCaml, charge deux constantes, effectue quelques opérations
  191. arithétiques et affiche le résultat à l'écran
  192. {[
  193. .text | { text =
  194. main: | label "main"
  195. #charge 42 dans $a0 et 23 dans $a1 | ++ comment "charge 42 dans $a0 et 23 dans $a1"
  196. li $a0, 42 | ++ li a0 42
  197. li $a1, 23 | ++ li a1 23
  198. mul $a0, $a0, $a1 | ++ mul a0 a0 oreg a1 (* on utilise oreg pour dire que la dernière
  199. | operande est un registre *)
  200. #place le contenu de $a0 sur la pile | ++ comment "place le contenu de $a0 sur la pile"
  201. sub $sp, $sp, 4 | ++ sub sp sp oi 4
  202. sw $a0, 0($sp) | ++ sw a0 areg (0, sp)
  203. |
  204. #appelle une routine d'affichage | ++ comment "appelle la routine d'affichage"
  205. jal print_int | ++ jal "print_int"
  206. |
  207. #termine | ++ comment "termine"
  208. li $v0, 10 | ++ li v0 10
  209. syscall | ++ syscall
  210. |
  211. print_int: | ++ label "print_int"
  212. lw $a0, 0($sp) | ++ lw a0 areg (0, sp)
  213. add $sp, $sp, 4 | ++ add sp sp oi 4
  214. li $v0, 1 | ++ li v0 1
  215. syscall | ++ syscall
  216. #affiche un retour chariot | ++ comment "affiche un retour chariot"
  217. la $a0, newline | ++ la a0 alab "newline"
  218. li $v0, 4 | ++ li v0 4
  219. syscall | ++ syscall
  220. jr $ra | ++ jr ra ; (* fin du label text *)
  221. |
  222. .data | data =
  223. newline: | label "newline"
  224. .asciiz "\n" | ++ asciiz "\n" ;
  225. | } (* fin du record *)
  226. ]}
  227. *)