From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,3ebbc56fbadf761 X-Google-Attributes: gid103376,public From: ocremel@idiom.com (Olivier Cremel) Subject: Re: Invalid asm statement with GNAT - Help ! Date: 1996/08/12 Message-ID: <4up7ie$j9b@idiom.com>#1/1 X-Deja-AN: 173862763 distribution: world references: <4u7mdh$gvm@enst.enst.fr> organization: Idiom Consulting - ISP, http://www.idiom.com newsgroups: comp.lang.ada Date: 1996-08-12T00:00:00+00:00 List-Id: Olivier Hainque (hainque@news.enst.fr) wrote: : Hello all, : I am trying to port the GNAT runtime for an embedded OS running on : a 68302. : I configured gcc as a cross compiler for C and Ada and have troubles : while building a dummy runtime for my target : : $ make CC=gcc CFLAGS="-m68302 -msoft-float" gnatlib : ... Everything runs fine for the first files, but ... : ../../xgcc -B../../ -c -m68302 -msoft-float -O2 -gnatpg -I. : -I../../gcc-2.7.2/ada a-calcon.adb : leads to the following : : /var/tmp/cca002bf.s: Assembler messages: : /var/tmp/cca002bf.s:9: Error: invalid instruction for this architecture; : needs fpu (68040, 68060 or 68881/68882) -- statement `fmovem #0xfc,sp@-' : ignored : xgcc: Internal compiler error: program as got fatal signal 10 : :-( : Of course, the runtime is not ported yet, so I don't expect it to be : completely operational at this time. However, I do not understand how the : compilation of an ada file, having specified special options, could lead : to an assembly file still containing unsupported statements for the given : target. I thought it was weird too. I bumped into the problem when building GNAT itself for a 68000 target. The 68881 registers are always defined when compiling for a 68xxx target whether they exist or not. To prevent the compiler from using them if they do not exist, they are specified as not being able to hold any kind of value. So far, so good. And, indeed, the fmovem instruction you see has not been generated by the compiler, it comes from the output_function_prologue and output_function_epilogue functions in m68k.c. Those two functions output the proper statements to save used registers and restore them at the beginning and end of a function. They are outputting the fmovem instructions because the compiler told them that 688881 registers were used. How is that possible ? If the code is using an NOTE_INSN_SETJUMP insn, then the compiler assumes everything must be saved and mark all defined registers (without caring about whether they can hold something or not) as used. And GNAT seems to love that insn. QED. I don't know if it's normal behavior to use that insn since I never got the problem with C code. But the cure is easy. You need to recheck in output_function_prologue and output_function_epilogue for 68881 existence. m68k.c: in output_function_prologue: #ifdef SUPPORT_SUN_FPA for (regno = 24; regno < 56; regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) { #ifdef MOTOROLA asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n", reg_names[regno]); #else asm_fprintf (stream, "\tfpmoved %s,%Rsp@-\n", reg_names[regno]); #endif } #endif + if (TARGET_68881) + { for (regno = 16; regno < 24; regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) mask |= 1 << (regno - 16); + } if ((mask & 0xff) != 0) { #ifdef MOTOROLA asm_fprintf (stream, "\tfmovm %0I0x%x,-(%Rsp)\n", mask & 0xff); #else asm_fprintf (stream, "\tfmovem %0I0x%x,%Rsp@-\n", mask & 0xff); #endif } mask = 0; in output_function_epilogue: FUNCTION_EXTRA_EPILOGUE (stream, size); #endif nregs = 0; fmask = 0; fpoffset = 0; #ifdef SUPPORT_SUN_FPA for (regno = 24 ; regno < 56 ; regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) nregs++; fpoffset = nregs * 8; #endif nregs = 0; + if (TARGET_68881) + { for (regno = 16; regno < 24; regno++) if (regs_ever_live[regno] && ! call_used_regs[regno]) { nregs++; fmask |= 1 << (23 - regno); } + } foffset = fpoffset + nregs * 12; nregs = 0; mask = 0; if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; for (regno = 0; regno < 16; regno++)