utnd03
utnd03

Reputation: 21

GCC ignores `-mcpu=arm7tdmi` flag and generates unsupported instruction

I'm trying to compile a small program for arm7tdmi (i.e. armv4t), using the command arm-linux-gnueabi-gcc -march=armv4t -mcpu=arm7tdmi -nostartfiles -static test.c -o test on Debian (gcc version 10.2.1, Debian 10.2.1-6). However, GCC seems to ignore the cpu and arch flags, and generates instructions that are unsupported on armv4t, e.g. clz, as shown by objdump:

   104f4:       0a000071        beq     106c0 <.divsi3_skip_div0_test+0x1f0>
   104f8:       e16f2f13        clz     r2, r3
   104fc:       e16f0f11        clz     r0, r1
   10500:       e0402002        sub     r2, r0, r2
   10504:       e272201f        rsbs    r2, r2, #31

I also checked the binary using readelf, and it shows the architecture is actually armv5te:

File Attributes
  Tag_CPU_name: "5TE"
  Tag_CPU_arch: v5TE
  Tag_ARM_ISA_use: Yes
  Tag_THUMB_ISA_use: Thumb-1

May I ask what's going on here? Why is GCC ignoring the -mcpu and -march flags?

Here's the content of test.c:

#include <stdint.h>
#include <stddef.h>
 
void _start() {
        const size_t len = 8;
        uint8_t arr[8] = {10, 12, 8, 5, 0, 2, 3, 55};
        uint8_t *data = arr;
        uint16_t a = 1, b = 0, m = 7;
 
        for(int i=0; i<len; i++) {
                a = (a + data[i]) % m;
                b = (a + b) % m;
        }
 
        uint32_t res = (uint32_t)b << 16 | (uint32_t)a;
}

Upvotes: 2

Views: 457

Answers (1)

artless-noise-bye-due2AI
artless-noise-bye-due2AI

Reputation: 22420

You also need to add '-nostdlib' or it will drag in files that have been compiled with Armv5. The 'arm-linux' kernel does not support ARMv4 CPUs as they do not have an MMU. You are viewing assembler from the gcc library which is compiled for Armv5.

The example label divsi3, shows that you are using division operation and this is coded in libgcc, which will link with the code. It is brought in by your % m code.

You can code and supply your own divsi3, or get a compiler library that supports Armv4. The libgcc.a must be generated (downgraded) to support that CPU. Gcc's backend is capable of generating code for all members of the ARM32/Thumb family, but not support libraries (without multi-lib support).

There is no bug in the compiler. If you look at the assembler for _start, it will not contain clz. If the % 7 could be % 8, you can downgrade to a &7 and the divsi3 would not be needed.

You can see why here.

It is a variation on this question. The issue is that the linker 'gnu ld' has no flag to say, reject Armv5 code.

  • Provide divsi3 configured with Armv4.
  • Provide your own divsi3 with a Division algorithm.
  • Avoid the functionality (down grade to &).

Upvotes: 2

Related Questions