10. 浮点指令

这些指令支持使用 ARM 浮点协处理器(在诸如配备了协处理器的 OpenMV Cam 等平台上)。FPU 有 32 个名为 s0-s31 的寄存器,每个都可以保存一个单精度浮点数。可以用 vmov 指令在 FPU 寄存器和 ARM 内核寄存器之间传递数据。

请注意,MicroPython 不支持把浮点数传递给汇编函数,你也不能把一个浮点数放入 r0 并期望得到合理的结果。有两种方法可以克服这一点。第一种是使用数组,第二种是传递和/或返回整数,并在代码中进行浮点数与整数之间的转换。

10.1. 文档约定

记法:Sd, Sm, Sn 表示 FPU 寄存器,Rd, Rm, Rn 表示 ARM 内核寄存器。后者可以是任何 ARM 内核寄存器,不过寄存器 R13-R15 在此上下文中不太可能合适。

10.2. 算术

  • 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)

寄存器可以相同:vmul(S0, S0, S0) 会执行 S0 = S0*S0

10.3. 在 ARM 内核寄存器和 FPU 寄存器之间移动

  • vmov(Sd, Rm) Sd = Rm

  • vmov(Rd, Sm) Rd = Sm

FPU 有一个名为 FPSCR 的寄存器,类似于 ARM 内核的 APSR,它存储条件码以及其他数据。以下指令提供对它的访问。

  • vmrs(APSR_nzcv, FPSCR)

将浮点的 N、Z、C 和 V 标志移动到 APSR 的 N、Z、C 和 V 标志。

这通常在诸如 FPU 比较之类的指令之后执行,以便能够由汇编代码测试条件码。下面是该指令的一种更通用的形式。

  • vmrs(Rd, FPSCR) Rd = FPSCR

10.4. 在 FPU 寄存器和内存之间移动

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

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

其中 [Rn + offset] 表示将 Rn 加上偏移量所得到的内存地址。偏移量以字节为单位指定。由于每个浮点值占用一个 32 位的字,因此在访问浮点数组时,偏移量必须始终是四字节的倍数。

10.5. 数据比较

  • vcmp(Sd, Sm)

比较 Sd 和 Sm 中的值,并设置 FPU 的 N、Z、C 和 V 标志。这之后通常会跟一条 vmrs(APSR_nzcv, FPSCR),以便能够测试结果。

10.6. 在整数和浮点数之间转换

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

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