diff --git a/section_2/float/fmov.md b/section_2/float/fmov.md new file mode 100644 index 0000000..3fc3296 --- /dev/null +++ b/section_2/float/fmov.md @@ -0,0 +1,74 @@ +# `fmov` + +The `fmov` instruction is used to move floating point values in and out +of floating point registers and to some degree, moving data between +integer and floating point registers. + +## Loading Floating Point Numbers as Immediate Values + +Just as we saw with integer +registers, some values can be used as immediate values and some cannot. + +For example, this works: + +`mov x0, 65536` + +but this does not: + +`mov x0, 65537` + +The reason is that all AARCH64 instructions must fit within a 32 bit +instruction that must hold the instruction's op code, its flags and +other bits and bobs plus any immediate value. In the above example we +can see that the `mov` instruction provides up to 16 bits for an +immediate value. + +The constraints placed on immediate values for `fmov` are much tighter +because floating point numbers are far more complex than integers. + +Make sure you have read and understand [this chapter](./what.md) before +proceeding. + +Let's take a look at some code: + +```text + fmov d0, 1.0 // works + fmov d0, 1.5 // works 2**-1 + fmov d0, 1.75 // works 2**-1 + 2**-2 + fmov d0, 1.875 // works 2**-1 + 2**-2 + 2**-3 + fmov d0, 1.9375 // works the preceding + 2**-4 + fmov d0, 1.96875 // Zoinks! +``` + +From this we can see that an immediate value for an `fmov` seems to have +4 bits available for the mantissa. In fact, the only values that work +as immediate values will be those floating point values whose fractional +values are combinations of: + +* 1/2 + +* 1/4 + +* 1/8 and + +* 1/16 + +As far as exponents go, `fmov` can accommodate 3 bits. So, exponents of +plus or minus 2**7 can be used. + +## Loading / Storing Floating Point Numbers in General + +When in doubt, load fixed floating point numbers from memory. This is +covered [in this chapter](./literals.md). + +## SIMD + +`fmov` can also deal with the more complicated special cases induced by +SIMD instruction. + +## Movement To / From Integer Registers + +`fmov` can *bits* between the integer and floating point registers. We +emphasize the *bits*. No conversions are done using `fmov`. There exist +other instructions for that. See [this chapter](./rounding.md) for more +information. diff --git a/section_2/float/test.s b/section_2/float/test.s index 90b0fee..68632dd 100644 --- a/section_2/float/test.s +++ b/section_2/float/test.s @@ -1,99 +1,13 @@ - .section __TEXT,__text,regular,pure_instructions - .build_version macos, 13, 0 sdk_version 13, 1 - .globl _main ; -- Begin function main - .p2align 2 -_main: ; @main - .cfi_startproc -; %bb.0: - sub sp, sp, #80 - stp x22, x21, [sp, #32] ; 16-byte Folded Spill - stp x20, x19, [sp, #48] ; 16-byte Folded Spill - stp x29, x30, [sp, #64] ; 16-byte Folded Spill - add x29, sp, #64 - .cfi_def_cfa w29, 16 - .cfi_offset w30, -8 - .cfi_offset w29, -16 - .cfi_offset w19, -24 - .cfi_offset w20, -32 - .cfi_offset w21, -40 - .cfi_offset w22, -48 -Lloh0: - adrp x20, _d@PAGE -Lloh1: - add x20, x20, _d@PAGEOFF - ldr d0, [x20] -Lloh2: - adrp x21, _f@PAGE -Lloh3: - add x21, x21, _f@PAGEOFF - ldr s1, [x21] - fcvt d1, s1 - str d1, [sp, #16] - str d0, [sp, #8] - str xzr, [sp] -Lloh4: - adrp x19, l_.str@PAGE -Lloh5: - add x19, x19, l_.str@PAGEOFF - mov x0, x19 - bl _printf - ldr d0, [x20, #8] - ldr s1, [x21, #4] - fcvt d1, s1 - str d1, [sp, #16] - str d0, [sp, #8] - mov w8, #1 - str x8, [sp] - mov x0, x19 - bl _printf - ldr d0, [x20, #16] - ldr s1, [x21, #8] - fcvt d1, s1 - str d1, [sp, #16] - str d0, [sp, #8] - mov w8, #2 - str x8, [sp] - mov x0, x19 - bl _printf - ldr d0, [x20, #24] - ldr s1, [x21, #12] - fcvt d1, s1 - str d1, [sp, #16] - str d0, [sp, #8] - mov w8, #3 - str x8, [sp] - mov x0, x19 - bl _printf - mov w0, #0 - ldp x29, x30, [sp, #64] ; 16-byte Folded Reload - ldp x20, x19, [sp, #48] ; 16-byte Folded Reload - ldp x22, x21, [sp, #32] ; 16-byte Folded Reload - add sp, sp, #80 - ret - .loh AdrpAdd Lloh4, Lloh5 - .loh AdrpAdd Lloh2, Lloh3 - .loh AdrpAdd Lloh0, Lloh1 - .cfi_endproc - ; -- End function - .section __DATA,__data - .globl _d ; @d - .p2align 3 -_d: - .quad 0x3ff8e38da3c21188 ; double 1.555555 - .quad 0x40055554fbdad752 ; double 2.6666660000000002 - .quad 0x400e38e325d4a5df ; double 3.7777769999999999 - .quad 0x40138e38a7e73a36 ; double 4.8888879999999997 + .text + .p2align 2 + .global test - .globl _f ; @f - .p2align 2 -_f: - .long 0x3f8e38e3 ; float 1.11111104 - .long 0x400e38e3 ; float 2.22222209 - .long 0x40555554 ; float 3.33333302 - .long 0x408e38e3 ; float 4.44444418 +test: fmov d0, 1.0 + fmov d0, 1.5 + fmov d0, 1.75 + fmov d0, 1.875 + fmov d0, 1.9375 + fmov d0, 1.96875 + ret - .section __TEXT,__cstring,cstring_literals -l_.str: ; @.str - .asciz "index %ld double %f float %f\n" - -.subsections_via_symbols + .end