10. Instruções de ponto flutuante

Estas instruções dão suporte ao uso do coprocessador de ponto flutuante ARM (em plataformas como as OpenMV Cams que possuem um). A FPU tem 32 registradores conhecidos como s0-s31, cada um dos quais pode armazenar um float de precisão simples. Os dados podem ser transferidos entre os registradores da FPU e os registradores do núcleo ARM com a instrução vmov.

Observe que o MicroPython não suporta passar floats para funções em assembler, nem você pode colocar um float em r0 e esperar um resultado razoável. Há duas maneiras de contornar isso. A primeira é usar arrays, e a segunda é passar e/ou retornar inteiros e convertê-los de e para floats no código.

10.1. Convenções do documento

Notação: Sd, Sm, Sn denotam registradores da FPU, Rd, Rm, Rn denotam registradores do núcleo ARM. Os últimos podem ser qualquer registrador do núcleo ARM, embora os registradores R13-R15 provavelmente não sejam apropriados neste contexto.

10.2. Aritmética

  • vadd(Sd, Sn, Sm) Sd = Sn + Sm

  • vsub(Sd, Sn, Sm) Sd = Sn - Sm

  • vneg(Sd, Sm) Sd = -Sm

  • vmul(Sd, Sn, Sm) Sd = Sn * Sm

  • vdiv(Sd, Sn, Sm) Sd = Sn / Sm

  • vsqrt(Sd, Sm) Sd = sqrt(Sm)

Os registradores podem ser idênticos: vmul(S0, S0, S0) executará S0 = S0*S0

10.3. Mover entre os registradores do núcleo ARM e da FPU

  • vmov(Sd, Rm) Sd = Rm

  • vmov(Rd, Sm) Rd = Sm

A FPU tem um registrador conhecido como FPSCR, similar ao APSR do núcleo ARM, que armazena códigos de condição e outros dados. As instruções a seguir fornecem acesso a ele.

  • vmrs(APSR_nzcv, FPSCR)

Move as flags N, Z, C e V de ponto flutuante para as flags N, Z, C e V do APSR.

Isto é feito após uma instrução como uma comparação da FPU para permitir que os códigos de condição sejam testados pelo código assembler. A seguir está uma forma mais geral da instrução.

  • vmrs(Rd, FPSCR) Rd = FPSCR

10.4. Mover entre registrador da FPU e memória

  • vldr(Sd, [Rn, offset]) Sd = [Rn + offset]

  • vstr(Sd, [Rn, offset]) [Rn + offset] = Sd

Onde [Rn + offset] denota o endereço de memória obtido somando Rn ao offset. Isto é especificado em bytes. Como cada valor float ocupa uma word de 32 bits, ao acessar arrays de floats o offset deve sempre ser um múltiplo de quatro bytes.

10.5. Comparação de dados

  • vcmp(Sd, Sm)

Compara os valores em Sd e Sm e define as flags N, Z, C e V da FPU. Isto normalmente seria seguido por vmrs(APSR_nzcv, FPSCR) para permitir que os resultados sejam testados.

10.6. Converter entre inteiro e float

  • vcvt_f32_s32(Sd, Sm) Sd = float(Sm)

  • vcvt_s32_f32(Sd, Sm) Sd = int(Sm)