bitmap kid
bitmap kid

Reputation: 311

How to disable ARM coprocessor instructions with gcc?

Is there a way with a recent gcc to disable the use of coprocessor instructions: CDP, LDC, STC, MCR and MRC ?

They seem to be grouped in an autoconf variable named arm_coproc1_ok.

I tried to set the options -march=armv4 and -mfloat-abi=soft but nothing helps. My binaries always contain the instructions.

Whether it's my source code or libc (newlib), I find copro instructions.

This c++ code source,

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;
}

...generate this binary (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

Same remark with libc.a of newlib at 0x080 (mrc instruction):

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}

...among others obviouly.

Thank you.

Upvotes: 2

Views: 536

Answers (2)

old_timer
old_timer

Reputation: 71526

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

of which

code:

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

padding?

   c:   e1a00000    nop         ; (mov r0, r0)

data pool:

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

and here you go

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

the correct way to view the disassembled information is:

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

another way to look at this is to compile to 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"

notice the lack of an stc instructions? If you convert those .words to hex you will see the pattern that a disassembler would recognize as an stc if it didnt know this was data.

And we can see where the nop came from.

Upvotes: 1

James Greenhalgh
James Greenhalgh

Reputation: 2491

You’re reading the literal pool (data) as code. Those “instructions” will never execute.

Try turning your

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

Constant in to hexadecimal, and you’ll see why no amount of GCC options will eliminate this from your generated binary!

Upvotes: 0

Related Questions