简介
种类——-符号位————-指数位—————-尾数位—-
float—第31位(占1bit)—第30-23位(占8bit)—-第22-0位(占23bit)
double–第63位(占1bit)—第62-52位(占11bit)—第51-0位(占52bit)
单精度浮点数的有效位是7位,因为尾数位23位最大值为2^24 - 1=16777215,对应十进制最大为10^7
float a = 10.12345678;
printf("a=%f\n", a);
结果是10.123457,有效数字是7位
float a = 0.12345678;
printf("a=%f\n", a);
结果是0.123457,有效数字是6位,好奇怪不是7位。
arm中浮点数计算
arm中浮点数计算目前可以通过VFP或者NEON
VFP: Vector Float Point,向量浮点计算单元,
NEON: SIMD(Single Instruction Multiple Data)
编译选项
-mfpu=name (vfpvx or neon) 指定FPU单元
-mfloat-abi=name (soft, hard, softfp) 指定软件浮点,硬件浮点或者兼容软浮点调用接口
soft, 不使用硬件浮点单元,gcc使用软件浮点库来完成浮点运算
softfp, 使用硬件浮点单元,生成硬件浮点指令,生成何种类型的硬件浮点指令由-mfpu选项指定,调用接口的规则和soft选项一致
hard, 使用硬件浮点单元,生成硬件浮点指令,与softfp的区别在于调用接口的规则不同。
如果只指定-mfpu,那么默认编译不会选择硬件浮点指令集
如果只指定-mfloat-abi = hard或者softfp,那么编译会使用硬件浮点指令集
int main(void)
{
float f1, f2, f3;
f1 = 1.2;
f2 = 1.3;
f3 = f1 / f2;
return 0;
}
-mfpu=neon
arm-eabi-gcc -S hello.c -mfpu=neon
.arch armv5te
.fpu softvfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 18, 4
.file "hello.c"
.global __aeabi_fdiv
.text
.align 2
.global main
.type main, %function
main:
.fnstart
.LFB0:
@ args = 0, pretend = 0, frame = 16
@ frame_needed = 1, uses_anonymous_args = 0
stmfd sp!, {fp, lr}
.save {fp, lr}
.LCFI0:
.setfp fp, sp, #4
add fp, sp, #4
.LCFI1:
.pad #16
sub sp, sp, #16
.LCFI2:
ldr r3, .L3 @ float
str r3, [fp, #-16] @ float
ldr r3, .L3+4 @ float
str r3, [fp, #-12] @ float
ldr r0, [fp, #-16] @ float
ldr r1, [fp, #-12] @ float
bl __aeabi_fdiv
mov r3, r0
str r3, [fp, #-8] @ float
mov r3, #0
mov r0, r3
sub sp, fp, #4
ldmfd sp!, {fp, pc}
.L4:
.align 2
.L3:
.word 1067030938
.word 1067869798
.LFE0:
.fnend
.size main, .-main
.ident "GCC: (Sourcery G++ Lite 2009q3-67) 4.4.1"
.section .note.GNU-stack,"",%progbits
-mfpu=vfp
arm-eabi-gcc -S hello.c -mfpu=vfp
.arch armv5te
.fpu softvfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 18, 4
.file "hello.c"
.global __aeabi_fdiv
.text
.align 2
.global main
.type main, %function
main:
.fnstart
.LFB0:
@ args = 0, pretend = 0, frame = 16
@ frame_needed = 1, uses_anonymous_args = 0
stmfd sp!, {fp, lr}
.save {fp, lr}
.LCFI0:
.setfp fp, sp, #4
add fp, sp, #4
.LCFI1:
.pad #16
sub sp, sp, #16
.LCFI2:
ldr r3, .L3 @ float
str r3, [fp, #-16] @ float
ldr r3, .L3+4 @ float
str r3, [fp, #-12] @ float
ldr r0, [fp, #-16] @ float
ldr r1, [fp, #-12] @ float
bl __aeabi_fdiv
mov r3, r0
str r3, [fp, #-8] @ float
mov r3, #0
mov r0, r3
sub sp, fp, #4
ldmfd sp!, {fp, pc}
.L4:
.align 2
.L3:
.word 1067030938
.word 1067869798
.LFE0:
.fnend
.size main, .-main
.ident "GCC: (Sourcery G++ Lite 2009q3-67) 4.4.1"
.section .note.GNU-stack,"",%progbits
可以看到上面两个例子,使用的是.fpu softvfp
-mfpu=neon -mfloat-abi=hard
arm-eabi-gcc -S hello.c -mfpu=neon -mfloat-abi=hard
.arch armv5te
.eabi_attribute 27, 3
.eabi_attribute 28, 1
.fpu neon
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 18, 4
.file "hello.c"
.text
.align 2
.global main
.type main, %function
main:
.fnstart
.LFB0:
@ args = 0, pretend = 0, frame = 16
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
.save {fp}
.LCFI0:
.setfp fp, sp, #0
add fp, sp, #0
.LCFI1:
.pad #20
sub sp, sp, #20
.LCFI2:
flds s15, .L3
fsts s15, [fp, #-16]
flds s15, .L3+4
fsts s15, [fp, #-12]
flds s14, [fp, #-16]
flds s15, [fp, #-12]
fdivs s15, s14, s15
fsts s15, [fp, #-8]
mov r3, #0
mov r0, r3
add sp, fp, #0
ldmfd sp!, {fp}
bx lr
.L4:
.align 2
.L3:
.word 1067030938
.word 1067869798
.LFE0:
.fnend
.size main, .-main
.ident "GCC: (Sourcery G++ Lite 2009q3-67) 4.4.1"
.section .note.GNU-stack,"",%progbits
-mfpu=neon -mfloat-abi=softfp
arm-eabi-gcc -S hello.c -mfpu=neon -mfloat-abi=softfp
.arch armv5te
.eabi_attribute 27, 3
.fpu neon
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 18, 4
.file "hello.c"
.text
.align 2
.global main
.type main, %function
main:
.fnstart
.LFB0:
@ args = 0, pretend = 0, frame = 16
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
.save {fp}
.LCFI0:
.setfp fp, sp, #0
add fp, sp, #0
.LCFI1:
.pad #20
sub sp, sp, #20
.LCFI2:
flds s15, .L3
fsts s15, [fp, #-16]
flds s15, .L3+4
fsts s15, [fp, #-12]
flds s14, [fp, #-16]
flds s15, [fp, #-12]
fdivs s15, s14, s15
fsts s15, [fp, #-8]
mov r3, #0
mov r0, r3
add sp, fp, #0
ldmfd sp!, {fp}
bx lr
.L4:
.align 2
.L3:
.word 1067030938
.word 1067869798
.LFE0:
.fnend
.size main, .-main
.ident "GCC: (Sourcery G++ Lite 2009q3-67) 4.4.1"
.section .note.GNU-stack,"",%progbits
-mfpu=vfpv3 -mfloat-abi=hard
arm-eabi-gcc -S hello.c -mfpu=vfpv3 -mfloat-abi=hard
.arch armv5te
.eabi_attribute 27, 3
.eabi_attribute 28, 1
.fpu vfpv3
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 18, 4
.file "hello.c"
.text
.align 2
.global main
.type main, %function
main:
.fnstart
.LFB0:
@ args = 0, pretend = 0, frame = 16
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
.save {fp}
.LCFI0:
.setfp fp, sp, #0
add fp, sp, #0
.LCFI1:
.pad #20
sub sp, sp, #20
.LCFI2:
flds s15, .L3
fsts s15, [fp, #-16]
flds s15, .L3+4
fsts s15, [fp, #-12]
flds s14, [fp, #-16]
flds s15, [fp, #-12]
fdivs s15, s14, s15
fsts s15, [fp, #-8]
mov r3, #0
mov r0, r3
add sp, fp, #0
ldmfd sp!, {fp}
bx lr
.L4:
.align 2
.L3:
.word 1067030938
.word 1067869798
.LFE0:
.fnend
.size main, .-main
.ident "GCC: (Sourcery G++ Lite 2009q3-67) 4.4.1"
.section .note.GNU-stack,"",%progbits
-mfpu=vfpv3 -mfloat-abi=softfp
arm-eabi-gcc -S hello.c -mfpu=vfpv3 -mfloat-abi=softfp
.arch armv5te
.eabi_attribute 27, 3
.fpu vfpv3
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 18, 4
.file "hello.c"
.text
.align 2
.global main
.type main, %function
main:
.fnstart
.LFB0:
@ args = 0, pretend = 0, frame = 16
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
.save {fp}
.LCFI0:
.setfp fp, sp, #0
add fp, sp, #0
.LCFI1:
.pad #20
sub sp, sp, #20
.LCFI2:
flds s15, .L3
fsts s15, [fp, #-16]
flds s15, .L3+4
fsts s15, [fp, #-12]
flds s14, [fp, #-16]
flds s15, [fp, #-12]
fdivs s15, s14, s15
fsts s15, [fp, #-8]
mov r3, #0
mov r0, r3
add sp, fp, #0
ldmfd sp!, {fp}
bx lr
.L4:
.align 2
.L3:
.word 1067030938
.word 1067869798
.LFE0:
.fnend
.size main, .-main
.ident "GCC: (Sourcery G++ Lite 2009q3-67) 4.4.1"
.section .note.GNU-stack,"",%progbits
使用softfp和hard使用的指令集是一样的,都是硬件浮点, neon和vfp的区别,仅仅体现在.fpu vfpv3和.fpu neon。
-mfloat-abi=hard
arm-eabi-gcc -S hello.c -mfloat-abi=hard
.arch armv5te
.eabi_attribute 27, 3
.eabi_attribute 28, 1
.fpu vfp
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 18, 4
.file "hello.c"
.text
.align 2
.global main
.type main, %function
main:
.fnstart
.LFB0:
@ args = 0, pretend = 0, frame = 16
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
.save {fp}
.LCFI0:
.setfp fp, sp, #0
add fp, sp, #0
.LCFI1:
.pad #20
sub sp, sp, #20
.LCFI2:
flds s15, .L3
fsts s15, [fp, #-16]
flds s15, .L3+4
fsts s15, [fp, #-12]
flds s14, [fp, #-16]
flds s15, [fp, #-12]
fdivs s15, s14, s15
fsts s15, [fp, #-8]
mov r3, #0
mov r0, r3
add sp, fp, #0
ldmfd sp!, {fp}
bx lr
.L4:
.align 2
.L3:
.word 1067030938
.word 1067869798
.LFE0:
.fnend
.size main, .-main
.ident "GCC: (Sourcery G++ Lite 2009q3-67) 4.4.1"
.section .note.GNU-stack,"",%progbits
当直接使用-mfloat-abi=hard时,会默认使用.fpu vfp硬件浮点。