# 10. Floating Point instructions¶

These instructions support the use of the ARM floating point coprocessor
(on platforms such as the Pyboard and the OpenMV Cam which are equipped with one). The FPU
has 32 registers known as `s0-s31`

each of which can hold a single
precision floating point number. Data can be passed between the FPU registers and the
ARM core registers with the `vmov`

instruction.

Note that MicroPython doesn’t support passing floats to
assembler functions, nor can you put a float into `r0`

and expect a
reasonable result. There are two ways to overcome this. The first is to
use arrays, and the second is to pass and/or return integers and convert
to and from floats in code.

## 10.1. Document conventions¶

Notation: `Sd, Sm, Sn`

denote FPU registers, `Rd, Rm, Rn`

denote ARM core
registers. The latter can be any ARM core register although registers
`R13-R15`

are unlikely to be appropriate in this context.

## 10.2. Arithmetic¶

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

Registers may be identical: `vmul(S0, S0, S0)`

will execute `S0 = S0*S0`

## 10.3. Move between ARM core and FPU registers¶

- vmov(Sd, Rm)
`Sd = Rm`

- vmov(Rd, Sm)
`Rd = Sm`

The FPU has a register known as FPSCR, similar to the ARM core’s APSR, which stores condition codes plus other data. The following instructions provide access to this.

- vmrs(APSR_nzcv, FPSCR)

Move the floating-point N, Z, C, and V flags to the APSR N, Z, C, and V flags.

This is done after an instruction such as an FPU comparison to enable the condition codes to be tested by the assembler code. The following is a more general form of the instruction.

- vmrs(Rd, FPSCR)
`Rd = FPSCR`

## 10.4. Move between FPU register and memory¶

- vldr(Sd, [Rn, offset])
`Sd = [Rn + offset]`

- vstr(Sd, [Rn, offset])
`[Rn + offset] = Sd`

Where `[Rn + offset]`

denotes the memory address obtained by adding Rn to the offset. This
is specified in bytes. When accessing arrays of floats the offset must always be a multiple of four bytes
since each floating point value occupies a 32 bit word.

## 10.5. Data Comparison¶

- vcmp(Sd, Sm)

Compare the values in Sd and Sm and set the FPU N, Z,
C, and V flags. This would normally be followed by `vmrs(APSR_nzcv, FPSCR)`

to enable the results to be tested.

## 10.6. Convert between integers and floats¶

- vcvt_f32_s32(Sd, Sm)
`Sd = float(Sm)`

- vcvt_s32_f32(Sd, Sm)
`Sd = int(Sm)`