INE5309 - Linguagem Assembly Arquitetura FPU · 2007. 3. 21. · Universidade Federal de Santa...

19
Universidade Federal de Santa Catarina CTC - Centro Tecnológico Ciências da Computação INE5309 - Linguagem Assembly Arquitetura FPU: Implementação no MIPS32 Alunos: Guilherme Fernandes Raphanelli Diogo D. Fonseca dos Santos

Transcript of INE5309 - Linguagem Assembly Arquitetura FPU · 2007. 3. 21. · Universidade Federal de Santa...

  • Universidade Federal de Santa Catarina

    CTC - Centro Tecnológico

    Ciências da Computação

    INE5309 - Linguagem Assembly

    Arquitetura FPU:Implementação no MIPS32

    Alunos: Guilherme Fernandes Raphanelli

    Diogo D. Fonseca dos Santos

  • SUMÁRIO

    1. Introdução ......................................................................................... 1

    2. Representação Binária .................................................................. 1

    3. Registradores .................................................................................. 2

    3.1. Formato de Valores para FPRs ............................................... 4

    4. Instruções ......................................................................................... 4

    5. Exceções na FPU ........................................................................... 6

    5.1. Invalid Operation Exception ..................................................... 6

    5.2. Division By Zero Exception ...................................................... 7

    5.3. Underflow Exception .................................................................. 7

    5.4. Overflow Exception ..................................................................... 7

    5.5. Inexact Exception ....................................................................... 7

    6. Exercícios ......................................................................................... 8

    6.1. Detecção de Overflow para Multiplicação ............................ 8

    6.2. Visualização de Contexto ....................................................... 10

    APÊNDICE A – Detecção de overflow em multipicação em Ponto flutuante..................................................................................12

    APÊNDICE B – Visualização de CONTExto da FPU..............14

  • 1. Introdução

    O suporte para operações de ponto flutuante nas diferentes arquiteturas é normalmente dado através de componentes diferentes de onde ocorrem as operações com inteiros. Estes componentes são designados como Floating-Point Unit (FPU), ou unidade de ponto flutuante. Na arquitetura MIPS32 - chamada de MIPS ao longo do documento - a FPU é implementada principalmente através do Co-processador 1, o co-processador de ponto flutuante, também conhecido como floating-point accelerator (FPA).

    Para utilizar a FPU no MIPS é necessário que ela esteja habilitada. Para isto é necessário habilitar o Co-processador 1 através de uma operação privilegiada fornecida pelo Co-processador de Controle do Sistema. Este documento abordará diferentes aspectos da FPU do MIPS, expostos no seguintes capítulos:

    2. Representação Binária

    A arquitetura MIPS segue o padrão Institute of Electrical and Electronics Engineers (IEEE) 754, o IEEE Standard for Binary Floating-Point Arithmetic. Este padrão define os tipos de dados em ponto flutuante, as operações aritméticas, de comparação e de conversão básicas, e um modelo computacional.

    A FPU do MIPS oferece suporte aos tipos de dados em ponto flutuante e ao tipos de dados em ponto fixo. Os tipos de dados em ponto flutuante implementados são os single precision, ou de precisão única, e double precision, ou de precisão dobrada, como definidos pelo IEEE 754. O tipo de dado em ponto fixo é o de inteiros sinalizados, fornecido pela arquitetura da CPU. Os formatos definidos são os seguintes:

    1

  • • ponto flutuante 32-bit single precision (tipo S, pode ser visto na Figura 1).

    • ponto flutuante 64-bit double precision (tipo D, pode ser visto na Figura 2).

    • ponto fixo 32-bit word (tipo W, pode ser visto na Figura 3).

    Figura 1 - Formato tipo S

    Figura 2 - Formato tipo D

    O formato tipo W oferece a mesma representação utilizada pela CPU nas operações de ponto fixo, mas não suportando inteiros não sinalizados. O formato tipo S é uma representação de ponto flutuante com 32-bits, tendo 8 bits para o expoente, 23 bits de mantissa e 1 para sinalização. O tipo D estende esta representação para 11 bits de expoente e 52 de mantissa. Para acomodar este formato na arquitetura MIPS32, a FPU divide o número em dois registradores de 32-bits, como mostrado na Figura 2.

    Figura 3 - Formato tipo W

    3. Registradores

    As CPUs MIPS possuem 32 registradores de ponto flutuante, normalmente referidos como $f0-f$31. Entretanto, mesmo as CPUs MIPS32 possuem suporte a números ponto flutuante double precision de 64 bits. Assim, estas CPUs apenas

    2

  • realizam operações aritméticas nos 16 registradores pares, sendo os 16 registradores ímpares usados para cuidar dos 32 bits mais significativos destes números de 64 bits. Para a manipulação de dados inteiros qualquer registrador pode ser utilizado.

    Registrador Nome Uso

    $f0,$f2 fv0-fv1 Valor retornado por funções.

    $f4,$f6,$f8,$f10 ft0-ft3 Temporários.

    $f12,$f14 fa0-fa1 Argumentos de funções

    $f16,$f18 ft4-ft5 Temporários.

    $f20,$f22,$f24

    $f26,$f28,$f30

    fs0-fs5 Variáveis de registro.

    Tabela 1 - Convenção para Registradores da FPU

    Assim como os registradores de uso geral, os registradores de operando ponto flutuante (FPR) também possuem uma convenção de nomes e de uso. A convenção de uso é análoga à dos registrados de uso geral. A Tabela 1 descreve estas convenções.

    A arquitetura MIPS32 também suporta registradores para controle de ponto flutuante, os Floating Point Control registers (FCRs). Existem 5 registradores para controle da FPU, com 32 bits cada. Os registradores suportados são os seguintes:

    • FIR - FP Implementation and Revision register

    • FCCR - FP Condition Codes register

    • FEXR - FP Exceptions register

    3

  • • FENR - FP Enables register

    • FCSR - FP Control/Status register

    O acesso a estes registradores não é privilegiado, eles podem ser acessados por qualquer programa que consiga executar instruções de ponto flutuante. Os FCRs podem ser acessados através das instruções CTC1 e CFC1.

    3.1.Formato de Valores para FPRs

    Ao contrário da CPU, a FPU não interpreta a codificação binária dos operadores de origem nem produz uma codificação binária para o resultado de cada operação. Um valor guardado em um FPR tem um formato, ou tipo, e pode ser usado apenas por instruções que operam nesse formato. Este formato pode ser: uninterpreted (não interpretado), unknown (desconhecido), ou um dos tipos numéricos válidos, single, double ou word.

    Um valor é definido como uninterpreted após ser carregado em um registrador ponto flutuante como dado binário, o que acontece usando moves a partir de inteiros ou loads. Assim que este registrador for utilizado por uma função de formato específico, o valor será definido como sendo do mesmo formato.

    O formato unknown é utilizado quando uma operação de um formato utiliza um registrador de origem com um valor de formato diferente. Neste caso, tanto o valor util izado quanto o resultado são definidos como unknown.

    4. Instruções

    Os co-processadores, assim como a CPU, operam em dados naturalmente alinhados. A FPU possui loads e stores que

    4

  • usam o mesmo tipo de endereçamento registrador+offset usado pela CPU. As instruções da FPU possuem formatos diferentes dos especificados para as instruções da CPU. As instruições normalmente possuem uma versão double e uma single, identificadas por d e s respectivamente. A Tabela 2 mostra algumas destas instruções.

    Instrução Uso

    lwc1 fd, disp(rs) fd = *(rs + disp). Load da memória para registrador. Pode-se usar as pseudo-intruções l .s fd, address (single) ou l .d(double).

    swc1 fd, disp(rs) *(rs+disp) = fd. Store do registrador para memória. Pseudo-instruções: s.s ou s.d.

    mtc1 rs, fd fd = rs. Move de registrador inteiro (rs) para registrador fp (fd). 32bits não interpretados.

    mfc1 rd, fs rd = fs. Move de registrador fp para registrador inteiro. 32bits não interpretados.

    mov.s fs,fd

    mov.d fs,fd

    fd = fs. Move entre registradores fp.

    add.s fd, fs1, fs2

    add.d fd, fs1, fs2

    fd = fs1 + fs2.

    mul.s fd, fs1, fs2

    mul.d fd, fs1, fs2

    fd = fs1 x fs2.

    Tabela 2 - Instruções FP MIPS32

    A FPU oferece diversas operações além das operações básicas mostradas na Tabela 2. As operações podem ser separadas em 6 classes distintas: Instruções para transferência de dados, instruções aritméticas, instruções de conversão, instruções para mover valores de operando formatados, instruções condicionais e instruções variadas. Estas operações podem ser encontradas em [2].

    5

  • 5. Exceções na FPU

    As exceções FPU são implementadas na arquitetura MIPS FPU com os campos Cause, Enable e campos de Flag do registrador Control/Status. Os bits de Flag implementam os flags de status de exceção IEEE , e os bit Cause e Enable controlam o trapping de exceções. Cada campo tem um bit para cada uma das cinco condições de exceção da IEEE.

    A FPU possui um modo de funcionamento especial, o precise exception mode. Neste modo o trap é gerado antes que a instrução que causou a exceção, ou qualquer instrução em seguida, possa terminar e escrever seus resultados. Se desejado, o software que detecta a exceção pode recomeçar a execução da instrução interrompida depois de tratá-la.

    As cinco exceções FPU IEEE implementadas na arquitetura MIPS32 são: Invalid-Operation Exception (Operação Inválida), Division-By-Zero Exception (Divisão por zero), Underflow Exception, Overflow Exception e Inexact Exception. Estas exceções serão explicadas a seguir.

    5.1.Invalid Operation Exception

    Algumas situações que são definadas como uma operação inválida:

    • Um ou ambos os operandos de uma operação aritmética sinalizam NaN.

    • Adição ou subtração: subtração de infinitos.

    • Multiplicação: 0 vezes infinito, com quaisquer sinais.

    • Divisão: 0/0 ou divisão de infinitos, com quaisquer sinais.

    6

  • 5.2.Division By Zero Exception

    Acusa-se uma execeção de Divisão por zero se o divisor for zero e o dividendo for um número finito diferente de zero. O resultado, caso nenhuma trap ocorra, é definido como infinito. As divisões (0/0) e (∞/0) não causam a exceção de divisão por zero. O resultado de (0/0) é uma exceção inválida da operação. O resultado de (∞/0) é uma infinidade corretamente sinalizada.

    5.3.Underflow Exception

    Duas situações podem causar uma exceção de underflow:

    • Tininess: a criação de um resultado não-zero minúsculo que, por ser minúsculo, pode causar alguma outra exceção mais tarde como o excesso na divisão.

    • Perda de exatidão: a perda de exatidão extraordinária que ocorre na aproximação de tais números minúsculos com números não-normalizados.

    5.4.Overflow Exception

    Uma exceção de overflow acontece quando o valor de um resultado arredondado em ponto flutuante, caso o expoente não tivesse limites, é maior do que o formato de destino com o maior número finito.

    5.5.Inexact Exception

    7

  • Uma Inexact Exception ocorre nas seguintes situações:

    • O resultado arredondado de uma operação não é exato.

    • O resultado arredondado de uma operação gera overflow sem ocasionar um trap de overflow.

    6. Exercícios

    O exercício de detecção de overflow para multiplicação e o de visualização de contexto desenvolvidos em sala de aula foram modificados para utilizarem a FPU. Muitas modificações foram necessárias dadas as diferenças entre a CPU e a FPU, e pelas dificuldades do ambiente de testes. As ferramentas SPIM e gxEmul foram utilizadas para reproduzir ao máximo as condições sob as quais os exercícios foram feitos no laboratório.

    6.1.Detecção de Overflow para Multiplicação

    O exercício original era realizar manualmente a detecção de overflow de uma multiplicação, o que para números inteiros era realizado comparando-se os sinais. Os números de ponto flutuante, segundo o padrão IEEE 754 implementado pelo MIPS32, possuem um indicador próprio de overflow, tornando desnecessária a técnica anterior.

    Quando uma operação em ponto flutuante gera um número muito grande para ser armazenado, situação conhecida como overflow, a FPU automaticamente define todos os bits de expoente do registrador destino como 1. Esta configuração significa um número tido como infinito, positivo ou negativo dependendo do bit de sinal, podendo ser utilizada para a verificação do overflow. O código fonte criado pode ser visto no Apêndice A.

    8

  • As primeiras diferenças com relação ao código anterior do exercício surgem no momento da entrada de dados do usuário. O código de chamada de sistema 6 é utilizado, ao invés do 5 original, para obter um número em ponto flutuante. Esta chamada de sistema coloca o número recebido no registrador $f0.

    Figura 4 - Multiplicação em Ponto Flutuante

    Depois de multiplicados os números recebidos, o resultado é movido para um registrador de uso geral. Operações de bits são utilizadas para se isolar os bits de expoente e verificar se todos estão habilitados. Caso afirmativo, é caracterizada a ocorrência de overflow e ocorre a notificação ao usuário. Caso contrário, o resultado é apresentado util izando-se o código de chamada de sistema 2, que imprime um número em ponto flutuante. Esta chamada de sistema utiliza o registrador $f12 como argumento. Uma operação bem sucedida pode ser vista na Figura 4, e uma onde ocorre overflow na Figura 5.

    Figura 5 - Overf low Detectado

    9

  • 6.2.Visualização de Contexto

    O objetivo deste exercício era a visualização do estado dos registradores de uso geral. Isto era realizado através da chamada de funções implementadas em C, utilizando o template para assembly. Para o exercício original era necessário o salvamento de contexto, mas tratando-se dos registradores da FPU isto não é necessário, já que estes registradores são completamente independentes do fluxo normal dos programas. O código fonte novo pode ser visto no Apêndice B.

    As primeiras dificuldades encontradas para imprimir o estado atual dos registradores da FPU foram relativas à falta de acesso direto através do template de assembly a estes registradores. Sendo assim, a maneira encontrada para realizar a tarefa foi, para cada registrador, copiar o valor do registrador de ponto flutuante para um registrador de uso geral, imprimindo-se então o valor deste registrador.

    Para facilitar a impressão das mensagens relativas a cada registrador, a estrutura da função print_register foi modificada, adicionando-lhe um argumento. A Figura 6, que pode ser encontrada junto ao código no Apêndice II, mostra o funcionamento deste programa. Uma versão modificada deste código foi implementada para verificar a consistência das informações através do SPIM. A Figura 7 mostra o resultado, podendo ser encontrada junto ao código no Apêndice B.

    REFERÊNCIAS BIBLIOGRÁFICAS

    1 SWEETMAN, D. See MIPS Run. EUA. Morgan Kaufmann Publishers, 1999.

    10

  • 2 MIPS Technologies. MIPS32 Architecture For Programmers Volume I: Introduction to the MIPS32 Architecture. mar. 2001.

    11

  • APÊNDICE A – DETECÇÃO DE OVERFLOW EM MULTIPICAÇÃO EM PONTO FLUTUANTE

    ### -------------------------------------------------------------------### Area de Dados### -------------------------------------------------------------------.dataget_v1: .asciiz "Enter the first value: "get_v2: .asciiz "Enter the second value: "put_res: .asciiz "The result is equal "overflow: .asciiz "Ocorreu overflow. "

    ### ------------------------------------------------------------------### Area de Codigo### ------------------------------------------------------------------.text.globl mainmain: addiu $sp, $sp, -4 sw $ra, 0($sp)

    la $a0, get_v1li $v0, 4syscallli $v0, 6syscall

    mov.d $f12, $f0

    la $a0, get_v2li $v0, 4syscallli $v0, 6syscall

    mul.s $f12, $f12, $f0mfc1 $t0, $f12srl $t0, $t0, 23addi $t1, $zero, 255and $t0, $t0, $t1bne $t0, $t1, result

    over: la $a0, overflow li $v0, 4 syscall

    j prologue

    result: la $a0, put_res li $v0, 4 syscall

    li $v0, 2

    12

  • syscall

    prologue: lw $ra, 0($sp) addiu $sp, $sp, 4 jr $ra

    ### ------------------------------------------------------------------### Funcao para imprimir elemento na tela### ------------------------------------------------------------------.data.globl newlinenewline: .asciiz "\n".globl commacomma: .asciiz ",".text.globl print_cmdprint_cmd: beq $a0, $zero, F0 li $v0, 1 syscall li $v0, 4 la $a0 comma syscall jr $ra F0:li $v0, 4 la $a0 newline syscall

    jr $ra

    .globl print_intprint_int: li $v0, 1 syscall li $v0, 4 la $a0 newline syscall

    jr $ra

    .globl print_stringprint_string: li $v0, 4 syscall jr $ra

    Código 1 - multiplicação.asm

    13

  • APÊNDICE B – VISUALIZAÇÃO DE CONTEXTO DA FPU

    ### -------------------------------------------------------------------### Area de Dados### -------------------------------------------------------------------.datan1: .float 3.5n2: .float 23.001msg: .asciiz "Mostrando registradores da FPU: \n"

    ### ------------------------------------------------------------------### Area de Codigo### ------------------------------------------------------------------.extern print_register.extern printstr

    .text

    .globl mainmain: addiu $sp, $sp, -4 sw $ra, 0($sp)

    l.s $f4, n1l.s $f6, n2

    mul.s $f12, $f4, $f6

    cvt.d.s $f22, $f12mul.d $f24, $f22, $f22mul.d $f26, $f24, $f24

    la $4, msgjal printstr

    #Imprimindo $f0mfc1 $16, $f0addi $4, $0, 16addi $5, $0, 0

    jal print_register

    #Imprimindo $f1mfc1 $16, $f1addi $4, $0, 16addi $5, $0, 1

    jal print_register

    mfc1 $16, $f2addi $4, $0, 16addi $5, $0, 2

    jal print_register

    mfc1 $16, $f3addi $4, $0, 16addi $5, $0, 3

    14

  • jal print_register

    mfc1 $16, $f4addi $4, $0, 16addi $5, $0, 4

    jal print_register

    mfc1 $16, $f5addi $4, $0, 16addi $5, $0, 5

    jal print_register

    mfc1 $16, $f6addi $4, $0, 16addi $5, $0, 6

    jal print_register

    mfc1 $16, $f7addi $4, $0, 16addi $5, $0, 7

    jal print_register

    ### Código encurtado, continuava assim para todos os registradores ###

    mfc1 $16, $f31addi $4, $0, 16addi $5, $0, 31

    jal print_register

    .globl prologueprologue: lw $ra, 0($sp) addiu $sp, $sp, 4 jr $ra

    Código 2 - contexto.asm

    ### -------------------------------------------------------------------### Area de Dados### -------------------------------------------------------------------.datan1: .float 3.5n2: .float 23.001msg: .asciiz "Mostrando registradores da FPU: \n"

    ### ------------------------------------------------------------------### Area de Codigo### ------------------------------------------------------------------.text.globl mainmain: addiu $sp, $sp, -4 sw $ra, 0($sp)

    15

  • l.s $f4, n1l.s $f6, n2

    mul.s $f12, $f4, $f6

    cvt.d.s $f22, $f12mul.d $f24, $f22, $f22mul.d $f26, $f24, $f24

    .globl prologueprologue: lw $ra, 0($sp) addiu $sp, $sp, 4 jr $ra

    Código 3 - Programa auxiliar, contexto-spim.asm

    Figura 6 - Resultado da Execução do programa contexto.asm

    16

  • Figura 7 - Visualização do contexto através do SPIM

    17

    1.Introdução2.Representação Binária3.Registradores3.1.Formato de Valores para FPRs4.Instruções5.Exceções na FPU5.1.Invalid Operation Exception5.2.Division By Zero Exception5.3.Underflow Exception5.4.Overflow Exception5.5.Inexact Exception6.Exercícios6.1.Detecção de Overflow para Multiplicação6.2.Visualização de Contexto