【问题标题】:GCC to emit ARM idiv instructionsGCC 发出 ARM idiv 指令
【发布时间】:2013-04-03 23:21:04
【问题描述】:

如何指示gccarm application processors 发出idiv(整数除法,udivsdiv)指令?

到目前为止,我能想到的唯一方法是将-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

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

$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 发出它们,但是如何?

【问题讨论】:

  • 你确定有一个实际的指令叫做idiv吗?我只能找到sdiv(有符号除法)和udiv(无符号除法)...
  • @unwind 我假设 idiv = sdiv | udiv
  • 您的目标具体是哪个 CPU? AFAIK Cortex-A15 支持 sdiv/udiv,但 Cortex-A5 不支持。两者都兼容 ARMv7-A。
  • @AustinPhillips 没什么特别的,我只是想了解是否有办法告诉 gcc 溢出 idiv 指令而不是链接到 __aeabi* 东西。一个例子可能是为支持 idiv 的模拟器构建 Android 堆栈。
  • 警告 conflicts with 看起来像一个错误。只是不要指定-march。请参阅arm.c,第 1644 行 - 或者这个逻辑可能只是为了解决这种情况。由于您请求的 CPUARCH更好,所以 ARCH 无效。我想你只是想要一个 naked -mcpu=cortex-a7(或-mcpu=cortex-a15-mcpu=cortex-r5)来获得idiv;这些是唯一支持它的 CPU,它们比 ARCH 更好。

标签: gcc arm


【解决方案1】:

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

如果编译器不支持该指令,您始终可以使用 inline-assembler 来获取指令。Note2 由于您的 op-code 相当罕见/特定于机器,因此在gcc 源中获取它可能不是那么努力。特别是,有 archtune/cpu 标志。 tune/cpu 用于更具体的机器,但 arch 假设允许该架构中的所有 机器。如果我理解的话,这个op-code 似乎违反了这条规则。

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

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

注意 1:这是针对 stock 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: 如果 gcc 正在向 gas 传递选项以阻止使用 udiv/sdiv 指令,请参见 pre-processor as Assembler。例如,您可以使用 asm(" .long &lt;opcode&gt;\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"

【讨论】:

  • (+1) 感谢您给机器定义一些勇气,我想我可以定义一个新的机器类型,例如从 armv7-a 复制的 armv7-ad。我不认为你可以使用内联汇编程序,编译器仍然会为不匹配的指令哭泣。关于马赫,mcpu,mtune ...所以整数div是可选的,马赫是可选的......然后我希望马赫变体或像fpu这样的额外标志。我希望 mcpu/mtune 能够为优化器提供一些指令调度信息——这就是我犹豫使用 cortex-a15 的原因。
  • @auselen 你试过-mcpu=cortex-a7吗?或者那不适合你的机器?看起来它提供与-mcpu=cortex-a15 相同的 FL_ARM_DIV 权限。
  • 不。假设我使用支持 idiv 的 cortex-a9。也许我可以使用“-mcpu=cortex-a15 -mtune=cortex-a9”,稍后我会测试。
  • 好的,在 gcc-4.7 中 cortex-a9 不支持它。您可以更改 arm-cores.def 以创建一个新的 corecortex-a9-div 然后使用 FL_ARM_DIV 标志表示支持 idiv(复制现有的 cortex-a9)。然后你可以使用-mcpu=cortex-a9-div。可能还没有gcc 支持这个。看起来-mcpu=cortex-a7 是一个替代选择。 Cortex a7、a9、a15 都有不同的调度器。
  • @auselen 嗯,但只有 cortex-a15idiv 的日程安排。甚至cortex-a7 也缺少它。也许更好地发布到gcc 邮件列表,以使调度程序的某些部分正常工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-12
  • 2023-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多