module Mips:sig
..end
Mips
permet l'écriture de code MIPS dans du code
OCaml, sans utiliser un préprocesseur. Un exemple complet est
donné ci-dessous, dans la section exemple.
Un descriptif détaillé des instructions peut être trouvé dans l'appendice A de: 'Computer Organization and Design: The Hardware/Software Interface.' (Hennessy & Patterson, Elsevier). Le pdf de l'appendice A est disponible à cette URL:
http://pages.cs.wisc.edu/~larus/HP_AppA.pdf
type 'a
asm
'a
est utilisé comme type fantôme.typetext =
[ `text ] asm
typedata =
[ `data ] asm
type
program = {
|
text : |
|
data : |
val print_program : Format.formatter -> program -> unit
print_program fmt p
imprime le code du programme p
dans le
formatter fmt
type 'a
register
'a
est un type fantôme représentant encodant le fait
que le registre est un registre général (type word
) ou un registre du co-processeur
flottant (type double
).typeword =
[ `word ]
typedouble =
[ `double ]
val v0 : word register
val v1 : word register
val a0 : word register
val a1 : word register
val a2 : word register
val a3 : word register
val t0 : word register
val t1 : word register
val t2 : word register
val t3 : word register
val s0 : word register
val s1 : word register
val ra : word register
val sp : word register
val fp : word register
val gp : word register
val zero : word register
val f0 : double register
val f2 : double register
val f4 : double register
val f6 : double register
val f8 : double register
val f10 : double register
val f12 : double register
typelabel =
string
type 'a
operand
val oreg : word register operand
val oi : int operand
val oi32 : int32 operand
val li : word register -> int -> text
val li32 : word register -> int32 -> text
val abs : word register -> word register -> text
abs r1 r2
stocke dans r1 la valeur absolue de r2val neg : word register -> word register -> text
neg r1 r2
stocke dans r1 l'opposé de r2val add : word register ->
word register -> 'a operand -> 'a -> text
val sub : word register ->
word register -> 'a operand -> 'a -> text
val mul : word register ->
word register -> 'a operand -> 'a -> text
val div : word register ->
word register -> 'a operand -> 'a -> text
val rem : word register ->
word register -> 'a operand -> 'a -> text
add rdst rsrc1 ospec o
stocke dans rdst le résultat de l'opération entre rsrc1 et o. La
constante 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
val cvt_d_w : double register -> double register -> 'a asm
cvt_d_w f1 f2
convertit l'entier placé dans le registre f2
en
flottant double précision et place le résultat dans f1
val cvt_w_d : double register -> double register -> 'a asm
cvt_w_d f1 f2
convertit le flottant double précision placé dans
le registre f2
en entier et place le résultat dans f1
val abs_d : double register -> double register -> text
abs_d f1 f2
stocke dans f1
la valeur absolue de f2
val neg_d : double register -> double register -> text
neg_d f1 f2
stocke dans f1
l'opposé de f2
val add_d : double register ->
double register -> double register -> text
val sub_d : double register ->
double register -> double register -> text
val mul_d : double register ->
double register -> double register -> text
val div_d : double register ->
double register -> double register -> text
val clz : word register -> word register -> text
val and_ : word register ->
word register -> word register -> text
val or_ : word register ->
word register -> word register -> text
val not_ : word register -> word register -> text
val seq : word register ->
word register -> word register -> text
val sge : word register ->
word register -> word register -> text
val sgt : word register ->
word register -> word register -> text
val sle : word register ->
word register -> word register -> text
val slt : word register ->
word register -> word register -> text
val sne : word register ->
word register -> word register -> text
sop ra rb rc
met ra
à 1 si rb op rc
et à 0
dans le cas contraire (eq
: ==
, ge
: >=
, gt
: >
, le
:
<=
, lt
: <=
, ne
: !=
)val c_eq_d : double register -> double register -> text
val c_le_d : double register -> double register -> text
val c_lt_d : double register -> double register -> text
s_op_d fa fb
met le registre de condition du
co-processeur flottant à 1 si ra op rb
et à 0 dans le cas
contraire (eq
: ==
, le
: <=
, lt
: <=
). Les instructions
bclf
et bclt
permettent de tester le registre de condition.val b : label -> text
val beq : word register -> word register -> label -> text
val bne : word register -> word register -> label -> text
val bge : word register -> word register -> label -> text
val bgt : word register -> word register -> label -> text
val ble : word register -> word register -> label -> text
val blt : word register -> word register -> label -> text
bop ra rb label
branche vers le label label
si ra op rb
val beqz : word register -> label -> text
val bnez : word register -> label -> text
val bgez : word register -> label -> text
val bgtz : word register -> label -> text
val blez : word register -> label -> text
val bltz : word register -> label -> text
bopz ra rb label
branche vers le label label
si ra op 0
val bc1f : label -> text
bc1f label
saute vers le label label
si le registre de condition
du co-processeur flottant vaut 0val bc1t : label -> text
bc1f label
saute vers le label label
si le registre de condition
du co-processeur flottant vaut 1val jr : word 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 : word register -> text
jalr r
Continue l'exécution à l'adresse spécifiée par le
registre r
, sauve l'adresse de retour dans $ra.type 'a
address
type abstrait pour représenter des adresses
val alab : label address
val areg : (int * 'a register) address
val la : word 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
octetsval lbu : word register -> 'a address -> 'a -> text
val lb : word register -> 'a address -> 'a -> 'b asm
val lw : word register -> 'a address -> 'a -> text
val lwc1 : double register -> 'a address -> 'a -> text
val ldc1 : double register -> 'a address -> 'a -> text
val sb : word register -> 'a address -> 'a -> text
val sw : word register -> 'a address -> 'a -> text
val swc1 : double register -> 'a address -> 'a -> text
val sdc1 : double register -> 'a address -> 'a -> text
val move : word register -> word register -> text
move rd rs
copie le registre source rs
dans le registre
destination rd
val mov_d : double register -> double register -> text
mov_d fd fs
copie le registre source flottant fs
dans le registre
destination fd
val mfc1 : word register -> double register -> text
mfc1 r1 f1
copie le registre f1
du co-processeur flottant vers le registre
général r1
val mtc1 : word register -> double register -> text
mfc1 r1 f1
copie le registre général r1
dans le registre f1
du co-processeur flottant.val nop : [> ] asm
val label : label -> [> ] asm
val syscall : text
val comment : string -> [> ] asm
val align : int -> [> ] asm
align n
aligne le code suivant l'instruction sur 2^n octetsval space : int -> data
space n
réserve n
octets non initialisés dans la zone dataval asciiz : string -> data
val word : int list -> data
val address : label list -> data
val double : float list -> data
val (@@) : ([< `data | `text ] as 'a) asm -> 'a asm -> 'a asm
val (++) : ([< `data | `text ] as 'a) asm -> 'a asm -> 'a asm
@@
val set_stack_alignment : int -> unit
val get_stack_alignment : unit -> int
set_stack_alignment
lève une exception si l'alignement n'est pas une
puissance de 2.val push : [< `double | `word ] register -> text
push r
place le contenu de r
au sommet de la pile. $sp pointe
sur l'adresse de la dernière case occupéeval peek : [< `double | `word ] register -> text
peek r
place la valeur en sommet de pile dans r
sans dépilerval pop : [< `double | `word ] register -> text
pop r
place la valeur en sommet de pile dans r
et dépile
.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 *)