GCC发出ARM idiv指令

时间:2013-04-03 08:12:17

标签: gcc arm

如何指示gccidiv发出udiv(整数除法,sdivarm application processors)指示?

到目前为止,我能想出的唯一方法是使用-mcpu=cortex-a15和gcc 4.7。

$cat idiv.c
int test_idiv(int a, int b) {
    return a / b;
}

在gcc 4.7上(与Android NDK r8e捆绑在一起)

$gcc -O2 -mcpu=cortex-a15 -c idiv.c
$objdump -S idiv.o

00000000 <test_idiv>:
   0:   e710f110    sdiv    r0, r0, r1
   4:   e12fff1e    bx  lr

如果您在idiv.c:1:0: warning: switch -mcpu=cortex-a15 conflicts with -march=armv7-a switch [enabled by default]旁边添加-march=armv7-a并且不会发出-mcpu=cortex-a15指令,那么即使这一个也会idiv

$gcc -O2 -mcpu=cortex-a15 -march=armv7-a -c idiv.c

idiv.c:1:0: warning: switch -mcpu=cortex-a15 conflicts with -march=armv7-a switch [enabled by default]

$objdump -S idiv.o
00000000 <test_idiv>:
   0:   e92d4008    push    {r3, lr}
   4:   ebfffffe    bl  0 <__aeabi_idiv>
   8:   e8bd8008    pop {r3, pc}

在gcc 4.6(与Android NDK r8e捆绑在一起)上,它根本不会发出idiv条指令,但认可-mcpu=cortex-a15也不会向-mcpu=cortex-a15 -march=armv7-a组合投诉。

Afaik idivarmv7上是可选的,所以应该有一种更简洁的方法来指示gcc发出它们但是如何?

1 个答案:

答案 0 :(得分:5)

如果指令不在机器描述中,那么我怀疑gcc是否会发出代码。 注1

如果编译器不支持,你总是可以使用 inline-assembler 来获取指令。 Note2 因为你的op-code非常罕见/特定于机器,在gcc来源中可能没有那么多努力。特别是,有 arch tune / cpu 标志。 tune / cpu 适用于更具体的计算机,但 arch 假设允许该体系结构中的所有计算机。如果我明白的话,这op-code似乎打破了这个规则。

对于gcc 4.6.2,看起来 thumb2 cortex-r4 是使用这些说明的提示,正如您在{{1 4.7.2,似乎添加 cortex-a15 来使用这些指令。使用gcc 4.7.2时, thumb2.md 文件不再具有gcc / udiv。但是,它可能包含在其他地方;我不是100%熟悉所有机器描述语言。似乎 cortex-a7 cortex-a15 cortex-r5 可以使用4.7.2启用这些指令。 注3

这不直接回答问题,但确实提供了一些信息/路径来获得答案。您可以使用sdiv编译模块,但这可能会产生链接器问题。此外,还有-mcpu=cortex-r4,您可以在每个函数的基础上指定代码生成器使用的 machine-description 。我自己没有使用过这些,但它们只是尝试的可能性。通常,您不希望保留错误的机器,因为它可能会生成次优(也可能是非法)操作码。您必须进行实验,然后提供真实答案。

注1:这适用于 stock int my_idiv(int a, int b) __attribute__ ((__target__ ("arch=cortexe-r4"))); 4.6.2和4.7.2。我不知道你的Android编译器是否有补丁。

gcc
gcc-4.6.2/gcc/config/arm$ grep [ius]div *.md
arm.md: "...,sdiv,udiv,other"
cortex-r4.md:;; We guess that division of A/B using sdiv or udiv, on average, 
cortex-r4.md:;; This gives a latency of nine for udiv and ten for sdiv.
cortex-r4.md:(define_insn_reservation "cortex_r4_udiv" 9
cortex-r4.md:       (eq_attr "insn" "udiv"))
cortex-r4.md:(define_insn_reservation "cortex_r4_sdiv" 10
cortex-r4.md:       (eq_attr "insn" "sdiv"))
thumb2.md:  "sdiv%?\t%0, %1, %2"
thumb2.md:   (set_attr "insn" "sdiv")]
thumb2.md:(define_insn "udivsi3"
thumb2.md:      (udiv:SI (match_operand:SI 1 "s_register_operand"  "r")
thumb2.md:  "udiv%?\t%0, %1, %2"
thumb2.md:   (set_attr "insn" "udiv")]

注2:如果gcc-4.7.2/gcc/config/arm$ grep -i [ius]div *.md arm.md: "...,sdiv,udiv,other" arm.md: "TARGET_IDIV" arm.md: "sdiv%?\t%0, %1, %2" arm.md: (set_attr "insn" "sdiv")] arm.md:(define_insn "udivsi3" arm.md: (udiv:SI (match_operand:SI 1 "s_register_operand" "r") arm.md: "TARGET_IDIV" arm.md: "udiv%?\t%0, %1, %2" arm.md: (set_attr "insn" "udiv")] cortex-a15.md:(define_insn_reservation "cortex_a15_udiv" 9 cortex-a15.md: (eq_attr "insn" "udiv")) cortex-a15.md:(define_insn_reservation "cortex_a15_sdiv" 10 cortex-a15.md: (eq_attr "insn" "sdiv")) cortex-r4.md:;; We guess that division of A/B using sdiv or udiv, on average, cortex-r4.md:;; This gives a latency of nine for udiv and ten for sdiv. cortex-r4.md:(define_insn_reservation "cortex_r4_udiv" 9 cortex-r4.md: (eq_attr "insn" "udiv")) cortex-r4.md:(define_insn_reservation "cortex_r4_sdiv" 10 cortex-r4.md: (eq_attr "insn" "sdiv")) gcc传递阻止使用gas指令的选项,请参见pre-processor as Assembler。例如,您可以使用udiv/sdiv其中操作码是一些标记粘贴的字符串编码宏编码宏输出。此外,您可以注释汇编程序以指定asm(" .long <opcode>\n");中的更改。所以你可以暂时撒谎并说你有 cortex-r4 等。

<强>注3:

machine