arm中除法和浮点运算

在学习正点原子I.MX6ull芯片开发板的时候,有两个裸机实验(串口和spi)涉及到了除法运算以及浮点运算,

先声明,除法运算(定点和浮点,浮点除法是浮点运算的一种)和浮点运算是两个东西:

1.除法分为定点除法和浮点除法,arm中定点除法例如32位无符号整形除法,是没有直接的汇编指令的,需要借助软件库来实现;

2.浮点数的除法可以调用软件库来进行软件模拟,也可以借助硬件进行浮点数运算(协处理器,cp15指令开启硬件浮点运算)。

 

一、定点数除法指令需要链接gcc库:

使用定点数除法运算的时候编译提示错误 (可以看出来uidiv uldiv,这些函数是针对int 和long 这些定点数进行除法运算的函数):

bsp_uart.c:(.text+0xd4):对‘__aeabi_uidivmod’未定义的引用
bsp_uart.c:(.text+0xe2):对‘__aeabi_uidiv’未定义的引用
bsp_uart.c:(.text+0xec):对‘__aeabi_uidiv’未定义的引用
bsp_uart.c:(.text+0x156):对‘__aeabi_uldivmod’未定义的引用
bsp_uart.c:(.text+0x166):对‘__aeabi_uidiv’未定义的引用
bsp_uart.c:(.text+0x17a):对‘__aeabi_uidiv’未定义的引用
bsp_uart.c:(.text+0x186):对‘__aeabi_uldivmod’未定义的引用
bsp_uart.c:(.text+0x1e2):对‘__aeabi_uidiv’未定义的引用
bsp_uart.c:(.text+0x236):对‘__aeabi_uidiv’未定义的引用
bsp_uart.c:(.text+0x240):对‘__aeabi_uidiv’未定义的引用

原因是ARM,没有定点数的除法指令。libgcc库包含除法指令的代码,于是加上链接库gcc:

-lgcc -L /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.4/

参考:https://blog.csdn.net/xgbing/article/details/7803846

另外定义函数:

void raise(int sig_nr){

}

应对除零异常的情况。

 

二、gcc编译器默认将浮点数除法指令直接翻译成汇编指令(例如vdiv.f32)供协处理器可以直接运行,裸机例程中需要我们手动设置cp15寄存器,来打开硬件浮点数除法(使用如下函数):

 void imx6ul_hardfpu_enable(void)

{

	uint32_t cpacr;

	uint32_t fpexc;



	/* 使能NEON和FPU */

	cpacr = __get_CPACR();

	cpacr = (cpacr & ~(CPACR_ASEDIS_Msk | CPACR_D32DIS_Msk))

		   |  (3UL << CPACR_cp10_Pos) | (3UL << CPACR_cp11_Pos);

	__set_CPACR(cpacr);

	fpexc = __get_FPEXC();

	fpexc |= 0x40000000UL;	

	__set_FPEXC(fpexc);

}

(注:我说的gcc默认是指现在的版本,可能更古老的gcc默认通过调用浮点数的软件除法库,来完成浮点数的除法)

另外,gcc编译硬件浮点运算最好给gcc传递如下参数来完成,经测试不指定好像默认也是硬件浮点运算

$(COBJS) : obj/%.o : %.c
	$(CC) -Wall -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin -c -O2  $(INCLUDE) -o $@ $<

 

你可能感兴趣的:(linux)