第三篇 ARM C 高效编程 - 除法以及求余

除法以及求余运算

/**
 * 结论:
 *    1. 大部分arm都有除法指令,但需要指定相应的编译标志,不然就会直接调用 c 库函数
 *    2. 指定相应的体系架构,可以生成更优的代码
 * compile with arm-linux-gnueabihf-gcc v8.3
 * flags: -O3 -mcpu=cortex-a7 -mtune=cortex-a7 -mfloat-abi=hard -mfpu=neon
 * 000103d8 :
 * 103d8:       e713f110        sdiv    r3, r0, r1  ; 除法指令
 * 103dc:       e0600391        mls     r0, r1, r3, r0 ; 乘减指令
 * 103e0:       e0830000        add     r0, r3, r0
 * 103e4:       e12fff1e        bx      lr
 * flags: -O3
 * 00010410 :
 * 10410:       e92d4010        push    {r4, lr}
 * 10414:       eb000089        bl      10640 <__aeabi_idivmod> ; 调用 c 库提供的除法函数,同时返回商和余数
 * 10418:       e0800001        add     r0, r0, r1
 * 1041c:       e8bd8010        pop     {r4, pc}
 */

int combined_div_mod(int a, int b)
{
	return (a / b) + (a % b);
}
/**
 * 结论:
 *     1. 尽量将求余操作转为加法操作
 * compile with arm-linux-gnueabihf-gcc v8.3
 * flags: -O3 -mcpu=cortex-a7 -mtune=cortex-a7 -mfloat-abi=hard -mfpu=neon
 * 000103d8 :
 * 103d8:       e2800001        add     r0, r0, #1
 * 103dc:       e3083889        movw    r3, #34953      ; 0x8889
 * 103e0:       e3483888        movt    r3, #34952      ; 0x8888
 * 103e4:       e3a0203c        mov     r2, #60 ; 0x3c
 * 103e8:       e0831093        umull   r1, r3, r3, r0 ; 无符号长乘法
 * 103ec:       e1a032a3        lsr     r3, r3, #5
 * 103f0:       e0600392        mls     r0, r2, r3, r0 ; 乘减指令
 * 103f4:       e12fff1e        bx      lr
 * 000103f8 :
 * 103f8:       e2800001        add     r0, r0, #1
 * 103fc:       e350003c        cmp     r0, #60 ; 0x3c
 * 10400:       23a00000        movcs   r0, #0
 * 10404:       e12fff1e        bx      lr
 */

uint32_t counter1(uint32_t count)
{
	return (++count % 60);
}

uint32_t counter2(uint32_t count)
{
	if (++count >= 60)
		count = 0;
	return (count);
}
/**
 * 结论:
 *    1. 无符号数比有符号数除法更快
 *    2. 除数如果为 2 的幂。将转为超快的移位操作
 *    3. 除数如果为常数,也可以转为移位操作,不过要多一些指令,尤其是多了一条乘法指令
 *    4. 其余情况就只能调用除法指令
 * compile with arm-linux-gnueabihf-gcc v8.3
 * flags: -O3 -mcpu=cortex-a7 -mtune=cortex-a7 -mfloat-abi=hard -mfpu=neon
 * 00010410 :
 * 10410:       e1a00220        lsr     r0, r0, #4
 * 10414:       e12fff1e        bx      lr
 * 00010424 :
 * 10424:       e280300f        add     r3, r0, #15
 * 10428:       e3500000        cmp     r0, #0
 * 1042c:       b1a00003        movlt   r0, r3
 * 10430:       e1a00240        asr     r0, r0, #4
 * 10434:       e12fff1e        bx      lr
 * 000103e0 :
 * 103e0:       e730f110        udiv    r0, r0, r1 ; 除法指令
 * 103e4:       e12fff1e        bx      lr
 * 000103e8 :
 * 103e8:       e30f30f1        movw    r3, #61681      ; 0xf0f1
 * 103ec:       e34f30f0        movt    r3, #61680      ; 0xf0f0
 * 103f0:       e0803093        umull   r3, r0, r3, r0  ; 长乘法指令
 * 103f4:       e1a00220        lsr     r0, r0, #4
 * 103f8:       e12fff1e        bx      lr
 */

uint32_t div16u(uint32_t a)
{
  return a / 16;
}

int div16s(int a)
{
  return a / 16;
}

uint32_t div_xx_u(uint32_t a, uint32_t b)
{
  return a / b;
}

uint32_t div17u(uint32_t a)
{
  return a / 17;
}

你可能感兴趣的:(ARM-高效C编程,arm,c语言)