Próbuję ogarnąć używanie FPU z rdzenia Cortex-M4 w GCC.
1. Mam toolchain linaro, multilib:
2. W Makefile dodaję:
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16
do kompilatora i linkera
3. W kodzie włączanie koprocesora
4. Jest jakiś prosty kod:
No i teraz na czym polega problem:
a. Przy optymalizacji wyłączonej kod jest umiarkowanie dziwny, ale ogólnie obleci:
Jak widać wykorzystana jest instrukcja vsqrt. Głupie jest to warunkowe wywołanie normalnego sqrtf, które w sumie i tak nigdy nie jest wywoływane, tylko gdy jakieś argumenty są niezbyt poprawne - jeśli dobrze rozumiem to w przypadku podania zera.
b. Przy włączeniu jakiejkolwiek optymalizacji zaczyna się robić dziwnie:
np. -O1
(dla innych optymalizacji jest podobnie - wywoływane jest po prostu sqrtf)
Problem zaczyna się przy analizie funkcji sqrtf, która niby jest hardfloat, ale po kilku instrukcjach wywołuje __ieee754_sqrtf, które już z hardfloat nie ma prawie nic wspólnego poza jednym mnożeniem i jednym dzieleniem (pomijam przpisanie z rejestrów float do zwykłych).
Czy ktoś potrafi to wytłumaczyć i powiedzieć co można z tym zrobić? Czy jest to jakaś dziwaczna konfiguracja multilib, która jest bezsensowna?
4\/3!!
1. Mam toolchain linaro, multilib:
>arm-none-eabi-gcc -print-multi-lib
.;
thumb;@mthumb
fpu;@mfloat-abi=hard
armv6-m;@mthumb@march=armv6s-m
armv7-m;@mthumb@march=armv7-m
armv7e-m;@mthumb@march=armv7e-m
armv7-r/thumb;@mthumb@march=armv7-r
armv7-r/thumb/fpu;@mthumb@mfloat-abi=hard@march=armv7-r@mfpu=vfpv3-d16
armv7e-m/fpu;@mthumb@mfloat-abi=hard@march=armv7e-m@mfpu=fpv4-sp-d16
armv7-r/thumb/softfp;@mthumb@mfloat-abi=softfp@march=armv7-r@mfpu=vfpv3-d16
armv7e-m/softfp;@mthumb@mfloat-abi=softfp@march=armv7e-m@mfpu=fpv4-sp-d162. W Makefile dodaję:
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16
do kompilatora i linkera
3. W kodzie włączanie koprocesora
Kod: text
4. Jest jakiś prosty kod:
Kod: text
No i teraz na czym polega problem:
a. Przy optymalizacji wyłączonej kod jest umiarkowanie dziwny, ale ogólnie obleci:
volatile float i = 4.123456;
8000254: 4b1b ldr r3, [pc, #108] ; (80002c4 <main+0x84>)
8000256: 607b str r3, [r7, #4]
[inContentAd]
i = sqrtf(i*i*i);
8000258: ed97 7a01 vldr s14, [r7, #4]
800025c: edd7 7a01 vldr s15, [r7, #4]
8000260: ee27 7a27 vmul.f32 s14, s14, s15
8000264: edd7 7a01 vldr s15, [r7, #4]
8000268: ee27 7a27 vmul.f32 s14, s14, s15
800026c: eef1 7ac7 vsqrt.f32 s15, s14
8000270: eef4 7a67 vcmp.f32 s15, s15
8000274: eef1 fa10 vmrs APSR_nzcv, fpscr
8000278: d005 beq.n 8000286 <main+0x46>
800027a: eeb0 0a47 vmov.f32 s0, s14
800027e: f000 f831 bl 80002e4 <sqrtf>
8000282: eef0 7a40 vmov.f32 s15, s0
8000286: ee17 3a90 vmov r3, s15
800028a: 607b str r3, [r7, #4]Jak widać wykorzystana jest instrukcja vsqrt. Głupie jest to warunkowe wywołanie normalnego sqrtf, które w sumie i tak nigdy nie jest wywoływane, tylko gdy jakieś argumenty są niezbyt poprawne - jeśli dobrze rozumiem to w przypadku podania zera.
b. Przy włączeniu jakiejkolwiek optymalizacji zaczyna się robić dziwnie:
np. -O1
volatile float i = 4.123456;
800022a: f24f 335a movw r3, #62298 ; 0xf35a
800022e: f2c4 0383 movt r3, #16515 ; 0x4083
8000232: 9301 str r3, [sp, #4]
i = sqrtf(i*i*i);
8000234: ed9d 0a01 vldr s0, [sp, #4]
8000238: ed9d 7a01 vldr s14, [sp, #4]
800023c: eddd 7a01 vldr s15, [sp, #4]
8000240: ee20 0a07 vmul.f32 s0, s0, s14
8000244: ee20 0a27 vmul.f32 s0, s0, s15
8000248: f000 f828 bl 800029c <sqrtf>
800024c: ed8d 0a01 vstr s0, [sp, #4](dla innych optymalizacji jest podobnie - wywoływane jest po prostu sqrtf)
Problem zaczyna się przy analizie funkcji sqrtf, która niby jest hardfloat, ale po kilku instrukcjach wywołuje __ieee754_sqrtf, które już z hardfloat nie ma prawie nic wspólnego poza jednym mnożeniem i jednym dzieleniem (pomijam przpisanie z rejestrów float do zwykłych).
Czy ktoś potrafi to wytłumaczyć i powiedzieć co można z tym zrobić? Czy jest to jakaś dziwaczna konfiguracja multilib, która jest bezsensowna?
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-wf_sqrt.o)
out/main.o (sqrtf)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-ef_sqrt.o)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-wf_sqrt.o) (__ieee754_sqrtf)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-s_lib_ver.o)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-wf_sqrt.o) (__fdlib_version)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-s_matherr.o)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-wf_sqrt.o) (matherr)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-sf_fpclassify.o)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-wf_sqrt.o) (__fpclassifyf)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/armv7e-m/fpu\libgcc.a(_arm_addsubdf3.o)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-wf_sqrt.o) (__aeabi_f2d)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/armv7e-m/fpu\libgcc.a(_arm_muldivdf3.o)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-wf_sqrt.o) (__aeabi_ddiv)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/armv7e-m/fpu\libgcc.a(_arm_truncdfsf2.o)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-wf_sqrt.o) (__aeabi_d2f)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libg.a(lib_a-errno.o)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libm.a(lib_a-wf_sqrt.o) (__errno)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libg.a(lib_a-impure.o)
c:/program files/linaro/arm-none-eabi-gcc-4_6/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/armv7e-m/fpu\libg.a(lib_a-errno.o) (_impure_ptr)4\/3!!