Patchwork libgcc erroneously built as armv5 for arm920t(armv4t)

login
register
mail settings
Submitter adam hussein\(!\)
Date Sept. 26, 2013, 3:34 p.m.
Message ID <1380209693.38971.YahooMailNeo@web162205.mail.bf1.yahoo.com>
Download mbox | patch
Permalink /patch/278212/
State Rejected
Headers show

Comments

adam hussein\(!\) - Sept. 26, 2013, 3:34 p.m.
I've been building the at91rm9200ek configuration of buildroot to get a toolchain I can use to build u-boot with some board specific configuration.

This is an ARM920T core chip with ARMv4T architecture  - later ARM9 series have ARMv5TE architecture (http://en.wikipedia.org/wiki/ARM9)

When gcc is built, or perhaps specifically libgcc only, it seems the selection of 920t/v4 architecture gets lost and v5 is used instead.
This means that when I use it to build u-boot, I find it has the __udivsi3 function using the illegal (to v4) instruction CLZ (count leading zeros).

The easiest workaround for me is to specify arm7tdmi and be done with it, but I'd like to try contributing a proper fix if possible.

It turns out that this issue has been around for some time:

e.g. 2006: http://www.mail-archive.com/oe@handhelds.org/msg02024.html
e.g. 2007: http://permalink.gmane.org/gmane.comp.lib.uclibc.buildroot/3139
e.g. 2007: http://web.archive.org/web/20070815094037/http://bugs.busybox.net/view.php?id=1406 (referred to in previous link)

and then the last link has this patch:
http://web.archive.org/web/20070815094037/http://bugs.busybox.net/file_download.php?file_id=1059&type=bug

...which seems not to have made it into the main repo, and no longer applies correctly; all the locations have changed.


So, here follows an up-to-date version of it. I hope someone finds it useful and avoids repeating all my 'digging about'.

And many thanks to 'bjdooks' for the original.


----
Thomas Petazzoni - Sept. 26, 2013, 3:54 p.m.
Hello,

On Thu, 26 Sep 2013 08:34:53 -0700 (PDT), adam hussein\(!\) wrote:
> I've been building the at91rm9200ek configuration of buildroot to get
> a toolchain I can use to build u-boot with some board specific
> configuration.
> 
> This is an ARM920T core chip with ARMv4T architecture  - later ARM9
> series have ARMv5TE architecture (http://en.wikipedia.org/wiki/ARM9)
> 
> When gcc is built, or perhaps specifically libgcc only, it seems the
> selection of 920t/v4 architecture gets lost and v5 is used instead.
> This means that when I use it to build u-boot, I find it has the
> __udivsi3 function using the illegal (to v4) instruction CLZ (count
> leading zeros).
> 
> The easiest workaround for me is to specify arm7tdmi and be done with
> it, but I'd like to try contributing a proper fix if possible.
> 
> It turns out that this issue has been around for some time:
> 
> e.g. 2006: http://www.mail-archive.com/oe@handhelds.org/msg02024.html
> e.g. 2007:
> http://permalink.gmane.org/gmane.comp.lib.uclibc.buildroot/3139 e.g.
> 2007:
> http://web.archive.org/web/20070815094037/http://bugs.busybox.net/view.php?id=1406
> (referred to in previous link)
> 
> and then the last link has this patch:
> http://web.archive.org/web/20070815094037/http://bugs.busybox.net/file_download.php?file_id=1059&type=bug
> 
> ...which seems not to have made it into the main repo, and no longer
> applies correctly; all the locations have changed.
> 
> 
> So, here follows an up-to-date version of it. I hope someone finds it
> useful and avoids repeating all my 'digging about'.
> 
> And many thanks to 'bjdooks' for the original.

Interesting. First, thanks for the investigation.

When you select BR2_arm920t as the ARM processor, we are already
passing --with-arch=armv4t to the gcc configure. So, gcc should already
avoid the use of CLZ, since ARMv4T does not support it.

Have you investigated why passing the --with-cpu argument is also
needed, in addition to --with-arch?

Thanks!

Thomas
Yann E. MORIN - Sept. 26, 2013, 5:52 p.m.
Thomas, Adam, All,

On 2013-09-26 17:54 +0200, Thomas Petazzoni spake thusly:
> Hello,
> 
> On Thu, 26 Sep 2013 08:34:53 -0700 (PDT), adam hussein\(!\) wrote:
> > I've been building the at91rm9200ek configuration of buildroot to get
> > a toolchain I can use to build u-boot with some board specific
> > configuration.
> > 
> > This is an ARM920T core chip with ARMv4T architecture  - later ARM9
> > series have ARMv5TE architecture (http://en.wikipedia.org/wiki/ARM9)
> > 
> > When gcc is built, or perhaps specifically libgcc only, it seems the
> > selection of 920t/v4 architecture gets lost and v5 is used instead.
> > This means that when I use it to build u-boot, I find it has the
> > __udivsi3 function using the illegal (to v4) instruction CLZ (count
> > leading zeros).
> > 
> > The easiest workaround for me is to specify arm7tdmi and be done with
> > it, but I'd like to try contributing a proper fix if possible.
> > 
> > It turns out that this issue has been around for some time:
> > 
> > e.g. 2006: http://www.mail-archive.com/oe@handhelds.org/msg02024.html
> > e.g. 2007:
> > http://permalink.gmane.org/gmane.comp.lib.uclibc.buildroot/3139 e.g.
> > 2007:
> > http://web.archive.org/web/20070815094037/http://bugs.busybox.net/view.php?id=1406
> > (referred to in previous link)
> > 
> > and then the last link has this patch:
> > http://web.archive.org/web/20070815094037/http://bugs.busybox.net/file_download.php?file_id=1059&type=bug
> > 
> > ...which seems not to have made it into the main repo, and no longer
> > applies correctly; all the locations have changed.
> > 
> > 
> > So, here follows an up-to-date version of it. I hope someone finds it
> > useful and avoids repeating all my 'digging about'.
> > 
> > And many thanks to 'bjdooks' for the original.
> 
> Interesting. First, thanks for the investigation.
> 
> When you select BR2_arm920t as the ARM processor, we are already
> passing --with-arch=armv4t to the gcc configure. So, gcc should already
> avoid the use of CLZ, since ARMv4T does not support it.
> 
> Have you investigated why passing the --with-cpu argument is also
> needed, in addition to --with-arch?

In crosstool-Ng, we have this:
    http://crosstool-ng.org/hg/crosstool-ng/annotate/98b7806295cc/patches/gcc/4.4.5/210-arm-unbreak-armv4t.patch#l1

For gcc, if --with-cpu is not specified, then it defaults to
TARGET_CPU_arm10tdmi which is an armv5 (as far as I understand it).

The patch above downgrades the default CPU to an armv4t. Maybe worth a
try. That, or passing --with-cpu=... as suggested by Adam.

Regards,
Yann E. MORIN.
Peter Korsgaard - Sept. 26, 2013, 7 p.m.
>>>>> "Thomas" == Thomas Petazzoni <thomas.petazzoni@free-electrons.com> writes:

Hi,

 Thomas> Interesting. First, thanks for the investigation.

 Thomas> When you select BR2_arm920t as the ARM processor, we are
 Thomas> already passing --with-arch=armv4t to the gcc configure. So,
 Thomas> gcc should already avoid the use of CLZ, since ARMv4T does not
 Thomas> support it.

It indeed sounds quite strange, as I've run buildroot rootfs'es on the
mini2440 (which is arm920t) back in 2011 at least.

I don't have access to that hardware anymore though.
Thomas Petazzoni - Sept. 27, 2013, 7:31 a.m.
Dear Yann E. MORIN,

On Thu, 26 Sep 2013 19:52:21 +0200, Yann E. MORIN wrote:

> In crosstool-Ng, we have this:
>     http://crosstool-ng.org/hg/crosstool-ng/annotate/98b7806295cc/patches/gcc/4.4.5/210-arm-unbreak-armv4t.patch#l1
> 
> For gcc, if --with-cpu is not specified, then it defaults to
> TARGET_CPU_arm10tdmi which is an armv5 (as far as I understand it).

So even when --with-arch=armv7a, gcc will use --with-cpu=arm10tdmi? I'm
not sure to understand what will be the effect of having
--with-arch=armv7a and --with-cpu=arm10tdmi.

> The patch above downgrades the default CPU to an armv4t. Maybe worth a
> try. That, or passing --with-cpu=... as suggested by Adam.

Ok.

Thomas
adam hussein\(!\) - Sept. 27, 2013, 11:23 a.m.
>In crosstool-Ng, we have this:
>    http://crosstool-ng.org/hg/crosstool-ng/annotate/98b7806295cc/patches/gcc/4.4.5/210-arm-unbreak-armv4t.patch#l1
>
>For gcc, if --with-cpu is not specified, then it defaults to
>TARGET_CPU_arm10tdmi which is an armv5 (as far as I understand it).
>
>The patch above downgrades the default CPU to an armv4t. Maybe worth a
>try. That, or passing --with-cpu=... as suggested by Adam.

Hi,

I have got a similar patch in:
    package/gcc/4.7.3/830-arm_unbreak_armv4t.patch
...to edit SUBTARGET_CPU_DEFAULT to use arm9tdmi instead of the arm5t arm10tdmi 
core.

The file affected, gcc/config/arm/linux-eabi.h, has no equivalent to set the architecture to arm4t as default.
I wonder if libgcc has no translation from the cpu/core to the architecture.

Following back from the __udivsi3 libgcc function...

My exception was at:
    20127a2c:    e16f3f10     clz    r3, r0

which is in:
    20127a10 <__udivsi3>:

u-boot.map states:
     .text          0x20127a10      0x20c /opt/arm-2009q1/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/libgcc.a(_udivsi3.o)

then in ../buildroot-2013.08.1/output/build/host-gcc-final-4.7.3/build/arm-buildroot-linux-uclibcgnueabi/libgcc/_udivsi3.dep 
    _udivsi3.o: ../../../libgcc/config/arm/lib1funcs.S _udivsi3.vis \
                     ../../../libgcc/config/arm/ieee754-df.S \
                     ../../../libgcc/config/arm/ieee754-sf.S \
                     ../../../libgcc/config/arm/bpabi.S

The assembler code at the start:

    20127a10 <__udivsi3>:
    20127a10:    e2512001     subs    r2, r1, #1    ; 0x1
    20127a14:    012fff1e     bxeq    lr
    20127a18:    3a000074     bcc    20127bf0 <__udivsi3+0x1e0>
    20127a1c:    e1500001     cmp    r0, r1
    20127a20:    9a00006b     bls    20127bd4 <__udivsi3+0x1c4>
    20127a24:    e1110002     tst    r1, r2
    20127a28:    0a00006c     beq    20127be0 <__udivsi3+0x1d0>

matches an available version(within "#else /* ARM version/Thumb-2.  */")
This then uses the macro ARM_DIV_BODY, which sure enough gives the CLZ containing options.

    .macro ARM_DIV_BODY dividend, divisor, result, curbit
    
    #if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
    
    #if defined (__thumb2__)
            clz     \curbit, \dividend
            clz     \result, \divisor
    ...
    #else
            clz     \curbit, \dividend
            clz     \result, \divisor
    ...
    #endif
    
    #else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
    #if __ARM_ARCH__ >= 5
    
            clz     \curbit, \divisor
            clz     \result, \dividend
    ...
    #else /* __ARM_ARCH__ < 5 */
    ...

So, we clearly have __ARM_ARCH__ >= 5.
The value of this is defined at the beginning of the same file, in the absense of any of:
    __ARM_ARCH_2__,
    __ARM_ARCH_3__,
    __ARM_ARCH_3M__,
    __ARM_ARCH_4__ or
    __ARM_ARCH_4T__
..being defined.

I notice with a 'grep -r "__ARM_ARCH_" *" that 'libffi' does something similar.
But, I can't find where this is set. 
Or rather, I don't think it is set in one piece.
The file:
    gcc/config/arm/arm-cores.def
..seems to be a bridge from 'arm9tdmi', specifying '4T', presumably to append make up __ARM_ARCH_4T__

But the construction of this I unfortunately cannot find.

Any of this jog a memory?

Cheers,
Adam

Patch

diff -ruN buildroot-2013.08.1-orig/arch/Config.in.arm buildroot-2013.08.1/arch/Config.in.arm
--- buildroot-2013.08.1-orig/arch/Config.in.arm    2013-09-17 12:42:07.000000000 +0100
+++ buildroot-2013.08.1/arch/Config.in.arm    2013-09-25 15:42:16.923369027 +0100
@@ -117,6 +117,24 @@ 
     bool "iwmmxt"
 endchoice

+# what we pass to the --with-cpu= option to gcc
+config BR2_ARM_gcc_cpu
+    string
+    default arm610          if BR2_arm610
+    default arm710          if BR2_arm710
+    default arm720t         if BR2_arm720t
+    default arm920t         if BR2_arm920t
+    default arm922t         if BR2_arm922t
+    default arm926t         if BR2_arm926t
+    default arm1136jf-s     if BR2_arm1136jf_s
+    default arm1176Jz-s     if BR2_arm1176jz_s
+    default arm1176jfz-s    if BR2_arm1176jzf_s
+    default strongarm110    if BR2_sa110
+    default strongarm1100   if BR2_sa1100
+    default xscale          if BR2_xscale
+    default iwmmxt          if BR2_iwmmxt
+
+
 config BR2_arm1136jf_s
     bool
     default BR2_arm1136jf_s_r0 || BR2_arm1136jf_s_r1
diff -ruN buildroot-2013.08.1-orig/package/gcc/gcc.mk buildroot-2013.08.1/package/gcc/gcc.mk
--- buildroot-2013.08.1-orig/package/gcc/gcc.mk    2013-09-17 12:42:07.000000000 +0100
+++ buildroot-2013.08.1/package/gcc/gcc.mk    2013-09-25 15:49:01.605600268 +0100
@@ -159,6 +160,13 @@ 
 ifneq ($(call qstrip,$(BR2_GCC_TARGET_ABI)),)
 HOST_GCC_COMMON_CONF_OPT += --with-abi=$(BR2_GCC_TARGET_ABI)
 endif
+
+ifeq ($(BR2_arm),y)
+ifeq ($(BR2_generic_arm),)
+HOST_GCC_COMMON_CONF_OPT += --with-cpu=$(BR2_ARM_gcc_cpu)
+endif
+endif
+
 # GCC doesn't support --with-cpu for bfin
 ifeq ($(BR2_bfin),)
 ifneq ($(call qstrip,$(BR2_GCC_TARGET_CPU)),)