首页 > 解决方案 > 如何使用 gcc 禁用 ARM 协处理器指令?

问题描述

最近的 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

与 0x080 处的 newlib 的 libc.a 相同的注释(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}

……很明显。

谢谢你。

标签: gccarmbare-metal

解决方案


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 是从哪里来的。


推荐阅读