summaryrefslogtreecommitdiff
path: root/docs/reference/asm_thumb2_float.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/reference/asm_thumb2_float.rst')
-rw-r--r--docs/reference/asm_thumb2_float.rst77
1 files changed, 77 insertions, 0 deletions
diff --git a/docs/reference/asm_thumb2_float.rst b/docs/reference/asm_thumb2_float.rst
new file mode 100644
index 000000000..4acb734ee
--- /dev/null
+++ b/docs/reference/asm_thumb2_float.rst
@@ -0,0 +1,77 @@
+Floating Point instructions
+==============================
+
+These instructions support the use of the ARM floating point coprocessor
+(on platforms such as the Pyboard which are equipped with one). The FPU
+has 32 registers known as ``s0-s31`` each of which can hold a single
+precision float. 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.
+
+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.
+
+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``
+
+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``
+
+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. Since each float value occupies a 32 bit word, when accessing arrays of
+floats the offset must always be a multiple of four bytes.
+
+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.
+
+Convert between integer and float
+---------------------------------
+
+* vcvt\_f32\_s32(Sd, Sm) ``Sd = float(Sm)``
+* vcvt\_s32\_f32(Sd, Sm) ``Sd = int(Sm)``