GCC 发出 ARM idiv 指令

标签 gcc arm

我该如何指导gcc发射 idiv (整数除法,udivsdiv )arm 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 投诉组合。

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

最佳答案

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

如果编译器不支持它,你总是可以使用 inline-assembler 来获取指令。注 2 因为你的 op-code相当罕见/特定于机器,在 gcc 中获得它可能没有太多努力。来源。特别是,有 arch 和 tune/cpu 标志。 tune/cpu 用于更具体的机器,但 arch 应该允许该架构中的所有机器。这个op-code如果我理解的话,似乎违反了这条规则。

对于 gcc 4.6.2,看起来 thumb2 和 cortex-r4 是使用这些指令的提示,正如您在 gcc 中所指出的那样4.7.2,cortex-a15好像加了使用这些指令。与 gcc 4.7.2,thumb2.md 文件不再有udiv/sdiv .但是,它可能包含在其他地方;我不是 100% 熟悉所有的机器描述语言。 cortex-a7、cortex-a15 和 cortex-r5 似乎也可以在 4.7.2 中启用这些指令。注3

这并不能直接回答问题,但确实提供了一些信息/路径来获得答案。您可以使用 -mcpu=cortex-r4 编译模块,尽管这可能会产生链接器问题。还有int my_idiv(int a, int b) __attribute__ ((__target__ ("arch=cortexe-r4"))); ,您可以在其中基于每个功能指定代码生成器使用的机器描述。我自己没有使用过任何这些,但它们只是尝试的可能性。通常,您不想保留错误的机器,因为它可能会生成次优(并且可能是非法的)操作码。您将不得不进行试验,然后可能会提供 真实 回答。

注1:这是股票 gcc 4.6.2 和 4.7.2。不知道你的安卓编译器有没有补丁。

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")]

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"))

注2:pre-processor as Assembler如果 gcc正在将选项传递给 gas阻止使用 udiv/sdiv指示。例如,您可以使用 asm(" .long <opcode>\n");其中 opcode 是一些标记粘贴的字符串化寄存器编码宏输出。此外,您可以注释您的汇编程序以指定 machine 中的更改。 .所以你可以暂时撒谎说你有一个cortex-r4等。

注3:

gcc-4.7.2/gcc/config/arm$ grep -E 'TARGET_IDIV|arm_arch_arm_hwdiv|FL_ARM_DIV' *
arm.c:#define FL_ARM_DIV    (1 << 23)         /* Hardware divide (ARM mode).  */
arm.c:int arm_arch_arm_hwdiv;
arm.c:  arm_arch_arm_hwdiv = (insn_flags & FL_ARM_DIV) != 0;
arm-cores.def:ARM_CORE("cortex-a7",  cortexa7,  7A, ... FL_ARM_DIV
arm-cores.def:ARM_CORE("cortex-a15", cortexa15, 7A, ... FL_ARM_DIV
arm-cores.def:ARM_CORE("cortex-r5",  cortexr5,  7R, ... FL_ARM_DIV
arm.h:  if (TARGET_IDIV)                                \
arm.h:#define TARGET_IDIV               ((TARGET_ARM && arm_arch_arm_hwdiv) \
arm.h:extern int arm_arch_arm_hwdiv;
arm.md:  "TARGET_IDIV"
arm.md:  "TARGET_IDIV"

关于GCC 发出 ARM idiv 指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15782089/

相关文章:

c++ - LD_LIBRARY_PATH 和 LD_LIBRARY_PATH 有什么区别?

c - OS X 上的 Pthread 和 gcc 编译问题

c++ - 嵌入式系统中固有、内联、外部的区别?

android - 如何在 linux 内核中定义和触发我自己的新 softirq?

集会? LD & 移动

c++ - 尝试执行文件时出现 "sh: ./<file> not found"错误

gcc 链接器在所选的库路径中找到 .so 和 .a?

c - 如何在 Intel 语法中将立即值传递给汇编中的 shr?

c++ - 混合单独编译的对象

c - Neon 内在功能是通过从所有元素中减去最小元素来防止溢出[无循环]