(* Biblioteca para produzir código 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 2018 João Reis (University of Beira Interior) - tradução para português *) (** {0 Biblioteca para escrever programamas MIPS } O módulo {!Mips} permite a escrita de código MIPS usando código OCaml, sem necessidade de um pré-processador. Exemplo: O programa abaixo, feito à esquerda em MIPS e à direita em OCaml, carrega duas constantes, realiza alguma operações aritméticas e exibe o resultado no ecrã {[ .text | { text = main: | label "main" #carrega 42 para $a0 e 23 para $a1 | ++ comment "carrega 42 para $a0 e 23 para $a1" li $a0, 42 | ++ li a0 42 li $a1, 23 | ++ li a1 23 mul $a0, $a0, $a1 | ++ mul a0 a0 oreg a1 (* usamos oreg para dizer que o último | operando é um registo *) #colocar o conteúdo de $a0 na pilha | ++ comment "colocar o conteúdo de $a0 na pilha" sub $sp, $sp, 4 | ++ sub sp sp oi 4 sw $a0, 0($sp) | ++ sw a0 areg (0, sp) | #chamar a rotina de print | ++ comment "chamar a rotina de print" jal print_int | ++ jal "print_int" | #terminar | ++ comment "terminar" 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 #exibir o carriage return | ++ comment "exibir o carriage return" la $a0, newline | ++ la a0 alab "newline" li $v0, 4 | ++ li v0 4 syscall | ++ syscall jr $ra | ++ jr ra ; (* fim da etiqueta de texto *) | .data | data = newline: | label "newline" .asciiz "\n" | ++ asciiz "\n" ; | } (* fim do registo *) ]} *) type 'a asm (** tipo abstrato para representar o código assembly. O parâmetro ['a] é utilisado como tipo fantasma. *) type text = [ `text ] asm (** tipo que representa o código assembly localizado na zona de texto *) type data = [ `data ] asm (** tipo que representante o código assembly localizado na zona de dados *) type program = { text : text; data : data; } (** um programa é constituído por uma zona de texto e uma zona de dados *) val print_program : Format.formatter -> program -> unit (** [print_program fmt p] imprime o código do programa [p] no formatador [fmt] *) val print_in_file: file:string -> program -> unit type register = string 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 s0 : register val s1 : register val ra : register val sp : register val fp : register val gp : register val zero : register (** Constantes que representam os registos manipuláveis. [zero] está ligado a 0 *) type label = string (** As etiquetas de endereços são cadeias de caracteres *) type 'a operand val oreg : register operand val oi : int operand val oi32 : int32 operand (** tipo abstrato que representa o último operando de uma expressão aritmética bem como 3 constantes (um registo, um inteiro ou um inteiro de 32 bits) *) (** {1 Operações aritméticas } *) val li : register -> int -> text val li32 : register -> int32 -> text (** Carregamento de constantes inteiras *) val abs : register -> register -> text (** [abs r1 r2] alojar em r1 o valor absoluto de r2 *) val neg : register -> register -> text (** [neg r1 r2] alojar em r1 a negação 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 (** As 5 operações aritméticas de base: [add rdst rsrc1 ospec o] alojar em rdst o resultado da operação entre rsrc1 e o. A constante ospec especifica se é um imediato, imediato de 32 bits ou um registo. Exemple: [add v0 v1 oreg v2] [div v0 v1 oi 424] [sub t0 a0 oi32 2147483647l] *) (** {1 Operações lógicas } *) val and_ : register -> register -> register -> text val or_ : register -> register -> register -> text val not_ : register -> register -> text val clz : register -> register -> text (** Operações de manipulação de bits. "e" bit a bit, "ou" bit a bit, "não" bit a bit e clz (count leading zero) *) (** {1 Comparações } *) val seq : register -> register -> 'a operand -> 'a -> text val sne : register -> register -> 'a operand -> 'a -> text val sge : register -> register -> 'a operand -> 'a -> text val sgt : register -> register -> 'a operand -> 'a -> text val sle : register -> register -> 'a operand -> 'a -> text val slt : register -> register -> 'a operand -> 'a -> text (** a condicional [sop ra rb rc] coloca [ra] a 1 se [rb op rc] e a 0 em caso contrário (eq : ==, ge : >=, gt : >, le : <=, lt : <=, ne : !=) *) (** {1 Saltos } *) val b : label -> text (** salto incondicional *) 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] salta para a etiqueta [label] se [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] salta para a etiqueta [label] se [ra op 0] *) val jr : register -> text (** [jr r] Continua a execução no endereço especificado no registo [r] *) val jal : label -> text (** [jal l] Continua a execução no endereço especificado pela etiqueta [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], guardando o endereço de retorno em $ra. *) (** {1 Leitura / escrita em memória } *) type 'a address (** tipo abstrato que representa os endereços *) val alab : label address val areg : (int * register) address (** Os endereços são dados por uma etiqueta ou por um par offset, registo *) val la : register -> 'a address -> 'a -> text (** [la reg alab "foo"] carrega para [reg] o endereço da etiqueta "foo" [la reg1 areg (x, reg2)] carrega para [reg1] o endereço contido em [reg2] com offset de [x] octetos *) val lbu : register -> 'a address -> 'a -> text (** carregar o octeto para o endereço dado sem extensão de sinal (valor entre 0 e 255) *) val lw : register -> 'a address -> 'a -> text (** carregar o inteiro de 32bits para o endereço dado *) val sb : register -> 'a address -> 'a -> text (** escrever os 8 bits menor significância do registo dado pelo endereço dado *) val sw : register -> 'a address -> 'a -> text (** escrever o conteúdo do registo para o endereço dado *) val move : register -> register -> text (** {1 Diversos } *) val nop : [> ] asm (** a instrução vazia. Pode estar em texto ou em dados *) val label : label -> [> ] asm (** uma etiqueta. Pode encontrar-se em texto ou dados *) val syscall : text (** a instrução syscall *) val comment : string -> [> ] asm (** colocar um comentário no código gerado. Pode encontrar-se em texto ou dados *) val align : int -> [> ] asm (** [align n] alinha o código após a instrução em 2^n octetos *) val asciiz : string -> data (** coloca uma cadeia de carateres constante (terminada par 0) na zona de dados *) val dword : int list -> data (** coloca uma lista de palavras de memória na zona de dados *) val address : label list -> data (** coloca uma lista de endereços (denotados pelas etiquetas) na zona de dados *) val space: int -> data (** [space n] aloca [n] octetos no segmento de dados *) val inline: string -> [> ] asm (** [inline s] copia a cadeia [s] tal e qual como está para o ficheiro assembly *) val ( ++ ) : ([< `text`data ] asm as 'a)-> 'a -> 'a (** concatena duas extremidades de códigos (quer texto com text, quer dados com dados) *) (** {1 Manipulação da pilha} *) val push : register -> text (** [push r] coloca o conteúdo de [r] no topo da pilha. Nota : $sp aponta para o endereço do úlimto bloco ocupado *) val pop : register -> text (** [pop r] coloca a palavra no topo da pilha em [r] removendo-a da pilha *) val popn: int -> text (** [popn n] remove [n] octetos do topo da pilha *) val peek : register -> text (** [peek r] coloca a palavra no topo da pilha em [r] sem a remover da pilha *)
This document was generated using caml2html