2

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;
}
utnd03
  • 21
  • 1
  • 3
  • Can you reproduce it on [godbolt](https://godbolt.org/)? I can't get gcc to emit `clz` on this code. – Nate Eldredge Jun 20 '22 at 21:57
  • Also state the version of gcc you are using. – Nate Eldredge Jun 20 '22 at 21:58
  • 3
    Are you actually using `-march`? It isn't included in your quoted command line. – Nate Eldredge Jun 20 '22 at 21:59
  • You should be using the `arm-**none**-gnueabi-gcc`, as it looks like you are writing for bare-metal. And it looks like it makes the difference. Not sure why though. – Eugene Sh. Jun 20 '22 at 22:01
  • @NateEldrege I thought -mcpu=... would imply -march ? Also I tried setting both -mcpu and -march, and the result was the same. – utnd03 Jun 20 '22 at 22:04
  • 2
    @NateEldredge https://arm.godbolt.org/z/1hb3f14Po - `march` does not help (the `linux` version). – Eugene Sh. Jun 20 '22 at 22:04
  • @EugeneSh yes... strangely arm-none-eabi-gcc would generate `armv4t` code by default, even without the `-mcpu...` flags – utnd03 Jun 20 '22 at 22:07
  • @utnd03 Well, the defaults should be documented somewhere – Eugene Sh. Jun 20 '22 at 22:07
  • The doc says when `gcc` is being built, the `--with-arch` option can be used to set the default architecture that gcc will target. I checked mine with `arm-linux-gnueabi-gcc -v` and it was indeed `--with-arch=armv5te`. However, this doesn't explain why `-march=armv4t` has no apparent effect... – utnd03 Jun 20 '22 at 22:14
  • Well, there is always a possibility of a bug.. – Eugene Sh. Jun 20 '22 at 22:15
  • Interestingly enough, in godbolt all the GCC versions (the `-linux-` variants) above v8.5 are not supporting compilation of this code for `armv4tdmi`. Maybe they have realized that this option is buggy and removed it? – Eugene Sh. Jun 20 '22 at 22:19
  • @EugeneSh.: It's a 1994 CPU architecture, removing it makes perfect sense. – MSalters Jun 20 '22 at 23:31
  • https://godbolt.org/z/czeGnPbEa - no clz – 0___________ Jun 21 '22 at 00:09
  • @EugeneSh. it compiles – 0___________ Jun 21 '22 at 00:10
  • @0 it does not without the FPU options, which seem to do some magic for v8.5 too and it does not produce the unsupported instructions. So it does look like some buggy unhandled options combination. – Eugene Sh. Jun 21 '22 at 13:17
  • Ah, the trick for godbolt is "compile to binary". As noted in the answer, the offending instruction isn't actually in the assembly emitted by the compiler, but in the library function that is linked in. – Nate Eldredge Jun 22 '22 at 13:09

1 Answers1

2

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 &).
artless noise
  • 21,212
  • 6
  • 68
  • 105
  • See also: [`-freestanding` option to gcc](https://stackoverflow.com/questions/17692428/what-is-ffreestanding-option-in-gcc), tag [tag:freestanding], and tag [tag:embedded]. `-freestandiing` is the best option as it says that 'arm-linux-gnueabi-gcc' is equivalent to 'arm-none-gnueabi-gcc' as you have removed the OS and libc triple that normally defines a compiler and only the machine backend matters. Of course many don't grok that and insist that you must use the newlib version of gcc (which can also have the same issue). – artless noise Jun 21 '22 at 18:34
  • It should at least tell that an unsupported option was provided, no? – Eugene Sh. Jun 21 '22 at 19:02
  • There is a possibility for the linker to give a diagnostic. However, this can be desireable in some cases. Not for libgcc. But you might have opencv or ffmpeg with code for arch that is id at runtime. – artless noise Jun 22 '22 at 02:44
  • Here is [another question on `-fpie`](https://stackoverflow.com/questions/15386970/position-independent-executable-pie-for-armcortex-m3) that might be related. Ie, the stock libraries that are built with the compiler are **these compiler options are not the ones you are looking for**. There should be multi-lib versions released for these cases... in a perfect world. – artless noise Jun 29 '22 at 18:28
  • And [this question on static binaries](https://stackoverflow.com/questions/10465875/is-there-an-option-to-gnu-ld-to-omit-dynamic-linker-pt-interp-completely) might be helpful as it is peculiar to using 'arm-linux' vs 'arm-none'. u-boot's *arch/arm/lib* gives a list of functionality that may need to be implemented with '-freestanding'. It also has in implementation of divsi3 in lib1funcs.S. – artless noise Jun 30 '22 at 16:23