【问题标题】:How to disable ARM coprocessor instructions with gcc?如何使用 gcc 禁用 ARM 协处理器指令?
【发布时间】:2020-07-02 11:31:31
【问题描述】:

最近的 gcc 有没有办法禁用协处理器指令:CDP、LDC、STC、MCR 和 MRC?

它们似乎被分组在一个名为 arm_coproc1_ok 的 autoconf 变量中。

我尝试设置选项 -march=armv4-mfloat-abi=soft 但没有任何帮助。我的二进制文件总是包含说明。

不管是我的源代码还是libc(newlib),我都找copro指令。

这个c++代码源,

double Bbp::S(int j)
{
    double s = 0.0;        // Summation of Total, Left
    double t;              // Each term of right summation
    int    r;              // Denominator
    int    k;              // Loop index
    double EPS = 1.0e-17;  // Loop-exit accuration of the right summation

    // Left Sum (0 ... d)
    for (k = 0; k <= d; k++) {
        r = 8 * k + j;
        t = (double)compModExp(16, d - k, r);
        t /= r;
        s += t - (int)t;
        s -= (int)s;
    }

    // Right sum (d + 1 ...)
    while (1) {
        r = 8 * k + j;
        t = std::pow(16.0, (double)(d - k));
        t /= (double)r;
        if (t < EPS) break;
        s += t;
        s -= (int)s;
        k ++;
    }

    return s;
}

...生成这个二进制文件(stc at 0x44c):

000001c0 <_ZN3Bbp1SEi>:
 1c0:   e52de004        push    {lr}            ; (str lr, [sp, #-4]!)
 1c4:   e24dd034        sub     sp, sp, #52     ; 0x34
 1c8:   e58d0004        str     r0, [sp, #4]
 1cc:   e58d1000        str     r1, [sp]
 1d0:   e3a02000        mov     r2, #0
...
 440:   e49df004        pop     {pc}            ; (ldr pc, [sp], #4)
 444:   e1a00000        nop                     ; (mov r0, r0)
 448:   4646d497                        ; <UNDEFINED> instruction: 0x4646d497
 44c:   3c670ef5        stclcc  14, cr0, [r7], #-980    ; 0xfffffc2c

与newlib的libc.a在0x080(mrc指令)相同的注释:

00000028 <etens>:
  28:   4a926576        bmi     fe499608 <enan+0xfe49565c>
  2c:   153f804a        ldrne   r8, [pc, #-74]! ; ffffffea <enan+0xffffc03e>
  30:   979ac94c        ldrls   ip, [sl, ip, asr #18]
...
  5c:   75868175        strvc   r8, [r6, #373]  ; 0x175
  60:   4d48c976        vstrmi.16       s25, [r8, #-236]        ; 0xffffff14    ; <UNPREDICTABLE>
  64:   58f89c66        ldmpl   r8!, {r1, r2, r5, r6, sl, fp, ip, pc}^
  68:   5c54bc50        mrrcpl  12, 5, fp, r4, cr0
  6c:   91c6cc65        bicls   ip, r6, r5, ror #24
  70:   a0aea60e        adcge   sl, lr, lr, lsl #12
  74:   46a3e319        ssatmi  lr, #4, r9, lsl #6
  78:   eab7851e        b       fede14f8 <enan+0xfeddd54c>
  7c:   901b98fe                        ; <UNDEFINED> instruction: 0x901b98fe
  80:   de8dddbb        mcrle   13, 4, sp, cr13, cr11, {5}

...显然还有其他。

谢谢。

【问题讨论】:

  • 意思是当你为这些指令编写汇编语言代码时,工具仍然在汇编它们?或者您选择与项目链接的库恰好有这些独立于您使用这些限制构建的代码?
  • 举例说明如何使用 gcc 编译的 C 代码获取 mrc/mcr。请提供一个最小的例子。
  • 感谢您的回复。我修改了我的问题。
  • 第一个反汇编器反汇编数据的不是stc指令。第二个中的 mcr 也是如此。只是一些池数据。
  • 为了改变那些你需要改变程序中的数据值,使它们不像那些指令。

标签: gcc arm bare-metal


【解决方案1】:
double fun ( void )
{
    double EPS = 1.0e-17;
    return(EPS);
}

00000000 <fun>:
   0:   e28f1008    add r1, pc, #8
   4:   e8910003    ldm r1, {r0, r1}
   8:   e1a0f00e    mov pc, lr
   c:   e1a00000    nop         ; (mov r0, r0)
  10:   4646d497            ; <UNDEFINED> instruction: 0x4646d497
  14:   3c670ef5    stclcc  14, cr0, [r7], #-980    ; 0xfffffc2c

其中

代码:

00000000 <fun>:
   0:   e28f1008    add r1, pc, #8
   4:   e8910003    ldm r1, {r0, r1}
   8:   e1a0f00e    mov pc, lr

填充?

   c:   e1a00000    nop         ; (mov r0, r0)

数据池:

  10:   4646d497            ; <UNDEFINED> instruction: 0x4646d497
  14:   3c670ef5    stclcc  14, cr0, [r7], #-980    ; 0xfffffc2c

你来了

double fun ( void )
{
    double EPS = 1.0e-16;
    return(EPS);
}

00000000 <fun>:
   0:   e28f1008    add r1, pc, #8
   4:   e8910003    ldm r1, {r0, r1}
   8:   e1a0f00e    mov pc, lr
   c:   e1a00000    nop         ; (mov r0, r0)
  10:   97d889bc            ; <UNDEFINED> instruction: 0x97d889bc
  14:   3c9cd2b2    lfmcc   f5, 1, [r12], {178} ; 0xb2

查看反汇编信息的正确方法是:

00000000 <fun>:
   0:   e28f1008    add r1, pc, #8
   4:   e8910003    ldm r1, {r0, r1}
   8:   e1a0f00e    mov pc, lr
   c:   e1a00000
  10:   4646d497
  14:   3c670ef5

查看这个的另一种方法是编译为 asm

    .arch armv4
    .eabi_attribute 20, 1
    .eabi_attribute 21, 1
    .eabi_attribute 23, 3
    .eabi_attribute 24, 1
    .eabi_attribute 25, 1
    .eabi_attribute 26, 1
    .eabi_attribute 30, 2
    .eabi_attribute 34, 0
    .eabi_attribute 18, 4
    .file   "so.c"
    .text
    .align  2
    .global fun
    .syntax unified
    .arm
    .fpu softvfp
    .type   fun, %function
fun:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed = 0, uses_anonymous_args = 0
    @ link register save eliminated.
    adr r1, .L3
    ldmia   r1, {r0-r1}
    mov pc, lr
.L4:
    .align  3
.L3:
    .word   1179047063
    .word   1013386997
    .size   fun, .-fun
    .ident  "GCC: (GNU) 9.2.0"

注意到缺少 stc 指令了吗?如果您将这些 .words 转换为十六进制,您将看到反汇编程序在不知道这是数据的情况下将其识别为 stc 的模式。

我们可以看到 nop 是从哪里来的。

【讨论】:

  • “j'ai honte”用英语怎么说?我很惭愧?非常感谢!谢谢你,我明白了。
  • 你不是第一个也不是最后一个。反汇编程序只能做这么多,不是也不能是完美的。
【解决方案2】:

您正在将文字池(数据)作为代码读取。那些“指令”永远不会执行。

试着转动你的

double EPS = 1.0e-17;  // Loop-exit accuration of the right summation

常量为十六进制,你会明白为什么没有多少 GCC 选项会从你生成的二进制文件中消除它!

【讨论】:

  • 谢谢詹姆斯!我现在明白了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-25
  • 2011-09-01
相关资源
最近更新 更多