Bug 53386 - Bad assembly code produced for m68000
Summary: Bad assembly code produced for m68000
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 4.6.3
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-05-17 02:45 UTC by Luis Alves
Modified: 2020-02-21 02:40 UTC (History)
2 users (show)

See Also:
Host: i686
Target: m68k-uclinux
Build:
Known to work:
Known to fail:
Last reconfirmed: 2015-01-19 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Luis Alves 2012-05-17 02:45:05 UTC
Hi,

I'm currently using gcc 4.2.4 to build uClinux for a 68000 target (68HC000 cpu).

I've update my toolchain to newer tool versions but now gcc (4.6.4) is producing bad assembly for this target.

I'm almost sure that it is producing only 68020 assembly code and/or ignoring the -m68000 switch (I checked that when specifying -m68000 or -m68020 gcc is producing the same assembly code).


Here is a simple testcase (a line from the kernel where my system was hanging):

C instruction (from 'proc_net_ns_init' function):

[...]
memcpy(netd->name, "net", 4);
[...]


4.2.4 assembly output:
[...]
  60:	157c 006e 004d 	moveb #110,%a2@(77)
  66:	157c 0065 004e 	moveb #101,%a2@(78)
  6c:	157c 0074 004f 	moveb #116,%a2@(79)
  72:	422a 0050      	clrb %a2@(80)
[...]


4.6.4 assembly output:
[...]
  42:	217c 6e65 7400 	movel #1852142592,%a0@(77)
  48:	004d 
[...]


Since the opcode movel has an odd displacement, it is causing an address/bus error exception, halting the cpu.



Another difference I've noticed while tracing the above issue, is the way parameters are placed in the stack for the function call:


4.2.4 assembly:
[...]
movel  absolute_address,%sp-
[...]


4.6.4 assembly:
[...]
moveaw  value1,%a0
addal   value2,%a0
movel   %a0@,%sp-
[...]


This is not critical but at a first look, it look it has slower execution and produces larger code (is this correct?).




Command line used in this test (from the kernel build):

m68k-uclinux-gcc -m68000 -Wp,-MD,net/sunrpc/.rpc_pipe.o.d -isystem /usr/local/lib/gcc/m68k-uclinux/4.5.1/include -I/root/m68k/20120401/uClinux-dist/linux-3.x/arch/m68k/include -Iarch/m68k/include/generated -Iinclude  -include /root/m68k/20120401/uClinux-dist/linux-3.x/include/linux/kconfig.h -D__KERNEL__ -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -fno-delete-null-pointer-checks -O2 -pipe -DUTS_SYSNAME=\"uClinux\" -D__uClinux__ -fomit-frame-pointer -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -DCC_HAVE_ASM_GOTO    -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(rpc_pipe)"  -D"KBUILD_MODNAME=KBUILD_STR(sunrpc)" -c -o fs/proc/proc_net.o fs/proc/proc_net.c



Anyone knows what is the latest gcc version where code for 68000 is still ok?
(I didn't want to go and build version by version until I find the one that's broken...)



Regards,
Luis Alves
Comment 1 Andreas Schwab 2012-05-17 08:23:45 UTC
config/m68k/linux.h:
/* for 68k machines this only needs to be TRUE for the 68000 */

#undef STRICT_ALIGNMENT
#define STRICT_ALIGNMENT 0
#undef M68K_HONOR_TARGET_STRICT_ALIGNMENT
#define M68K_HONOR_TARGET_STRICT_ALIGNMENT 0
Comment 2 Luis Alves 2012-05-17 10:18:47 UTC
Thanks a lot Andreas,
Changes those flags to true and it's working good now.

Also a minor correction: I was trying to build gcc 4.6.3 (not 4.6.4).


(I've changed status to RESOLVED-INVALID since this is not a bug but a configuration issue)

Regards,
Luis Alves
Comment 3 Luis Alves 2012-05-17 10:19:11 UTC
Thanks a lot Andreas,
Changed those flags to true and it's working good now.

Also a minor correction: I was trying to build gcc 4.6.3 (not 4.6.4).


(I've changed status to RESOLVED-INVALID since this is not a bug but a configuration issue)

Regards,
Luis Alves
Comment 4 Mikael Pettersson 2012-05-17 10:52:55 UTC
(In reply to comment #3)
> (I've changed status to RESOLVED-INVALID since this is not a bug but a
> configuration issue)

I'm not so sure about that.  For supported target triplets you are not supposed to have to edit any gcc sources to get a correct compiler.
Comment 5 Luis Alves 2012-05-17 11:00:19 UTC
I agree with that.
I'll just leave it UNCONFIRMED until someone decides what to do with this.
Comment 6 Mikael Pettersson 2012-05-17 11:09:08 UTC
The behaviour changed between gcc-4.2.4 (ok) and gcc-4.3.6 (bad).
Comment 7 Mikael Pettersson 2012-05-17 11:31:35 UTC
gcc-4.3.x changed gcc/config.gcc:

--- gcc-4.2.4/gcc/config.gcc    2008-03-13 20:11:43.000000000 +0100
+++ gcc-4.3.6/gcc/config.gcc    2011-02-25 00:02:14.000000000 +0100
...
-m68k-*-uclinux*)               # Motorola m68k/ColdFire running uClinux with uClibc
-       tm_file="m68k/m68k.h m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h m68k/uclinux.h"
-       tm_defines="${tm_defines} MOTOROLA USE_GAS"
-       tmake_file=m68k/t-uclinux
+m68k-*-uclinuxoldabi*)         # Motorola m68k/ColdFire running uClinux
+                               # with uClibc, using the original
+                               # m68k-elf-based ABI
+       default_m68k_cpu=68020
+       default_cf_cpu=5206
+       tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h m68k/uclinux-oldabi.h"
+       tm_defines="${tm_defines} MOTOROLA=1"
+       tmake_file="m68k/t-floatlib m68k/t-uclinux"
+       use_fixproto=no
+       ;;
+m68k-*-uclinux*)               # Motorola m68k/ColdFire running uClinux
+                               # with uClibc, using the new GNU/Linux-style
+                               # ABI.
+       default_m68k_cpu=68020
+       default_cf_cpu=5206
+       tm_file="${tm_file} dbxelf.h elfos.h svr4.h linux.h flat.h m68k/linux.h m68k/uclinux.h ./sysroot-suffix.h"
+       tm_defines="${tm_defines} MOTOROLA=1 UCLIBC_DEFAULT=1"
+       extra_options="${extra_options} linux.opt"
+       tmake_file="m68k/t-floatlib m68k/t-uclinux m68k/t-mlibs"
        use_fixproto=no
        ;;

Upping the default m68k cpu to 020 is suspicious, but the real problem is the inclusion of m68k/linux.h in tm_files, as that disables strict-alignment support, even when compiling with an explicit -m68000 option.

I don't know anthing about the uClinux m68k "old" and "new" ABIs, but it looks like you will get correct behaviour if you build for m68k-uclinuxoldabi --with-cpu=m68000.
Comment 8 Mikael Pettersson 2012-05-17 12:57:20 UTC
Fallout from a deliberate ABI change in 4.3.x, see
<http://gcc.gnu.org/ml/gcc-patches/2007-01/msg00773.html> and its followups.

I don't like the way an existing target triplet was reassigned an entirely different meaning, but it's too late to do anything about that now.

Configuring for m68k-uclinuxoldabi is the correct solution for gcc-4.3 and newer if you need m68000-compatible code.

You can close this as invalid now.
Comment 9 Luis Alves 2012-05-17 14:29:07 UTC
Thanks Mikael,

But... will I have any (future) problems if I just change the flags in the <config/m68k/linux.h> ?

In a small test I've made that solutions seems to produce good code for the 68000 but I'm afraid I might end up with a 'crippled' gcc.
Comment 10 Mikael Pettersson 2012-05-17 15:02:51 UTC
See the gcc-patches thread I referred to in #c8, gcc-4.3 also changed low-level ABI details, with the consequence that gcc-4.2 and gcc-4.3 generate incompatible code for m68k-uclinux.  If you want 4.3 and newer to behave as 4.2 and older you should use m68k-uclinuxoldabi.  Patching m68k/linux.h might work, but it's not a supported configuration.
Comment 11 Andreas Schwab 2012-05-17 15:30:09 UTC
I would be ok with changing linux.h to honor -mstrict-align, though m68k_return_in_memory would have to be left out.  The default will of course continue to be -mno-strict-align.
Comment 12 Luis Alves 2012-05-17 15:44:12 UTC
(In reply to comment #10)
> See the gcc-patches thread I referred to in #c8, gcc-4.3 also changed low-level
> ABI details, with the consequence that gcc-4.2 and gcc-4.3 generate
> incompatible code for m68k-uclinux.  If you want 4.3 and newer to behave as 4.2
> and older you should use m68k-uclinuxoldabi.  Patching m68k/linux.h might work,
> but it's not a supported configuration.

Just wanted to add that I use gcc to fully build a uClinux-dist (kernel+userland binaries) so it really doesn't bother me if the gcc >= 4.3 generates incompatible code with gcc-4.2.

And I dare to say that this is the case for everyone using uClinux.
Comment 13 Luis Alves 2012-05-18 17:00:11 UTC
I've built gcc with the m68k/linux.h patched for the 68000 but it's not working as expected.

As test I've used linux kernel 3.3

Results are compared to the use of gcc-4.2.4 vs gcc-4.6.3 (gcc-4.7.0 doesn't even build itself because of an ICE).

(Using the same kernel configuration, only changed gcc version)

Kernel Size:
4.2.4: 2158592 bytes
4.6.3: 2244608 bytes (around 4% increase)


Using 4.2.4 kernel boots as expected and everything works fine.
With 4.6.3 the kernel boots and after a few seconds starts a non-stop SPAM of BUGs:

[...]
BUG: scheduling while atomic: ksoftirqd/0/3/0x00000000
[...]
BUG: scheduling while atomic: kthreadd/2/0x00000000
[...]
BUG: scheduling while atomic: kworker/0:0/4/0x04000002
[...]

Until eventually panics.




Anyway, building gcc for target "m68k-uclinuxoldabi" is a bit awkward.
I've tried to build and the message I got is that target will be removed soon. Also it would give a lot of work to integrate it with the existing tools because of the resulting prefix (binutils, elf2flt, ...).



As of "gcc -m68000" not generating correct code for the 68000 I would still say that IT IS a gcc bug...
Comment 14 Jeffrey A. Law 2015-01-19 22:49:24 UTC
We really need a testcase for the issue raised in c#13.  Without a reasonable testcase, there really isn't anything we can do.
Comment 15 Jeffrey A. Law 2020-02-21 02:40:25 UTC
Nothing we can do without a testcase.