|
| 1 | +Floating Point instructions |
| 2 | +============================== |
| 3 | + |
| 4 | +These instructions support the use of the ARM floating point coprocessor |
| 5 | +(on platforms such as the Pyboard which are equipped with one). The FPU |
| 6 | +has 32 registers known as ``s0-s31`` each of which can hold a single |
| 7 | +precision float. Data can be passed between the FPU registers and the |
| 8 | +ARM core registers with the ``vmov`` instruction. |
| 9 | + |
| 10 | +Note that MicroPython doesn't support passing floats to |
| 11 | +assembler functions, nor can you put a float into ``r0`` and expect a |
| 12 | +reasonable result. There are two ways to overcome this. The first is to |
| 13 | +use arrays, and the second is to pass and/or return integers and convert |
| 14 | +to and from floats in code. |
| 15 | + |
| 16 | +Document conventions |
| 17 | +-------------------- |
| 18 | + |
| 19 | +Notation: ``Sd, Sm, Sn`` denote FPU registers, ``Rd, Rm, Rn`` denote ARM core |
| 20 | +registers. The latter can be any ARM core register although registers |
| 21 | +``R13-R15`` are unlikely to be appropriate in this context. |
| 22 | + |
| 23 | +Arithmetic |
| 24 | +---------- |
| 25 | + |
| 26 | +* vadd(Sd, Sn, Sm) ``Sd = Sn + Sm`` |
| 27 | +* vsub(Sd, Sn, Sm) ``Sd = Sn - Sm`` |
| 28 | +* vneg(Sd, Sm) ``Sd = -Sm`` |
| 29 | +* vmul(Sd, Sn, Sm) ``Sd = Sn * Sm`` |
| 30 | +* vdiv(Sd, Sn, Sm) ``Sd = Sn / Sm`` |
| 31 | +* vsqrt(Sd, Sm) ``Sd = sqrt(Sm)`` |
| 32 | + |
| 33 | +Registers may be identical: ``vmul(S0, S0, S0)`` will execute ``S0 = S0*S0`` |
| 34 | + |
| 35 | +Move between ARM core and FPU registers |
| 36 | +--------------------------------------- |
| 37 | + |
| 38 | +* vmov(Sd, Rm) ``Sd = Rm`` |
| 39 | +* vmov(Rd, Sm) ``Rd = Sm`` |
| 40 | + |
| 41 | +The FPU has a register known as FPSCR, similar to the ARM core's APSR, which stores condition |
| 42 | +codes plus other data. The following instructions provide access to this. |
| 43 | + |
| 44 | +* vmrs(APSR\_nzcv, FPSCR) |
| 45 | + |
| 46 | +Move the floating-point N, Z, C, and V flags to the APSR N, Z, C, and V flags. |
| 47 | + |
| 48 | +This is done after an instruction such as an FPU |
| 49 | +comparison to enable the condition codes to be tested by the assembler |
| 50 | +code. The following is a more general form of the instruction. |
| 51 | + |
| 52 | +* vmrs(Rd, FPSCR) ``Rd = FPSCR`` |
| 53 | + |
| 54 | +Move between FPU register and memory |
| 55 | +------------------------------------ |
| 56 | + |
| 57 | +* vldr(Sd, [Rn, offset]) ``Sd = [Rn + offset]`` |
| 58 | +* vstr(Sd, [Rn, offset]) ``[Rn + offset] = Sd`` |
| 59 | + |
| 60 | +Where ``[Rn + offset]`` denotes the memory address obtained by adding Rn to the offset. This |
| 61 | +is specified in bytes. Since each float value occupies a 32 bit word, when accessing arrays of |
| 62 | +floats the offset must always be a multiple of four bytes. |
| 63 | + |
| 64 | +Data Comparison |
| 65 | +--------------- |
| 66 | + |
| 67 | +* vcmp(Sd, Sm) |
| 68 | + |
| 69 | +Compare the values in Sd and Sm and set the FPU N, Z, |
| 70 | +C, and V flags. This would normally be followed by ``vmrs(APSR_nzcv, FPSCR)`` |
| 71 | +to enable the results to be tested. |
| 72 | + |
| 73 | +Convert between integer and float |
| 74 | +--------------------------------- |
| 75 | + |
| 76 | +* vcvt\_f32\_s32(Sd, Sm) ``Sd = float(Sm)`` |
| 77 | +* vcvt\_s32\_f32(Sd, Sm) ``Sd = int(Sm)`` |
0 commit comments