From 2a266d02ba4304af542da2cc521ecc0edc1c9706 Mon Sep 17 00:00:00 2001 From: "David E. O'Brien" Date: Thu, 26 Aug 1999 09:30:50 +0000 Subject: Virgin import of gcc from EGCS 1.1.2 --- contrib/gcc/config/i386/386bsd.h | 9 +- contrib/gcc/config/i386/aix386ng.h | 15 +- contrib/gcc/config/i386/att.h | 21 +- contrib/gcc/config/i386/bsd.h | 8 +- contrib/gcc/config/i386/bsd386.h | 19 +- contrib/gcc/config/i386/crtdll.h | 42 + contrib/gcc/config/i386/dgux.c | 190 ++ contrib/gcc/config/i386/dgux.h | 265 ++ contrib/gcc/config/i386/freebsd-elf.h | 44 +- contrib/gcc/config/i386/freebsd.h | 349 ++- contrib/gcc/config/i386/freebsd.h.fixed | 349 ++- contrib/gcc/config/i386/gas.h | 48 +- contrib/gcc/config/i386/gmon-sol2.c | 409 +++ contrib/gcc/config/i386/gnu.h | 15 +- contrib/gcc/config/i386/go32.h | 34 +- contrib/gcc/config/i386/i386.c | 2908 +++++++++++++++++---- contrib/gcc/config/i386/i386.h | 1313 ++++++++-- contrib/gcc/config/i386/i386.md | 4193 +++++++++++++++++++++++-------- contrib/gcc/config/i386/isc.h | 8 +- contrib/gcc/config/i386/linux-aout.h | 20 +- contrib/gcc/config/i386/linux-oldld.h | 21 +- contrib/gcc/config/i386/linux.h | 73 +- contrib/gcc/config/i386/lynx.h | 8 +- contrib/gcc/config/i386/mingw32.h | 95 + contrib/gcc/config/i386/moss.h | 34 + contrib/gcc/config/i386/netbsd.h | 23 +- contrib/gcc/config/i386/next.h | 15 +- contrib/gcc/config/i386/openbsd.h | 130 + contrib/gcc/config/i386/osf1-ci.asm | 65 + contrib/gcc/config/i386/osf1-cn.asm | 46 + contrib/gcc/config/i386/osf1elf.h | 260 ++ contrib/gcc/config/i386/osf1elfgdb.h | 7 + contrib/gcc/config/i386/osfelf.h | 4 +- contrib/gcc/config/i386/osfrose.h | 37 +- contrib/gcc/config/i386/ptx4-i.h | 247 ++ contrib/gcc/config/i386/rtems.h | 34 + contrib/gcc/config/i386/rtemself.h | 169 ++ contrib/gcc/config/i386/sco.h | 8 +- contrib/gcc/config/i386/sco4.h | 6 +- contrib/gcc/config/i386/sco4dbx.h | 6 +- contrib/gcc/config/i386/sco5.h | 957 +++++++ contrib/gcc/config/i386/sco5gas.h | 24 + contrib/gcc/config/i386/scodbx.h | 8 +- contrib/gcc/config/i386/seq-gas.h | 4 +- contrib/gcc/config/i386/seq-sysv3.h | 14 - contrib/gcc/config/i386/sol2-c1.asm | 4 +- contrib/gcc/config/i386/sol2-gc1.asm | 160 ++ contrib/gcc/config/i386/sol2.h | 46 +- contrib/gcc/config/i386/sun386.h | 7 +- contrib/gcc/config/i386/svr3.ifile | 5 +- contrib/gcc/config/i386/svr3dbx.h | 22 +- contrib/gcc/config/i386/svr3gas.h | 18 +- contrib/gcc/config/i386/svr3z.ifile | 5 +- contrib/gcc/config/i386/sysv3.h | 8 +- contrib/gcc/config/i386/sysv4.h | 14 +- contrib/gcc/config/i386/t-crtpic | 1 + contrib/gcc/config/i386/t-dgux | 4 + contrib/gcc/config/i386/t-mingw32 | 4 + contrib/gcc/config/i386/t-next | 3 + contrib/gcc/config/i386/t-osf | 2 + contrib/gcc/config/i386/t-osf1elf | 18 + contrib/gcc/config/i386/t-sco5 | 20 + contrib/gcc/config/i386/t-sco5gas | 20 + contrib/gcc/config/i386/t-sol2 | 22 +- contrib/gcc/config/i386/t-winnt | 6 +- contrib/gcc/config/i386/unix.h | 47 +- contrib/gcc/config/i386/vxi386.h | 23 + contrib/gcc/config/i386/winnt.c | 526 +++- contrib/gcc/config/i386/x-dgux | 11 + contrib/gcc/config/i386/x-osf1elf | 8 + contrib/gcc/config/i386/x-osfrose | 10 +- contrib/gcc/config/i386/x-sco5 | 10 + contrib/gcc/config/i386/xm-aix.h | 35 - contrib/gcc/config/i386/xm-bsd386.h | 3 - contrib/gcc/config/i386/xm-dgux.h | 12 + contrib/gcc/config/i386/xm-dos.h | 6 - contrib/gcc/config/i386/xm-isc.h | 2 - contrib/gcc/config/i386/xm-linux.h | 4 +- contrib/gcc/config/i386/xm-mingw32.h | 42 + contrib/gcc/config/i386/xm-openbsd.h | 23 + contrib/gcc/config/i386/xm-os2.h | 28 +- contrib/gcc/config/i386/xm-osf.h | 30 - contrib/gcc/config/i386/xm-osf1elf.h | 6 + contrib/gcc/config/i386/xm-sco.h | 9 - contrib/gcc/config/i386/xm-sco5.h | 7 + contrib/gcc/config/i386/xm-sun.h | 6 +- contrib/gcc/config/i386/xm-sysv4.h | 11 - contrib/gcc/config/i386/xm-vsta.h | 24 - 88 files changed, 11267 insertions(+), 2559 deletions(-) create mode 100644 contrib/gcc/config/i386/crtdll.h create mode 100644 contrib/gcc/config/i386/dgux.c create mode 100644 contrib/gcc/config/i386/dgux.h create mode 100644 contrib/gcc/config/i386/gmon-sol2.c create mode 100644 contrib/gcc/config/i386/mingw32.h create mode 100644 contrib/gcc/config/i386/moss.h create mode 100644 contrib/gcc/config/i386/openbsd.h create mode 100644 contrib/gcc/config/i386/osf1-ci.asm create mode 100644 contrib/gcc/config/i386/osf1-cn.asm create mode 100644 contrib/gcc/config/i386/osf1elf.h create mode 100644 contrib/gcc/config/i386/osf1elfgdb.h create mode 100644 contrib/gcc/config/i386/ptx4-i.h create mode 100644 contrib/gcc/config/i386/rtems.h create mode 100644 contrib/gcc/config/i386/rtemself.h create mode 100644 contrib/gcc/config/i386/sco5.h create mode 100644 contrib/gcc/config/i386/sco5gas.h create mode 100644 contrib/gcc/config/i386/sol2-gc1.asm create mode 100644 contrib/gcc/config/i386/t-dgux create mode 100644 contrib/gcc/config/i386/t-mingw32 create mode 100644 contrib/gcc/config/i386/t-osf create mode 100644 contrib/gcc/config/i386/t-osf1elf create mode 100644 contrib/gcc/config/i386/t-sco5 create mode 100644 contrib/gcc/config/i386/t-sco5gas create mode 100644 contrib/gcc/config/i386/vxi386.h create mode 100644 contrib/gcc/config/i386/x-dgux create mode 100644 contrib/gcc/config/i386/x-osf1elf create mode 100644 contrib/gcc/config/i386/x-sco5 create mode 100644 contrib/gcc/config/i386/xm-dgux.h create mode 100644 contrib/gcc/config/i386/xm-mingw32.h create mode 100644 contrib/gcc/config/i386/xm-openbsd.h create mode 100644 contrib/gcc/config/i386/xm-osf1elf.h create mode 100644 contrib/gcc/config/i386/xm-sco5.h (limited to 'contrib/gcc/config/i386') diff --git a/contrib/gcc/config/i386/386bsd.h b/contrib/gcc/config/i386/386bsd.h index cdab5f57c88c..7962321325c9 100644 --- a/contrib/gcc/config/i386/386bsd.h +++ b/contrib/gcc/config/i386/386bsd.h @@ -49,11 +49,6 @@ } \ } -/* There are conflicting reports about whether this system uses - a different assembler syntax. wilson@cygnus.com says # is right. */ -#undef COMMENT_BEGIN -#define COMMENT_BEGIN "#" - #undef ASM_APP_ON #define ASM_APP_ON "#APP\n" @@ -68,13 +63,13 @@ i386.md for an explanation of the expression this outputs. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) /* Indicate that jump tables go in the text section. This is necessary when compiling PIC code. */ -#define JUMP_TABLES_IN_TEXT_SECTION +#define JUMP_TABLES_IN_TEXT_SECTION 1 /* Don't default to pcc-struct-return, because gcc is the only compiler, and we want to retain compatibility with older gcc versions. */ diff --git a/contrib/gcc/config/i386/aix386ng.h b/contrib/gcc/config/i386/aix386ng.h index 5d09fc305098..a177b69250f8 100644 --- a/contrib/gcc/config/i386/aix386ng.h +++ b/contrib/gcc/config/i386/aix386ng.h @@ -1,6 +1,6 @@ /* Definitions for IBM PS2 running AIX/386. - From: Minh Tran-Le - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. + Contributed by Minh Tran-Le . This file is part of GNU CC. @@ -27,7 +27,7 @@ Boston, MA 02111-1307, USA. */ #include "svr3.h" /* Use the ATT assembler syntax. - This overrides at least one macro (ASM_OUTPUT_LABELREF) from svr3.h. */ + This overrides at least one macro (USER_LABEL_PREFIX) from svr3.h. */ #include "i386/att.h" @@ -44,10 +44,10 @@ Boston, MA 02111-1307, USA. */ /* Specify predefined symbols in preprocessor. */ -#define CPP_PREDEFINES "-Dps2 -Dunix -Di386 -Asystem(unix) -Asystem(aix) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dps2 -Dunix -Asystem(aix)" -#define CPP_SPEC \ - "%{posix:-D_POSIX_SOURCE}%{!posix:-DAIX} -D_I386 -D_AIX -D_MBCS" +#define CPP_SPEC "%(cpp_cpu) \ + %{posix:-D_POSIX_SOURCE}%{!posix:-DAIX} -D_I386 -D_AIX -D_MBCS" /* special flags for the aix assembler to generate the short form for all qualifying forward reference */ @@ -132,8 +132,7 @@ const_section () \ # undef EXTRA_SECTION_FUNCTIONS # define EXTRA_SECTION_FUNCTIONS \ - CONST_SECTION_FUNCTION \ - BSS_SECTION_FUNCTION + CONST_SECTION_FUNCTION /* for collect2 */ # define OBJECT_FORMAT_COFF diff --git a/contrib/gcc/config/i386/att.h b/contrib/gcc/config/i386/att.h index f8bbb764306b..e5c2d9c7e994 100644 --- a/contrib/gcc/config/i386/att.h +++ b/contrib/gcc/config/i386/att.h @@ -1,5 +1,5 @@ /* Definitions for AT&T assembler syntax for the Intel 80386. - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -68,18 +68,6 @@ do \ /* Can't use ASM_OUTPUT_SKIP in text section; it doesn't leave 0s. */ #define ASM_NO_SKIP_IN_TEXT 1 - -#undef BSS_SECTION_FUNCTION /* Override the definition from svr3.h. */ -#define BSS_SECTION_FUNCTION \ -void \ -bss_section () \ -{ \ - if (in_section != in_bss) \ - { \ - fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \ - in_section = in_bss; \ - } \ -} /* Define the syntax of labels and symbol definitions/declarations. */ @@ -99,8 +87,7 @@ bss_section () \ #define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ fprintf (FILE, ".%s%d:\n", PREFIX, NUM) -/* This is how to output a reference to a user-level label named NAME. */ +/* The prefix to add to user-visible assembler symbols. */ -#undef ASM_OUTPUT_LABELREF -#define ASM_OUTPUT_LABELREF(FILE,NAME) \ - fprintf (FILE, "%s", NAME) +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" diff --git a/contrib/gcc/config/i386/bsd.h b/contrib/gcc/config/i386/bsd.h index 6bf7399dc312..d50be3664c11 100644 --- a/contrib/gcc/config/i386/bsd.h +++ b/contrib/gcc/config/i386/bsd.h @@ -1,7 +1,7 @@ /* Definitions for BSD assembler syntax for Intel 386 (actually AT&T syntax for insns and operands, adapted to BSD conventions for symbol names and debugging.) - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -115,12 +115,12 @@ Boston, MA 02111-1307, USA. */ fprintf (FILE, "%s%d:\n", PREFIX, NUM) #endif -/* This is how to output a reference to a user-level label named NAME. */ +/* The prefix to add to user-visible assembler symbols. */ #ifdef NO_UNDERSCORES -#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "%s", NAME) +#define USER_LABEL_PREFIX "" #else -#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "_%s", NAME) +#define USER_LABEL_PREFIX "_" #endif /* not NO_UNDERSCORES */ /* Sequent has some changes in the format of DBX symbols. */ diff --git a/contrib/gcc/config/i386/bsd386.h b/contrib/gcc/config/i386/bsd386.h index 935a2e06404d..c0dcf87cbdd9 100644 --- a/contrib/gcc/config/i386/bsd386.h +++ b/contrib/gcc/config/i386/bsd386.h @@ -1,5 +1,5 @@ -/* Configuration for an i386 running BSDI's BSD/386 1.1 as the target - machine. */ +/* Configuration for an i386 running BSDI's BSD/OS (formerly known as BSD/386) + as the target machine. */ #include "i386/386bsd.h" @@ -16,3 +16,18 @@ #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE 32 + +/* This is suitable for BSD/OS 3.0; we don't know about earlier releases. */ +#undef ASM_COMMENT_START +#define ASM_COMMENT_START " #" + +/* Until they use ELF or something that handles dwarf2 unwinds + and initialization stuff better. */ +#define DWARF2_UNWIND_INFO 0 + +/* BSD/OS still uses old binutils that don't insert nops by default + when the .align directive demands to insert extra space in the text + segment. */ +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG)) diff --git a/contrib/gcc/config/i386/crtdll.h b/contrib/gcc/config/i386/crtdll.h new file mode 100644 index 000000000000..f7eaf2b71e63 --- /dev/null +++ b/contrib/gcc/config/i386/crtdll.h @@ -0,0 +1,42 @@ +/* Operating system specific defines to be used when targeting GCC for + hosting on Windows32, using GNU tools and the Windows32 API Library, + as distinct from winnt.h, which is used to build GCC for use with a + windows style library and tool set and uses the Microsoft tools. + This variant uses CRTDLL.DLL insted of MSVCRTDLL.DLL. + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -D_WIN32 -DWIN32 -D__WIN32__ \ + -D__MINGW32__ -DWINNT -D_X86_=1 -D__STDC__=1\ + -D__stdcall=__attribute__((__stdcall__)) \ + -D_stdcall=__attribute__((__stdcall__)) \ + -D__cdecl=__attribute__((__cdecl__)) \ + -D__declspec(x)=__attribute__((x)) \ + -Asystem(winnt) -Acpu(i386) -Amachine(i386)" + +#undef LIBGCC_SPEC +#define LIBGCC_SPEC "-lmingw32 -lgcc -lmoldname -lcrtdll" + +/* Specify a different entry point when linking a DLL */ +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{mdll:dllcrt1%O%s} %{!mdll:crt1%O%s}" + +#undef MATH_LIBRARY +#define MATH_LIBRARY "-lcrtdll" diff --git a/contrib/gcc/config/i386/dgux.c b/contrib/gcc/config/i386/dgux.c new file mode 100644 index 000000000000..ff36135380c3 --- /dev/null +++ b/contrib/gcc/config/i386/dgux.c @@ -0,0 +1,190 @@ +/* Subroutines for GNU compiler for Intel 80x86 running DG/ux + Copyright (C) 1993, 1995, 1997 Free Software Foundation, Inc. + Currently maintained by (gcc@dg-rtp.dg.com) + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include +#include "i386/i386.c" + + +extern char *version_string; + +struct option +{ + char *string; + int *variable; + int on_value; +}; + +static int +output_option (file, sep, type, name, indent, pos, max) + FILE *file; + char *sep; + char *type; + char *name; + char *indent; + int pos; + int max; +{ + if (strlen (sep) + strlen (type) + strlen (name) + pos > max) + { + fprintf (file, indent); + return fprintf (file, "%s%s", type, name); + } + return pos + fprintf (file, "%s%s%s", sep, type, name); +} + +static struct { char *name; int value; } m_options[] = TARGET_SWITCHES; + +static void +output_options (file, f_options, f_len, W_options, W_len, + pos, max, sep, indent, term) + FILE *file; + struct option *f_options; + struct option *W_options; + int f_len, W_len; + int pos; + int max; + char *indent; + char *term; +{ + register int j; + + if (optimize) + pos = output_option (file, sep, "-O", "", indent, pos, max); + if (write_symbols != NO_DEBUG) + pos = output_option (file, sep, "-g", "", indent, pos, max); +/* if (flag_traditional) + pos = output_option (file, sep, "-traditional", "", indent, pos, max);*/ + if (profile_flag) + pos = output_option (file, sep, "-p", "", indent, pos, max); + if (profile_block_flag) + pos = output_option (file, sep, "-a", "", indent, pos, max); + + for (j = 0; j < f_len; j++) + if (*f_options[j].variable == f_options[j].on_value) + pos = output_option (file, sep, "-f", f_options[j].string, + indent, pos, max); + + for (j = 0; j < W_len; j++) + if (*W_options[j].variable == W_options[j].on_value) + pos = output_option (file, sep, "-W", W_options[j].string, + indent, pos, max); + + for (j = 0; j < sizeof m_options / sizeof m_options[0]; j++) + if (m_options[j].name[0] != '\0' + && m_options[j].value > 0 + && ((m_options[j].value & target_flags) + == m_options[j].value)) + pos = output_option (file, sep, "-m", m_options[j].name, + indent, pos, max); + + pos = output_option (file, sep, "-mcpu=", ix86_cpu_string, indent, pos, max); + pos = output_option (file, sep, "-march=", ix86_arch_string, indent, pos, max); + fprintf (file, term); +} + +/* Output to FILE the start of the assembler file. */ + +void +output_file_start (file, f_options, f_len, W_options, W_len) + FILE *file; + struct option *f_options; + struct option *W_options; + int f_len, W_len; +{ + register int pos; + + output_file_directive (file, main_input_filename); + fprintf (file, "\t.version\t\"01.01\"\n"); \ + /* Switch to the data section so that the coffsem symbol and the + gcc2_compiled. symbol aren't in the text section. */ + data_section (); + + pos = fprintf (file, "\n// cc1 (%s) arguments:", VERSION_STRING); + output_options (file, f_options, f_len, W_options, W_len, + pos, 75, " ", "\n// ", "\n\n"); + +#ifdef TARGET_IDENTIFY_REVISION + if (TARGET_IDENTIFY_REVISION) + { + char indent[256]; + + time_t now = time ((time_t *)0); + sprintf (indent, "]\"\n\t%s\t \"@(#)%s [", IDENT_ASM_OP, main_input_filename); + fprintf (file, indent+3); + pos = fprintf (file, "gcc %s, %.24s,", VERSION_STRING, ctime (&now)); + output_options (file, f_options, f_len, W_options, W_len, + pos, 150 - strlen (indent), " ", indent, "]\"\n\n"); + } +#endif /* TARGET_IDENTIFY_REVISION */ +} + +#ifndef CROSS_COMPILE +#if defined (_abort_aux) +/* Debugging aid to be registered via `atexit'. See the definition + of abort in dgux.h. */ +void +abort_aux () +{ + extern int insn_; + extern char * file_; + extern int line_; + static int done; + rtx line_note; + + if (done++) + return; + if (file_ || line_) + { + if (write_symbols != NO_DEBUG) + { + for (line_note = (rtx) insn_ ; line_note != 0 ; line_note = PREV_INSN (line_note)) + if (GET_CODE (line_note) == NOTE && NOTE_LINE_NUMBER (line_note) > 0) + break; + if (line_note != 0) + { + error_with_file_and_line (NOTE_SOURCE_FILE (line_note), + NOTE_LINE_NUMBER (line_note), + "Internal gcc abort from %s:%d", + file_ ? file_ : "", line_); + if (insn_ && file_ && strcmp (file_, "toplev.c")) + { + error_with_file_and_line (NOTE_SOURCE_FILE (line_note), + NOTE_LINE_NUMBER (line_note), + "The local variable `insn' has the value:", 0); + debug_rtx ((rtx) insn_); + } + } + } + if (write_symbols == NO_DEBUG || line_note == 0) + { + error ("Internal gcc abort from %s:%d", + file_ ? file_ : "", line_); + if (insn_ && file_ && strcmp (file_, "toplev.c")) + { + error ("The local variable `insn' has the value:", 0); + debug_rtx ((rtx) insn_); + } + } + } +} +#endif +#endif + + diff --git a/contrib/gcc/config/i386/dgux.h b/contrib/gcc/config/i386/dgux.h new file mode 100644 index 000000000000..dae050f6c0bd --- /dev/null +++ b/contrib/gcc/config/i386/dgux.h @@ -0,0 +1,265 @@ +/* Target definitions for GNU compiler for Intel 80x86 running DG/ux + Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Currently maintained by gcc@dg-rtp.dg.com. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* for now, we are just like the sysv4 version with a + few hacks +*/ + +#include "i386/sysv4.h" + +#ifndef VERSION_INFO2 +#define VERSION_INFO2 "$Revision: 1.3 $" +#endif + +#ifndef VERSION_STRING +#define VERSION_STRING version_string +#endif + +/* Identify the compiler. */ +/* TARGET_VERSION used by toplev.c VERSION_STRING used by -midentify-revision */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (%s%s, %s)", \ + VERSION_INFO1, VERSION_INFO2, __DATE__) +#undef VERSION_INFO1 +#define VERSION_INFO1 "ix86 DG/ux, " + +/* Augment TARGET_SWITCHES with the MXDB options. */ +#define MASK_STANDARD 0x40000000 /* Retain standard information */ +#define MASK_NOLEGEND 0x20000000 /* Discard legend information */ +#define MASK_EXTERNAL_LEGEND 0x10000000 /* Make external legends */ +#define MASK_IDENTIFY_REVISION 0x08000000 /* Emit 'ident' to .s */ +#define MASK_WARN_PASS_STRUCT 0x04000000 /* Emit 'ident' to .s */ + +#define TARGET_STANDARD (target_flags & MASK_STANDARD) +#define TARGET_NOLEGEND (target_flags & MASK_NOLEGEND) +#define TARGET_EXTERNAL_LEGEND (target_flags & MASK_EXTERNAL_LEGEND) +#define TARGET_IDENTIFY_REVISION (target_flags & MASK_IDENTIFY_REVISION) +#define TARGET_WARN_PASS_STRUCT (target_flags & MASK_WARN_PASS_STRUCT) + +#undef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES \ + { "standard", MASK_STANDARD }, \ + { "legend", -MASK_NOLEGEND }, \ + { "no-legend", MASK_NOLEGEND }, \ + { "external-legend", MASK_EXTERNAL_LEGEND }, \ + { "identify-revision", MASK_IDENTIFY_REVISION }, \ + { "warn-passed-structs", MASK_WARN_PASS_STRUCT }, + +#undef DWARF_DEBUGGING_INFO +#define DWARF_DEBUGGING_INFO + +/* + allow -gstabs so that those who have gnu-as installed + can debug c++ programs. +*/ +#undef DBX_DEBUGGING_INFO +#define DBX_DEBUGGING_INFO + +#define PREFERRED_DEBUGGING_TYPE DWARF_DEBUG + +/* Override svr[34].h. */ +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + output_file_start (FILE, f_options, sizeof f_options / sizeof f_options[0], \ + W_options, sizeof W_options / sizeof W_options[0]) + +/* ix86 abi specified type for wchar_t */ + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + + +/* Some machines may desire to change what optimizations are performed for + various optimization levels. This macro, if defined, is executed once + just after the optimization level is determined and before the remainder + of the command options have been parsed. Values set in this macro are + used as the default values for the other command line options. + + LEVEL is the optimization level specified; 2 if -O2 is specified, + 1 if -O is specified, and 0 if neither is specified. */ + +/* This macro used to store 0 in flag_signed_bitfields. + Not only is that misuse of this macro; the whole idea is wrong. + + The GNU C dialect makes bitfields signed by default, + regardless of machine type. Making any machine inconsistent in this + regard is bad for portability. + + I chose to make bitfields signed by default because this is consistent + with the way ordinary variables are handled: `int' equals `signed int'. + If there is a good reason to prefer making bitfields unsigned by default, + it cannot have anything to do with the choice of machine. + If the reason is good enough, we should change the convention for all machines. + + -- rms, 20 July 1991. */ + +/* + this really should go into dgux-local.h +*/ + +#undef OPTIMIZATION_OPTIONS +#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) \ + do { \ + extern int flag_signed_bitfields; \ + flag_signed_bitfields = 0; \ + abort_helper (); \ + optimization_options (LEVEL,SIZE); \ + } while (0) + + +/* The normal location of the `ld' and `as' programs */ + +#undef MD_EXEC_PREFIX +#define MD_EXEC_PREFIX "/usr/bin/" + +/* The normal location of the various *crt*.o files is the */ + +#undef MD_STARTFILE_PREFIX +#define MD_STARTFILE_PREFIX "/usr/lib/" + +/* Macros to be automatically defined. + __CLASSIFY_TYPE__ is used in the and header + files with DG/UX revision 5.40 and later. This allows GNU CC to + operate without installing the header files. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -D__ix86 -Dunix -DDGUX -D__CLASSIFY_TYPE__=2\ + -Asystem(unix) -Asystem(svr4) -Acpu(i386) -Amachine(i386)" + + /* + If not -ansi, -traditional, or restricting include files to one + specific source target, specify full DG/UX features. + */ +#undef CPP_SPEC +#define CPP_SPEC "%{!ansi:%{!traditional:-D__OPEN_NAMESPACE__}}" + +/* Assembler support (legends for mxdb). */ +#undef ASM_SPEC +#define ASM_SPEC "\ +%{mno-legend:%{mstandard:-Wc,off}}\ +%{g:%{!mno-legend:-Wc,-fix-bb,-s\"%i\"\ +%{traditional:,-lc}%{!traditional:,-lansi-c}\ +%{mstandard:,-keep-std}\ +%{mexternal-legend:,-external}}}" + +/* Override svr4.h. */ + +/* hassey 3/12/94 keep svr4 ASM_FINAL_SPEC allows -pipe to work */ + +/* Linker and library spec's. + -static, -shared, -symbolic, -h* and -z* access AT&T V.4 link options. + -svr4 instructs gcc to place /usr/lib/values-X[cat].o on link the line. + The absence of -msvr4 indicates linking done in a COFF environment and + adds the link script to the link line. In all environments, the first + and last objects are crtbegin.o and crtend.o. + When the -G link option is used (-shared and -symbolic) a final link is + not being done. */ + +#undef LIB_SPEC +#define LIB_SPEC \ +"%{!shared:%{!symbolic:-lc}}" + +#undef LINK_SPEC +#define LINK_SPEC "%{z*} %{h*} %{v:-V} \ + %{static:-dn -Bstatic} \ + %{shared:-G -dy} \ + %{symbolic:-Bsymbolic -G -dy} \ + %{pg:-L/usr/lib/libp}%{p:-L/usr/lib/libp}" + +#ifdef CROSS_COMPILE + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared:%{!symbolic:%{pg:gcrt1.o%s} \ + %{!pg:%{p:mcrt1.o%s} \ + %{!p:crt1.o%s}}}} \ + %{pg:gcrti.o%s}%{!pg:crti.o%s} \ + crtbegin.o%s \ + %{ansi:values-Xc.o%s} \ + %{!ansi:%{traditional:values-Xt.o%s} \ + %{!traditional:values-Xa.o%s}}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s %{pg:gcrtn.o}%{!pg:crtn.o%s}" + +#else + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared:%{!symbolic:%{pg:gcrt1.o%s} \ + %{!pg:%{p:/lib/mcrt1.o%s} \ + %{!p:/lib/crt1.o%s}}} \ + %{pg:gcrti.o%s}%{!pg:/lib/crti.o%s}} \ + crtbegin.o%s \ + %{ansi:/lib/values-Xc.o%s} \ + %{!ansi:%{traditional:/lib/values-Xt.o%s} \ + %{!traditional:/lib/values-Xa.o%s}}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s %{pg:gcrtn.o}%{!pg:/lib/crtn.o}" + +#endif /* CROSS_COMPILE */ + +#if !defined (no_abort) || defined (CRT_BEGIN) || defined (CRT_END) +#undef abort + +char insn; int insn_; char * file_; int line_; +#define abort() \ + (insn_ = (int) insn, \ + file_ = __FILE__, \ + line_ = __LINE__, \ + fancy_abort ()) +#define abort_helper() \ + do { \ + extern void abort_aux (); \ + atexit (abort_aux); \ + } while (0) +#define _abort_aux +#endif /* no abort */ + +/* The maximum alignment which the object file format can support. + page alignment would seem to be enough */ +#undef MAX_OFILE_ALIGNMENT +#define MAX_OFILE_ALIGNMENT 0x1000 + +/* Must use data section for relocatable constants when pic. */ +#undef SELECT_RTX_SECTION +#define SELECT_RTX_SECTION(MODE,RTX) \ +{ \ + if (flag_pic && symbolic_operand (RTX)) \ + data_section (); \ + else \ + const_section (); \ +} + +/* This supplements FUNCTION_ARG's definition in i386.h to check + TARGET_WARN_PASS_STRUCT */ + +#undef FUNCTION_ARG +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \ +((((MODE) == BLKmode && TARGET_WARN_PASS_STRUCT) ? \ + warning ("argument is a structure"),0 : 0), \ + (function_arg (&CUM, MODE, TYPE, NAMED))) + +/* Add .align 1 to avoid .backalign bug in assembler */ +#undef CONST_SECTION_ASM_OP +#define CONST_SECTION_ASM_OP ".section\t.rodata\n\t.align 1" diff --git a/contrib/gcc/config/i386/freebsd-elf.h b/contrib/gcc/config/i386/freebsd-elf.h index 393ede749e38..0a556fe01bdd 100644 --- a/contrib/gcc/config/i386/freebsd-elf.h +++ b/contrib/gcc/config/i386/freebsd-elf.h @@ -1,8 +1,8 @@ /* Definitions for Intel 386 running FreeBSD with ELF format - Copyright (C) 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1996 Free Software Foundation, Inc. Contributed by Eric Youngdale. Modified for stabs-in-ELF by H.J. Lu. - Adapted from Linux version by John Polstra. + Adapted from GNU/Linux version by John Polstra. This file is part of GNU CC. @@ -21,31 +21,29 @@ along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* A lie, I guess, but the general idea behind FreeBSD/ELF is that we are - supposed to be outputting something that will assemble under SVr4. - This gets us pretty close. */ -#include /* Base i386 target machine definitions */ -#include /* Use the i386 AT&T assembler syntax */ -#include /* some common stuff */ - #undef TARGET_VERSION #define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)"); /* The svr4 ABI for the i386 says that records and unions are returned in memory. */ +/* On FreeBSD, we do not. */ #undef DEFAULT_PCC_STRUCT_RETURN -#define DEFAULT_PCC_STRUCT_RETURN 1 +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* This gets defined in tm.h->linux.h->svr4.h, and keeps us from using + libraries compiled with the native cc, so undef it. */ +#undef NO_DOLLAR_IN_LABEL /* This is how to output an element of a case-vector that is relative. This is only used for PIC code. See comments by the `casesi' insn in i386.md for an explanation of the expression this outputs. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) /* Indicate that jump tables go in the text section. This is necessary when compiling PIC code. */ -#define JUMP_TABLES_IN_TEXT_SECTION +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) /* Copy this from the svr4 specifications... */ /* Define the register numbers to be used in Dwarf debugging information. @@ -147,14 +145,10 @@ Boston, MA 02111-1307, USA. */ #define WCHAR_TYPE_SIZE BITS_PER_WORD #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -D__ELF__ -D__FreeBSD__=2 -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Di386 -Dunix -D__ELF__ -D__FreeBSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" #undef CPP_SPEC -#if TARGET_CPU_DEFAULT == 2 -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!m386:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#else -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m486:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#endif +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" #undef LIB_SPEC #if 1 @@ -196,4 +190,16 @@ Boston, MA 02111-1307, USA. */ %{static:-static}}}" /* Get perform_* macros to build libgcc.a. */ -#include "i386/perform.h" + +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1< +/* Definitions for Intel 386 running FreeBSD with ELF format + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Eric Youngdale. + Modified for stabs-in-ELF by H.J. Lu. + Adapted from GNU/Linux version by John Polstra. This file is part of GNU CC. @@ -20,231 +21,185 @@ along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* This goes away when the math-emulator is fixed */ -#define TARGET_CPU_DEFAULT 0400 /* TARGET_NO_FANCY_MATH_387 */ +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)"); -/* This is tested by i386gas.h. */ -#define YES_UNDERSCORES - -/* Don't assume anything about the header files. */ -#define NO_IMPLICIT_EXTERN_C - -#include "i386/gstabs.h" - -/* Get perform_* macros to build libgcc.a. */ -#include "i386/perform.h" - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -D__FreeBSD__ -D__386BSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" - -/* Like the default, except no -lg. */ -#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}" - -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "short unsigned int" - -#define WCHAR_UNSIGNED 1 - -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 16 - -#define HAVE_ATEXIT - -/* There are conflicting reports about whether this system uses - a different assembler syntax. wilson@cygnus.com says # is right. */ -#undef COMMENT_BEGIN -#define COMMENT_BEGIN "#" - -#undef ASM_APP_ON -#define ASM_APP_ON "#APP\n" +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ +/* On FreeBSD, we do not. */ +#undef DEFAULT_PCC_STRUCT_RETURN +#define DEFAULT_PCC_STRUCT_RETURN 0 -#undef ASM_APP_OFF -#define ASM_APP_OFF "#NO_APP\n" - -/* The following macros are stolen from i386v4.h */ -/* These have to be defined to get PIC code correct */ +/* This gets defined in tm.h->linux.h->svr4.h, and keeps us from using + libraries compiled with the native cc, so undef it. */ +#undef NO_DOLLAR_IN_LABEL /* This is how to output an element of a case-vector that is relative. This is only used for PIC code. See comments by the `casesi' insn in i386.md for an explanation of the expression this outputs. */ - #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) /* Indicate that jump tables go in the text section. This is necessary when compiling PIC code. */ +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) + +/* Copy this from the svr4 specifications... */ +/* Define the register numbers to be used in Dwarf debugging information. + The SVR4 reference port C compiler uses the following register numbers + in its Dwarf output code: + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) \ +((n) == 0 ? 0 \ + : (n) == 1 ? 2 \ + : (n) == 2 ? 1 \ + : (n) == 3 ? 3 \ + : (n) == 4 ? 6 \ + : (n) == 5 ? 7 \ + : (n) == 6 ? 5 \ + : (n) == 7 ? 4 \ + : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ + : (-1)) + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ -#define JUMP_TABLES_IN_TEXT_SECTION - -/* Don't default to pcc-struct-return, because gcc is the only compiler, and - we want to retain compatibility with older gcc versions. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Profiling routines, partially copied from i386/osfrose.h. */ - -/* Redefine this to use %eax instead of %edx. */ #undef FUNCTION_PROFILER #define FUNCTION_PROFILER(FILE, LABELNO) \ { \ if (flag_pic) \ { \ - fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%eax\n", \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \ LPREFIX, (LABELNO)); \ fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \ } \ else \ { \ - fprintf (FILE, "\tmovl $%sP%d,%%eax\n", LPREFIX, (LABELNO)); \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO)); \ fprintf (FILE, "\tcall mcount\n"); \ } \ } -/* - * Some imports from svr4.h in support of shared libraries. - * Currently, we need the DECLARE_OBJECT_SIZE stuff. - */ - -/* Define the strings used for the special svr4 .type and .size directives. - These strings generally do not vary from one system running svr4 to - another, but if a given system (e.g. m88k running svr) needs to use - different pseudo-op names for these, they may be overridden in the - file which includes this one. */ - -#define TYPE_ASM_OP ".type" -#define SIZE_ASM_OP ".size" - -/* The following macro defines the format used to output the second - operand of the .type assembler directive. Different svr4 assemblers - expect various different forms for this operand. The one given here - is just a default. You may need to override it in your machine- - specific tm.h file (depending upon the particulars of your assembler). */ - -#define TYPE_OPERAND_FMT "@%s" - -/* Write the extra assembler code needed to declare a function's result. - Most svr4 assemblers don't require any special declaration of the - result value, but there are exceptions. */ +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -Dunix -D__ELF__ -D__FreeBSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" -#ifndef ASM_DECLARE_RESULT -#define ASM_DECLARE_RESULT(FILE, RESULT) -#endif +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" -/* These macros generate the special .type and .size directives which - are used to set the corresponding fields of the linker symbol table - entries in an ELF object file under SVR4. These macros also output - the starting labels for the relevant functions/objects. */ - -/* Write the extra assembler code needed to declare a function properly. - Some svr4 assemblers need to also have something extra said about the - function's return value. We allow for that here. */ - -#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ - do { \ - fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc (',', FILE); \ - fprintf (FILE, TYPE_OPERAND_FMT, "function"); \ - putc ('\n', FILE); \ - ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ - ASM_OUTPUT_LABEL(FILE, NAME); \ - } while (0) - -/* Write the extra assembler code needed to declare an object properly. */ - -#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ - do { \ - fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc (',', FILE); \ - fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ - putc ('\n', FILE); \ - size_directive_output = 0; \ - if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \ - { \ - size_directive_output = 1; \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ - } \ - ASM_OUTPUT_LABEL(FILE, NAME); \ - } while (0) - -/* Output the size directive for a decl in rest_of_decl_compilation - in the case where we did not do so before the initializer. - Once we find the error_mark_node, we know that the value of - size_directive_output was set - by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */ - -#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ -do { \ - char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ - if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ - && ! AT_END && TOP_LEVEL \ - && DECL_INITIAL (DECL) == error_mark_node \ - && !size_directive_output) \ - { \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, name); \ - fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL)));\ - } \ - } while (0) - - -/* This is how to declare the size of a function. */ - -#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ - do { \ - if (!flag_inhibit_size_directive) \ - { \ - char label[256]; \ - static int labelno; \ - labelno++; \ - ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \ - ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, (FNAME)); \ - fprintf (FILE, ","); \ - assemble_name (FILE, label); \ - fprintf (FILE, "-"); \ - assemble_name (FILE, (FNAME)); \ - putc ('\n', FILE); \ - } \ - } while (0) - -#define ASM_SPEC " %| %{fpic:-k} %{fPIC:-k}" -#define LINK_SPEC \ - "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*}" - -/* This is defined when gcc is compiled in the BSD-directory-tree, and must - * make up for the gap to all the stuff done in the GNU-makefiles. +#undef LIB_SPEC +#if 1 +/* We no longer link with libc_p.a or libg.a by default. If you + * want to profile or debug the C library, please add + * -lc_p or -ggdb to LDFLAGS at the link time, respectively. */ +#define LIB_SPEC \ + "%{!shared: %{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} \ + %{!ggdb:-lc} %{ggdb:-lg}}" +#else +#define LIB_SPEC \ + "%{!shared: \ + %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" +#endif -#ifdef FREEBSD_NATIVE +/* Provide a LINK_SPEC appropriate for FreeBSD. Here we provide support + for the special GCC options -static and -shared, which allow us to + link things in one of these three modes by applying the appropriate + combinations of options at link-time. We like to support here for + as many of the other GNU linker options as possible. But I don't + have the time to search for those flags. I am sure how to add + support for -soname shared_object_name. H.J. + + I took out %{v:%{!V:-V}}. It is too much :-(. They can use + -Wl,-V. + + When the -shared link option is used a final link is not being + done. */ + +#undef LINK_SPEC +#define LINK_SPEC "-m elf_i386 %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /usr/libexec/ld-elf.so.1}} \ + %{static:-static}}}" -#define INCLUDE_DEFAULTS { \ - { "/usr/include", 0 }, \ - { "/usr/include/g++", 1 }, \ - { 0, 0} \ - } +/* Get perform_* macros to build libgcc.a. */ -#undef MD_EXEC_PREFIX -#define MD_EXEC_PREFIX "/usr/libexec/" +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1< +/* Definitions for Intel 386 running FreeBSD with ELF format + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Eric Youngdale. + Modified for stabs-in-ELF by H.J. Lu. + Adapted from GNU/Linux version by John Polstra. This file is part of GNU CC. @@ -20,231 +21,185 @@ along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* This goes away when the math-emulator is fixed */ -#define TARGET_CPU_DEFAULT 0400 /* TARGET_NO_FANCY_MATH_387 */ +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)"); -/* This is tested by i386gas.h. */ -#define YES_UNDERSCORES - -/* Don't assume anything about the header files. */ -#define NO_IMPLICIT_EXTERN_C - -#include "i386/gstabs.h" - -/* Get perform_* macros to build libgcc.a. */ -#include "i386/perform.h" - -#undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -D__FreeBSD__ -D__386BSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" - -/* Like the default, except no -lg. */ -#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}" - -#undef SIZE_TYPE -#define SIZE_TYPE "unsigned int" - -#undef PTRDIFF_TYPE -#define PTRDIFF_TYPE "int" - -#undef WCHAR_TYPE -#define WCHAR_TYPE "short unsigned int" - -#define WCHAR_UNSIGNED 1 - -#undef WCHAR_TYPE_SIZE -#define WCHAR_TYPE_SIZE 16 - -#define HAVE_ATEXIT - -/* There are conflicting reports about whether this system uses - a different assembler syntax. wilson@cygnus.com says # is right. */ -#undef COMMENT_BEGIN -#define COMMENT_BEGIN "#" - -#undef ASM_APP_ON -#define ASM_APP_ON "#APP\n" +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ +/* On FreeBSD, we do not. */ +#undef DEFAULT_PCC_STRUCT_RETURN +#define DEFAULT_PCC_STRUCT_RETURN 0 -#undef ASM_APP_OFF -#define ASM_APP_OFF "#NO_APP\n" - -/* The following macros are stolen from i386v4.h */ -/* These have to be defined to get PIC code correct */ +/* This gets defined in tm.h->linux.h->svr4.h, and keeps us from using + libraries compiled with the native cc, so undef it. */ +#undef NO_DOLLAR_IN_LABEL /* This is how to output an element of a case-vector that is relative. This is only used for PIC code. See comments by the `casesi' insn in i386.md for an explanation of the expression this outputs. */ - #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) /* Indicate that jump tables go in the text section. This is necessary when compiling PIC code. */ +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) + +/* Copy this from the svr4 specifications... */ +/* Define the register numbers to be used in Dwarf debugging information. + The SVR4 reference port C compiler uses the following register numbers + in its Dwarf output code: + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) \ +((n) == 0 ? 0 \ + : (n) == 1 ? 2 \ + : (n) == 2 ? 1 \ + : (n) == 3 ? 3 \ + : (n) == 4 ? 6 \ + : (n) == 5 ? 7 \ + : (n) == 6 ? 5 \ + : (n) == 7 ? 4 \ + : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ + : (-1)) + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ -#define JUMP_TABLES_IN_TEXT_SECTION - -/* Don't default to pcc-struct-return, because gcc is the only compiler, and - we want to retain compatibility with older gcc versions. */ -#define DEFAULT_PCC_STRUCT_RETURN 0 - -/* Profiling routines, partially copied from i386/osfrose.h. */ - -/* Redefine this to use %eax instead of %edx. */ #undef FUNCTION_PROFILER #define FUNCTION_PROFILER(FILE, LABELNO) \ { \ if (flag_pic) \ { \ - fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%eax\n", \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \ LPREFIX, (LABELNO)); \ fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \ } \ else \ { \ - fprintf (FILE, "\tmovl $%sP%d,%%eax\n", LPREFIX, (LABELNO)); \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO)); \ fprintf (FILE, "\tcall mcount\n"); \ } \ } -/* - * Some imports from svr4.h in support of shared libraries. - * Currently, we need the DECLARE_OBJECT_SIZE stuff. - */ - -/* Define the strings used for the special svr4 .type and .size directives. - These strings generally do not vary from one system running svr4 to - another, but if a given system (e.g. m88k running svr) needs to use - different pseudo-op names for these, they may be overridden in the - file which includes this one. */ - -#define TYPE_ASM_OP ".type" -#define SIZE_ASM_OP ".size" - -/* The following macro defines the format used to output the second - operand of the .type assembler directive. Different svr4 assemblers - expect various different forms for this operand. The one given here - is just a default. You may need to override it in your machine- - specific tm.h file (depending upon the particulars of your assembler). */ - -#define TYPE_OPERAND_FMT "@%s" - -/* Write the extra assembler code needed to declare a function's result. - Most svr4 assemblers don't require any special declaration of the - result value, but there are exceptions. */ +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -Dunix -D__ELF__ -D__FreeBSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)" -#ifndef ASM_DECLARE_RESULT -#define ASM_DECLARE_RESULT(FILE, RESULT) -#endif +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" -/* These macros generate the special .type and .size directives which - are used to set the corresponding fields of the linker symbol table - entries in an ELF object file under SVR4. These macros also output - the starting labels for the relevant functions/objects. */ - -/* Write the extra assembler code needed to declare a function properly. - Some svr4 assemblers need to also have something extra said about the - function's return value. We allow for that here. */ - -#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ - do { \ - fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc (',', FILE); \ - fprintf (FILE, TYPE_OPERAND_FMT, "function"); \ - putc ('\n', FILE); \ - ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ - ASM_OUTPUT_LABEL(FILE, NAME); \ - } while (0) - -/* Write the extra assembler code needed to declare an object properly. */ - -#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ - do { \ - fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \ - assemble_name (FILE, NAME); \ - putc (',', FILE); \ - fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ - putc ('\n', FILE); \ - size_directive_output = 0; \ - if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \ - { \ - size_directive_output = 1; \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, NAME); \ - fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ - } \ - ASM_OUTPUT_LABEL(FILE, NAME); \ - } while (0) - -/* Output the size directive for a decl in rest_of_decl_compilation - in the case where we did not do so before the initializer. - Once we find the error_mark_node, we know that the value of - size_directive_output was set - by ASM_DECLARE_OBJECT_NAME when it was run for the same decl. */ - -#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ -do { \ - char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ - if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ - && ! AT_END && TOP_LEVEL \ - && DECL_INITIAL (DECL) == error_mark_node \ - && !size_directive_output) \ - { \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, name); \ - fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL)));\ - } \ - } while (0) - - -/* This is how to declare the size of a function. */ - -#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ - do { \ - if (!flag_inhibit_size_directive) \ - { \ - char label[256]; \ - static int labelno; \ - labelno++; \ - ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \ - ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \ - fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \ - assemble_name (FILE, (FNAME)); \ - fprintf (FILE, ","); \ - assemble_name (FILE, label); \ - fprintf (FILE, "-"); \ - assemble_name (FILE, (FNAME)); \ - putc ('\n', FILE); \ - } \ - } while (0) - -#define ASM_SPEC " %| %{fpic:-k} %{fPIC:-k}" -#define LINK_SPEC \ - "%{!nostdlib:%{!r*:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} %{assert*}" - -/* This is defined when gcc is compiled in the BSD-directory-tree, and must - * make up for the gap to all the stuff done in the GNU-makefiles. +#undef LIB_SPEC +#if 1 +/* We no longer link with libc_p.a or libg.a by default. If you + * want to profile or debug the C library, please add + * -lc_p or -ggdb to LDFLAGS at the link time, respectively. */ +#define LIB_SPEC \ + "%{!shared: %{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} \ + %{!ggdb:-lc} %{ggdb:-lg}}" +#else +#define LIB_SPEC \ + "%{!shared: \ + %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ + %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" +#endif -#ifdef FREEBSD_NATIVE +/* Provide a LINK_SPEC appropriate for FreeBSD. Here we provide support + for the special GCC options -static and -shared, which allow us to + link things in one of these three modes by applying the appropriate + combinations of options at link-time. We like to support here for + as many of the other GNU linker options as possible. But I don't + have the time to search for those flags. I am sure how to add + support for -soname shared_object_name. H.J. + + I took out %{v:%{!V:-V}}. It is too much :-(. They can use + -Wl,-V. + + When the -shared link option is used a final link is not being + done. */ + +#undef LINK_SPEC +#define LINK_SPEC "-m elf_i386 %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /usr/libexec/ld-elf.so.1}} \ + %{static:-static}}}" -#define INCLUDE_DEFAULTS { \ - { "/usr/include", 0 }, \ - { "/usr/include/g++", 1 }, \ - { 0, 0} \ - } +/* Get perform_* macros to build libgcc.a. */ -#undef MD_EXEC_PREFIX -#define MD_EXEC_PREFIX "/usr/libexec/" +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1<, + * 14/8/96 based on the original gmon.c in GCC and the hacked version + * solaris 2 sparc version (config/sparc/gmon-sol.c) by Mark Eichin. To do + * process profiling on solaris 2.X X86 + * + * It must be used in conjunction with sol2-gc1.asm, which is used to start + * and stop process monitoring. + * + * Differences. + * + * On Solaris 2 _mcount is called by library functions not mcount, so support + * has been added for both. + * + * Also the prototype for profil() is different + * + * Solaris 2 does not seem to have char *minbrk whcih allows the setting of + * the minimum SBRK region so this code has been removed and lets pray malloc + * does not mess it up. + * + * Notes + * + * This code could easily be integrated with the original gmon.c and perhaps + * should be. + */ + +#ifndef lint +static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 5/22/91"; +#endif /* not lint */ + +#if 0 +#include + +#endif +#ifdef DEBUG +#include +#endif + +#if 0 +#include "i386/gmon.h" +#else + +struct phdr { + char *lpc; + char *hpc; + int ncnt; +}; + + +#define HISTFRACTION 2 +#define HISTCOUNTER unsigned short +#define HASHFRACTION 1 +#define ARCDENSITY 2 +#define MINARCS 50 +#define BASEADDRESS 0x8000000 /* On Solaris 2 X86 all executables start here + and not at 0 */ + +struct tostruct { + char *selfpc; + long count; + unsigned short link; +}; +struct rawarc { + unsigned long raw_frompc; + unsigned long raw_selfpc; + long raw_count; +}; +#define ROUNDDOWN(x,y) (((x)/(y))*(y)) +#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y)) +#endif + +/* char *minbrk; */ + +#ifdef __alpha +extern char *sbrk (); +#endif + + /* + * froms is actually a bunch of unsigned shorts indexing tos + */ +static int profiling = 3; +static unsigned short *froms; +static struct tostruct *tos = 0; +static long tolimit = 0; +static char *s_lowpc = 0; +static char *s_highpc = 0; +static unsigned long s_textsize = 0; + +static int ssiz; +static char *sbuf; +static int s_scale; + /* see profil(2) where this is describe (incorrectly) */ +#define SCALE_1_TO_1 0x10000L + +#define MSG "No space for profiling buffer(s)\n" + +extern int errno; + +monstartup(lowpc, highpc) + char *lowpc; + char *highpc; +{ + int monsize; + char *buffer; + register int o; + + /* + * round lowpc and highpc to multiples of the density we're using + * so the rest of the scaling (here and in gprof) stays in ints. + */ + lowpc = (char *) + ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER)); + s_lowpc = lowpc; + highpc = (char *) + ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER)); + s_highpc = highpc; + s_textsize = highpc - lowpc; + monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr); + buffer = (char *) sbrk( monsize ); + if ( buffer == (char *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + return; + } + froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION ); + if ( froms == (unsigned short *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + froms = 0; + return; + } + tolimit = s_textsize * ARCDENSITY / 100; + if ( tolimit < MINARCS ) { + tolimit = MINARCS; + } else if ( tolimit > 65534 ) { + tolimit = 65534; + } + tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) ); + if ( tos == (struct tostruct *) -1 ) { + write( 2 , MSG , sizeof(MSG) ); + froms = 0; + tos = 0; + return; + } +/* minbrk = (char *) sbrk(0);*/ + tos[0].link = 0; + sbuf = buffer; + ssiz = monsize; + ( (struct phdr *) buffer ) -> lpc = lowpc; + ( (struct phdr *) buffer ) -> hpc = highpc; + ( (struct phdr *) buffer ) -> ncnt = ssiz; + monsize -= sizeof(struct phdr); + if ( monsize <= 0 ) + return; + o = highpc - lowpc; + if( monsize < o ) +#ifndef hp300 + s_scale = ( (float) monsize / o ) * SCALE_1_TO_1; +#else /* avoid floating point */ + { + int quot = o / monsize; + + if (quot >= 0x10000) + s_scale = 1; + else if (quot >= 0x100) + s_scale = 0x10000 / quot; + else if (o >= 0x800000) + s_scale = 0x1000000 / (o / (monsize >> 8)); + else + s_scale = 0x1000000 / ((o << 8) / monsize); + } +#endif + else + s_scale = SCALE_1_TO_1; + moncontrol(1); +} + +_mcleanup() +{ + int fd; + int fromindex; + int endfrom; + char *frompc; + int toindex; + struct rawarc rawarc; + + moncontrol(0); + fd = creat( "gmon.out" , 0666 ); + if ( fd < 0 ) { + perror( "mcount: gmon.out" ); + return; + } +# ifdef DEBUG + fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz ); +# endif DEBUG + + write( fd , sbuf , ssiz ); + endfrom = s_textsize / (HASHFRACTION * sizeof(*froms)); + for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) { + if ( froms[fromindex] == 0 ) { + continue; + } + frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms)); + for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) { +# ifdef DEBUG + fprintf( stderr , + "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" , + frompc , tos[toindex].selfpc , tos[toindex].count ); +# endif DEBUG + rawarc.raw_frompc = (unsigned long) frompc; + rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc; + rawarc.raw_count = tos[toindex].count; + write( fd , &rawarc , sizeof rawarc ); + } + } + close( fd ); +} + +/* Solaris 2 libraries use _mcount. */ +asm(".globl _mcount; _mcount: jmp internal_mcount"); +/* This is for compatibility with old versions of gcc which used mcount. */ +asm(".globl mcount; mcount: jmp internal_mcount"); + +internal_mcount() +{ + register char *selfpc; + register unsigned short *frompcindex; + register struct tostruct *top; + register struct tostruct *prevtop; + register long toindex; + static char already_setup; + + /* + * find the return address for mcount, + * and the return address for mcount's caller. + */ + + /* selfpc = pc pushed by mcount call. + This identifies the function that was just entered. */ + selfpc = (void *) __builtin_return_address (0); + /* frompcindex = pc in preceding frame. + This identifies the caller of the function just entered. */ + frompcindex = (void *) __builtin_return_address (1); + + if(!already_setup) { + extern etext(); + already_setup = 1; +/* monstartup(0, etext); */ + monstartup(0x08040000, etext); +#ifdef USE_ONEXIT + on_exit(_mcleanup, 0); +#else + atexit(_mcleanup); +#endif + } + /* + * check that we are profiling + * and that we aren't recursively invoked. + */ + if (profiling) { + goto out; + } + profiling++; + /* + * check that frompcindex is a reasonable pc value. + * for example: signal catchers get called from the stack, + * not from text space. too bad. + */ + frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc); + if ((unsigned long)frompcindex > s_textsize) { + goto done; + } + frompcindex = + &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))]; + toindex = *frompcindex; + if (toindex == 0) { + /* + * first time traversing this arc + */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + *frompcindex = toindex; + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = 0; + goto done; + } + top = &tos[toindex]; + if (top->selfpc == selfpc) { + /* + * arc at front of chain; usual case. + */ + top->count++; + goto done; + } + /* + * have to go looking down chain for it. + * top points to what we are looking at, + * prevtop points to previous top. + * we know it is not at the head of the chain. + */ + for (; /* goto done */; ) { + if (top->link == 0) { + /* + * top is end of the chain and none of the chain + * had top->selfpc == selfpc. + * so we allocate a new tostruct + * and link it to the head of the chain. + */ + toindex = ++tos[0].link; + if (toindex >= tolimit) { + goto overflow; + } + top = &tos[toindex]; + top->selfpc = selfpc; + top->count = 1; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + /* + * otherwise, check the next arc on the chain. + */ + prevtop = top; + top = &tos[top->link]; + if (top->selfpc == selfpc) { + /* + * there it is. + * increment its count + * move it to the head of the chain. + */ + top->count++; + toindex = prevtop->link; + prevtop->link = top->link; + top->link = *frompcindex; + *frompcindex = toindex; + goto done; + } + + } +done: + profiling--; + /* and fall through */ +out: + return; /* normal return restores saved registers */ + +overflow: + profiling++; /* halt further profiling */ +# define TOLIMIT "mcount: tos overflow\n" + write(2, TOLIMIT, sizeof(TOLIMIT)); + goto out; +} + +/* + * Control profiling + * profiling is what mcount checks to see if + * all the data structures are ready. + */ +moncontrol(mode) + int mode; +{ + if (mode) + { + /* start */ + profil((unsigned short *)(sbuf + sizeof(struct phdr)), + ssiz - sizeof(struct phdr), + (int)s_lowpc, s_scale); + + profiling = 0; + } else { + /* stop */ + profil((unsigned short *)0, 0, 0, 0); + profiling = 3; + } +} diff --git a/contrib/gcc/config/i386/gnu.h b/contrib/gcc/config/i386/gnu.h index 1ad5df991e44..971a5f880c27 100644 --- a/contrib/gcc/config/i386/gnu.h +++ b/contrib/gcc/config/i386/gnu.h @@ -4,16 +4,19 @@ #include #undef CPP_PREDEFINES -#define CPP_PREDEFINES GNU_CPP_PREDEFINES("i386") +#define CPP_PREDEFINES "-Di386 -Acpu(i386) -Amachine(i386) \ +-Dunix -Asystem(unix) -DMACH -Asystem(mach) -D__GNU__ -Asystem(gnu)" + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 GNU)"); #undef LINK_SPEC #define LINK_SPEC "-m elf_i386 %{shared:-shared} \ %{!shared: \ - %{!ibcs: \ - %{!static: \ - %{rdynamic:-export-dynamic} \ - %{!dynamic-linker:-dynamic-linker /lib/ld.so} \ - %{!rpath:-rpath /lib/}} %{static:-static}}}" + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld.so}} \ + %{static:-static}}" /* Get machine-independent configuration parameters for the GNU system. */ diff --git a/contrib/gcc/config/i386/go32.h b/contrib/gcc/config/i386/go32.h index 5618a0dd0fba..dd03cc8a75d1 100644 --- a/contrib/gcc/config/i386/go32.h +++ b/contrib/gcc/config/i386/go32.h @@ -1,5 +1,7 @@ /* Configuration for an i386 running MS-DOS with djgpp/go32. */ +#include "dbxcoff.h" + /* Don't assume anything about the header files. */ #define NO_IMPLICIT_EXTERN_C @@ -53,7 +55,13 @@ dtor_section () \ fprintf (FILE, "\n"); \ } while (0) -#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ +/* Allow (eg) __attribute__((section "locked")) to work */ +#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC)\ + do { \ + fprintf (FILE, "\t.section %s\n", NAME); \ + } while (0) + +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ do { \ dtor_section (); \ fprintf (FILE, "%s\t", ASM_LONG); \ @@ -61,4 +69,28 @@ dtor_section () \ fprintf (FILE, "\n"); \ } while (0) +/* Output at beginning of assembler file. */ +/* The .file command should always begin the output. */ +/* Use the main_input_filename instead of dump_base_name */ + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + do { \ + output_file_directive (FILE, main_input_filename); \ + } while (0) + +/* This is how to output an assembler line + that says to advance the location counter + to a multiple of 2**LOG bytes. */ + +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG) != 0) fprintf ((FILE), "\t.p2align %d\n", LOG) + +/* djgpp has atexit (). */ +#undef HAVE_ATEXIT +#define HAVE_ATEXIT +/* djgpp automatically calls its own version of __main, so don't define one + in libgcc, nor call one in main(). */ +#define HAS_INIT_SECTION diff --git a/contrib/gcc/config/i386/i386.c b/contrib/gcc/config/i386/i386.c index 48c58a09d8e5..b2512a02980a 100644 --- a/contrib/gcc/config/i386/i386.c +++ b/contrib/gcc/config/i386/i386.c @@ -1,5 +1,5 @@ /* Subroutines for insn-output.c for Intel X86. - Copyright (C) 1988, 1992, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1988, 92, 94-98, 1999 Free Software Foundation, Inc. This file is part of GNU CC. @@ -16,12 +16,11 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +Boston, MA 02111-1307, USA. */ -#include #include -#include #include "config.h" +#include "system.h" #include "rtl.h" #include "regs.h" #include "hard-reg-set.h" @@ -33,7 +32,11 @@ Boston, MA 02111-1307, USA. */ #include "insn-attr.h" #include "tree.h" #include "flags.h" +#include "except.h" #include "function.h" +#include "recog.h" +#include "expr.h" +#include "toplev.h" #ifdef EXTRA_CONSTRAINT /* If EXTRA_CONSTRAINT is defined, then the 'S' @@ -44,11 +47,69 @@ Boston, MA 02111-1307, USA. */ even if the conditional was untrue. */ #endif -#define AT_BP(mode) (gen_rtx (MEM, (mode), frame_pointer_rtx)) +#ifndef CHECK_STACK_LIMIT +#define CHECK_STACK_LIMIT -1 +#endif + +/* Type of an operand for ix86_{binary,unary}_operator_ok */ +enum reg_mem +{ + reg_p, + mem_p, + imm_p +}; + +/* Processor costs (relative to an add) */ +struct processor_costs i386_cost = { /* 386 specific costs */ + 1, /* cost of an add instruction */ + 1, /* cost of a lea instruction */ + 3, /* variable shift costs */ + 2, /* constant shift costs */ + 6, /* cost of starting a multiply */ + 1, /* cost of multiply per each bit set */ + 23 /* cost of a divide/mod */ +}; + +struct processor_costs i486_cost = { /* 486 specific costs */ + 1, /* cost of an add instruction */ + 1, /* cost of a lea instruction */ + 3, /* variable shift costs */ + 2, /* constant shift costs */ + 12, /* cost of starting a multiply */ + 1, /* cost of multiply per each bit set */ + 40 /* cost of a divide/mod */ +}; + +struct processor_costs pentium_cost = { + 1, /* cost of an add instruction */ + 1, /* cost of a lea instruction */ + 4, /* variable shift costs */ + 1, /* constant shift costs */ + 11, /* cost of starting a multiply */ + 0, /* cost of multiply per each bit set */ + 25 /* cost of a divide/mod */ +}; + +struct processor_costs pentiumpro_cost = { + 1, /* cost of an add instruction */ + 1, /* cost of a lea instruction */ + 3, /* variable shift costs */ + 1, /* constant shift costs */ + 4, /* cost of starting a multiply */ + 0, /* cost of multiply per each bit set */ + 17 /* cost of a divide/mod */ +}; + +struct processor_costs *ix86_cost = &pentium_cost; + +#define AT_BP(mode) (gen_rtx_MEM ((mode), frame_pointer_rtx)) extern FILE *asm_out_file; extern char *strcat (); +static void ix86_epilogue PROTO((int)); +static void ix86_prologue PROTO((int)); + char *singlemove_string (); char *output_move_const_single (); char *output_fp_cc0_set (); @@ -68,7 +129,7 @@ enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] = SIREG, DIREG, INDEX_REGS, GENERAL_REGS, /* FP registers */ FP_TOP_REG, FP_SECOND_REG, FLOAT_REGS, FLOAT_REGS, - FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, + FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, FLOAT_REGS, /* arg pointer */ INDEX_REGS }; @@ -80,24 +141,48 @@ struct rtx_def *i386_compare_op0 = NULL_RTX; struct rtx_def *i386_compare_op1 = NULL_RTX; struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); +/* which cpu are we scheduling for */ +enum processor_type ix86_cpu; + +/* which instruction set architecture to use. */ +int ix86_arch; + +/* Strings to hold which cpu and instruction set architecture to use. */ +char *ix86_cpu_string; /* for -mcpu= */ +char *ix86_arch_string; /* for -march= */ + /* Register allocation order */ char *i386_reg_alloc_order; static char regs_allocated[FIRST_PSEUDO_REGISTER]; /* # of registers to use to pass arguments. */ -char *i386_regparm_string; /* # registers to use to pass args */ -int i386_regparm; /* i386_regparm_string as a number */ +char *i386_regparm_string; -/* Alignment to use for loops and jumps */ -char *i386_align_loops_string; /* power of two alignment for loops */ -char *i386_align_jumps_string; /* power of two alignment for non-loop jumps */ -char *i386_align_funcs_string; /* power of two alignment for functions */ +/* i386_regparm_string as a number */ +int i386_regparm; -int i386_align_loops; /* power of two alignment for loops */ -int i386_align_jumps; /* power of two alignment for non-loop jumps */ -int i386_align_funcs; /* power of two alignment for functions */ +/* Alignment to use for loops and jumps: */ + +/* Power of two alignment for loops. */ +char *i386_align_loops_string; + +/* Power of two alignment for non-loop jumps. */ +char *i386_align_jumps_string; + +/* Values 1-5: see jump.c */ +int i386_branch_cost; +char *i386_branch_cost_string; + +/* Power of two alignment for functions. */ +int i386_align_funcs; +char *i386_align_funcs_string; + +/* Power of two alignment for loops. */ +int i386_align_loops; + +/* Power of two alignment for non-loop jumps. */ +int i386_align_jumps; - /* Sometimes certain combinations of command options do not make sense on a particular target machine. You can define a macro `OVERRIDE_OPTIONS' to take account of this. This macro, if @@ -110,19 +195,39 @@ int i386_align_funcs; /* power of two alignment for functions */ void override_options () { - int ch, i, regno; - char *p; + int ch, i, j; int def_align; + static struct ptt + { + char *name; /* Canonical processor name. */ + enum processor_type processor; /* Processor type enum value. */ + struct processor_costs *cost; /* Processor costs */ + int target_enable; /* Target flags to enable. */ + int target_disable; /* Target flags to disable. */ + } processor_target_table[] + = {{PROCESSOR_I386_STRING, PROCESSOR_I386, &i386_cost, 0, 0}, + {PROCESSOR_I486_STRING, PROCESSOR_I486, &i486_cost, 0, 0}, + {PROCESSOR_I586_STRING, PROCESSOR_PENTIUM, &pentium_cost, 0, 0}, + {PROCESSOR_PENTIUM_STRING, PROCESSOR_PENTIUM, &pentium_cost, 0, 0}, + {PROCESSOR_I686_STRING, PROCESSOR_PENTIUMPRO, &pentiumpro_cost, + 0, 0}, + {PROCESSOR_PENTIUMPRO_STRING, PROCESSOR_PENTIUMPRO, + &pentiumpro_cost, 0, 0}}; + + int ptt_size = sizeof (processor_target_table) / sizeof (struct ptt); + #ifdef SUBTARGET_OVERRIDE_OPTIONS SUBTARGET_OVERRIDE_OPTIONS; #endif - /* Validate registers in register allocation order */ + /* Validate registers in register allocation order. */ if (i386_reg_alloc_order) { for (i = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++) { + int regno = 0; + switch (ch) { case 'a': regno = 0; break; @@ -137,23 +242,75 @@ override_options () } if (regs_allocated[regno]) - fatal ("Register '%c' was already specified in the allocation order", ch); + fatal ("Register '%c' already specified in allocation order", ch); regs_allocated[regno] = 1; } } - /* Validate -mregparm= value */ + if (ix86_arch_string == 0) + { + ix86_arch_string = PROCESSOR_PENTIUM_STRING; + if (ix86_cpu_string == 0) + ix86_cpu_string = PROCESSOR_DEFAULT_STRING; + } + + for (i = 0; i < ptt_size; i++) + if (! strcmp (ix86_arch_string, processor_target_table[i].name)) + { + ix86_arch = processor_target_table[i].processor; + if (ix86_cpu_string == 0) + ix86_cpu_string = processor_target_table[i].name; + break; + } + + if (i == ptt_size) + { + error ("bad value (%s) for -march= switch", ix86_arch_string); + ix86_arch_string = PROCESSOR_PENTIUM_STRING; + ix86_arch = PROCESSOR_DEFAULT; + } + + if (ix86_cpu_string == 0) + ix86_cpu_string = PROCESSOR_DEFAULT_STRING; + + for (j = 0; j < ptt_size; j++) + if (! strcmp (ix86_cpu_string, processor_target_table[j].name)) + { + ix86_cpu = processor_target_table[j].processor; + ix86_cost = processor_target_table[j].cost; + if (i > j && (int) ix86_arch >= (int) PROCESSOR_PENTIUMPRO) + error ("-mcpu=%s does not support -march=%s", + ix86_cpu_string, ix86_arch_string); + + target_flags |= processor_target_table[j].target_enable; + target_flags &= ~processor_target_table[j].target_disable; + break; + } + + if (j == ptt_size) + { + error ("bad value (%s) for -mcpu= switch", ix86_cpu_string); + ix86_cpu_string = PROCESSOR_DEFAULT_STRING; + ix86_cpu = PROCESSOR_DEFAULT; + } + + /* Validate -mregparm= value. */ if (i386_regparm_string) { i386_regparm = atoi (i386_regparm_string); if (i386_regparm < 0 || i386_regparm > REGPARM_MAX) - fatal ("-mregparm=%d is not between 0 and %d", i386_regparm, REGPARM_MAX); + fatal ("-mregparm=%d is not between 0 and %d", + i386_regparm, REGPARM_MAX); } - def_align = (TARGET_386) ? 2 : 4; + /* The 486 suffers more from non-aligned cache line fills, and the + larger code size results in a larger cache foot-print and more misses. + The 486 has a 16 byte cache line, pentium and pentiumpro have a 32 byte + cache line. */ + def_align = (TARGET_486) ? 4 : 2; - /* Validate -malign-loops= value, or provide default */ + /* Validate -malign-loops= value, or provide default. */ if (i386_align_loops_string) { i386_align_loops = atoi (i386_align_loops_string); @@ -162,9 +319,13 @@ override_options () i386_align_loops, MAX_CODE_ALIGN); } else +#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN + i386_align_loops = 4; +#else i386_align_loops = 2; +#endif - /* Validate -malign-jumps= value, or provide default */ + /* Validate -malign-jumps= value, or provide default. */ if (i386_align_jumps_string) { i386_align_jumps = atoi (i386_align_jumps_string); @@ -173,9 +334,13 @@ override_options () i386_align_jumps, MAX_CODE_ALIGN); } else +#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN + i386_align_jumps = 4; +#else i386_align_jumps = def_align; +#endif - /* Validate -malign-functions= value, or provide default */ + /* Validate -malign-functions= value, or provide default. */ if (i386_align_funcs_string) { i386_align_funcs = atoi (i386_align_funcs_string); @@ -185,6 +350,21 @@ override_options () } else i386_align_funcs = def_align; + + /* Validate -mbranch-cost= value, or provide default. */ + if (i386_branch_cost_string) + { + i386_branch_cost = atoi (i386_branch_cost_string); + if (i386_branch_cost < 0 || i386_branch_cost > 5) + fatal ("-mbranch-cost=%d is not between 0 and 5", + i386_branch_cost); + } + else + i386_branch_cost = 1; + + /* Keep nonleaf frame pointers. */ + if (TARGET_OMIT_LEAF_FRAME_POINTER) + flag_omit_frame_pointer = 1; } /* A C statement (sans semicolon) to choose the order in which to @@ -203,13 +383,16 @@ override_options () void order_regs_for_local_alloc () { - int i, ch, order, regno; + int i, ch, order; + + /* User specified the register allocation order. */ - /* User specified the register allocation order */ if (i386_reg_alloc_order) { for (i = order = 0; (ch = i386_reg_alloc_order[i]) != '\0'; i++) { + int regno = 0; + switch (ch) { case 'a': regno = 0; break; @@ -226,59 +409,116 @@ order_regs_for_local_alloc () for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { - if (!regs_allocated[i]) + if (! regs_allocated[i]) reg_alloc_order[order++] = i; } } - /* If users did not specify a register allocation order, favor eax - normally except if DImode variables are used, in which case - favor edx before eax, which seems to cause less spill register - not found messages. */ + /* If user did not specify a register allocation order, use natural order. */ else { - rtx insn; - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) reg_alloc_order[i] = i; + } +} + +void +optimization_options (level, size) + int level; + int size ATTRIBUTE_UNUSED; +{ + /* For -O2 and beyond, turn off -fschedule-insns by default. It tends to + make the problem with not enough registers even worse. */ +#ifdef INSN_SCHEDULING + if (level > 1) + flag_schedule_insns = 0; +#endif +} + +/* Sign-extend a 16-bit constant */ - if (optimize) - { - int use_dca = FALSE; +struct rtx_def * +i386_sext16_if_const (op) + struct rtx_def *op; +{ + if (GET_CODE (op) == CONST_INT) + { + HOST_WIDE_INT val = INTVAL (op); + HOST_WIDE_INT sext_val; + if (val & 0x8000) + sext_val = val | ~0xffff; + else + sext_val = val & 0xffff; + if (sext_val != val) + op = GEN_INT (sext_val); + } + return op; +} + +/* Return nonzero if the rtx is aligned */ - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - { - if (GET_CODE (insn) == INSN) - { - rtx set = NULL_RTX; - rtx pattern = PATTERN (insn); - - if (GET_CODE (pattern) == SET) - set = pattern; - - else if ((GET_CODE (pattern) == PARALLEL - || GET_CODE (pattern) == SEQUENCE) - && GET_CODE (XVECEXP (pattern, 0, 0)) == SET) - set = XVECEXP (pattern, 0, 0); - - if (set && GET_MODE (SET_SRC (set)) == DImode) - { - use_dca = TRUE; - break; - } - } - } +static int +i386_aligned_reg_p (regno) + int regno; +{ + return (regno == STACK_POINTER_REGNUM + || (! flag_omit_frame_pointer && regno == FRAME_POINTER_REGNUM)); +} - if (use_dca) - { - reg_alloc_order[0] = 1; /* edx */ - reg_alloc_order[1] = 2; /* ecx */ - reg_alloc_order[2] = 0; /* eax */ - } - } +int +i386_aligned_p (op) + rtx op; +{ + /* Registers and immediate operands are always "aligned". */ + if (GET_CODE (op) != MEM) + return 1; + + /* Don't even try to do any aligned optimizations with volatiles. */ + if (MEM_VOLATILE_P (op)) + return 0; + + /* Get address of memory operand. */ + op = XEXP (op, 0); + + switch (GET_CODE (op)) + { + case CONST_INT: + if (INTVAL (op) & 3) + break; + return 1; + + /* Match "reg + offset" */ + case PLUS: + if (GET_CODE (XEXP (op, 1)) != CONST_INT) + break; + if (INTVAL (XEXP (op, 1)) & 3) + break; + + op = XEXP (op, 0); + if (GET_CODE (op) != REG) + break; + + /* ... fall through ... */ + + case REG: + return i386_aligned_reg_p (REGNO (op)); + + default: + break; } + + return 0; } + +/* Return nonzero if INSN looks like it won't compute useful cc bits + as a side effect. This information is only a hint. */ +int +i386_cc_probably_useless_p (insn) + rtx insn; +{ + return ! next_cc0_user (insn); +} /* Return nonzero if IDENTIFIER with arguments ARGS is a valid machine specific attribute for DECL. The attributes in ATTRIBUTES have previously been @@ -286,10 +526,10 @@ order_regs_for_local_alloc () int i386_valid_decl_attribute_p (decl, attributes, identifier, args) - tree decl; - tree attributes; - tree identifier; - tree args; + tree decl ATTRIBUTE_UNUSED; + tree attributes ATTRIBUTE_UNUSED; + tree identifier ATTRIBUTE_UNUSED; + tree args ATTRIBUTE_UNUSED; { return 0; } @@ -301,11 +541,12 @@ i386_valid_decl_attribute_p (decl, attributes, identifier, args) int i386_valid_type_attribute_p (type, attributes, identifier, args) tree type; - tree attributes; + tree attributes ATTRIBUTE_UNUSED; tree identifier; tree args; { if (TREE_CODE (type) != FUNCTION_TYPE + && TREE_CODE (type) != METHOD_TYPE && TREE_CODE (type) != FIELD_DECL && TREE_CODE (type) != TYPE_DECL) return 0; @@ -315,17 +556,17 @@ i386_valid_type_attribute_p (type, attributes, identifier, args) if (is_attribute_p ("stdcall", identifier)) return (args == NULL_TREE); - /* Cdecl attribute says the callee is a normal C declaration */ + /* Cdecl attribute says the callee is a normal C declaration. */ if (is_attribute_p ("cdecl", identifier)) return (args == NULL_TREE); /* Regparm attribute specifies how many integer arguments are to be - passed in registers */ + passed in registers. */ if (is_attribute_p ("regparm", identifier)) { tree cst; - if (!args || TREE_CODE (args) != TREE_LIST + if (! args || TREE_CODE (args) != TREE_LIST || TREE_CHAIN (args) != NULL_TREE || TREE_VALUE (args) == NULL_TREE) return 0; @@ -351,8 +592,8 @@ i386_valid_type_attribute_p (type, attributes, identifier, args) int i386_comp_type_attributes (type1, type2) - tree type1; - tree type2; + tree type1 ATTRIBUTE_UNUSED; + tree type2 ATTRIBUTE_UNUSED; { return 1; } @@ -381,30 +622,27 @@ i386_return_pops_args (fundecl, funtype, size) tree funtype; int size; { - int rtd = TARGET_RTD; + int rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE); - if (TREE_CODE (funtype) == IDENTIFIER_NODE) - return 0; - - /* Cdecl functions override -mrtd, and never pop the stack */ - if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) - return 0; + /* Cdecl functions override -mrtd, and never pop the stack. */ + if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) { - /* Stdcall functions will pop the stack if not variable args */ - if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))) - rtd = 1; + /* Stdcall functions will pop the stack if not variable args. */ + if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))) + rtd = 1; - if (rtd) - { - if (TYPE_ARG_TYPES (funtype) == NULL_TREE - || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node)) - return size; + if (rtd + && (TYPE_ARG_TYPES (funtype) == NULL_TREE + || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) + == void_type_node))) + return size; + } - if (aggregate_value_p (TREE_TYPE (funtype))) - return GET_MODE_SIZE (Pmode); - } + /* Lose any fake structure return argument. */ + if (aggregate_value_p (TREE_TYPE (funtype))) + return GET_MODE_SIZE (Pmode); - return 0; + return 0; } @@ -416,7 +654,7 @@ i386_return_pops_args (fundecl, funtype, size) void init_cumulative_args (cum, fntype, libname) - CUMULATIVE_ARGS *cum; /* argument info to initialize */ + CUMULATIVE_ARGS *cum; /* Argument info to initialize */ tree fntype; /* tree ptr for function decl */ rtx libname; /* SYMBOL_REF of library name or 0 */ { @@ -427,12 +665,9 @@ init_cumulative_args (cum, fntype, libname) { fprintf (stderr, "\ninit_cumulative_args ("); if (fntype) - { - tree ret_type = TREE_TYPE (fntype); - fprintf (stderr, "fntype code = %s, ret code = %s", - tree_code_name[ (int)TREE_CODE (fntype) ], - tree_code_name[ (int)TREE_CODE (ret_type) ]); - } + fprintf (stderr, "fntype code = %s, ret code = %s", + tree_code_name[(int) TREE_CODE (fntype)], + tree_code_name[(int) TREE_CODE (TREE_TYPE (fntype))]); else fprintf (stderr, "no fntype"); @@ -447,6 +682,7 @@ init_cumulative_args (cum, fntype, libname) if (fntype) { tree attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (fntype)); + if (attr) cum->nregs = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))); } @@ -459,11 +695,10 @@ init_cumulative_args (cum, fntype, libname) if (cum->nregs) { for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0; - param != (tree)0; - param = next_param) + param != 0; param = next_param) { next_param = TREE_CHAIN (param); - if (next_param == (tree)0 && TREE_VALUE (param) != void_type_node) + if (next_param == 0 && TREE_VALUE (param) != void_type_node) cum->nregs = 0; } } @@ -485,12 +720,13 @@ function_arg_advance (cum, mode, type, named) tree type; /* type of the argument or 0 if lib support */ int named; /* whether or not the argument was named */ { - int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); + int bytes + = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; if (TARGET_DEBUG_ARG) fprintf (stderr, - "function_adv( size=%d, words=%2d, nregs=%d, mode=%4s, named=%d )\n\n", + "function_adv (sz=%d, wds=%2d, nregs=%d, mode=%s, named=%d)\n\n", words, cum->words, cum->nregs, GET_MODE_NAME (mode), named); cum->words += words; @@ -527,12 +763,14 @@ function_arg (cum, mode, type, named) int named; /* != 0 for normal args, == 0 for ... args */ { rtx ret = NULL_RTX; - int bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); + int bytes + = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; switch (mode) { - default: /* for now, pass fp/complex values on the stack */ + /* For now, pass fp/complex values on the stack. */ + default: break; case BLKmode: @@ -541,14 +779,14 @@ function_arg (cum, mode, type, named) case HImode: case QImode: if (words <= cum->nregs) - ret = gen_rtx (REG, mode, cum->regno); + ret = gen_rtx_REG (mode, cum->regno); break; } if (TARGET_DEBUG_ARG) { fprintf (stderr, - "function_arg( size=%d, words=%2d, nregs=%d, mode=%4s, named=%d", + "function_arg (size=%d, wds=%2d, nregs=%d, mode=%4s, named=%d", words, cum->words, cum->nregs, GET_MODE_NAME (mode), named); if (ret) @@ -568,14 +806,13 @@ function_arg (cum, mode, type, named) int function_arg_partial_nregs (cum, mode, type, named) - CUMULATIVE_ARGS *cum; /* current arg information */ - enum machine_mode mode; /* current arg mode */ - tree type; /* type of the argument or 0 if lib support */ - int named; /* != 0 for normal args, == 0 for ... args */ + CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED; /* current arg information */ + enum machine_mode mode ATTRIBUTE_UNUSED; /* current arg mode */ + tree type ATTRIBUTE_UNUSED; /* type of the argument or 0 if lib support */ + int named ATTRIBUTE_UNUSED; /* != 0 for normal args, == 0 for ... args */ { return 0; } - /* Output an insn whose source is a 386 integer register. SRC is the rtx for the register, and TEMPLATE is the op-code template. SRC may @@ -609,18 +846,19 @@ output_op_from_reg (src, template) if (size > UNITS_PER_WORD) { rtx high; + if (size > 2 * UNITS_PER_WORD) { - high = gen_rtx (REG, SImode, REGNO (src) + 2); + high = gen_rtx_REG (SImode, REGNO (src) + 2); output_asm_insn (AS1 (push%L0,%0), &high); } - high = gen_rtx (REG, SImode, REGNO (src) + 1); + + high = gen_rtx_REG (SImode, REGNO (src) + 1); output_asm_insn (AS1 (push%L0,%0), &high); } - output_asm_insn (AS1 (push%L0,%0), &src); + output_asm_insn (AS1 (push%L0,%0), &src); output_asm_insn (template, xops); - output_asm_insn (AS2 (add%L3,%2,%3), xops); } @@ -630,27 +868,45 @@ output_op_from_reg (src, template) otherwise a `fst' float store is done. */ void -output_to_reg (dest, dies) +output_to_reg (dest, dies, scratch_mem) rtx dest; int dies; + rtx scratch_mem; { rtx xops[4]; int size = GET_MODE_SIZE (GET_MODE (dest)); - xops[0] = AT_SP (Pmode); + if (! scratch_mem) + xops[0] = AT_SP (Pmode); + else + xops[0] = scratch_mem; + xops[1] = stack_pointer_rtx; xops[2] = GEN_INT (size); xops[3] = dest; - output_asm_insn (AS2 (sub%L1,%2,%1), xops); + if (! scratch_mem) + output_asm_insn (AS2 (sub%L1,%2,%1), xops); if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_INT) { if (dies) output_asm_insn (AS1 (fistp%z3,%y0), xops); + else if (GET_MODE (xops[3]) == DImode && ! dies) + { + /* There is no DImode version of this without a stack pop, so + we must emulate it. It doesn't matter much what the second + instruction is, because the value being pushed on the FP stack + is not used except for the following stack popping store. + This case can only happen without optimization, so it doesn't + matter that it is inefficient. */ + output_asm_insn (AS1 (fistp%z3,%0), xops); + output_asm_insn (AS1 (fild%z3,%0), xops); + } else output_asm_insn (AS1 (fist%z3,%y0), xops); } + else if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_FLOAT) { if (dies) @@ -666,19 +922,38 @@ output_to_reg (dest, dies) output_asm_insn (AS1 (fst%z3,%y0), xops); } } + else abort (); - output_asm_insn (AS1 (pop%L0,%0), &dest); + if (! scratch_mem) + output_asm_insn (AS1 (pop%L0,%0), &dest); + else + output_asm_insn (AS2 (mov%L0,%0,%3), xops); + if (size > UNITS_PER_WORD) { - dest = gen_rtx (REG, SImode, REGNO (dest) + 1); - output_asm_insn (AS1 (pop%L0,%0), &dest); + dest = gen_rtx_REG (SImode, REGNO (dest) + 1); + if (! scratch_mem) + output_asm_insn (AS1 (pop%L0,%0), &dest); + else + { + xops[0] = adj_offsettable_operand (xops[0], 4); + xops[3] = dest; + output_asm_insn (AS2 (mov%L0,%0,%3), xops); + } + if (size > 2 * UNITS_PER_WORD) { - dest = gen_rtx (REG, SImode, REGNO (dest) + 1); - output_asm_insn (AS1 (pop%L0,%0), &dest); + dest = gen_rtx_REG (SImode, REGNO (dest) + 1); + if (! scratch_mem) + output_asm_insn (AS1 (pop%L0,%0), &dest); + else + { + xops[0] = adj_offsettable_operand (xops[0], 4); + output_asm_insn (AS2 (mov%L0,%0,%3), xops); + } } } } @@ -696,9 +971,7 @@ singlemove_string (operands) return "push%L1 %1"; } else if (GET_CODE (operands[1]) == CONST_DOUBLE) - { - return output_move_const_single (operands); - } + return output_move_const_single (operands); else if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == REG) return AS2 (mov%L0,%1,%0); else if (CONSTANT_P (operands[1])) @@ -730,11 +1003,11 @@ find_addr_reg (addr) else abort (); } + if (GET_CODE (addr) == REG) return addr; abort (); } - /* Output an insn to add the constant N to the register X. */ @@ -750,7 +1023,7 @@ asm_add (n, x) output_asm_insn (AS1 (dec%L0,%0), xops); else if (n == 1) output_asm_insn (AS1 (inc%L0,%0), xops); - else if (n < 0) + else if (n < 0 || n == 128) { xops[1] = GEN_INT (-n); output_asm_insn (AS2 (sub%L0,%1,%0), xops); @@ -761,7 +1034,6 @@ asm_add (n, x) output_asm_insn (AS2 (add%L0,%1,%0), xops); } } - /* Output assembler code to perform a doubleword move insn with operands OPERANDS. */ @@ -828,11 +1100,11 @@ output_move_double (operands) operands[0] = XEXP (XEXP (operands[0], 0), 0); asm_add (-size, operands[0]); if (GET_MODE (operands[1]) == XFmode) - operands[0] = gen_rtx (MEM, XFmode, operands[0]); + operands[0] = gen_rtx_MEM (XFmode, operands[0]); else if (GET_MODE (operands[0]) == DFmode) - operands[0] = gen_rtx (MEM, DFmode, operands[0]); + operands[0] = gen_rtx_MEM (DFmode, operands[0]); else - operands[0] = gen_rtx (MEM, DImode, operands[0]); + operands[0] = gen_rtx_MEM (DImode, operands[0]); optype0 = OFFSOP; } @@ -842,11 +1114,11 @@ output_move_double (operands) operands[1] = XEXP (XEXP (operands[1], 0), 0); asm_add (-size, operands[1]); if (GET_MODE (operands[1]) == XFmode) - operands[1] = gen_rtx (MEM, XFmode, operands[1]); + operands[1] = gen_rtx_MEM (XFmode, operands[1]); else if (GET_MODE (operands[1]) == DFmode) - operands[1] = gen_rtx (MEM, DFmode, operands[1]); + operands[1] = gen_rtx_MEM (DFmode, operands[1]); else - operands[1] = gen_rtx (MEM, DImode, operands[1]); + operands[1] = gen_rtx_MEM (DImode, operands[1]); optype1 = OFFSOP; } @@ -872,8 +1144,8 @@ output_move_double (operands) { if (optype0 == REGOP) { - middlehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2); + middlehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); + latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 2); } else if (optype0 == OFFSOP) { @@ -885,11 +1157,11 @@ output_move_double (operands) middlehalf[0] = operands[0]; latehalf[0] = operands[0]; } - + if (optype1 == REGOP) { - middlehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2); + middlehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); + latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 2); } else if (optype1 == OFFSOP) { @@ -918,17 +1190,20 @@ output_move_double (operands) latehalf[1] = operands[1]; } } - else /* size is not 12: */ + + else { + /* Size is not 12. */ + if (optype0 == REGOP) - latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + latehalf[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); else if (optype0 == OFFSOP) latehalf[0] = adj_offsettable_operand (operands[0], 4); else latehalf[0] = operands[0]; if (optype1 == REGOP) - latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); + latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); else if (optype1 == OFFSOP) latehalf[1] = adj_offsettable_operand (operands[1], 4); else if (optype1 == CNSTOP) @@ -960,34 +1235,34 @@ output_move_double (operands) { /* If both halves of dest are used in the src memory address, compute the address into latehalf of dest. */ -compadr: + compadr: xops[0] = latehalf[0]; xops[1] = XEXP (operands[1], 0); output_asm_insn (AS2 (lea%L0,%a1,%0), xops); - if( GET_MODE (operands[1]) == XFmode ) + if (GET_MODE (operands[1]) == XFmode) { -/* abort (); */ - operands[1] = gen_rtx (MEM, XFmode, latehalf[0]); + operands[1] = gen_rtx_MEM (XFmode, latehalf[0]); middlehalf[1] = adj_offsettable_operand (operands[1], size-8); latehalf[1] = adj_offsettable_operand (operands[1], size-4); } else { - operands[1] = gen_rtx (MEM, DImode, latehalf[0]); + operands[1] = gen_rtx_MEM (DImode, latehalf[0]); latehalf[1] = adj_offsettable_operand (operands[1], size-4); } } + else if (size == 12 && reg_mentioned_p (middlehalf[0], XEXP (operands[1], 0))) { /* Check for two regs used by both source and dest. */ if (reg_mentioned_p (operands[0], XEXP (operands[1], 0)) || reg_mentioned_p (latehalf[0], XEXP (operands[1], 0))) - goto compadr; + goto compadr; /* JRV says this can't happen: */ if (addreg0 || addreg1) - abort(); + abort (); /* Only the middle reg conflicts; simply put it last. */ output_asm_insn (singlemove_string (operands), operands); @@ -995,6 +1270,7 @@ compadr: output_asm_insn (singlemove_string (middlehalf), middlehalf); return ""; } + else if (reg_mentioned_p (operands[0], XEXP (operands[1], 0))) /* If the low half of dest is mentioned in the source memory address, the arrange to emit the move late half first. */ @@ -1009,12 +1285,13 @@ compadr: such overlap can't happen in memory unless the user explicitly sets it up, and that is an undefined circumstance. */ -/* +#if 0 if (optype0 == PUSHOP || optype1 == PUSHOP || (optype0 == REGOP && optype1 == REGOP && REGNO (operands[0]) == REGNO (latehalf[1])) || dest_overlapped_low) -*/ +#endif + if (optype0 == PUSHOP || optype1 == PUSHOP || (optype0 == REGOP && optype1 == REGOP && ((middlehalf[1] && REGNO (operands[0]) == REGNO (middlehalf[1])) @@ -1032,17 +1309,17 @@ compadr: /* Undo the adds we just did. */ if (addreg0) - asm_add (-4, addreg0); + asm_add (-4, addreg0); if (addreg1) asm_add (-4, addreg1); if (size == 12) { - output_asm_insn (singlemove_string (middlehalf), middlehalf); - if (addreg0) - asm_add (-4, addreg0); - if (addreg1) - asm_add (-4, addreg1); + output_asm_insn (singlemove_string (middlehalf), middlehalf); + if (addreg0) + asm_add (-4, addreg0); + if (addreg1) + asm_add (-4, addreg1); } /* Do low-numbered word. */ @@ -1081,7 +1358,6 @@ compadr: return ""; } - #define MAX_TMPS 2 /* max temporary registers used */ @@ -1095,12 +1371,12 @@ output_move_pushmem (operands, insn, length, tmp_start, n_operands) int tmp_start; int n_operands; { - - struct { - char *load; - char *push; - rtx xops[2]; - } tmp_info[MAX_TMPS]; + struct + { + char *load; + char *push; + rtx xops[2]; + } tmp_info[MAX_TMPS]; rtx src = operands[1]; int max_tmps = 0; @@ -1110,7 +1386,7 @@ output_move_pushmem (operands, insn, length, tmp_start, n_operands) int i, num_tmps; rtx xops[1]; - if (!offsettable_memref_p (src)) + if (! offsettable_memref_p (src)) fatal_insn ("Source is not offsettable", insn); if ((length & 3) != 0) @@ -1146,7 +1422,8 @@ output_move_pushmem (operands, insn, length, tmp_start, n_operands) { tmp_info[num_tmps].load = AS2(mov%L0,%0,%1); tmp_info[num_tmps].push = AS1(push%L0,%1); - tmp_info[num_tmps].xops[0] = adj_offsettable_operand (src, offset + stack_offset); + tmp_info[num_tmps].xops[0] + = adj_offsettable_operand (src, offset + stack_offset); offset -= 4; } @@ -1162,9 +1439,7 @@ output_move_pushmem (operands, insn, length, tmp_start, n_operands) return ""; } - - /* Output the appropriate code to move data between two memory locations */ char * @@ -1175,11 +1450,12 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) int tmp_start; int n_operands; { - struct { - char *load; - char *store; - rtx xops[3]; - } tmp_info[MAX_TMPS]; + struct + { + char *load; + char *store; + rtx xops[3]; + } tmp_info[MAX_TMPS]; rtx dest = operands[0]; rtx src = operands[1]; @@ -1194,10 +1470,10 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx) return output_move_pushmem (operands, insn, length, tmp_start, n_operands); - if (!offsettable_memref_p (src)) + if (! offsettable_memref_p (src)) fatal_insn ("Source is not offsettable", insn); - if (!offsettable_memref_p (dest)) + if (! offsettable_memref_p (dest)) fatal_insn ("Destination is not offsettable", insn); /* Figure out which temporary registers we have available */ @@ -1205,7 +1481,7 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) { if (GET_CODE (operands[i]) == REG) { - if ((length & 1) != 0 && !qi_tmp && QI_REG_P (operands[i])) + if ((length & 1) != 0 && qi_tmp == 0 && QI_REG_P (operands[i])) qi_tmp = operands[i]; if (reg_overlap_mentioned_p (operands[i], dest)) @@ -1214,19 +1490,21 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) if (reg_overlap_mentioned_p (operands[i], src)) fatal_insn ("Temporary register overlaps the source", insn); - tmp_info[ max_tmps++ ].xops[2] = operands[i]; + tmp_info[max_tmps++].xops[2] = operands[i]; if (max_tmps == MAX_TMPS) break; } } if (max_tmps == 0) - fatal_insn ("No scratch registers were found to do memory->memory moves", insn); + fatal_insn ("No scratch registers were found to do memory->memory moves", + insn); if ((length & 1) != 0) { - if (!qi_tmp) - fatal_insn ("No byte register found when moving odd # of bytes.", insn); + if (qi_tmp == 0) + fatal_insn ("No byte register found when moving odd # of bytes.", + insn); } while (length > 1) @@ -1237,17 +1515,24 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) { tmp_info[num_tmps].load = AS2(mov%L0,%1,%2); tmp_info[num_tmps].store = AS2(mov%L0,%2,%0); - tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset); - tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset); + tmp_info[num_tmps].xops[0] + = adj_offsettable_operand (dest, offset); + tmp_info[num_tmps].xops[1] + = adj_offsettable_operand (src, offset); + offset += 4; length -= 4; } + else if (length >= 2) { tmp_info[num_tmps].load = AS2(mov%W0,%1,%2); tmp_info[num_tmps].store = AS2(mov%W0,%2,%0); - tmp_info[num_tmps].xops[0] = adj_offsettable_operand (dest, offset); - tmp_info[num_tmps].xops[1] = adj_offsettable_operand (src, offset); + tmp_info[num_tmps].xops[0] + = adj_offsettable_operand (dest, offset); + tmp_info[num_tmps].xops[1] + = adj_offsettable_operand (src, offset); + offset += 2; length -= 2; } @@ -1273,7 +1558,6 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) return ""; } - int standard_80387_constant_p (x) @@ -1289,7 +1573,7 @@ standard_80387_constant_p (x) set_float_handler (handler); REAL_VALUE_FROM_CONST_DOUBLE (d, x); - is0 = REAL_VALUES_EQUAL (d, dconst0); + is0 = REAL_VALUES_EQUAL (d, dconst0) && !REAL_VALUE_MINUS_ZERO (d); is1 = REAL_VALUES_EQUAL (d, dconst1); set_float_handler (NULL_PTR); @@ -1321,6 +1605,7 @@ output_move_const_single (operands) if (conval == 2) return "fld1"; } + if (GET_CODE (operands[1]) == CONST_DOUBLE) { REAL_VALUE_TYPE r; long l; @@ -1332,6 +1617,7 @@ output_move_const_single (operands) REAL_VALUE_TO_TARGET_SINGLE (r, l); operands[1] = GEN_INT (l); } + return singlemove_string (operands); } @@ -1341,18 +1627,20 @@ output_move_const_single (operands) int symbolic_operand (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { switch (GET_CODE (op)) { case SYMBOL_REF: case LABEL_REF: return 1; + case CONST: op = XEXP (op, 0); return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF || GET_CODE (XEXP (op, 0)) == LABEL_REF) && GET_CODE (XEXP (op, 1)) == CONST_INT); + default: return 0; } @@ -1366,7 +1654,7 @@ symbolic_operand (op, mode) int call_insn_operand (op, mode) rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) == MEM && ((CONSTANT_ADDRESS_P (XEXP (op, 0)) @@ -1374,9 +1662,10 @@ call_insn_operand (op, mode) && general_operand (XEXP (op, 0), Pmode)) || (GET_CODE (XEXP (op, 0)) == REG && XEXP (op, 0) != arg_pointer_rtx - && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER - && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER)))) + && ! (REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER + && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER)))) return 1; + return 0; } @@ -1386,15 +1675,16 @@ call_insn_operand (op, mode) int expander_call_insn_operand (op, mode) rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { if (GET_CODE (op) == MEM && (CONSTANT_ADDRESS_P (XEXP (op, 0)) || (GET_CODE (XEXP (op, 0)) == REG && XEXP (op, 0) != arg_pointer_rtx - && !(REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER - && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER)))) + && ! (REGNO (XEXP (op, 0)) >= FIRST_PSEUDO_REGISTER + && REGNO (XEXP (op, 0)) <= LAST_VIRTUAL_REGISTER)))) return 1; + return 0; } @@ -1410,12 +1700,22 @@ arithmetic_comparison_operator (op, mode) if (mode != VOIDmode && mode != GET_MODE (op)) return 0; + code = GET_CODE (op); if (GET_RTX_CLASS (code) != '<') return 0; return (code != GT && code != LE); } + +int +ix86_logical_operator (op, mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR; +} + /* Returns 1 if OP contains a symbol reference */ @@ -1440,6 +1740,7 @@ symbolic_reference_mentioned_p (op) if (symbolic_reference_mentioned_p (XVECEXP (op, i, j))) return 1; } + else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i))) return 1; } @@ -1447,89 +1748,477 @@ symbolic_reference_mentioned_p (op) return 0; } -/* This function generates the assembly code for function entry. - FILE is an stdio stream to output the code to. - SIZE is an int: how many units of temporary storage to allocate. */ +/* Attempt to expand a binary operator. Make the expansion closer to the + actual machine, then just general_operand, which will allow 3 separate + memory references (one output, two input) in a single insn. Return + whether the insn fails, or succeeds. */ -void -function_prologue (file, size) - FILE *file; - int size; +int +ix86_expand_binary_operator (code, mode, operands) + enum rtx_code code; + enum machine_mode mode; + rtx operands[]; { - register int regno; - int limit; - rtx xops[4]; - int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table - || current_function_uses_const_pool); + int modified; - xops[0] = stack_pointer_rtx; - xops[1] = frame_pointer_rtx; - xops[2] = GEN_INT (size); - if (frame_pointer_needed) + /* Recognize = for commutative operators */ + if (GET_RTX_CLASS (code) == 'c' + && (rtx_equal_p (operands[0], operands[2]) + || immediate_operand (operands[1], mode))) { - output_asm_insn ("push%L1 %1", xops); - output_asm_insn (AS2 (mov%L0,%0,%1), xops); + rtx temp = operands[1]; + operands[1] = operands[2]; + operands[2] = temp; } - if (size) - output_asm_insn (AS2 (sub%L0,%2,%0), xops); + /* If optimizing, copy to regs to improve CSE */ + if (TARGET_PSEUDO && optimize + && ((reload_in_progress | reload_completed) == 0)) + { + if (GET_CODE (operands[1]) == MEM + && ! rtx_equal_p (operands[0], operands[1])) + operands[1] = force_reg (GET_MODE (operands[1]), operands[1]); - /* Note If use enter it is NOT reversed args. - This one is not reversed from intel!! - I think enter is slower. Also sdb doesn't like it. - But if you want it the code is: - { - xops[3] = const0_rtx; - output_asm_insn ("enter %2,%3", xops); - } - */ - limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); - for (regno = limit - 1; regno >= 0; regno--) - if ((regs_ever_live[regno] && ! call_used_regs[regno]) - || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) - { - xops[0] = gen_rtx (REG, SImode, regno); - output_asm_insn ("push%L0 %0", xops); - } + if (GET_CODE (operands[2]) == MEM) + operands[2] = force_reg (GET_MODE (operands[2]), operands[2]); - if (pic_reg_used) - { - xops[0] = pic_offset_table_rtx; - xops[1] = (rtx) gen_label_rtx (); + if (GET_CODE (operands[1]) == CONST_INT && code == MINUS) + { + rtx temp = gen_reg_rtx (GET_MODE (operands[0])); - output_asm_insn (AS1 (call,%P1), xops); - ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (xops[1])); - output_asm_insn (AS1 (pop%L0,%0), xops); - output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops); + emit_move_insn (temp, operands[1]); + operands[1] = temp; + return TRUE; + } } -} -/* Return 1 if it is appropriate to emit `ret' instructions in the - body of a function. Do this only if the epilogue is simple, needing a - couple of insns. Prior to reloading, we can't tell how many registers - must be saved, so return 0 then. + if (!ix86_binary_operator_ok (code, mode, operands)) + { + /* If not optimizing, try to make a valid insn (optimize code + previously did this above to improve chances of CSE) */ - If NON_SAVING_SETJMP is defined and true, then it is not possible - for the epilogue to be simple, so return 0. This is a special case - since NON_SAVING_SETJMP will not cause regs_ever_live to change until - final, but jump_optimize may need to know sooner if a `return' is OK. */ + if ((! TARGET_PSEUDO || !optimize) + && ((reload_in_progress | reload_completed) == 0) + && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[2]) == MEM)) + { + modified = FALSE; + if (GET_CODE (operands[1]) == MEM + && ! rtx_equal_p (operands[0], operands[1])) + { + operands[1] = force_reg (GET_MODE (operands[1]), operands[1]); + modified = TRUE; + } -int -simple_386_epilogue () -{ - int regno; - int nregs = 0; - int reglimit = (frame_pointer_needed - ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); - int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table - || current_function_uses_const_pool); + if (GET_CODE (operands[2]) == MEM) + { + operands[2] = force_reg (GET_MODE (operands[2]), operands[2]); + modified = TRUE; + } -#ifdef NON_SAVING_SETJMP - if (NON_SAVING_SETJMP && current_function_calls_setjmp) - return 0; -#endif + if (GET_CODE (operands[1]) == CONST_INT && code == MINUS) + { + rtx temp = gen_reg_rtx (GET_MODE (operands[0])); - if (! reload_completed) + emit_move_insn (temp, operands[1]); + operands[1] = temp; + return TRUE; + } + + if (modified && ! ix86_binary_operator_ok (code, mode, operands)) + return FALSE; + } + else + return FALSE; + } + + return TRUE; +} + +/* Return TRUE or FALSE depending on whether the binary operator meets the + appropriate constraints. */ + +int +ix86_binary_operator_ok (code, mode, operands) + enum rtx_code code; + enum machine_mode mode ATTRIBUTE_UNUSED; + rtx operands[3]; +{ + return (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM) + && (GET_CODE (operands[1]) != CONST_INT || GET_RTX_CLASS (code) == 'c'); +} + +/* Attempt to expand a unary operator. Make the expansion closer to the + actual machine, then just general_operand, which will allow 2 separate + memory references (one output, one input) in a single insn. Return + whether the insn fails, or succeeds. */ + +int +ix86_expand_unary_operator (code, mode, operands) + enum rtx_code code; + enum machine_mode mode; + rtx operands[]; +{ + /* If optimizing, copy to regs to improve CSE */ + if (TARGET_PSEUDO + && optimize + && ((reload_in_progress | reload_completed) == 0) + && GET_CODE (operands[1]) == MEM) + operands[1] = force_reg (GET_MODE (operands[1]), operands[1]); + + if (! ix86_unary_operator_ok (code, mode, operands)) + { + if ((! TARGET_PSEUDO || optimize == 0) + && ((reload_in_progress | reload_completed) == 0) + && GET_CODE (operands[1]) == MEM) + { + operands[1] = force_reg (GET_MODE (operands[1]), operands[1]); + if (! ix86_unary_operator_ok (code, mode, operands)) + return FALSE; + } + else + return FALSE; + } + + return TRUE; +} + +/* Return TRUE or FALSE depending on whether the unary operator meets the + appropriate constraints. */ + +int +ix86_unary_operator_ok (code, mode, operands) + enum rtx_code code ATTRIBUTE_UNUSED; + enum machine_mode mode ATTRIBUTE_UNUSED; + rtx operands[2] ATTRIBUTE_UNUSED; +{ + return TRUE; +} + +static rtx pic_label_rtx; +static char pic_label_name [256]; +static int pic_label_no = 0; + +/* This function generates code for -fpic that loads %ebx with + the return address of the caller and then returns. */ + +void +asm_output_function_prefix (file, name) + FILE *file; + char *name ATTRIBUTE_UNUSED; +{ + rtx xops[2]; + int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table + || current_function_uses_const_pool); + xops[0] = pic_offset_table_rtx; + xops[1] = stack_pointer_rtx; + + /* Deep branch prediction favors having a return for every call. */ + if (pic_reg_used && TARGET_DEEP_BRANCH_PREDICTION) + { + tree prologue_node; + + if (pic_label_rtx == 0) + { + pic_label_rtx = gen_label_rtx (); + ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", pic_label_no++); + LABEL_NAME (pic_label_rtx) = pic_label_name; + } + + prologue_node = make_node (FUNCTION_DECL); + DECL_RESULT (prologue_node) = 0; + + /* This used to call ASM_DECLARE_FUNCTION_NAME() but since it's an + internal (non-global) label that's being emitted, it didn't make + sense to have .type information for local labels. This caused + the SCO OpenServer 5.0.4 ELF assembler grief (why are you giving + me debug info for a label that you're declaring non-global?) this + was changed to call ASM_OUTPUT_LABEL() instead. */ + + + ASM_OUTPUT_LABEL (file, pic_label_name); + output_asm_insn ("movl (%1),%0", xops); + output_asm_insn ("ret", xops); + } +} + +/* Generate the assembly code for function entry. + FILE is an stdio stream to output the code to. + SIZE is an int: how many units of temporary storage to allocate. */ + +void +function_prologue (file, size) + FILE *file ATTRIBUTE_UNUSED; + int size ATTRIBUTE_UNUSED; +{ + if (TARGET_SCHEDULE_PROLOGUE) + { + pic_label_rtx = 0; + return; + } + + ix86_prologue (0); +} + +/* Expand the prologue into a bunch of separate insns. */ + +void +ix86_expand_prologue () +{ + if (! TARGET_SCHEDULE_PROLOGUE) + return; + + ix86_prologue (1); +} + +void +load_pic_register (do_rtl) + int do_rtl; +{ + rtx xops[4]; + + if (TARGET_DEEP_BRANCH_PREDICTION) + { + xops[0] = pic_offset_table_rtx; + if (pic_label_rtx == 0) + { + pic_label_rtx = gen_label_rtx (); + ASM_GENERATE_INTERNAL_LABEL (pic_label_name, "LPR", pic_label_no++); + LABEL_NAME (pic_label_rtx) = pic_label_name; + } + + xops[1] = gen_rtx_MEM (QImode, + gen_rtx (SYMBOL_REF, Pmode, + LABEL_NAME (pic_label_rtx))); + + if (do_rtl) + { + emit_insn (gen_prologue_get_pc (xops[0], xops[1])); + emit_insn (gen_prologue_set_got (xops[0], + gen_rtx (SYMBOL_REF, Pmode, + "$_GLOBAL_OFFSET_TABLE_"), + xops[1])); + } + else + { + output_asm_insn (AS1 (call,%X1), xops); + output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_,%0", xops); + pic_label_rtx = 0; + } + } + + else + { + xops[0] = pic_offset_table_rtx; + xops[1] = gen_label_rtx (); + + if (do_rtl) + { + /* We can't put a raw CODE_LABEL into the RTL, and we can't emit + a new CODE_LABEL after reload, so we need a single pattern to + emit the 3 necessary instructions. */ + emit_insn (gen_prologue_get_pc_and_set_got (xops[0])); + } + else + { + output_asm_insn (AS1 (call,%P1), xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + CODE_LABEL_NUMBER (xops[1])); + output_asm_insn (AS1 (pop%L0,%0), xops); + output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops); + } + } + + /* When -fpic, we must emit a scheduling barrier, so that the instruction + that restores %ebx (which is PIC_OFFSET_TABLE_REGNUM), does not get + moved before any instruction which implicitly uses the got. */ + + if (do_rtl) + emit_insn (gen_blockage ()); +} + +static void +ix86_prologue (do_rtl) + int do_rtl; +{ + register int regno; + int limit; + rtx xops[4]; + int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table + || current_function_uses_const_pool); + long tsize = get_frame_size (); + rtx insn; + int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset; + + xops[0] = stack_pointer_rtx; + xops[1] = frame_pointer_rtx; + xops[2] = GEN_INT (tsize); + + if (frame_pointer_needed) + { + if (do_rtl) + { + insn = emit_insn (gen_rtx (SET, VOIDmode, + gen_rtx_MEM (SImode, + gen_rtx (PRE_DEC, SImode, + stack_pointer_rtx)), + frame_pointer_rtx)); + + RTX_FRAME_RELATED_P (insn) = 1; + insn = emit_move_insn (xops[1], xops[0]); + RTX_FRAME_RELATED_P (insn) = 1; + } + + else + { + output_asm_insn ("push%L1 %1", xops); +#ifdef INCOMING_RETURN_ADDR_RTX + if (dwarf2out_do_frame ()) + { + char *l = dwarf2out_cfi_label (); + + cfa_store_offset += 4; + cfa_offset = cfa_store_offset; + dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset); + dwarf2out_reg_save (l, FRAME_POINTER_REGNUM, - cfa_store_offset); + } +#endif + + output_asm_insn (AS2 (mov%L0,%0,%1), xops); +#ifdef INCOMING_RETURN_ADDR_RTX + if (dwarf2out_do_frame ()) + dwarf2out_def_cfa ("", FRAME_POINTER_REGNUM, cfa_offset); +#endif + } + } + + if (tsize == 0) + ; + else if (! TARGET_STACK_PROBE || tsize < CHECK_STACK_LIMIT) + { + if (do_rtl) + { + insn = emit_insn (gen_prologue_set_stack_ptr (xops[2])); + RTX_FRAME_RELATED_P (insn) = 1; + } + else + { + output_asm_insn (AS2 (sub%L0,%2,%0), xops); +#ifdef INCOMING_RETURN_ADDR_RTX + if (dwarf2out_do_frame ()) + { + cfa_store_offset += tsize; + if (! frame_pointer_needed) + { + cfa_offset = cfa_store_offset; + dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, cfa_offset); + } + } +#endif + } + } + else + { + xops[3] = gen_rtx_REG (SImode, 0); + if (do_rtl) + emit_move_insn (xops[3], xops[2]); + else + output_asm_insn (AS2 (mov%L0,%2,%3), xops); + + xops[3] = gen_rtx_MEM (FUNCTION_MODE, + gen_rtx (SYMBOL_REF, Pmode, "_alloca")); + + if (do_rtl) + emit_call_insn (gen_rtx (CALL, VOIDmode, xops[3], const0_rtx)); + else + output_asm_insn (AS1 (call,%P3), xops); + } + + /* Note If use enter it is NOT reversed args. + This one is not reversed from intel!! + I think enter is slower. Also sdb doesn't like it. + But if you want it the code is: + { + xops[3] = const0_rtx; + output_asm_insn ("enter %2,%3", xops); + } + */ + + limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); + for (regno = limit - 1; regno >= 0; regno--) + if ((regs_ever_live[regno] && ! call_used_regs[regno]) + || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) + { + xops[0] = gen_rtx_REG (SImode, regno); + if (do_rtl) + { + insn = emit_insn (gen_rtx (SET, VOIDmode, + gen_rtx_MEM (SImode, + gen_rtx (PRE_DEC, SImode, + stack_pointer_rtx)), + xops[0])); + + RTX_FRAME_RELATED_P (insn) = 1; + } + else + { + output_asm_insn ("push%L0 %0", xops); +#ifdef INCOMING_RETURN_ADDR_RTX + if (dwarf2out_do_frame ()) + { + char *l = dwarf2out_cfi_label (); + + cfa_store_offset += 4; + if (! frame_pointer_needed) + { + cfa_offset = cfa_store_offset; + dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, cfa_offset); + } + + dwarf2out_reg_save (l, regno, - cfa_store_offset); + } +#endif + } + } + + if (pic_reg_used) + load_pic_register (do_rtl); + + /* If we are profiling, make sure no instructions are scheduled before + the call to mcount. However, if -fpic, the above call will have + done that. */ + if ((profile_flag || profile_block_flag) + && ! pic_reg_used && do_rtl) + emit_insn (gen_blockage ()); +} + +/* Return 1 if it is appropriate to emit `ret' instructions in the + body of a function. Do this only if the epilogue is simple, needing a + couple of insns. Prior to reloading, we can't tell how many registers + must be saved, so return 0 then. Return 0 if there is no frame + marker to de-allocate. + + If NON_SAVING_SETJMP is defined and true, then it is not possible + for the epilogue to be simple, so return 0. This is a special case + since NON_SAVING_SETJMP will not cause regs_ever_live to change + until final, but jump_optimize may need to know sooner if a + `return' is OK. */ + +int +ix86_can_use_return_insn_p () +{ + int regno; + int nregs = 0; + int reglimit = (frame_pointer_needed + ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); + int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table + || current_function_uses_const_pool); + +#ifdef NON_SAVING_SETJMP + if (NON_SAVING_SETJMP && current_function_calls_setjmp) + return 0; +#endif + + if (! reload_completed) return 0; for (regno = reglimit - 1; regno >= 0; regno--) @@ -1540,15 +2229,29 @@ simple_386_epilogue () return nregs == 0 || ! frame_pointer_needed; } - /* This function generates the assembly code for function exit. FILE is an stdio stream to output the code to. SIZE is an int: how many units of temporary storage to deallocate. */ void function_epilogue (file, size) - FILE *file; - int size; + FILE *file ATTRIBUTE_UNUSED; + int size ATTRIBUTE_UNUSED; +{ + return; +} + +/* Restore function stack, frame, and registers. */ + +void +ix86_expand_epilogue () +{ + ix86_epilogue (1); +} + +static void +ix86_epilogue (do_rtl) + int do_rtl; { register int regno; register int nregs, limit; @@ -1556,12 +2259,11 @@ function_epilogue (file, size) rtx xops[3]; int pic_reg_used = flag_pic && (current_function_uses_pic_offset_table || current_function_uses_const_pool); + long tsize = get_frame_size (); /* Compute the number of registers to pop */ - limit = (frame_pointer_needed - ? FRAME_POINTER_REGNUM - : STACK_POINTER_REGNUM); + limit = (frame_pointer_needed ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM); nregs = 0; @@ -1570,66 +2272,158 @@ function_epilogue (file, size) || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) nregs++; - /* sp is often unreliable so we must go off the frame pointer, - */ + /* sp is often unreliable so we must go off the frame pointer. - /* In reality, we may not care if sp is unreliable, because we can - restore the register relative to the frame pointer. In theory, - since each move is the same speed as a pop, and we don't need the - leal, this is faster. For now restore multiple registers the old - way. */ + In reality, we may not care if sp is unreliable, because we can restore + the register relative to the frame pointer. In theory, since each move + is the same speed as a pop, and we don't need the leal, this is faster. + For now restore multiple registers the old way. */ - offset = -size - (nregs * UNITS_PER_WORD); + offset = - tsize - (nregs * UNITS_PER_WORD); xops[2] = stack_pointer_rtx; + /* When -fpic, we must emit a scheduling barrier, so that the instruction + that restores %ebx (which is PIC_OFFSET_TABLE_REGNUM), does not get + moved before any instruction which implicitly uses the got. This + includes any instruction which uses a SYMBOL_REF or a LABEL_REF. + + Alternatively, this could be fixed by making the dependence on the + PIC_OFFSET_TABLE_REGNUM explicit in the RTL. */ + + if (flag_pic || profile_flag || profile_block_flag) + emit_insn (gen_blockage ()); + if (nregs > 1 || ! frame_pointer_needed) { if (frame_pointer_needed) { - xops[0] = adj_offsettable_operand (AT_BP (Pmode), offset); - output_asm_insn (AS2 (lea%L2,%0,%2), xops); + xops[0] = adj_offsettable_operand (AT_BP (QImode), offset); + if (do_rtl) + emit_insn (gen_movsi_lea (xops[2], XEXP (xops[0], 0))); + else + output_asm_insn (AS2 (lea%L2,%0,%2), xops); } for (regno = 0; regno < limit; regno++) if ((regs_ever_live[regno] && ! call_used_regs[regno]) || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) { - xops[0] = gen_rtx (REG, SImode, regno); - output_asm_insn ("pop%L0 %0", xops); + xops[0] = gen_rtx_REG (SImode, regno); + + if (do_rtl) + emit_insn (gen_pop (xops[0])); + else + output_asm_insn ("pop%L0 %0", xops); } } + else for (regno = 0; regno < limit; regno++) if ((regs_ever_live[regno] && ! call_used_regs[regno]) || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) { - xops[0] = gen_rtx (REG, SImode, regno); + xops[0] = gen_rtx_REG (SImode, regno); xops[1] = adj_offsettable_operand (AT_BP (Pmode), offset); - output_asm_insn (AS2 (mov%L0,%1,%0), xops); + + if (do_rtl) + emit_move_insn (xops[0], xops[1]); + else + output_asm_insn (AS2 (mov%L0,%1,%0), xops); + offset += 4; } if (frame_pointer_needed) { - /* On i486, mov & pop is faster than "leave". */ + /* If not an i386, mov & pop is faster than "leave". */ - if (!TARGET_386) + if (TARGET_USE_LEAVE) { - xops[0] = frame_pointer_rtx; - output_asm_insn (AS2 (mov%L2,%0,%2), xops); - output_asm_insn ("pop%L0 %0", xops); + if (do_rtl) + emit_insn (gen_leave()); + else + output_asm_insn ("leave", xops); } else - output_asm_insn ("leave", xops); + { + xops[0] = frame_pointer_rtx; + xops[1] = stack_pointer_rtx; + + if (do_rtl) + { + emit_insn (gen_epilogue_set_stack_ptr()); + emit_insn (gen_pop (xops[0])); + } + else + { + output_asm_insn (AS2 (mov%L2,%0,%2), xops); + output_asm_insn ("pop%L0 %0", xops); + } + } } - else if (size) + + else if (tsize) { - /* If there is no frame pointer, we must still release the frame. */ + /* Intel's docs say that for 4 or 8 bytes of stack frame one should + use `pop' and not `add'. */ + int use_pop = tsize == 4; + + /* Use two pops only for the Pentium processors. */ + if (tsize == 8 && !TARGET_386 && !TARGET_486) + { + rtx retval = current_function_return_rtx; + + xops[1] = gen_rtx_REG (SImode, 1); /* %edx */ + + /* This case is a bit more complex. Since we cannot pop into + %ecx twice we need a second register. But this is only + available if the return value is not of DImode in which + case the %edx register is not available. */ + use_pop = (retval == NULL + || ! reg_overlap_mentioned_p (xops[1], retval)); + } + + if (use_pop) + { + xops[0] = gen_rtx_REG (SImode, 2); /* %ecx */ + + if (do_rtl) + { + /* We have to prevent the two pops here from being scheduled. + GCC otherwise would try in some situation to put other + instructions in between them which has a bad effect. */ + emit_insn (gen_blockage ()); + emit_insn (gen_pop (xops[0])); + if (tsize == 8) + emit_insn (gen_pop (xops[1])); + } + else + { + output_asm_insn ("pop%L0 %0", xops); + if (tsize == 8) + output_asm_insn ("pop%L1 %1", xops); + } + } + else + { + /* If there is no frame pointer, we must still release the frame. */ + xops[0] = GEN_INT (tsize); + + if (do_rtl) + emit_insn (gen_rtx (SET, VOIDmode, xops[2], + gen_rtx (PLUS, SImode, xops[2], xops[0]))); + else + output_asm_insn (AS2 (add%L2,%0,%2), xops); + } + } - xops[0] = GEN_INT (size); - output_asm_insn (AS2 (add%L2,%0,%2), xops); +#ifdef FUNCTION_BLOCK_PROFILER_EXIT + if (profile_block_flag == 2) + { + FUNCTION_BLOCK_PROFILER_EXIT(file); } +#endif if (current_function_pops_args && current_function_args_size) { @@ -1642,18 +2436,38 @@ function_epilogue (file, size) if (current_function_pops_args >= 32768) { /* ??? Which register to use here? */ - xops[0] = gen_rtx (REG, SImode, 2); - output_asm_insn ("pop%L0 %0", xops); - output_asm_insn (AS2 (add%L2,%1,%2), xops); - output_asm_insn ("jmp %*%0", xops); + xops[0] = gen_rtx_REG (SImode, 2); + + if (do_rtl) + { + emit_insn (gen_pop (xops[0])); + emit_insn (gen_rtx (SET, VOIDmode, xops[2], + gen_rtx (PLUS, SImode, xops[1], xops[2]))); + emit_jump_insn (xops[0]); + } + else + { + output_asm_insn ("pop%L0 %0", xops); + output_asm_insn (AS2 (add%L2,%1,%2), xops); + output_asm_insn ("jmp %*%0", xops); + } } else - output_asm_insn ("ret %1", xops); + { + if (do_rtl) + emit_jump_insn (gen_return_pop_internal (xops[1])); + else + output_asm_insn ("ret %1", xops); + } } else - output_asm_insn ("ret", xops); + { + if (do_rtl) + emit_jump_insn (gen_return_internal ()); + else + output_asm_insn ("ret", xops); + } } - /* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression that is a valid memory address for an instruction. @@ -1703,14 +2517,14 @@ legitimate_address_p (mode, addr, strict) if (TARGET_DEBUG_ADDR) { fprintf (stderr, - "\n==========\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n", + "\n======\nGO_IF_LEGITIMATE_ADDRESS, mode = %s, strict = %d\n", GET_MODE_NAME (mode), strict); debug_rtx (addr); } if (GET_CODE (addr) == REG || GET_CODE (addr) == SUBREG) - base = addr; /* base reg */ + base = addr; else if (GET_CODE (addr) == PLUS) { @@ -1723,13 +2537,13 @@ legitimate_address_p (mode, addr, strict) { if (code1 == REG || code1 == SUBREG) { - indx = op0; /* index + base */ + indx = op0; /* index + base */ base = op1; } else { - base = op0; /* base + displacement */ + base = op0; /* base + displacement */ disp = op1; } } @@ -1740,10 +2554,10 @@ legitimate_address_p (mode, addr, strict) scale = XEXP (op0, 1); if (code1 == REG || code1 == SUBREG) - base = op1; /* index*scale + base */ + base = op1; /* index*scale + base */ else - disp = op1; /* index*scale + disp */ + disp = op1; /* index*scale + disp */ } else if (code0 == PLUS && GET_CODE (XEXP (op0, 0)) == MULT) @@ -1756,7 +2570,7 @@ legitimate_address_p (mode, addr, strict) else if (code0 == PLUS) { - indx = XEXP (op0, 0); /* index + base + disp */ + indx = XEXP (op0, 0); /* index + base + disp */ base = XEXP (op0, 1); disp = op1; } @@ -1770,12 +2584,12 @@ legitimate_address_p (mode, addr, strict) else if (GET_CODE (addr) == MULT) { - indx = XEXP (addr, 0); /* index*scale */ + indx = XEXP (addr, 0); /* index*scale */ scale = XEXP (addr, 1); } else - disp = addr; /* displacement */ + disp = addr; /* displacement */ /* Allow arg pointer and stack pointer as index if there is not scaling */ if (base && indx && !scale @@ -1786,10 +2600,12 @@ legitimate_address_p (mode, addr, strict) indx = tmp; } - /* Validate base register */ - /* Don't allow SUBREG's here, it can lead to spill failures when the base + /* Validate base register: + + Don't allow SUBREG's here, it can lead to spill failures when the base is one word out of a two word structure, which is represented internally as a DImode int. */ + if (base) { if (GET_CODE (base) != REG) @@ -1798,16 +2614,17 @@ legitimate_address_p (mode, addr, strict) return FALSE; } - if ((strict && !REG_OK_FOR_BASE_STRICT_P (base)) - || (!strict && !REG_OK_FOR_BASE_NONSTRICT_P (base))) + if ((strict && ! REG_OK_FOR_BASE_STRICT_P (base)) + || (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (base))) { ADDR_INVALID ("Base is not valid.\n", base); return FALSE; } } - /* Validate index register */ - /* Don't allow SUBREG's here, it can lead to spill failures when the index + /* Validate index register: + + Don't allow SUBREG's here, it can lead to spill failures when the index is one word out of a two word structure, which is represented internally as a DImode int. */ if (indx) @@ -1818,17 +2635,17 @@ legitimate_address_p (mode, addr, strict) return FALSE; } - if ((strict && !REG_OK_FOR_INDEX_STRICT_P (indx)) - || (!strict && !REG_OK_FOR_INDEX_NONSTRICT_P (indx))) + if ((strict && ! REG_OK_FOR_INDEX_STRICT_P (indx)) + || (! strict && ! REG_OK_FOR_INDEX_NONSTRICT_P (indx))) { ADDR_INVALID ("Index is not valid.\n", indx); return FALSE; } } else if (scale) - abort (); /* scale w/o index invalid */ + abort (); /* scale w/o index invalid */ - /* Validate scale factor */ + /* Validate scale factor: */ if (scale) { HOST_WIDE_INT value; @@ -1847,32 +2664,44 @@ legitimate_address_p (mode, addr, strict) } } - /* Validate displacement */ + /* Validate displacement + Constant pool addresses must be handled special. They are + considered legitimate addresses, but only if not used with regs. + When printed, the output routines know to print the reference with the + PIC reg, even though the PIC reg doesn't appear in the RTL. */ if (disp) { - if (!CONSTANT_ADDRESS_P (disp)) + if (GET_CODE (disp) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (disp) + && base == 0 + && indx == 0) + ; + + else if (!CONSTANT_ADDRESS_P (disp)) { ADDR_INVALID ("Displacement is not valid.\n", disp); return FALSE; } - if (GET_CODE (disp) == CONST_DOUBLE) + else if (GET_CODE (disp) == CONST_DOUBLE) { ADDR_INVALID ("Displacement is a const_double.\n", disp); return FALSE; } - if (flag_pic && SYMBOLIC_CONST (disp) && base != pic_offset_table_rtx - && (indx != pic_offset_table_rtx || scale != NULL_RTX)) + else if (flag_pic && SYMBOLIC_CONST (disp) + && base != pic_offset_table_rtx + && (indx != pic_offset_table_rtx || scale != NULL_RTX)) { ADDR_INVALID ("Displacement is an invalid pic reference.\n", disp); return FALSE; } - if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp) - && (base != NULL_RTX || indx != NULL_RTX)) + else if (HALF_PIC_P () && HALF_PIC_ADDRESS_P (disp) + && (base != NULL_RTX || indx != NULL_RTX)) { - ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", disp); + ADDR_INVALID ("Displacement is an invalid half-pic reference.\n", + disp); return FALSE; } } @@ -1883,7 +2712,6 @@ legitimate_address_p (mode, addr, strict) /* Everything looks valid, return true */ return TRUE; } - /* Return a legitimate reference for ORIG (an address) using the register REG. If REG is 0, a new pseudo is generated. @@ -1933,15 +2761,15 @@ legitimize_pic_address (orig, reg) || GET_CODE (addr) == LABEL_REF) new = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig); else - new = gen_rtx (MEM, Pmode, - gen_rtx (PLUS, Pmode, - pic_offset_table_rtx, orig)); + new = gen_rtx_MEM (Pmode, + gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig)); emit_move_insn (reg, new); } current_function_uses_pic_offset_table = 1; return reg; } + else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS) { rtx base; @@ -1971,27 +2799,26 @@ legitimize_pic_address (orig, reg) base = gen_rtx (PLUS, Pmode, base, XEXP (addr, 0)); addr = XEXP (addr, 1); } - return gen_rtx (PLUS, Pmode, base, addr); + + return gen_rtx (PLUS, Pmode, base, addr); } return new; } - /* Emit insns to move operands[1] into operands[0]. */ void emit_pic_move (operands, mode) rtx *operands; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode); if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1])) - operands[1] = (rtx) force_reg (SImode, operands[1]); + operands[1] = force_reg (SImode, operands[1]); else operands[1] = legitimize_pic_address (operands[1], temp); } - /* Try machine-dependent ways of modifying an illegitimate address to be legitimate. If we find one, return the new, valid address. @@ -2017,7 +2844,7 @@ emit_pic_move (operands, mode) rtx legitimize_address (x, oldx, mode) register rtx x; - register rtx oldx; + register rtx oldx ATTRIBUTE_UNUSED; enum machine_mode mode; { int changed = 0; @@ -2025,7 +2852,8 @@ legitimize_address (x, oldx, mode) if (TARGET_DEBUG_ADDR) { - fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", GET_MODE_NAME (mode)); + fprintf (stderr, "\n==========\nLEGITIMIZE_ADDRESS, mode = %s\n", + GET_MODE_NAME (mode)); debug_rtx (x); } @@ -2038,14 +2866,14 @@ legitimize_address (x, oldx, mode) && (log = (unsigned)exact_log2 (INTVAL (XEXP (x, 1)))) < 4) { changed = 1; - x = gen_rtx (MULT, Pmode, - force_reg (Pmode, XEXP (x, 0)), + x = gen_rtx (MULT, Pmode, force_reg (Pmode, XEXP (x, 0)), GEN_INT (1 << log)); } if (GET_CODE (x) == PLUS) { - /* Canonicalize shifts by 0, 1, 2, 3 into multiply */ + /* Canonicalize shifts by 0, 1, 2, 3 into multiply. */ + if (GET_CODE (XEXP (x, 0)) == ASHIFT && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT && (log = (unsigned)exact_log2 (INTVAL (XEXP (XEXP (x, 0), 1)))) < 4) @@ -2066,7 +2894,7 @@ legitimize_address (x, oldx, mode) GEN_INT (1 << log)); } - /* Put multiply first if it isn't already */ + /* Put multiply first if it isn't already. */ if (GET_CODE (XEXP (x, 1)) == MULT) { rtx tmp = XEXP (x, 0); @@ -2083,18 +2911,21 @@ legitimize_address (x, oldx, mode) { changed = 1; x = gen_rtx (PLUS, Pmode, - gen_rtx (PLUS, Pmode, XEXP (x, 0), XEXP (XEXP (x, 1), 0)), + gen_rtx (PLUS, Pmode, XEXP (x, 0), + XEXP (XEXP (x, 1), 0)), XEXP (XEXP (x, 1), 1)); } - /* Canonicalize (plus (plus (mult (reg) (const)) (plus (reg) (const))) const) + /* Canonicalize + (plus (plus (mult (reg) (const)) (plus (reg) (const))) const) into (plus (plus (mult (reg) (const)) (reg)) (const)). */ else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT && GET_CODE (XEXP (XEXP (x, 0), 1)) == PLUS && CONSTANT_P (XEXP (x, 1))) { - rtx constant, other; + rtx constant; + rtx other = NULL_RTX; if (GET_CODE (XEXP (x, 1)) == CONST_INT) { @@ -2173,7 +3004,6 @@ legitimize_address (x, oldx, mode) return x; } - /* Print an integer constant expression in assembler syntax. Addition and subtraction are the only arithmetic that may appear in these @@ -2208,7 +3038,9 @@ output_pic_addr_const (file, x, code) assemble_name (asm_out_file, buf); } - if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)) + if (code == 'X') + ; /* No suffix, dammit. */ + else if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)) fprintf (file, "@GOTOFF(%%ebx)"); else if (code == 'P') fprintf (file, "@PLT"); @@ -2227,7 +3059,7 @@ output_pic_addr_const (file, x, code) break; case CONST_INT: - fprintf (file, "%d", INTVAL (x)); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x)); break; case CONST: @@ -2241,10 +3073,11 @@ output_pic_addr_const (file, x, code) { /* We can use %d if the number is <32 bits and positive. */ if (CONST_DOUBLE_HIGH (x) || CONST_DOUBLE_LOW (x) < 0) - fprintf (file, "0x%x%08x", - CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x)); + fprintf (file, "0x%lx%08lx", + (unsigned long) CONST_DOUBLE_HIGH (x), + (unsigned long) CONST_DOUBLE_LOW (x)); else - fprintf (file, "%d", CONST_DOUBLE_LOW (x)); + fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x)); } else /* We can't handle floating point constants; @@ -2253,20 +3086,20 @@ output_pic_addr_const (file, x, code) break; case PLUS: - /* Some assemblers need integer constants to appear last (eg masm). */ + /* Some assemblers need integer constants to appear first. */ if (GET_CODE (XEXP (x, 0)) == CONST_INT) { - output_pic_addr_const (file, XEXP (x, 1), code); - if (INTVAL (XEXP (x, 0)) >= 0) - fprintf (file, "+"); output_pic_addr_const (file, XEXP (x, 0), code); + if (INTVAL (XEXP (x, 1)) >= 0) + fprintf (file, "+"); + output_pic_addr_const (file, XEXP (x, 1), code); } else { - output_pic_addr_const (file, XEXP (x, 0), code); - if (INTVAL (XEXP (x, 1)) >= 0) - fprintf (file, "+"); output_pic_addr_const (file, XEXP (x, 1), code); + if (INTVAL (XEXP (x, 0)) >= 0) + fprintf (file, "+"); + output_pic_addr_const (file, XEXP (x, 0), code); } break; @@ -2281,16 +3114,138 @@ output_pic_addr_const (file, x, code) } } +/* Append the correct conditional move suffix which corresponds to CODE. */ + +static void +put_condition_code (code, reverse_cc, mode, file) + enum rtx_code code; + int reverse_cc; + enum mode_class mode; + FILE * file; +{ + int ieee = (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)); + if (reverse_cc && ! ieee) + code = reverse_condition (code); + + if (mode == MODE_INT) + switch (code) + { + case NE: + if (cc_prev_status.flags & CC_Z_IN_NOT_C) + fputs ("b", file); + else + fputs ("ne", file); + return; + + case EQ: + if (cc_prev_status.flags & CC_Z_IN_NOT_C) + fputs ("ae", file); + else + fputs ("e", file); + return; + + case GE: + if (cc_prev_status.flags & CC_NO_OVERFLOW) + fputs ("ns", file); + else + fputs ("ge", file); + return; + + case GT: + fputs ("g", file); + return; + + case LE: + fputs ("le", file); + return; + + case LT: + if (cc_prev_status.flags & CC_NO_OVERFLOW) + fputs ("s", file); + else + fputs ("l", file); + return; + + case GEU: + fputs ("ae", file); + return; + + case GTU: + fputs ("a", file); + return; + + case LEU: + fputs ("be", file); + return; + + case LTU: + fputs ("b", file); + return; + + default: + output_operand_lossage ("Invalid %%C operand"); + } + + else if (mode == MODE_FLOAT) + switch (code) + { + case NE: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "ne", file); + return; + case EQ: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "e", file); + return; + case GE: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "nb", file); + return; + case GT: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "nbe", file); + return; + case LE: + fputs (ieee ? (reverse_cc ? "nb" : "b") : "be", file); + return; + case LT: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "b", file); + return; + case GEU: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "nb", file); + return; + case GTU: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "nbe", file); + return; + case LEU: + fputs (ieee ? (reverse_cc ? "nb" : "b") : "be", file); + return; + case LTU: + fputs (ieee ? (reverse_cc ? "ne" : "e") : "b", file); + return; + default: + output_operand_lossage ("Invalid %%C operand"); + } +} + /* Meaning of CODE: - f -- float insn (print a CONST_DOUBLE as a float rather than in hex). - D,L,W,B,Q,S -- print the opcode suffix for specified size of operand. + L,W,B,Q,S,T -- print the opcode suffix for specified size of operand. + C -- print opcode suffix for set/cmov insn. + c -- like C, but print reversed condition + F -- print opcode suffix for fcmov insn. + f -- like C, but print reversed condition R -- print the prefix for register names. z -- print the opcode suffix for the size of the current operand. * -- print a star (in certain assembler syntax) w -- print the operand as if it's a "word" (HImode) even if it isn't. c -- don't print special prefixes before constant operands. J -- print the appropriate jump operand. -*/ + s -- print a shift double count, followed by the assemblers argument + delimiter. + b -- print the QImode name of the register for the indicated operand. + %b0 would print %al if operands[0] is reg 0. + w -- likewise, print the HImode name of the register. + k -- likewise, print the SImode name of the register. + h -- print the QImode name for a "high" register, either ah, bh, ch or dh. + y -- print "st(0)" instead of "st" as a register. + P -- print as a PIC constant */ void print_operand (file, x, code) @@ -2384,6 +3339,7 @@ print_operand (file, x, code) case 'h': case 'y': case 'P': + case 'X': break; case 'J': @@ -2403,8 +3359,37 @@ print_operand (file, x, code) case LTU: fputs ("#branch never", file); return; /* no matching branches for GT nor LE */ + + default: + abort (); } - abort (); + + case 's': + if (GET_CODE (x) == CONST_INT || ! SHIFT_DOUBLE_OMITS_COUNT) + { + PRINT_OPERAND (file, x, 0); + fputs (AS2C (,) + 1, file); + } + + return; + + /* This is used by the conditional move instructions. */ + case 'C': + put_condition_code (GET_CODE (x), 0, MODE_INT, file); + return; + + /* Like above, but reverse condition */ + case 'c': + put_condition_code (GET_CODE (x), 1, MODE_INT, file); return; + + case 'F': + put_condition_code (GET_CODE (x), 0, MODE_FLOAT, file); + return; + + /* Like above, but reverse condition */ + case 'f': + put_condition_code (GET_CODE (x), 1, MODE_FLOAT, file); + return; default: { @@ -2415,10 +3400,12 @@ print_operand (file, x, code) } } } + if (GET_CODE (x) == REG) { PRINT_REG (x, code, file); } + else if (GET_CODE (x) == MEM) { PRINT_PTR (x, file); @@ -2432,30 +3419,39 @@ print_operand (file, x, code) else output_address (XEXP (x, 0)); } + else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode) { - REAL_VALUE_TYPE r; long l; + REAL_VALUE_TYPE r; + long l; + REAL_VALUE_FROM_CONST_DOUBLE (r, x); REAL_VALUE_TO_TARGET_SINGLE (r, l); PRINT_IMMED_PREFIX (file); - fprintf (file, "0x%x", l); + fprintf (file, "0x%lx", l); } + /* These float cases don't actually occur as immediate operands. */ else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode) { - REAL_VALUE_TYPE r; char dstr[30]; + REAL_VALUE_TYPE r; + char dstr[30]; + REAL_VALUE_FROM_CONST_DOUBLE (r, x); REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr); fprintf (file, "%s", dstr); } + else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == XFmode) { - REAL_VALUE_TYPE r; char dstr[30]; + REAL_VALUE_TYPE r; + char dstr[30]; + REAL_VALUE_FROM_CONST_DOUBLE (r, x); REAL_VALUE_TO_DECIMAL (r, "%.22e", dstr); fprintf (file, "%s", dstr); } - else + else { if (code != 'P') { @@ -2507,38 +3503,35 @@ print_operand_address (file, addr) offset = XEXP (addr, 1); addr = XEXP (addr, 0); } - if (GET_CODE (addr) != PLUS) ; + + if (GET_CODE (addr) != PLUS) + ; else if (GET_CODE (XEXP (addr, 0)) == MULT) - { - reg1 = XEXP (addr, 0); - addr = XEXP (addr, 1); - } + reg1 = XEXP (addr, 0), addr = XEXP (addr, 1); else if (GET_CODE (XEXP (addr, 1)) == MULT) - { - reg1 = XEXP (addr, 1); - addr = XEXP (addr, 0); - } + reg1 = XEXP (addr, 1), addr = XEXP (addr, 0); else if (GET_CODE (XEXP (addr, 0)) == REG) - { - reg1 = XEXP (addr, 0); - addr = XEXP (addr, 1); - } + reg1 = XEXP (addr, 0), addr = XEXP (addr, 1); else if (GET_CODE (XEXP (addr, 1)) == REG) - { - reg1 = XEXP (addr, 1); - addr = XEXP (addr, 0); - } + reg1 = XEXP (addr, 1), addr = XEXP (addr, 0); + if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT) { - if (reg1 == 0) reg1 = addr; - else reg2 = addr; + if (reg1 == 0) + reg1 = addr; + else + reg2 = addr; + addr = 0; } + if (offset != 0) { - if (addr != 0) abort (); + if (addr != 0) + abort (); addr = offset; } + if ((reg1 && GET_CODE (reg1) == MULT) || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) { @@ -2559,10 +3552,8 @@ print_operand_address (file, addr) { if (flag_pic) output_pic_addr_const (file, addr, 0); - else if (GET_CODE (addr) == LABEL_REF) output_asm_label (addr); - else output_addr_const (file, addr); } @@ -2593,6 +3584,7 @@ print_operand_address (file, addr) case MULT: { int scale; + if (GET_CODE (XEXP (addr, 0)) == CONST_INT) { scale = INTVAL (XEXP (addr, 0)); @@ -2603,8 +3595,9 @@ print_operand_address (file, addr) scale = INTVAL (XEXP (addr, 1)); ireg = XEXP (addr, 0); } + output_addr_const (file, const0_rtx); - PRINT_B_I_S ((rtx) 0, ireg, scale, file); + PRINT_B_I_S (NULL_RTX, ireg, scale, file); } break; @@ -2612,7 +3605,7 @@ print_operand_address (file, addr) if (GET_CODE (addr) == CONST_INT && INTVAL (addr) < 0x8000 && INTVAL (addr) >= -0x8000) - fprintf (file, "%d", INTVAL (addr)); + fprintf (file, "%d", (int) INTVAL (addr)); else { if (flag_pic) @@ -2625,7 +3618,7 @@ print_operand_address (file, addr) /* Set the cc_status for the results of an insn whose pattern is EXP. On the 80386, we assume that only test and compare insns, as well - as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, ASHIFT, + as SI, HI, & DI mode ADD, SUB, NEG, AND, IOR, XOR, BSF, ASHIFT, ASHIFTRT, and LSHIFTRT instructions set the condition codes usefully. Also, we assume that jumps, moves and sCOND don't affect the condition codes. All else clobbers the condition codes, by assumption. @@ -2645,40 +3638,51 @@ notice_update_cc (exp) /* Jumps do not alter the cc's. */ if (SET_DEST (exp) == pc_rtx) return; + /* Moving register or memory into a register: it doesn't alter the cc's, but it might invalidate the RTX's which we remember the cc's came from. (Note that moving a constant 0 or 1 MAY set the cc's). */ if (REG_P (SET_DEST (exp)) && (REG_P (SET_SRC (exp)) || GET_CODE (SET_SRC (exp)) == MEM - || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<')) + || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<' + || (GET_CODE (SET_SRC (exp)) == IF_THEN_ELSE + && GET_MODE_CLASS (GET_MODE (SET_DEST (exp))) == MODE_INT))) { if (cc_status.value1 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)) cc_status.value1 = 0; + if (cc_status.value2 && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) cc_status.value2 = 0; + return; } + /* Moving register into memory doesn't alter the cc's. It may invalidate the RTX's which we remember the cc's came from. */ if (GET_CODE (SET_DEST (exp)) == MEM && (REG_P (SET_SRC (exp)) || GET_RTX_CLASS (GET_CODE (SET_SRC (exp))) == '<')) { - if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM) + if (cc_status.value1 + && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value1)) cc_status.value1 = 0; - if (cc_status.value2 && GET_CODE (cc_status.value2) == MEM) + if (cc_status.value2 + && reg_overlap_mentioned_p (SET_DEST (exp), cc_status.value2)) cc_status.value2 = 0; + return; } + /* Function calls clobber the cc's. */ else if (GET_CODE (SET_SRC (exp)) == CALL) { CC_STATUS_INIT; return; } + /* Tests and compares set the cc's in predictable ways. */ else if (SET_DEST (exp) == cc0_rtx) { @@ -2686,14 +3690,14 @@ notice_update_cc (exp) cc_status.value1 = SET_SRC (exp); return; } + /* Certain instructions effect the condition codes. */ else if (GET_MODE (SET_SRC (exp)) == SImode || GET_MODE (SET_SRC (exp)) == HImode || GET_MODE (SET_SRC (exp)) == QImode) switch (GET_CODE (SET_SRC (exp))) { - case ASHIFTRT: case LSHIFTRT: - case ASHIFT: + case ASHIFTRT: case LSHIFTRT: case ASHIFT: /* Shifts on the 386 don't set the condition codes if the shift count is zero. */ if (GET_CODE (XEXP (SET_SRC (exp), 1)) != CONST_INT) @@ -2701,6 +3705,7 @@ notice_update_cc (exp) CC_STATUS_INIT; break; } + /* We assume that the CONST_INT is non-zero (this rtx would have been deleted if it were zero. */ @@ -2711,6 +3716,19 @@ notice_update_cc (exp) cc_status.value2 = SET_DEST (exp); break; + /* This is the bsf pattern used by ffs. */ + case UNSPEC: + if (XINT (SET_SRC (exp), 1) == 5) + { + /* Only the Z flag is defined after bsf. */ + cc_status.flags + = CC_NOT_POSITIVE | CC_NOT_NEGATIVE | CC_NO_OVERFLOW; + cc_status.value1 = XVECEXP (SET_SRC (exp), 0, 0); + cc_status.value2 = 0; + break; + } + /* FALLTHRU */ + default: CC_STATUS_INIT; } @@ -2725,14 +3743,21 @@ notice_update_cc (exp) if (SET_DEST (XVECEXP (exp, 0, 0)) == pc_rtx) return; if (SET_DEST (XVECEXP (exp, 0, 0)) == cc0_rtx) + { CC_STATUS_INIT; - if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0)))) - cc_status.flags |= CC_IN_80387; + if (stack_regs_mentioned_p (SET_SRC (XVECEXP (exp, 0, 0)))) + { + cc_status.flags |= CC_IN_80387; + if (0 && TARGET_CMOVE && stack_regs_mentioned_p + (XEXP (SET_SRC (XVECEXP (exp, 0, 0)), 1))) + cc_status.flags |= CC_FCOMI; + } else cc_status.value1 = SET_SRC (XVECEXP (exp, 0, 0)); return; } + CC_STATUS_INIT; } else @@ -2755,19 +3780,20 @@ split_di (operands, num, lo_half, hi_half) { while (num--) { - if (GET_CODE (operands[num]) == REG) - { - lo_half[num] = gen_rtx (REG, SImode, REGNO (operands[num])); - hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1); - } - else if (CONSTANT_P (operands[num])) + rtx op = operands[num]; + if (GET_CODE (op) == REG) { - split_double (operands[num], &lo_half[num], &hi_half[num]); + lo_half[num] = gen_rtx_REG (SImode, REGNO (op)); + hi_half[num] = gen_rtx_REG (SImode, REGNO (op) + 1); } - else if (offsettable_memref_p (operands[num])) + else if (CONSTANT_P (op)) + split_double (op, &lo_half[num], &hi_half[num]); + else if (offsettable_memref_p (op)) { - lo_half[num] = operands[num]; - hi_half[num] = adj_offsettable_operand (operands[num], 4); + rtx lo_addr = XEXP (op, 0); + rtx hi_addr = XEXP (adj_offsettable_operand (op, 4), 0); + lo_half[num] = change_address (op, SImode, lo_addr); + hi_half[num] = change_address (op, SImode, hi_addr); } else abort(); @@ -2797,7 +3823,6 @@ binary_387_op (op, mode) return 0; } } - /* Return 1 if this is a valid shift or rotate operation on a 386. OP is the expression matched, and MODE is its mode. */ @@ -2829,7 +3854,7 @@ shift_op (op, mode) int VOIDmode_compare_op (op, mode) register rtx op; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; { return GET_CODE (op) == COMPARE && GET_MODE (op) == VOIDmode; } @@ -2908,16 +3933,22 @@ output_387_binary_op (insn, operands) if (NON_STACK_REG_P (operands[1])) { output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1))); - RET; + return ""; } + else if (NON_STACK_REG_P (operands[2])) { output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1))); - RET; + return ""; } if (find_regno_note (insn, REG_DEAD, REGNO (operands[2]))) - return strcat (buf, AS2 (p,%2,%0)); + { + if (STACK_TOP_P (operands[0])) + return strcat (buf, AS2 (p,%0,%2)); + else + return strcat (buf, AS2 (p,%2,%0)); + } if (STACK_TOP_P (operands[0])) return strcat (buf, AS2C (%y2,%0)); @@ -2935,22 +3966,33 @@ output_387_binary_op (insn, operands) if (NON_STACK_REG_P (operands[1])) { output_op_from_reg (operands[1], strcat (buf, AS1 (r%z0,%1))); - RET; + return ""; } + else if (NON_STACK_REG_P (operands[2])) { output_op_from_reg (operands[2], strcat (buf, AS1 (%z0,%1))); - RET; + return ""; } if (! STACK_REG_P (operands[1]) || ! STACK_REG_P (operands[2])) abort (); if (find_regno_note (insn, REG_DEAD, REGNO (operands[2]))) - return strcat (buf, AS2 (rp,%2,%0)); + { + if (STACK_TOP_P (operands[0])) + return strcat (buf, AS2 (p,%0,%2)); + else + return strcat (buf, AS2 (rp,%2,%0)); + } if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return strcat (buf, AS2 (p,%1,%0)); + { + if (STACK_TOP_P (operands[0])) + return strcat (buf, AS2 (rp,%0,%1)); + else + return strcat (buf, AS2 (p,%1,%0)); + } if (STACK_TOP_P (operands[0])) { @@ -2983,8 +4025,7 @@ output_fix_trunc (insn, operands) int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; rtx xops[2]; - if (! STACK_TOP_P (operands[1]) || - (GET_MODE (operands[0]) == DImode && ! stack_top_dies)) + if (! STACK_TOP_P (operands[1])) abort (); xops[0] = GEN_INT (12); @@ -2997,11 +4038,23 @@ output_fix_trunc (insn, operands) output_asm_insn (AS1 (fldc%W3,%3), operands); if (NON_STACK_REG_P (operands[0])) - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, operands[3]); + else if (GET_CODE (operands[0]) == MEM) { if (stack_top_dies) output_asm_insn (AS1 (fistp%z0,%0), operands); + else if (GET_MODE (operands[0]) == DImode && ! stack_top_dies) + { + /* There is no DImode version of this without a stack pop, so + we must emulate it. It doesn't matter much what the second + instruction is, because the value being pushed on the FP stack + is not used except for the following stack popping store. + This case can only happen without optimization, so it doesn't + matter that it is inefficient. */ + output_asm_insn (AS1 (fistp%z0,%0), operands); + output_asm_insn (AS1 (fild%z0,%0), operands); + } else output_asm_insn (AS1 (fist%z0,%0), operands); } @@ -3024,6 +4077,21 @@ output_float_compare (insn, operands) int stack_top_dies; rtx body = XVECEXP (PATTERN (insn), 0, 0); int unordered_compare = GET_MODE (SET_SRC (body)) == CCFPEQmode; + rtx tmp; + + if (0 && TARGET_CMOVE && STACK_REG_P (operands[1])) + { + cc_status.flags |= CC_FCOMI; + cc_prev_status.flags &= ~CC_TEST_AX; + } + + if (! STACK_TOP_P (operands[0])) + { + tmp = operands[0]; + operands[0] = operands[1]; + operands[1] = tmp; + cc_status.flags |= CC_REVERSED; + } if (! STACK_TOP_P (operands[0])) abort (); @@ -3040,9 +4108,27 @@ output_float_compare (insn, operands) `fcompp' float compare */ if (unordered_compare) - output_asm_insn ("fucompp", operands); + { + if (cc_status.flags & CC_FCOMI) + { + output_asm_insn (AS2 (fucomip,%y1,%0), operands); + output_asm_insn (AS1 (fstp, %y0), operands); + return ""; + } + else + output_asm_insn ("fucompp", operands); + } else - output_asm_insn ("fcompp", operands); + { + if (cc_status.flags & CC_FCOMI) + { + output_asm_insn (AS2 (fcomip, %y1,%0), operands); + output_asm_insn (AS1 (fstp, %y0), operands); + return ""; + } + else + output_asm_insn ("fcompp", operands); + } } else { @@ -3052,9 +4138,9 @@ output_float_compare (insn, operands) unordered float compare. */ if (unordered_compare) - strcpy (buf, "fucom"); + strcpy (buf, (cc_status.flags & CC_FCOMI) ? "fucomi" : "fucom"); else if (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_FLOAT) - strcpy (buf, "fcom"); + strcpy (buf, (cc_status.flags & CC_FCOMI) ? "fcomi" : "fcom"); else strcpy (buf, "ficom"); @@ -3065,6 +4151,11 @@ output_float_compare (insn, operands) if (NON_STACK_REG_P (operands[1])) output_op_from_reg (operands[1], strcat (buf, AS1 (%z0,%1))); + else if (cc_status.flags & CC_FCOMI) + { + output_asm_insn (strcat (buf, AS2 (%z1,%y1,%0)), operands); + return ""; + } else output_asm_insn (strcat (buf, AS1 (%z1,%y1)), operands); } @@ -3084,15 +4175,39 @@ output_fp_cc0_set (insn) rtx insn; { rtx xops[3]; - rtx unordered_label; rtx next; enum rtx_code code; - xops[0] = gen_rtx (REG, HImode, 0); + xops[0] = gen_rtx_REG (HImode, 0); output_asm_insn (AS1 (fnsts%W0,%0), xops); if (! TARGET_IEEE_FP) - return "sahf"; + { + if (!(cc_status.flags & CC_REVERSED)) + { + next = next_cc0_user (insn); + + if (GET_CODE (next) == JUMP_INSN + && GET_CODE (PATTERN (next)) == SET + && SET_DEST (PATTERN (next)) == pc_rtx + && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE) + code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)); + else if (GET_CODE (PATTERN (next)) == SET) + code = GET_CODE (SET_SRC (PATTERN (next))); + else + return "sahf"; + + if (code == GT || code == LT || code == EQ || code == NE + || code == LE || code == GE) + { + /* We will test eax directly. */ + cc_status.flags |= CC_TEST_AX; + return ""; + } + } + + return "sahf"; + } next = next_cc0_user (insn); if (next == NULL_RTX) @@ -3102,17 +4217,27 @@ output_fp_cc0_set (insn) && GET_CODE (PATTERN (next)) == SET && SET_DEST (PATTERN (next)) == pc_rtx && GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE) + code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)); + else if (GET_CODE (PATTERN (next)) == SET) { - code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)); + if (GET_CODE (SET_SRC (PATTERN (next))) == IF_THEN_ELSE) + code = GET_CODE (XEXP (SET_SRC (PATTERN (next)), 0)); + else + code = GET_CODE (SET_SRC (PATTERN (next))); } - else if (GET_CODE (PATTERN (next)) == SET) + + else if (GET_CODE (PATTERN (next)) == PARALLEL + && GET_CODE (XVECEXP (PATTERN (next), 0, 0)) == SET) { - code = GET_CODE (SET_SRC (PATTERN (next))); + if (GET_CODE (SET_SRC (XVECEXP (PATTERN (next), 0, 0))) == IF_THEN_ELSE) + code = GET_CODE (XEXP (SET_SRC (XVECEXP (PATTERN (next), 0, 0)), 0)); + else + code = GET_CODE (SET_SRC (XVECEXP (PATTERN (next), 0, 0))); } else abort (); - xops[0] = gen_rtx (REG, QImode, 0); + xops[0] = gen_rtx_REG (QImode, 0); switch (code) { @@ -3168,7 +4293,8 @@ output_fp_cc0_set (insn) default: abort (); } - RET; + + return ""; } #define MAX_386_STACK_LOCALS 2 @@ -3179,6 +4305,8 @@ static rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS]; struct machine_function { rtx i386_stack_locals[(int) MAX_MACHINE_MODE][MAX_386_STACK_LOCALS]; + rtx pic_label_rtx; + char pic_label_name[256]; }; /* Functions to save and restore i386_stack_locals. @@ -3189,9 +4317,12 @@ void save_386_machine_status (p) struct function *p; { - p->machine = (struct machine_function *) xmalloc (sizeof i386_stack_locals); + p->machine + = (struct machine_function *) xmalloc (sizeof (struct machine_function)); bcopy ((char *) i386_stack_locals, (char *) p->machine->i386_stack_locals, sizeof i386_stack_locals); + p->machine->pic_label_rtx = pic_label_rtx; + bcopy (pic_label_name, p->machine->pic_label_name, 256); } void @@ -3200,7 +4331,10 @@ restore_386_machine_status (p) { bcopy ((char *) p->machine->i386_stack_locals, (char *) i386_stack_locals, sizeof i386_stack_locals); + pic_label_rtx = p->machine->pic_label_rtx; + bcopy (p->machine->pic_label_name, pic_label_name, 256); free (p->machine); + p->machine = NULL; } /* Clear stack slot assignments remembered from previous functions. @@ -3218,6 +4352,8 @@ clear_386_stack_locals () for (n = 0; n < MAX_386_STACK_LOCALS; n++) i386_stack_locals[(int) mode][n] = NULL_RTX; + pic_label_rtx = NULL_RTX; + bzero (pic_label_name, 256); /* Arrange to save and restore i386_stack_locals around nested functions. */ save_machine_status = save_386_machine_status; restore_machine_status = restore_386_machine_status; @@ -3243,3 +4379,897 @@ assign_386_stack_local (mode, n) return i386_stack_locals[(int) mode][n]; } + +int is_mul(op,mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return (GET_CODE (op) == MULT); +} + +int is_div(op,mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + return (GET_CODE (op) == DIV); +} + +#ifdef NOTYET +/* Create a new copy of an rtx. + Recursively copies the operands of the rtx, + except for those few rtx codes that are sharable. + Doesn't share CONST */ + +rtx +copy_all_rtx (orig) + register rtx orig; +{ + register rtx copy; + register int i, j; + register RTX_CODE code; + register char *format_ptr; + + code = GET_CODE (orig); + + switch (code) + { + case REG: + case QUEUED: + case CONST_INT: + case CONST_DOUBLE: + case SYMBOL_REF: + case CODE_LABEL: + case PC: + case CC0: + case SCRATCH: + /* SCRATCH must be shared because they represent distinct values. */ + return orig; + +#if 0 + case CONST: + /* CONST can be shared if it contains a SYMBOL_REF. If it contains + a LABEL_REF, it isn't sharable. */ + if (GET_CODE (XEXP (orig, 0)) == PLUS + && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF + && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT) + return orig; + break; +#endif + /* A MEM with a constant address is not sharable. The problem is that + the constant address may need to be reloaded. If the mem is shared, + then reloading one copy of this mem will cause all copies to appear + to have been reloaded. */ + } + + copy = rtx_alloc (code); + PUT_MODE (copy, GET_MODE (orig)); + copy->in_struct = orig->in_struct; + copy->volatil = orig->volatil; + copy->unchanging = orig->unchanging; + copy->integrated = orig->integrated; + /* intel1 */ + copy->is_spill_rtx = orig->is_spill_rtx; + + format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); + + for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++) + { + switch (*format_ptr++) + { + case 'e': + XEXP (copy, i) = XEXP (orig, i); + if (XEXP (orig, i) != NULL) + XEXP (copy, i) = copy_rtx (XEXP (orig, i)); + break; + + case '0': + case 'u': + XEXP (copy, i) = XEXP (orig, i); + break; + + case 'E': + case 'V': + XVEC (copy, i) = XVEC (orig, i); + if (XVEC (orig, i) != NULL) + { + XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); + for (j = 0; j < XVECLEN (copy, i); j++) + XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j)); + } + break; + + case 'w': + XWINT (copy, i) = XWINT (orig, i); + break; + + case 'i': + XINT (copy, i) = XINT (orig, i); + break; + + case 's': + case 'S': + XSTR (copy, i) = XSTR (orig, i); + break; + + default: + abort (); + } + } + return copy; +} + + +/* Try to rewrite a memory address to make it valid */ + +void +rewrite_address (mem_rtx) + rtx mem_rtx; +{ + rtx index_rtx, base_rtx, offset_rtx, scale_rtx, ret_rtx; + int scale = 1; + int offset_adjust = 0; + int was_only_offset = 0; + rtx mem_addr = XEXP (mem_rtx, 0); + char *storage = oballoc (0); + int in_struct = 0; + int is_spill_rtx = 0; + + in_struct = MEM_IN_STRUCT_P (mem_rtx); + is_spill_rtx = RTX_IS_SPILL_P (mem_rtx); + + if (GET_CODE (mem_addr) == PLUS + && GET_CODE (XEXP (mem_addr, 1)) == PLUS + && GET_CODE (XEXP (XEXP (mem_addr, 1), 0)) == REG) + { + /* This part is utilized by the combiner. */ + ret_rtx + = gen_rtx (PLUS, GET_MODE (mem_addr), + gen_rtx (PLUS, GET_MODE (XEXP (mem_addr, 1)), + XEXP (mem_addr, 0), XEXP (XEXP (mem_addr, 1), 0)), + XEXP (XEXP (mem_addr, 1), 1)); + + if (memory_address_p (GET_MODE (mem_rtx), ret_rtx)) + { + XEXP (mem_rtx, 0) = ret_rtx; + RTX_IS_SPILL_P (ret_rtx) = is_spill_rtx; + return; + } + + obfree (storage); + } + + /* This part is utilized by loop.c. + If the address contains PLUS (reg,const) and this pattern is invalid + in this case - try to rewrite the address to make it valid. */ + storage = oballoc (0); + index_rtx = base_rtx = offset_rtx = NULL; + + /* Find the base index and offset elements of the memory address. */ + if (GET_CODE (mem_addr) == PLUS) + { + if (GET_CODE (XEXP (mem_addr, 0)) == REG) + { + if (GET_CODE (XEXP (mem_addr, 1)) == REG) + base_rtx = XEXP (mem_addr, 1), index_rtx = XEXP (mem_addr, 0); + else + base_rtx = XEXP (mem_addr, 0), offset_rtx = XEXP (mem_addr, 1); + } + + else if (GET_CODE (XEXP (mem_addr, 0)) == MULT) + { + index_rtx = XEXP (mem_addr, 0); + if (GET_CODE (XEXP (mem_addr, 1)) == REG) + base_rtx = XEXP (mem_addr, 1); + else + offset_rtx = XEXP (mem_addr, 1); + } + + else if (GET_CODE (XEXP (mem_addr, 0)) == PLUS) + { + if (GET_CODE (XEXP (XEXP (mem_addr, 0), 0)) == PLUS + && GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0)) == MULT + && (GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 0)) + == REG) + && (GET_CODE (XEXP (XEXP (XEXP (XEXP (mem_addr, 0), 0), 0), 1)) + == CONST_INT) + && (GET_CODE (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1)) + == CONST_INT) + && GET_CODE (XEXP (XEXP (mem_addr, 0), 1)) == REG + && GET_CODE (XEXP (mem_addr, 1)) == SYMBOL_REF) + { + index_rtx = XEXP (XEXP (XEXP (mem_addr, 0), 0), 0); + offset_rtx = XEXP (mem_addr, 1); + base_rtx = XEXP (XEXP (mem_addr, 0), 1); + offset_adjust = INTVAL (XEXP (XEXP (XEXP (mem_addr, 0), 0), 1)); + } + else + { + offset_rtx = XEXP (mem_addr, 1); + index_rtx = XEXP (XEXP (mem_addr, 0), 0); + base_rtx = XEXP (XEXP (mem_addr, 0), 1); + } + } + + else if (GET_CODE (XEXP (mem_addr, 0)) == CONST_INT) + { + was_only_offset = 1; + index_rtx = NULL; + base_rtx = NULL; + offset_rtx = XEXP (mem_addr, 1); + offset_adjust = INTVAL (XEXP (mem_addr, 0)); + if (offset_adjust == 0) + { + XEXP (mem_rtx, 0) = offset_rtx; + RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx; + return; + } + } + else + { + obfree (storage); + return; + } + } + else if (GET_CODE (mem_addr) == MULT) + index_rtx = mem_addr; + else + { + obfree (storage); + return; + } + + if (index_rtx != 0 && GET_CODE (index_rtx) == MULT) + { + if (GET_CODE (XEXP (index_rtx, 1)) != CONST_INT) + { + obfree (storage); + return; + } + + scale_rtx = XEXP (index_rtx, 1); + scale = INTVAL (scale_rtx); + index_rtx = copy_all_rtx (XEXP (index_rtx, 0)); + } + + /* Now find which of the elements are invalid and try to fix them. */ + if (index_rtx && GET_CODE (index_rtx) == CONST_INT && base_rtx == NULL) + { + offset_adjust = INTVAL (index_rtx) * scale; + + if (offset_rtx != 0 && CONSTANT_P (offset_rtx)) + offset_rtx = plus_constant (offset_rtx, offset_adjust); + else if (offset_rtx == 0) + offset_rtx = const0_rtx; + + RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx; + XEXP (mem_rtx, 0) = offset_rtx; + return; + } + + if (base_rtx && GET_CODE (base_rtx) == PLUS + && GET_CODE (XEXP (base_rtx, 0)) == REG + && GET_CODE (XEXP (base_rtx, 1)) == CONST_INT) + { + offset_adjust += INTVAL (XEXP (base_rtx, 1)); + base_rtx = copy_all_rtx (XEXP (base_rtx, 0)); + } + + else if (base_rtx && GET_CODE (base_rtx) == CONST_INT) + { + offset_adjust += INTVAL (base_rtx); + base_rtx = NULL; + } + + if (index_rtx && GET_CODE (index_rtx) == PLUS + && GET_CODE (XEXP (index_rtx, 0)) == REG + && GET_CODE (XEXP (index_rtx, 1)) == CONST_INT) + { + offset_adjust += INTVAL (XEXP (index_rtx, 1)) * scale; + index_rtx = copy_all_rtx (XEXP (index_rtx, 0)); + } + + if (index_rtx) + { + if (! LEGITIMATE_INDEX_P (index_rtx) + && ! (index_rtx == stack_pointer_rtx && scale == 1 + && base_rtx == NULL)) + { + obfree (storage); + return; + } + } + + if (base_rtx) + { + if (! LEGITIMATE_INDEX_P (base_rtx) && GET_CODE (base_rtx) != REG) + { + obfree (storage); + return; + } + } + + if (offset_adjust != 0) + { + if (offset_rtx != 0 && CONSTANT_P (offset_rtx)) + offset_rtx = plus_constant (offset_rtx, offset_adjust); + else + offset_rtx = const0_rtx; + + if (index_rtx) + { + if (base_rtx) + { + if (scale != 1) + { + ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx), + gen_rtx (MULT, GET_MODE (index_rtx), + index_rtx, scale_rtx), + base_rtx); + + if (GET_CODE (offset_rtx) != CONST_INT + || INTVAL (offset_rtx) != 0) + ret_rtx = gen_rtx (PLUS, GET_MODE (ret_rtx), + ret_rtx, offset_rtx); + } + else + { + ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), + index_rtx, base_rtx); + + if (GET_CODE (offset_rtx) != CONST_INT + || INTVAL (offset_rtx) != 0) + ret_rtx = gen_rtx (PLUS, GET_MODE (ret_rtx), + ret_rtx, offset_rtx); + } + } + else + { + if (scale != 1) + { + ret_rtx = gen_rtx (MULT, GET_MODE (index_rtx), + index_rtx, scale_rtx); + + if (GET_CODE (offset_rtx) != CONST_INT + || INTVAL (offset_rtx) != 0) + ret_rtx = gen_rtx (PLUS, GET_MODE (ret_rtx), + ret_rtx, offset_rtx); + } + else + { + if (GET_CODE (offset_rtx) == CONST_INT + && INTVAL (offset_rtx) == 0) + ret_rtx = index_rtx; + else + ret_rtx = gen_rtx (PLUS, GET_MODE (index_rtx), + index_rtx, offset_rtx); + } + } + } + else + { + if (base_rtx) + { + if (GET_CODE (offset_rtx) == CONST_INT + && INTVAL (offset_rtx) == 0) + ret_rtx = base_rtx; + else + ret_rtx = gen_rtx (PLUS, GET_MODE (base_rtx), base_rtx, + offset_rtx); + } + else if (was_only_offset) + ret_rtx = offset_rtx; + else + { + obfree (storage); + return; + } + } + + XEXP (mem_rtx, 0) = ret_rtx; + RTX_IS_SPILL_P (XEXP (mem_rtx, 0)) = is_spill_rtx; + return; + } + else + { + obfree (storage); + return; + } +} +#endif /* NOTYET */ + +/* Return 1 if the first insn to set cc before INSN also sets the register + REG_RTX; otherwise return 0. */ +int +last_to_set_cc (reg_rtx, insn) + rtx reg_rtx, insn; +{ + rtx prev_insn = PREV_INSN (insn); + + while (prev_insn) + { + if (GET_CODE (prev_insn) == NOTE) + ; + + else if (GET_CODE (prev_insn) == INSN) + { + if (GET_CODE (PATTERN (prev_insn)) != SET) + return (0); + + if (rtx_equal_p (SET_DEST (PATTERN (prev_insn)), reg_rtx)) + { + if (sets_condition_code (SET_SRC (PATTERN (prev_insn)))) + return (1); + + return (0); + } + + else if (! doesnt_set_condition_code (SET_SRC (PATTERN (prev_insn)))) + return (0); + } + + else + return (0); + + prev_insn = PREV_INSN (prev_insn); + } + + return (0); +} + +int +doesnt_set_condition_code (pat) + rtx pat; +{ + switch (GET_CODE (pat)) + { + case MEM: + case REG: + return 1; + + default: + return 0; + + } +} + +int +sets_condition_code (pat) + rtx pat; +{ + switch (GET_CODE (pat)) + { + case PLUS: + case MINUS: + case AND: + case IOR: + case XOR: + case NOT: + case NEG: + case MULT: + case DIV: + case MOD: + case UDIV: + case UMOD: + return 1; + + default: + return (0); + } +} + +int +str_immediate_operand (op, mode) + register rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + if (GET_CODE (op) == CONST_INT && INTVAL (op) <= 32 && INTVAL (op) >= 0) + return 1; + + return 0; +} + +int +is_fp_insn (insn) + rtx insn; +{ + if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET + && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode)) + return 1; + + return 0; +} + +/* Return 1 if the mode of the SET_DEST of insn is floating point + and it is not an fld or a move from memory to memory. + Otherwise return 0 */ + +int +is_fp_dest (insn) + rtx insn; +{ + if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET + && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode) + && GET_CODE (SET_DEST (PATTERN (insn))) == REG + && REGNO (SET_DEST (PATTERN (insn))) >= FIRST_FLOAT_REG + && GET_CODE (SET_SRC (PATTERN (insn))) != MEM) + return 1; + + return 0; +} + +/* Return 1 if the mode of the SET_DEST of INSN is floating point and is + memory and the source is a register. */ + +int +is_fp_store (insn) + rtx insn; +{ + if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET + && (GET_MODE (SET_DEST (PATTERN (insn))) == DFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == SFmode + || GET_MODE (SET_DEST (PATTERN (insn))) == XFmode) + && GET_CODE (SET_DEST (PATTERN (insn))) == MEM + && GET_CODE (SET_SRC (PATTERN (insn))) == REG) + return 1; + + return 0; +} + +/* Return 1 if DEP_INSN sets a register which INSN uses as a base + or index to reference memory. + otherwise return 0 */ + +int +agi_dependent (insn, dep_insn) + rtx insn, dep_insn; +{ + if (GET_CODE (dep_insn) == INSN + && GET_CODE (PATTERN (dep_insn)) == SET + && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG) + return reg_mentioned_in_mem (SET_DEST (PATTERN (dep_insn)), insn); + + if (GET_CODE (dep_insn) == INSN && GET_CODE (PATTERN (dep_insn)) == SET + && GET_CODE (SET_DEST (PATTERN (dep_insn))) == MEM + && push_operand (SET_DEST (PATTERN (dep_insn)), + GET_MODE (SET_DEST (PATTERN (dep_insn))))) + return reg_mentioned_in_mem (stack_pointer_rtx, insn); + + return 0; +} + +/* Return 1 if reg is used in rtl as a base or index for a memory ref + otherwise return 0. */ + +int +reg_mentioned_in_mem (reg, rtl) + rtx reg, rtl; +{ + register char *fmt; + register int i, j; + register enum rtx_code code; + + if (rtl == NULL) + return 0; + + code = GET_CODE (rtl); + + switch (code) + { + case HIGH: + case CONST_INT: + case CONST: + case CONST_DOUBLE: + case SYMBOL_REF: + case LABEL_REF: + case PC: + case CC0: + case SUBREG: + return 0; + default: + break; + } + + if (code == MEM && reg_mentioned_p (reg, rtl)) + return 1; + + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + if (fmt[i] == 'E') + { + for (j = XVECLEN (rtl, i) - 1; j >= 0; j--) + if (reg_mentioned_in_mem (reg, XVECEXP (rtl, i, j))) + return 1; + } + + else if (fmt[i] == 'e' && reg_mentioned_in_mem (reg, XEXP (rtl, i))) + return 1; + } + + return 0; +} + +/* Output the appropriate insns for doing strlen if not just doing repnz; scasb + + operands[0] = result, initialized with the startaddress + operands[1] = alignment of the address. + operands[2] = scratch register, initialized with the startaddress when + not aligned, otherwise undefined + + This is just the body. It needs the initialisations mentioned above and + some address computing at the end. These things are done in i386.md. */ + +char * +output_strlen_unroll (operands) + rtx operands[]; +{ + rtx xops[18]; + + xops[0] = operands[0]; /* Result */ + /* operands[1]; * Alignment */ + xops[1] = operands[2]; /* Scratch */ + xops[2] = GEN_INT (0); + xops[3] = GEN_INT (2); + xops[4] = GEN_INT (3); + xops[5] = GEN_INT (4); + /* xops[6] = gen_label_rtx (); * label when aligned to 3-byte */ + /* xops[7] = gen_label_rtx (); * label when aligned to 2-byte */ + xops[8] = gen_label_rtx (); /* label of main loop */ + + if (TARGET_USE_Q_REG && QI_REG_P (xops[1])) + xops[9] = gen_label_rtx (); /* pentium optimisation */ + + xops[10] = gen_label_rtx (); /* end label 2 */ + xops[11] = gen_label_rtx (); /* end label 1 */ + xops[12] = gen_label_rtx (); /* end label */ + /* xops[13] * Temporary used */ + xops[14] = GEN_INT (0xff); + xops[15] = GEN_INT (0xff00); + xops[16] = GEN_INT (0xff0000); + xops[17] = GEN_INT (0xff000000); + + /* Loop to check 1..3 bytes for null to get an aligned pointer. */ + + /* Is there a known alignment and is it less than 4? */ + if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) < 4) + { + /* Is there a known alignment and is it not 2? */ + if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2) + { + xops[6] = gen_label_rtx (); /* Label when aligned to 3-byte */ + xops[7] = gen_label_rtx (); /* Label when aligned to 2-byte */ + + /* Leave just the 3 lower bits. + If this is a q-register, then the high part is used later + therefore use andl rather than andb. */ + output_asm_insn (AS2 (and%L1,%4,%1), xops); + + /* Is aligned to 4-byte address when zero */ + output_asm_insn (AS1 (je,%l8), xops); + + /* Side-effect even Parity when %eax == 3 */ + output_asm_insn (AS1 (jp,%6), xops); + + /* Is it aligned to 2 bytes ? */ + if (QI_REG_P (xops[1])) + output_asm_insn (AS2 (cmp%L1,%3,%1), xops); + else + output_asm_insn (AS2 (cmp%L1,%3,%1), xops); + + output_asm_insn (AS1 (je,%7), xops); + } + else + { + /* Since the alignment is 2, we have to check 2 or 0 bytes; + check if is aligned to 4 - byte. */ + output_asm_insn (AS2 (and%L1,%3,%1), xops); + + /* Is aligned to 4-byte address when zero */ + output_asm_insn (AS1 (je,%l8), xops); + } + + xops[13] = gen_rtx_MEM (QImode, xops[0]); + + /* Now compare the bytes; compare with the high part of a q-reg + gives shorter code. */ + if (QI_REG_P (xops[1])) + { + /* Compare the first n unaligned byte on a byte per byte basis. */ + output_asm_insn (AS2 (cmp%B1,%h1,%13), xops); + + /* When zero we reached the end. */ + output_asm_insn (AS1 (je,%l12), xops); + + /* Increment the address. */ + output_asm_insn (AS1 (inc%L0,%0), xops); + + /* Not needed with an alignment of 2 */ + if (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 2) + { + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + CODE_LABEL_NUMBER (xops[7])); + output_asm_insn (AS2 (cmp%B1,%h1,%13), xops); + output_asm_insn (AS1 (je,%l12), xops); + output_asm_insn (AS1 (inc%L0,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + CODE_LABEL_NUMBER (xops[6])); + } + + output_asm_insn (AS2 (cmp%B1,%h1,%13), xops); + } + else + { + output_asm_insn (AS2 (cmp%B13,%2,%13), xops); + output_asm_insn (AS1 (je,%l12), xops); + output_asm_insn (AS1 (inc%L0,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + CODE_LABEL_NUMBER (xops[7])); + output_asm_insn (AS2 (cmp%B13,%2,%13), xops); + output_asm_insn (AS1 (je,%l12), xops); + output_asm_insn (AS1 (inc%L0,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + CODE_LABEL_NUMBER (xops[6])); + output_asm_insn (AS2 (cmp%B13,%2,%13), xops); + } + + output_asm_insn (AS1 (je,%l12), xops); + output_asm_insn (AS1 (inc%L0,%0), xops); + } + + /* Generate loop to check 4 bytes at a time. It is not a good idea to + align this loop. It gives only huge programs, but does not help to + speed up. */ + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[8])); + + xops[13] = gen_rtx_MEM (SImode, xops[0]); + output_asm_insn (AS2 (mov%L1,%13,%1), xops); + + if (QI_REG_P (xops[1])) + { + /* On i586 it is faster to combine the hi- and lo- part as + a kind of lookahead. If anding both yields zero, then one + of both *could* be zero, otherwise none of both is zero; + this saves one instruction, on i486 this is slower + tested with P-90, i486DX2-66, AMD486DX2-66 */ + if (TARGET_PENTIUM) + { + output_asm_insn (AS2 (test%B1,%h1,%b1), xops); + output_asm_insn (AS1 (jne,%l9), xops); + } + + /* Check first byte. */ + output_asm_insn (AS2 (test%B1,%b1,%b1), xops); + output_asm_insn (AS1 (je,%l12), xops); + + /* Check second byte. */ + output_asm_insn (AS2 (test%B1,%h1,%h1), xops); + output_asm_insn (AS1 (je,%l11), xops); + + if (TARGET_PENTIUM) + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", + CODE_LABEL_NUMBER (xops[9])); + } + + else + { + /* Check first byte. */ + output_asm_insn (AS2 (test%L1,%14,%1), xops); + output_asm_insn (AS1 (je,%l12), xops); + + /* Check second byte. */ + output_asm_insn (AS2 (test%L1,%15,%1), xops); + output_asm_insn (AS1 (je,%l11), xops); + } + + /* Check third byte. */ + output_asm_insn (AS2 (test%L1,%16,%1), xops); + output_asm_insn (AS1 (je,%l10), xops); + + /* Check fourth byte and increment address. */ + output_asm_insn (AS2 (add%L0,%5,%0), xops); + output_asm_insn (AS2 (test%L1,%17,%1), xops); + output_asm_insn (AS1 (jne,%l8), xops); + + /* Now generate fixups when the compare stops within a 4-byte word. */ + output_asm_insn (AS2 (sub%L0,%4,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[10])); + output_asm_insn (AS1 (inc%L0,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[11])); + output_asm_insn (AS1 (inc%L0,%0), xops); + + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[12])); + + return ""; +} + +char * +output_fp_conditional_move (which_alternative, operands) + int which_alternative; + rtx operands[]; +{ + switch (which_alternative) + { + case 0: + /* r <- cond ? arg : r */ + output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); + break; + + case 1: + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); + break; + + default: + abort (); + } + + return ""; +} + +char * +output_int_conditional_move (which_alternative, operands) + int which_alternative; + rtx operands[]; +{ + int code = GET_CODE (operands[1]); + enum machine_mode mode; + rtx xops[4]; + + /* This is very tricky. We have to do it right. For a code segement + like: + + int foo, bar; + .... + foo = foo - x; + if (foo >= 0) + bar = y; + + final_scan_insn () may delete the insn which sets CC. We have to + tell final_scan_insn () if it should be reinserted. When CODE is + GT or LE, we have to check the CC_NO_OVERFLOW bit and return + NULL_PTR to tell final to reinsert the test insn because the + conditional move cannot be handled properly without it. */ + if ((code == GT || code == LE) + && (cc_prev_status.flags & CC_NO_OVERFLOW)) + return NULL_PTR; + + mode = GET_MODE (operands [0]); + if (mode == DImode) + { + xops [0] = gen_rtx_SUBREG (SImode, operands [0], 1); + xops [1] = operands [1]; + xops [2] = gen_rtx_SUBREG (SImode, operands [2], 1); + xops [3] = gen_rtx_SUBREG (SImode, operands [3], 1); + } + + switch (which_alternative) + { + case 0: + /* r <- cond ? arg : r */ + output_asm_insn (AS2 (cmov%C1,%2,%0), operands); + if (mode == DImode) + output_asm_insn (AS2 (cmov%C1,%2,%0), xops); + break; + + case 1: + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (cmov%c1,%3,%0), operands); + if (mode == DImode) + output_asm_insn (AS2 (cmov%c1,%3,%0), xops); + break; + + default: + abort (); + } + + return ""; +} diff --git a/contrib/gcc/config/i386/i386.h b/contrib/gcc/config/i386/i386.h index b00b0e509c5b..b8fef1148447 100644 --- a/contrib/gcc/config/i386/i386.h +++ b/contrib/gcc/config/i386/i386.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler for Intel X86 (386, 486, Pentium). - Copyright (C) 1988, 1992, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1988, 92, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. This file is part of GNU CC. @@ -17,8 +17,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - +Boston, MA 02111-1307, USA. */ /* The purpose of this file is to define the characteristics of the i386, independent of assembler syntax or operating system. @@ -53,6 +52,20 @@ Boston, MA 02111-1307, USA. */ #define HALF_PIC_FINISH(STREAM) #endif +/* Define the specific costs for a given cpu */ + +struct processor_costs { + int add; /* cost of an add instruction */ + int lea; /* cost of a lea instruction */ + int shift_var; /* variable shift costs */ + int shift_const; /* constant shift costs */ + int mult_init; /* cost of starting a multiply */ + int mult_bit; /* cost of multiply per each bit set */ + int divide; /* cost of a divide/mod */ +}; + +extern struct processor_costs *ix86_cost; + /* Run-time compilation parameters selecting different hardware subsets. */ extern int target_flags; @@ -66,20 +79,23 @@ extern int target_flags; /* Masks for the -m switches */ #define MASK_80387 000000000001 /* Hardware floating point */ -#define MASK_486 000000000002 /* 80486 specific */ -#define MASK_NOTUSED1 000000000004 /* bit not currently used */ +#define MASK_NOTUSED1 000000000002 /* bit not currently used */ +#define MASK_NOTUSED2 000000000004 /* bit not currently used */ #define MASK_RTD 000000000010 /* Use ret that pops args */ #define MASK_ALIGN_DOUBLE 000000000020 /* align doubles to 2 word boundary */ #define MASK_SVR3_SHLIB 000000000040 /* Uninit locals into bss */ #define MASK_IEEE_FP 000000000100 /* IEEE fp comparisons */ #define MASK_FLOAT_RETURNS 000000000200 /* Return float in st(0) */ #define MASK_NO_FANCY_MATH_387 000000000400 /* Disable sin, cos, sqrt */ - +#define MASK_OMIT_LEAF_FRAME_POINTER 0x00000800 /* omit leaf frame pointers */ /* Temporary codegen switches */ #define MASK_DEBUG_ADDR 000001000000 /* Debug GO_IF_LEGITIMATE_ADDRESS */ #define MASK_NO_WIDE_MULTIPLY 000002000000 /* Disable 32x32->64 multiplies */ #define MASK_NO_MOVE 000004000000 /* Don't generate mem->mem */ -#define MASK_DEBUG_ARG 000010000000 /* Debug function_arg */ +#define MASK_NO_PSEUDO 000010000000 /* Move op's args -> pseudos */ +#define MASK_DEBUG_ARG 000020000000 /* Debug function_arg */ +#define MASK_SCHEDULE_PROLOGUE 000040000000 /* Emit prologue as rtl */ +#define MASK_STACK_PROBE 000100000000 /* Enable stack probing */ /* Use the floating point instructions */ #define TARGET_80387 (target_flags & MASK_80387) @@ -112,6 +128,9 @@ extern int target_flags; This is because FreeBSD lacks these in the math-emulator-code */ #define TARGET_NO_FANCY_MATH_387 (target_flags & MASK_NO_FANCY_MATH_387) +/* Don't create frame pointers for leaf functions */ +#define TARGET_OMIT_LEAF_FRAME_POINTER (target_flags & MASK_OMIT_LEAF_FRAME_POINTER) + /* Temporary switches for tuning code generation */ /* Disable 32x32->64 bit multiplies that are used for long long multiplies @@ -119,6 +138,9 @@ extern int target_flags; #define TARGET_NO_WIDE_MULTIPLY (target_flags & MASK_NO_WIDE_MULTIPLY) #define TARGET_WIDE_MULTIPLY (!TARGET_NO_WIDE_MULTIPLY) +/* Emit/Don't emit prologue as rtl */ +#define TARGET_SCHEDULE_PROLOGUE (target_flags & MASK_SCHEDULE_PROLOGUE) + /* Debug GO_IF_LEGITIMATE_ADDRESS */ #define TARGET_DEBUG_ADDR (target_flags & MASK_DEBUG_ADDR) @@ -127,10 +149,25 @@ extern int target_flags; /* Hack macros for tuning code generation */ #define TARGET_MOVE ((target_flags & MASK_NO_MOVE) == 0) /* Don't generate memory->memory */ - -/* Specific hardware switches */ -#define TARGET_486 (target_flags & MASK_486) /* 80486DX, 80486SX, 80486DX[24] */ -#define TARGET_386 (!TARGET_486) /* 80386 */ +#define TARGET_PSEUDO ((target_flags & MASK_NO_PSEUDO) == 0) /* Move op's args into pseudos */ + +#define TARGET_386 (ix86_cpu == PROCESSOR_I386) +#define TARGET_486 (ix86_cpu == PROCESSOR_I486) +#define TARGET_PENTIUM (ix86_cpu == PROCESSOR_PENTIUM) +#define TARGET_PENTIUMPRO (ix86_cpu == PROCESSOR_PENTIUMPRO) +#define TARGET_USE_LEAVE (ix86_cpu == PROCESSOR_I386) +#define TARGET_PUSH_MEMORY (ix86_cpu == PROCESSOR_I386) +#define TARGET_ZERO_EXTEND_WITH_AND (ix86_cpu != PROCESSOR_I386 \ + && ix86_cpu != PROCESSOR_PENTIUMPRO) +#define TARGET_DOUBLE_WITH_ADD (ix86_cpu != PROCESSOR_I386) +#define TARGET_USE_BIT_TEST (ix86_cpu == PROCESSOR_I386) +#define TARGET_UNROLL_STRLEN (ix86_cpu != PROCESSOR_I386) +#define TARGET_USE_Q_REG (ix86_cpu == PROCESSOR_PENTIUM \ + || ix86_cpu == PROCESSOR_PENTIUMPRO) +#define TARGET_USE_ANY_REG (ix86_cpu == PROCESSOR_I486) +#define TARGET_CMOVE (ix86_arch == PROCESSOR_PENTIUMPRO) +#define TARGET_DEEP_BRANCH_PREDICTION (ix86_cpu == PROCESSOR_PENTIUMPRO) +#define TARGET_STACK_PROBE (target_flags & MASK_STACK_PROBE) #define TARGET_SWITCHES \ { { "80387", MASK_80387 }, \ @@ -138,10 +175,12 @@ extern int target_flags; { "hard-float", MASK_80387 }, \ { "soft-float", -MASK_80387 }, \ { "no-soft-float", MASK_80387 }, \ - { "386", -MASK_486 }, \ - { "no-386", MASK_486 }, \ - { "486", MASK_486 }, \ - { "no-486", -MASK_486 }, \ + { "386", 0 }, \ + { "no-386", 0 }, \ + { "486", 0 }, \ + { "no-486", 0 }, \ + { "pentium", 0 }, \ + { "pentiumpro", 0 }, \ { "rtd", MASK_RTD }, \ { "no-rtd", -MASK_RTD }, \ { "align-double", MASK_ALIGN_DOUBLE }, \ @@ -154,16 +193,62 @@ extern int target_flags; { "no-fp-ret-in-387", -MASK_FLOAT_RETURNS }, \ { "no-fancy-math-387", MASK_NO_FANCY_MATH_387 }, \ { "fancy-math-387", -MASK_NO_FANCY_MATH_387 }, \ + { "omit-leaf-frame-pointer", MASK_OMIT_LEAF_FRAME_POINTER }, \ + { "no-omit-leaf-frame-pointer",-MASK_OMIT_LEAF_FRAME_POINTER }, \ { "no-wide-multiply", MASK_NO_WIDE_MULTIPLY }, \ { "wide-multiply", -MASK_NO_WIDE_MULTIPLY }, \ + { "schedule-prologue", MASK_SCHEDULE_PROLOGUE }, \ + { "no-schedule-prologue", -MASK_SCHEDULE_PROLOGUE }, \ { "debug-addr", MASK_DEBUG_ADDR }, \ { "no-debug-addr", -MASK_DEBUG_ADDR }, \ { "move", -MASK_NO_MOVE }, \ { "no-move", MASK_NO_MOVE }, \ { "debug-arg", MASK_DEBUG_ARG }, \ { "no-debug-arg", -MASK_DEBUG_ARG }, \ + { "stack-arg-probe", MASK_STACK_PROBE }, \ + { "no-stack-arg-probe", -MASK_STACK_PROBE }, \ + { "windows", 0 }, \ + { "dll", 0 }, \ SUBTARGET_SWITCHES \ - { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT}} + { "", MASK_SCHEDULE_PROLOGUE | TARGET_DEFAULT}} + +/* Which processor to schedule for. The cpu attribute defines a list that + mirrors this list, so changes to i386.md must be made at the same time. */ + +enum processor_type + {PROCESSOR_I386, /* 80386 */ + PROCESSOR_I486, /* 80486DX, 80486SX, 80486DX[24] */ + PROCESSOR_PENTIUM, + PROCESSOR_PENTIUMPRO}; + +#define PROCESSOR_I386_STRING "i386" +#define PROCESSOR_I486_STRING "i486" +#define PROCESSOR_I586_STRING "i586" +#define PROCESSOR_PENTIUM_STRING "pentium" +#define PROCESSOR_I686_STRING "i686" +#define PROCESSOR_PENTIUMPRO_STRING "pentiumpro" + +extern enum processor_type ix86_cpu; + +extern int ix86_arch; + +/* Define the default processor. This is overridden by other tm.h files. */ +#define PROCESSOR_DEFAULT \ + ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_I486) \ + ? PROCESSOR_I486 \ + : ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUM) \ + ? PROCESSOR_PENTIUM \ + : ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUMPRO) \ + ? PROCESSOR_PENTIUMPRO \ + : PROCESSOR_I386 +#define PROCESSOR_DEFAULT_STRING \ + ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_I486) \ + ? PROCESSOR_I486_STRING \ + : ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUM) \ + ? PROCESSOR_PENTIUM_STRING \ + : ((enum processor_type) TARGET_CPU_DEFAULT == PROCESSOR_PENTIUMPRO) \ + ? PROCESSOR_PENTIUMPRO_STRING \ + : PROCESSOR_I386_STRING /* This macro is similar to `TARGET_SWITCHES' but defines names of command options that have values. Its definition is an @@ -175,11 +260,14 @@ extern int target_flags; option if the fixed part matches. The actual option name is made by appending `-m' to the specified name. */ #define TARGET_OPTIONS \ -{ { "reg-alloc=", &i386_reg_alloc_order }, \ +{ { "cpu=", &ix86_cpu_string}, \ + { "arch=", &ix86_arch_string}, \ + { "reg-alloc=", &i386_reg_alloc_order }, \ { "regparm=", &i386_regparm_string }, \ { "align-loops=", &i386_align_loops_string }, \ { "align-jumps=", &i386_align_jumps_string }, \ { "align-functions=", &i386_align_funcs_string }, \ + { "branch-cost=", &i386_branch_cost_string }, \ SUBTARGET_OPTIONS \ } @@ -198,6 +286,82 @@ extern int target_flags; #define SUBTARGET_SWITCHES #define SUBTARGET_OPTIONS +/* Define this to change the optimizations performed by default. */ +#define OPTIMIZATION_OPTIONS(LEVEL,SIZE) optimization_options(LEVEL,SIZE) + +/* Specs for the compiler proper */ + +#ifndef CC1_CPU_SPEC +#define CC1_CPU_SPEC "\ +%{!mcpu*: \ +%{m386:-mcpu=i386 -march=i386} \ +%{mno-486:-mcpu=i386 -march=i386} \ +%{m486:-mcpu=i486 -march=i486} \ +%{mno-386:-mcpu=i486 -march=i486} \ +%{mno-pentium:-mcpu=i486 -march=i486} \ +%{mpentium:-mcpu=pentium} \ +%{mno-pentiumpro:-mcpu=pentium} \ +%{mpentiumpro:-mcpu=pentiumpro}}" +#endif + +#define CPP_486_SPEC "%{!ansi:-Di486} -D__i486 -D__i486__" +#define CPP_586_SPEC "%{!ansi:-Di586 -Dpentium} \ + -D__i586 -D__i586__ -D__pentium -D__pentium__" +#define CPP_686_SPEC "%{!ansi:-Di686 -Dpentiumpro} \ + -D__i686 -D__i686__ -D__pentiumpro -D__pentiumpro__" + +#ifndef CPP_CPU_DEFAULT_SPEC +#if TARGET_CPU_DEFAULT == 1 +#define CPP_CPU_DEFAULT_SPEC "%(cpp_486)" +#else +#if TARGET_CPU_DEFAULT == 2 +#define CPP_CPU_DEFAULT_SPEC "%(cpp_586)" +#else +#if TARGET_CPU_DEFAULT == 3 +#define CPP_CPU_DEFAULT_SPEC "%(cpp_686)" +#else +#define CPP_CPU_DEFAULT_SPEC "" +#endif +#endif +#endif +#endif /* CPP_CPU_DEFAULT_SPEC */ + +#ifndef CPP_CPU_SPEC +#define CPP_CPU_SPEC "\ +-Asystem(unix) -Acpu(i386) -Amachine(i386) \ +%{!ansi:-Di386} -D__i386 -D__i386__ \ +%{mcpu=i486:%(cpp_486)} %{m486:%(cpp_486)} \ +%{mpentium:%(cpp_586)} %{mcpu=pentium:%(cpp_586)} \ +%{mpentiumpro:%(cpp_686)} %{mcpu=pentiumpro:%(cpp_686)} \ +%{!mcpu*:%{!m486:%{!mpentium*:%(cpp_cpu_default)}}}" +#endif + +#ifndef CC1_SPEC +#define CC1_SPEC "%(cc1_spec) " +#endif + +/* This macro defines names of additional specifications to put in the + specs that can be used in various specifications like CC1_SPEC. Its + definition is an initializer with a subgrouping for each command option. + + Each subgrouping contains a string constant, that defines the + specification name, and a string constant that used by the GNU CC driver + program. + + Do not define this macro if it does not need to do anything. */ + +#ifndef SUBTARGET_EXTRA_SPECS +#define SUBTARGET_EXTRA_SPECS +#endif + +#define EXTRA_SPECS \ + { "cpp_486", CPP_486_SPEC}, \ + { "cpp_586", CPP_586_SPEC}, \ + { "cpp_686", CPP_686_SPEC}, \ + { "cpp_cpu_default", CPP_CPU_DEFAULT_SPEC }, \ + { "cpp_cpu", CPP_CPU_SPEC }, \ + { "cc1_cpu", CC1_CPU_SPEC }, \ + SUBTARGET_EXTRA_SPECS /* target machine storage layout */ @@ -265,6 +429,79 @@ extern int target_flags; aligned on 64 bit boundaries. */ #define BIGGEST_ALIGNMENT (TARGET_ALIGN_DOUBLE ? 64 : 32) +/* If defined, a C expression to compute the alignment given to a + constant that is being placed in memory. CONSTANT is the constant + and ALIGN is the alignment that the object would ordinarily have. + The value of this macro is used instead of that alignment to align + the object. + + If this macro is not defined, then ALIGN is used. + + The typical use of this macro is to increase alignment for string + constants to be word aligned so that `strcpy' calls that copy + constants can be done inline. */ + +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \ + (TREE_CODE (EXP) == REAL_CST \ + ? ((TYPE_MODE (TREE_TYPE (EXP)) == DFmode && (ALIGN) < 64) \ + ? 64 \ + : (TYPE_MODE (TREE_TYPE (EXP)) == XFmode && (ALIGN) < 128) \ + ? 128 \ + : (ALIGN)) \ + : TREE_CODE (EXP) == STRING_CST \ + ? ((TREE_STRING_LENGTH (EXP) >= 31 && (ALIGN) < 256) \ + ? 256 \ + : (ALIGN)) \ + : (ALIGN)) + +/* If defined, a C expression to compute the alignment for a static + variable. TYPE is the data type, and ALIGN is the alignment that + the object would ordinarily have. The value of this macro is used + instead of that alignment to align the object. + + If this macro is not defined, then ALIGN is used. + + One use of this macro is to increase alignment of medium-size + data to make it all fit in fewer cache lines. Another is to + cause character arrays to be word-aligned so that `strcpy' calls + that copy constants to character arrays can be done inline. */ + +#define DATA_ALIGNMENT(TYPE, ALIGN) \ + ((AGGREGATE_TYPE_P (TYPE) \ + && TYPE_SIZE (TYPE) \ + && TREE_CODE (TYPE_SIZE (TYPE)) == INTEGER_CST \ + && (TREE_INT_CST_LOW (TYPE_SIZE (TYPE)) >= 256 \ + || TREE_INT_CST_HIGH (TYPE_SIZE (TYPE))) && (ALIGN) < 256) \ + ? 256 \ + : TREE_CODE (TYPE) == ARRAY_TYPE \ + ? ((TYPE_MODE (TREE_TYPE (TYPE)) == DFmode && (ALIGN) < 64) \ + ? 64 \ + : (TYPE_MODE (TREE_TYPE (TYPE)) == XFmode && (ALIGN) < 128) \ + ? 128 \ + : (ALIGN)) \ + : TREE_CODE (TYPE) == COMPLEX_TYPE \ + ? ((TYPE_MODE (TYPE) == DCmode && (ALIGN) < 64) \ + ? 64 \ + : (TYPE_MODE (TYPE) == XCmode && (ALIGN) < 128) \ + ? 128 \ + : (ALIGN)) \ + : ((TREE_CODE (TYPE) == RECORD_TYPE \ + || TREE_CODE (TYPE) == UNION_TYPE \ + || TREE_CODE (TYPE) == QUAL_UNION_TYPE) \ + && TYPE_FIELDS (TYPE)) \ + ? ((DECL_MODE (TYPE_FIELDS (TYPE)) == DFmode && (ALIGN) < 64) \ + ? 64 \ + : (DECL_MODE (TYPE_FIELDS (TYPE)) == XFmode && (ALIGN) < 128) \ + ? 128 \ + : (ALIGN)) \ + : TREE_CODE (TYPE) == REAL_TYPE \ + ? ((TYPE_MODE (TYPE) == DFmode && (ALIGN) < 64) \ + ? 64 \ + : (TYPE_MODE (TYPE) == XFmode && (ALIGN) < 128) \ + ? 128 \ + : (ALIGN)) \ + : (ALIGN)) + /* Set this non-zero if move instructions will actually fail to work when given unaligned data. */ #define STRICT_ALIGNMENT 0 @@ -278,12 +515,14 @@ extern int target_flags; #define MAX_CODE_ALIGN 6 /* 64 byte alignment */ /* Align loop starts for optimal branching. */ -#define ASM_OUTPUT_LOOP_ALIGN(FILE) ASM_OUTPUT_ALIGN (FILE, i386_align_loops) +#define LOOP_ALIGN(LABEL) (i386_align_loops) +#define LOOP_ALIGN_MAX_SKIP (i386_align_loops_string ? 0 : 7) /* This is how to align an instruction for optimal branching. On i486 we'll get better performance by aligning on a cache line (i.e. 16 byte) boundary. */ -#define ASM_OUTPUT_ALIGN_CODE(FILE) ASM_OUTPUT_ALIGN ((FILE), i386_align_jumps) +#define LABEL_ALIGN_AFTER_BARRIER(LABEL) (i386_align_jumps) +#define LABEL_ALIGN_AFTER_BARRIER_MAX_SKIP (i386_align_jumps_string ? 0 : 7) /* Standard register usage. */ @@ -292,6 +531,7 @@ extern int target_flags; for details. */ #define STACK_REGS +#define IS_STACK_MODE(mode) (mode==DFmode || mode==SFmode || mode==XFmode) /* Number of actual hardware registers. The hardware registers are assigned numbers for the compiler @@ -409,31 +649,23 @@ extern int target_flags; for cross-compiler testing. */ #define HARD_REGNO_MODE_OK(REGNO, MODE) \ - ((REGNO) < 2 ? 1 \ - : (REGNO) < 4 ? 1 \ + ((REGNO) < 4 ? 1 \ : FP_REGNO_P (REGNO) \ ? (((int) GET_MODE_CLASS (MODE) == (int) MODE_FLOAT \ || (int) GET_MODE_CLASS (MODE) == (int) MODE_COMPLEX_FLOAT) \ - && GET_MODE_UNIT_SIZE (MODE) <= 12) \ - : (int) (MODE) != (int) QImode) + && GET_MODE_UNIT_SIZE (MODE) <= (LONG_DOUBLE_TYPE_SIZE == 96 ? 12 : 8))\ + : (int) (MODE) != (int) QImode ? 1 \ + : (reload_in_progress | reload_completed) == 1) /* Value is 1 if it is a good idea to tie two pseudo registers when one has mode MODE1 and one has mode MODE2. If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2, for any hard reg, then this must be 0 for correct output. */ -#define MODES_TIEABLE_P(MODE1, MODE2) ((MODE1) == (MODE2)) - -/* A C expression returning the cost of moving data from a register of class - CLASS1 to one of CLASS2. - - On the i386, copying between floating-point and fixed-point - registers is expensive. */ - -#define REGISTER_MOVE_COST(CLASS1, CLASS2) \ - (((FLOAT_CLASS_P (CLASS1) && ! FLOAT_CLASS_P (CLASS2)) \ - || (! FLOAT_CLASS_P (CLASS1) && FLOAT_CLASS_P (CLASS2))) ? 10 \ - : 2) +#define MODES_TIEABLE_P(MODE1, MODE2) \ + ((MODE1) == (MODE2) \ + || ((MODE1) == SImode && (MODE2) == HImode \ + || (MODE1) == HImode && (MODE2) == SImode)) /* Specify the registers used for certain standard purposes. The values of these macros are register numbers. */ @@ -459,7 +691,7 @@ extern int target_flags; Zero means the frame pointer need not be set up (and parms may be accessed via the stack pointer) in functions that seem suitable. This is computed in `reload', in reload1.c. */ -#define FRAME_POINTER_REQUIRED 0 +#define FRAME_POINTER_REQUIRED (TARGET_OMIT_LEAF_FRAME_POINTER && !leaf_function_p ()) /* Base register for access to arguments of the function. */ #define ARG_POINTER_REGNUM 16 @@ -562,16 +794,16 @@ enum reg_class of length N_REG_CLASSES. */ #define REG_CLASS_CONTENTS \ -{ 0, \ - 0x1, 0x2, 0x4, 0x8, /* AREG, DREG, CREG, BREG */ \ - 0x3, /* AD_REGS */ \ - 0xf, /* Q_REGS */ \ - 0x10, 0x20, /* SIREG, DIREG */ \ - 0x07f, /* INDEX_REGS */ \ - 0x100ff, /* GENERAL_REGS */ \ - 0x0100, 0x0200, /* FP_TOP_REG, FP_SECOND_REG */ \ - 0xff00, /* FLOAT_REGS */ \ - 0x1ffff } +{ {0}, \ + {0x1}, {0x2}, {0x4}, {0x8}, /* AREG, DREG, CREG, BREG */ \ + {0x3}, /* AD_REGS */ \ + {0xf}, /* Q_REGS */ \ + {0x10}, {0x20}, /* SIREG, DIREG */ \ + {0x7f}, /* INDEX_REGS */ \ + {0x100ff}, /* GENERAL_REGS */ \ + {0x0100}, {0x0200}, /* FP_TOP_REG, FP_SECOND_REG */ \ + {0xff00}, /* FLOAT_REGS */ \ + {0x1ffff}} /* The same information, inverted: Return the class number of the smallest class containing @@ -584,7 +816,7 @@ enum reg_class rtl to be used as spill registers but prevents the compiler from extending the lifetime of these registers. */ -#define SMALL_REGISTER_CLASSES +#define SMALL_REGISTER_CLASSES 1 #define QI_REG_P(X) \ (REG_P (X) && REGNO (X) < 4) @@ -658,15 +890,25 @@ enum reg_class (C) == 'L' ? (VALUE) == 0xffff : \ (C) == 'M' ? (VALUE) >= 0 && (VALUE) <= 3 : \ (C) == 'N' ? (VALUE) >= 0 && (VALUE) <= 255 :\ + (C) == 'O' ? (VALUE) >= 0 && (VALUE) <= 32 : \ 0) /* Similar, but for floating constants, and defining letters G and H. Here VALUE is the CONST_DOUBLE rtx itself. We allow constants even if TARGET_387 isn't set, because the stack register converter may need to - load 0.0 into the function value register. */ + load 0.0 into the function value register. + + We disallow these constants when -fomit-frame-pointer and compiling + PIC code since reload might need to force the constant to memory. + Forcing the constant to memory changes the elimination offsets after + the point where they must stay constant. + + However, we must allow them after reload as completed as reg-stack.c + will create insns which use these constants. */ #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \ - ((C) == 'G' ? standard_80387_constant_p (VALUE) : 0) + (((reload_completed || !flag_pic || !flag_omit_frame_pointer) && (C) == 'G') \ + ? standard_80387_constant_p (VALUE) : 0) /* Place additional restrictions on the register class to use when it is necessary to be able to hold a value of mode MODE in a reload @@ -791,14 +1033,14 @@ enum reg_class If the precise function being called is known, FUNC is its FUNCTION_DECL; otherwise, FUNC is 0. */ #define FUNCTION_VALUE(VALTYPE, FUNC) \ - gen_rtx (REG, TYPE_MODE (VALTYPE), \ + gen_rtx_REG (TYPE_MODE (VALTYPE), \ VALUE_REGNO (TYPE_MODE (VALTYPE))) /* Define how to find the value returned by a library function assuming the value has mode MODE. */ #define LIBCALL_VALUE(MODE) \ - gen_rtx (REG, MODE, VALUE_REGNO (MODE)) + gen_rtx_REG (MODE, VALUE_REGNO (MODE)) /* Define the size of the result block used for communication between untyped_call and untyped_return. The block contains a DImode value @@ -825,7 +1067,7 @@ typedef struct i386_args { for a call to a function whose data type is FNTYPE. For a library call, FNTYPE is 0. */ -#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME) \ +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \ (init_cumulative_args (&CUM, FNTYPE, LIBNAME)) /* Update the data in CUM to advance over an argument @@ -858,6 +1100,14 @@ typedef struct i386_args { #define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \ (function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED)) +/* This macro is invoked just before the start of a function. + It is used here to output code for -fpic that will load the + return address into %ebx. */ + +#undef ASM_OUTPUT_FUNCTION_PREFIX +#define ASM_OUTPUT_FUNCTION_PREFIX(FILE, FNNAME) \ + asm_output_function_prefix (FILE, FNNAME) + /* This macro generates the assembly code for function entry. FILE is a stdio stream to output the code to. SIZE is an int: how many units of temporary storage to allocate. @@ -887,27 +1137,94 @@ typedef struct i386_args { } \ } -/* A C statement or compound statement to output to FILE some - assembler code to initialize basic-block profiling for the current - object module. This code should call the subroutine - `__bb_init_func' once per object module, passing it as its sole - argument the address of a block allocated in the object module. - The name of the block is a local symbol made with this statement: +/* There are three profiling modes for basic blocks available. + The modes are selected at compile time by using the options + -a or -ax of the gnu compiler. + The variable `profile_block_flag' will be set according to the + selected option. + + profile_block_flag == 0, no option used: + + No profiling done. + + profile_block_flag == 1, -a option used. + + Count frequency of execution of every basic block. + + profile_block_flag == 2, -ax option used. + + Generate code to allow several different profiling modes at run time. + Available modes are: + Produce a trace of all basic blocks. + Count frequency of jump instructions executed. + In every mode it is possible to start profiling upon entering + certain functions and to disable profiling of some other functions. + + The result of basic-block profiling will be written to a file `bb.out'. + If the -ax option is used parameters for the profiling will be read + from file `bb.in'. + +*/ + +/* The following macro shall output assembler code to FILE + to initialize basic-block profiling. + + If profile_block_flag == 2 + + Output code to call the subroutine `__bb_init_trace_func' + and pass two parameters to it. The first parameter is + the address of a block allocated in the object module. + The second parameter is the number of the first basic block + of the function. + + The name of the block is a local symbol made with this statement: + + ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); + + Of course, since you are writing the definition of + `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you + can take a short cut in the definition of this macro and use the + name that you know will result. + + The number of the first basic block of the function is + passed to the macro in BLOCK_OR_LABEL. + + If described in a virtual assembler language the code to be + output looks like: + + parameter1 <- LPBX0 + parameter2 <- BLOCK_OR_LABEL + call __bb_init_trace_func + + else if profile_block_flag != 0 + + Output code to call the subroutine `__bb_init_func' + and pass one single parameter to it, which is the same + as the first parameter to `__bb_init_trace_func'. - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); + The first word of this parameter is a flag which will be nonzero if + the object module has already been initialized. So test this word + first, and do not call `__bb_init_func' if the flag is nonzero. + Note: When profile_block_flag == 2 the test need not be done + but `__bb_init_trace_func' *must* be called. - Of course, since you are writing the definition of - `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you - can take a short cut in the definition of this macro and use the - name that you know will result. + BLOCK_OR_LABEL may be used to generate a label number as a + branch destination in case `__bb_init_func' will not be called. - The first word of this block is a flag which will be nonzero if the - object module has already been initialized. So test this word - first, and do not call `__bb_init_func' if the flag is nonzero. */ + If described in a virtual assembler language the code to be + output looks like: + + cmp (LPBX0),0 + jne local_label + parameter1 <- LPBX0 + call __bb_init_func +local_label: + +*/ #undef FUNCTION_BLOCK_PROFILER -#define FUNCTION_BLOCK_PROFILER(STREAM, LABELNO) \ +#define FUNCTION_BLOCK_PROFILER(FILE, BLOCK_OR_LABEL) \ do \ { \ static int num_func = 0; \ @@ -915,74 +1232,264 @@ do \ char block_table[80], false_label[80]; \ \ ASM_GENERATE_INTERNAL_LABEL (block_table, "LPBX", 0); \ - ASM_GENERATE_INTERNAL_LABEL (false_label, "LPBZ", num_func); \ \ - xops[0] = const0_rtx; \ - xops[1] = gen_rtx (SYMBOL_REF, VOIDmode, block_table); \ - xops[2] = gen_rtx (MEM, Pmode, gen_rtx (SYMBOL_REF, VOIDmode, false_label)); \ - xops[3] = gen_rtx (MEM, Pmode, gen_rtx (SYMBOL_REF, VOIDmode, "__bb_init_func")); \ - xops[4] = gen_rtx (MEM, Pmode, xops[1]); \ + xops[1] = gen_rtx_SYMBOL_REF (VOIDmode, block_table); \ xops[5] = stack_pointer_rtx; \ - xops[6] = GEN_INT (4); \ - xops[7] = gen_rtx (REG, Pmode, 0); /* eax */ \ + xops[7] = gen_rtx_REG (Pmode, 0); /* eax */ \ \ CONSTANT_POOL_ADDRESS_P (xops[1]) = TRUE; \ - CONSTANT_POOL_ADDRESS_P (xops[2]) = TRUE; \ - \ - output_asm_insn (AS2(cmp%L4,%0,%4), xops); \ - output_asm_insn (AS1(jne,%2), xops); \ \ - if (!flag_pic) \ - output_asm_insn (AS1(push%L1,%1), xops); \ - else \ + switch (profile_block_flag) \ { \ - output_asm_insn (AS2 (lea%L7,%a1,%7), xops); \ - output_asm_insn (AS1 (push%L7,%7), xops); \ - } \ \ - output_asm_insn (AS1(call,%P3), xops); \ - output_asm_insn (AS2(add%L0,%6,%5), xops); \ - ASM_OUTPUT_INTERNAL_LABEL (STREAM, "LPBZ", num_func); \ - num_func++; \ + case 2: \ + \ + xops[2] = GEN_INT ((BLOCK_OR_LABEL)); \ + xops[3] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, "__bb_init_trace_func")); \ + xops[6] = GEN_INT (8); \ + \ + output_asm_insn (AS1(push%L2,%2), xops); \ + if (!flag_pic) \ + output_asm_insn (AS1(push%L1,%1), xops); \ + else \ + { \ + output_asm_insn (AS2 (lea%L7,%a1,%7), xops); \ + output_asm_insn (AS1 (push%L7,%7), xops); \ + } \ + \ + output_asm_insn (AS1(call,%P3), xops); \ + output_asm_insn (AS2(add%L0,%6,%5), xops); \ + \ + break; \ + \ + default: \ + \ + ASM_GENERATE_INTERNAL_LABEL (false_label, "LPBZ", num_func); \ + \ + xops[0] = const0_rtx; \ + xops[2] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, false_label)); \ + xops[3] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, "__bb_init_func")); \ + xops[4] = gen_rtx_MEM (Pmode, xops[1]); \ + xops[6] = GEN_INT (4); \ + \ + CONSTANT_POOL_ADDRESS_P (xops[2]) = TRUE; \ + \ + output_asm_insn (AS2(cmp%L4,%0,%4), xops); \ + output_asm_insn (AS1(jne,%2), xops); \ + \ + if (!flag_pic) \ + output_asm_insn (AS1(push%L1,%1), xops); \ + else \ + { \ + output_asm_insn (AS2 (lea%L7,%a1,%7), xops); \ + output_asm_insn (AS1 (push%L7,%7), xops); \ + } \ + \ + output_asm_insn (AS1(call,%P3), xops); \ + output_asm_insn (AS2(add%L0,%6,%5), xops); \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, "LPBZ", num_func); \ + num_func++; \ + \ + break; \ + \ + } \ } \ while (0) +/* The following macro shall output assembler code to FILE + to increment a counter associated with basic block number BLOCKNO. + + If profile_block_flag == 2 + + Output code to initialize the global structure `__bb' and + call the function `__bb_trace_func' which will increment the + counter. -/* A C statement or compound statement to increment the count - associated with the basic block number BLOCKNO. Basic blocks are - numbered separately from zero within each compilation. The count - associated with block number BLOCKNO is at index BLOCKNO in a - vector of words; the name of this array is a local symbol made - with this statement: + `__bb' consists of two words. In the first word the number + of the basic block has to be stored. In the second word + the address of a block allocated in the object module + has to be stored. - ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2); + The basic block number is given by BLOCKNO. - Of course, since you are writing the definition of - `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you - can take a short cut in the definition of this macro and use the - name that you know will result. */ + The address of the block is given by the label created with + + ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 0); + + by FUNCTION_BLOCK_PROFILER. + + Of course, since you are writing the definition of + `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you + can take a short cut in the definition of this macro and use the + name that you know will result. + + If described in a virtual assembler language the code to be + output looks like: + + move BLOCKNO -> (__bb) + move LPBX0 -> (__bb+4) + call __bb_trace_func + + Note that function `__bb_trace_func' must not change the + machine state, especially the flag register. To grant + this, you must output code to save and restore registers + either in this macro or in the macros MACHINE_STATE_SAVE + and MACHINE_STATE_RESTORE. The last two macros will be + used in the function `__bb_trace_func', so you must make + sure that the function prologue does not change any + register prior to saving it with MACHINE_STATE_SAVE. + + else if profile_block_flag != 0 + + Output code to increment the counter directly. + Basic blocks are numbered separately from zero within each + compiled object module. The count associated with block number + BLOCKNO is at index BLOCKNO in an array of words; the name of + this array is a local symbol made with this statement: + + ASM_GENERATE_INTERNAL_LABEL (BUFFER, "LPBX", 2); + + Of course, since you are writing the definition of + `ASM_GENERATE_INTERNAL_LABEL' as well as that of this macro, you + can take a short cut in the definition of this macro and use the + name that you know will result. + + If described in a virtual assembler language the code to be + output looks like: + + inc (LPBX2+4*BLOCKNO) + +*/ -#define BLOCK_PROFILER(STREAM, BLOCKNO) \ +#define BLOCK_PROFILER(FILE, BLOCKNO) \ do \ { \ - rtx xops[1], cnt_rtx; \ + rtx xops[8], cnt_rtx; \ char counts[80]; \ + char *block_table = counts; \ \ - ASM_GENERATE_INTERNAL_LABEL (counts, "LPBX", 2); \ - cnt_rtx = gen_rtx (SYMBOL_REF, VOIDmode, counts); \ - SYMBOL_REF_FLAG (cnt_rtx) = TRUE; \ + switch (profile_block_flag) \ + { \ \ - if (BLOCKNO) \ - cnt_rtx = plus_constant (cnt_rtx, (BLOCKNO)*4); \ + case 2: \ \ - if (flag_pic) \ - cnt_rtx = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, cnt_rtx); \ + ASM_GENERATE_INTERNAL_LABEL (block_table, "LPBX", 0); \ + \ + xops[1] = gen_rtx_SYMBOL_REF (VOIDmode, block_table); \ + xops[2] = GEN_INT ((BLOCKNO)); \ + xops[3] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, "__bb_trace_func")); \ + xops[4] = gen_rtx_SYMBOL_REF (VOIDmode, "__bb"); \ + xops[5] = plus_constant (xops[4], 4); \ + xops[0] = gen_rtx_MEM (SImode, xops[4]); \ + xops[6] = gen_rtx_MEM (SImode, xops[5]); \ + \ + CONSTANT_POOL_ADDRESS_P (xops[1]) = TRUE; \ + \ + fprintf(FILE, "\tpushf\n"); \ + output_asm_insn (AS2(mov%L0,%2,%0), xops); \ + if (flag_pic) \ + { \ + xops[7] = gen_rtx_REG (Pmode, 0); /* eax */ \ + output_asm_insn (AS1(push%L7,%7), xops); \ + output_asm_insn (AS2(lea%L7,%a1,%7), xops); \ + output_asm_insn (AS2(mov%L6,%7,%6), xops); \ + output_asm_insn (AS1(pop%L7,%7), xops); \ + } \ + else \ + output_asm_insn (AS2(mov%L6,%1,%6), xops); \ + output_asm_insn (AS1(call,%P3), xops); \ + fprintf(FILE, "\tpopf\n"); \ + \ + break; \ + \ + default: \ + \ + ASM_GENERATE_INTERNAL_LABEL (counts, "LPBX", 2); \ + cnt_rtx = gen_rtx_SYMBOL_REF (VOIDmode, counts); \ + SYMBOL_REF_FLAG (cnt_rtx) = TRUE; \ \ - xops[0] = gen_rtx (MEM, SImode, cnt_rtx); \ - output_asm_insn (AS1(inc%L0,%0), xops); \ + if (BLOCKNO) \ + cnt_rtx = plus_constant (cnt_rtx, (BLOCKNO)*4); \ + \ + if (flag_pic) \ + cnt_rtx = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, cnt_rtx); \ + \ + xops[0] = gen_rtx_MEM (SImode, cnt_rtx); \ + output_asm_insn (AS1(inc%L0,%0), xops); \ + \ + break; \ + \ + } \ } \ while (0) +/* The following macro shall output assembler code to FILE + to indicate a return from function during basic-block profiling. + + If profiling_block_flag == 2: + + Output assembler code to call function `__bb_trace_ret'. + + Note that function `__bb_trace_ret' must not change the + machine state, especially the flag register. To grant + this, you must output code to save and restore registers + either in this macro or in the macros MACHINE_STATE_SAVE_RET + and MACHINE_STATE_RESTORE_RET. The last two macros will be + used in the function `__bb_trace_ret', so you must make + sure that the function prologue does not change any + register prior to saving it with MACHINE_STATE_SAVE_RET. + + else if profiling_block_flag != 0: + + The macro will not be used, so it need not distinguish + these cases. +*/ + +#define FUNCTION_BLOCK_PROFILER_EXIT(FILE) \ +do \ + { \ + rtx xops[1]; \ + \ + xops[0] = gen_rtx_MEM (Pmode, gen_rtx_SYMBOL_REF (VOIDmode, "__bb_trace_ret")); \ + \ + output_asm_insn (AS1(call,%P0), xops); \ + \ + } \ +while (0) + +/* The function `__bb_trace_func' is called in every basic block + and is not allowed to change the machine state. Saving (restoring) + the state can either be done in the BLOCK_PROFILER macro, + before calling function (rsp. after returning from function) + `__bb_trace_func', or it can be done inside the function by + defining the macros: + + MACHINE_STATE_SAVE(ID) + MACHINE_STATE_RESTORE(ID) + + In the latter case care must be taken, that the prologue code + of function `__bb_trace_func' does not already change the + state prior to saving it with MACHINE_STATE_SAVE. + + The parameter `ID' is a string identifying a unique macro use. + + On the i386 the initialization code at the begin of + function `__bb_trace_func' contains a `sub' instruction + therefore we handle save and restore of the flag register + in the BLOCK_PROFILER macro. */ + +#define MACHINE_STATE_SAVE(ID) \ + asm (" pushl %eax"); \ + asm (" pushl %ecx"); \ + asm (" pushl %edx"); \ + asm (" pushl %esi"); + +#define MACHINE_STATE_RESTORE(ID) \ + asm (" popl %esi"); \ + asm (" popl %edx"); \ + asm (" popl %ecx"); \ + asm (" popl %eax"); + /* EXIT_IGNORE_STACK should be nonzero if, when returning from a function, the stack pointer does not matter. The value is tested only in functions that have frame pointers. @@ -1008,14 +1515,19 @@ while (0) off the end. This happens if the function ends in an "exit" call, or if a `return' insn is emitted directly into the function. */ -#define FUNCTION_EPILOGUE(FILE, SIZE) \ +#if 0 +#define FUNCTION_BEGIN_EPILOGUE(FILE) \ do { \ rtx last = get_last_insn (); \ if (last && GET_CODE (last) == NOTE) \ last = prev_nonnote_insn (last); \ - if (! last || GET_CODE (last) != BARRIER) \ - function_epilogue (FILE, SIZE); \ +/* if (! last || GET_CODE (last) != BARRIER) \ + function_epilogue (FILE, SIZE);*/ \ } while (0) +#endif + +#define FUNCTION_EPILOGUE(FILE, SIZE) \ + function_epilogue (FILE, SIZE) /* Output assembler code for a block containing the constant parts of a trampoline, leaving space for the variable parts. */ @@ -1046,8 +1558,8 @@ do { \ #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \ { \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 1)), CXT); \ - emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 6)), FNADDR); \ + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 1)), CXT); \ + emit_move_insn (gen_rtx_MEM (SImode, plus_constant (TRAMP, 6)), FNADDR); \ } /* Definitions for register eliminations. @@ -1094,8 +1606,9 @@ do { \ \ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \ if ((regs_ever_live[regno] && ! call_used_regs[regno]) \ - || (current_function_uses_pic_offset_table \ - && regno == PIC_OFFSET_TABLE_REGNUM)) \ + || ((current_function_uses_pic_offset_table \ + || current_function_uses_const_pool) \ + && flag_pic && regno == PIC_OFFSET_TABLE_REGNUM)) \ offset += 4; \ \ (OFFSET) = offset + get_frame_size (); \ @@ -1239,12 +1752,13 @@ do { \ #define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \ { \ - rtx orig_x = (X); \ (X) = legitimize_address (X, OLDX, MODE); \ if (memory_address_p (MODE, X)) \ goto WIN; \ } +#define REWRITE_ADDRESS(x) rewrite_address(x) + /* Nonzero if the constant value X is a legitimate general operand when generating PIC code. It is given that flag_pic is on and that X satisfies CONSTANT_P or is a CONST_DOUBLE. */ @@ -1279,6 +1793,15 @@ do \ { \ rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \ ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \ + \ + if (TARGET_DEBUG_ADDR \ + && TREE_CODE_CLASS (TREE_CODE (DECL)) == 'd') \ + { \ + fprintf (stderr, "Encode %s, public = %d\n", \ + IDENTIFIER_POINTER (DECL_NAME (DECL)), \ + TREE_PUBLIC (DECL)); \ + } \ + \ SYMBOL_REF_FLAG (XEXP (rtl, 0)) \ = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \ || ! TREE_PUBLIC (DECL)); \ @@ -1349,10 +1872,11 @@ while (0) for the index in the tablejump instruction. */ #define CASE_VECTOR_MODE Pmode -/* Define this if the tablejump instruction expects the table - to contain offsets from the address of the table. - Do not define this if the table should contain absolute addresses. */ -/* #define CASE_VECTOR_PC_RELATIVE */ +/* Define as C expression which evaluates to nonzero if the tablejump + instruction expects the table to contain offsets from the address of the + table. + Do not define this if the table should contain absolute addresses. */ +/* #define CASE_VECTOR_PC_RELATIVE 1 */ /* Specify the tree operation to be used to convert reals to integers. This should be changed to take advantage of fist --wfs ?? @@ -1369,22 +1893,23 @@ while (0) in one reasonably fast instruction. */ #define MOVE_MAX 4 -/* MOVE_RATIO is the number of move instructions that is better than a - block move. Make this large on i386, since the block move is very - inefficient with small blocks, and the hard register needs of the - block move require much reload work. */ -#define MOVE_RATIO 5 +/* The number of scalar move insns which should be generated instead + of a string move insn or a library call. Increasing the value + will always make code faster, but eventually incurs high cost in + increased code size. -/* Define this if zero-extension is slow (more than one real instruction). */ -/* #define SLOW_ZERO_EXTEND */ + If you don't define this, a reasonable default is used. -/* Nonzero if access to memory by bytes is slow and undesirable. */ -#define SLOW_BYTE_ACCESS 0 + Make this large on i386, since the block move is very inefficient with small + blocks, and the hard register needs of the block move require much reload + work. */ + +#define MOVE_RATIO 5 /* Define if shifts truncate the shift count which implies one can omit a sign-extension or zero-extension of a shift count. */ -/* One i386, shifts do truncate the count. But bit opcodes don't. */ +/* On i386, shifts do truncate the count. But bit opcodes don't. */ /* #define SHIFT_COUNT_TRUNCATED */ @@ -1411,70 +1936,194 @@ while (0) is a byte address (for indexing purposes) so give the MEM rtx a byte's mode. */ #define FUNCTION_MODE QImode - -/* Define this if addresses of constant functions - shouldn't be put through pseudo regs where they can be cse'd. - Desirable on the 386 because a CALL with a constant address is - not much slower than one with a register address. On a 486, - it is faster to call with a constant address than indirect. */ -#define NO_FUNCTION_CSE - -/* Provide the costs of a rtl expression. This is in the body of a - switch on CODE. */ - -#define RTX_COSTS(X,CODE,OUTER_CODE) \ - case MULT: \ - return COSTS_N_INSNS (20); \ - case DIV: \ - case UDIV: \ - case MOD: \ - case UMOD: \ - return COSTS_N_INSNS (20); \ - case ASHIFTRT: \ - case LSHIFTRT: \ - case ASHIFT: \ - return (4 + rtx_cost (XEXP (X, 0), OUTER_CODE) \ - + rtx_cost (XEXP (X, 1), OUTER_CODE)); \ - case PLUS: \ - if (GET_CODE (XEXP (X, 0)) == MULT \ - && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ - && (INTVAL (XEXP (XEXP (X, 0), 1)) == 2 \ - || INTVAL (XEXP (XEXP (X, 0), 1)) == 4 \ - || INTVAL (XEXP (XEXP (X, 0), 1)) == 8)) \ - return (2 + rtx_cost (XEXP (XEXP (X, 0), 0), OUTER_CODE) \ - + rtx_cost (XEXP (X, 1), OUTER_CODE)); \ - break; - - -/* Compute the cost of computing a constant rtl expression RTX - whose rtx-code is CODE. The body of this macro is a portion - of a switch statement. If the code is computed here, - return it with a return statement. Otherwise, break from the switch. */ + +/* A part of a C `switch' statement that describes the relative costs + of constant RTL expressions. It must contain `case' labels for + expression codes `const_int', `const', `symbol_ref', `label_ref' + and `const_double'. Each case must ultimately reach a `return' + statement to return the relative cost of the use of that kind of + constant value in an expression. The cost may depend on the + precise value of the constant, which is available for examination + in X, and the rtx code of the expression in which it is contained, + found in OUTER_CODE. + + CODE is the expression code--redundant, since it can be obtained + with `GET_CODE (X)'. */ #define CONST_COSTS(RTX,CODE,OUTER_CODE) \ case CONST_INT: \ + return (unsigned) INTVAL (RTX) < 256 ? 0 : 1; \ case CONST: \ case LABEL_REF: \ case SYMBOL_REF: \ - return flag_pic && SYMBOLIC_CONST (RTX) ? 2 : 0; \ + return flag_pic && SYMBOLIC_CONST (RTX) ? 2 : 1; \ + \ case CONST_DOUBLE: \ { \ int code; \ if (GET_MODE (RTX) == VOIDmode) \ return 2; \ + \ code = standard_80387_constant_p (RTX); \ return code == 1 ? 0 : \ code == 2 ? 1 : \ 2; \ } -/* Compute the cost of an address. This is meant to approximate the size - and/or execution delay of an insn using that address. If the cost is - approximated by the RTL complexity, including CONST_COSTS above, as - is usually the case for CISC machines, this macro should not be defined. - For aggressively RISCy machines, only one insn format is allowed, so - this macro should be a constant. The value of this macro only matters - for valid addresses. +/* Delete the definition here when TOPLEVEL_COSTS_N_INSNS gets added to cse.c */ +#define TOPLEVEL_COSTS_N_INSNS(N) {total = COSTS_N_INSNS (N); break;} + +/* Like `CONST_COSTS' but applies to nonconstant RTL expressions. + This can be used, for example, to indicate how costly a multiply + instruction is. In writing this macro, you can use the construct + `COSTS_N_INSNS (N)' to specify a cost equal to N fast + instructions. OUTER_CODE is the code of the expression in which X + is contained. + + This macro is optional; do not define it if the default cost + assumptions are adequate for the target machine. */ + +#define RTX_COSTS(X,CODE,OUTER_CODE) \ + case ASHIFT: \ + if (GET_CODE (XEXP (X, 1)) == CONST_INT \ + && GET_MODE (XEXP (X, 0)) == SImode) \ + { \ + HOST_WIDE_INT value = INTVAL (XEXP (X, 1)); \ + \ + if (value == 1) \ + return COSTS_N_INSNS (ix86_cost->add) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + \ + if (value == 2 || value == 3) \ + return COSTS_N_INSNS (ix86_cost->lea) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + } \ + /* fall through */ \ + \ + case ROTATE: \ + case ASHIFTRT: \ + case LSHIFTRT: \ + case ROTATERT: \ + if (GET_MODE (XEXP (X, 0)) == DImode) \ + { \ + if (GET_CODE (XEXP (X, 1)) == CONST_INT) \ + { \ + if (INTVAL (XEXP (X, 1)) > 32) \ + return COSTS_N_INSNS(ix86_cost->shift_const + 2); \ + return COSTS_N_INSNS(ix86_cost->shift_const * 2); \ + } \ + return ((GET_CODE (XEXP (X, 1)) == AND \ + ? COSTS_N_INSNS(ix86_cost->shift_var * 2) \ + : COSTS_N_INSNS(ix86_cost->shift_var * 6 + 2)) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE)); \ + } \ + return COSTS_N_INSNS (GET_CODE (XEXP (X, 1)) == CONST_INT \ + ? ix86_cost->shift_const \ + : ix86_cost->shift_var) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + \ + case MULT: \ + if (GET_CODE (XEXP (X, 1)) == CONST_INT) \ + { \ + unsigned HOST_WIDE_INT value = INTVAL (XEXP (X, 1)); \ + int nbits = 0; \ + \ + if (value == 2) \ + return COSTS_N_INSNS (ix86_cost->add) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + if (value == 4 || value == 8) \ + return COSTS_N_INSNS (ix86_cost->lea) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + \ + while (value != 0) \ + { \ + nbits++; \ + value >>= 1; \ + } \ + \ + if (nbits == 1) \ + return COSTS_N_INSNS (ix86_cost->shift_const) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + \ + return COSTS_N_INSNS (ix86_cost->mult_init \ + + nbits * ix86_cost->mult_bit) \ + + rtx_cost(XEXP (X, 0), OUTER_CODE); \ + } \ + \ + else /* This is arbitrary */ \ + TOPLEVEL_COSTS_N_INSNS (ix86_cost->mult_init \ + + 7 * ix86_cost->mult_bit); \ + \ + case DIV: \ + case UDIV: \ + case MOD: \ + case UMOD: \ + TOPLEVEL_COSTS_N_INSNS (ix86_cost->divide); \ + \ + case PLUS: \ + if (GET_CODE (XEXP (X, 0)) == REG \ + && GET_MODE (XEXP (X, 0)) == SImode \ + && GET_CODE (XEXP (X, 1)) == PLUS) \ + return COSTS_N_INSNS (ix86_cost->lea); \ + \ + /* fall through */ \ + case AND: \ + case IOR: \ + case XOR: \ + case MINUS: \ + if (GET_MODE (X) == DImode) \ + return COSTS_N_INSNS (ix86_cost->add) * 2 \ + + (rtx_cost (XEXP (X, 0), OUTER_CODE) \ + << (GET_MODE (XEXP (X, 0)) != DImode)) \ + + (rtx_cost (XEXP (X, 1), OUTER_CODE) \ + << (GET_MODE (XEXP (X, 1)) != DImode)); \ + case NEG: \ + case NOT: \ + if (GET_MODE (X) == DImode) \ + TOPLEVEL_COSTS_N_INSNS (ix86_cost->add * 2) \ + TOPLEVEL_COSTS_N_INSNS (ix86_cost->add) + + +/* An expression giving the cost of an addressing mode that contains + ADDRESS. If not defined, the cost is computed from the ADDRESS + expression and the `CONST_COSTS' values. + + For most CISC machines, the default cost is a good approximation + of the true cost of the addressing mode. However, on RISC + machines, all instructions normally have the same length and + execution time. Hence all addresses will have equal costs. + + In cases where more than one form of an address is known, the form + with the lowest cost will be used. If multiple forms have the + same, lowest, cost, the one that is the most complex will be used. + + For example, suppose an address that is equal to the sum of a + register and a constant is used twice in the same basic block. + When this macro is not defined, the address will be computed in a + register and memory references will be indirect through that + register. On machines where the cost of the addressing mode + containing the sum is no higher than that of a simple indirect + reference, this will produce an additional instruction and + possibly require an additional register. Proper specification of + this macro eliminates this overhead for such machines. + + Similar use of this macro is made in strength reduction of loops. + + ADDRESS need not be valid as an address. In such a case, the cost + is not relevant and can be any value; invalid addresses need not be + assigned a different cost. + + On machines where an address involving more than one register is as + cheap as an address computation involving only one register, + defining `ADDRESS_COST' to reflect this can cause two registers to + be live over a region of code where only one would have been if + `ADDRESS_COST' were not defined in that manner. This effect should + be considered in the definition of this macro. Equivalent costs + should probably only be given to addresses with different numbers + of registers on machines with lots of registers. + + This macro will normally either not be defined or be defined as a + constant. For i386, it is better to use a complex address than let gcc copy the address into a reg and make a new pseudo. But not if the address @@ -1487,6 +2136,193 @@ while (0) && REG_P (XEXP (RTX, 0)))) ? 0 \ : REG_P (RTX) ? 1 \ : 2) + +/* A C expression for the cost of moving data of mode M between a + register and memory. A value of 2 is the default; this cost is + relative to those in `REGISTER_MOVE_COST'. + + If moving between registers and memory is more expensive than + between two registers, you should define this macro to express the + relative cost. + + On the i386, copying between floating-point and fixed-point + registers is expensive. */ + +#define REGISTER_MOVE_COST(CLASS1, CLASS2) \ + (((FLOAT_CLASS_P (CLASS1) && ! FLOAT_CLASS_P (CLASS2)) \ + || (! FLOAT_CLASS_P (CLASS1) && FLOAT_CLASS_P (CLASS2))) ? 10 \ + : 2) + + +/* A C expression for the cost of moving data of mode M between a + register and memory. A value of 2 is the default; this cost is + relative to those in `REGISTER_MOVE_COST'. + + If moving between registers and memory is more expensive than + between two registers, you should define this macro to express the + relative cost. */ + +/* #define MEMORY_MOVE_COST(M,C,I) 2 */ + +/* A C expression for the cost of a branch instruction. A value of 1 + is the default; other values are interpreted relative to that. */ + +#define BRANCH_COST i386_branch_cost + +/* Define this macro as a C expression which is nonzero if accessing + less than a word of memory (i.e. a `char' or a `short') is no + faster than accessing a word of memory, i.e., if such access + require more than one instruction or if there is no difference in + cost between byte and (aligned) word loads. + + When this macro is not defined, the compiler will access a field by + finding the smallest containing object; when it is defined, a + fullword load will be used if alignment permits. Unless bytes + accesses are faster than word accesses, using word accesses is + preferable since it may eliminate subsequent memory access if + subsequent accesses occur to other fields in the same word of the + structure, but to different bytes. */ + +#define SLOW_BYTE_ACCESS 0 + +/* Nonzero if access to memory by shorts is slow and undesirable. */ +#define SLOW_SHORT_ACCESS 0 + +/* Define this macro if zero-extension (of a `char' or `short' to an + `int') can be done faster if the destination is a register that is + known to be zero. + + If you define this macro, you must have instruction patterns that + recognize RTL structures like this: + + (set (strict_low_part (subreg:QI (reg:SI ...) 0)) ...) + + and likewise for `HImode'. */ + +/* #define SLOW_ZERO_EXTEND */ + +/* Define this macro to be the value 1 if unaligned accesses have a + cost many times greater than aligned accesses, for example if they + are emulated in a trap handler. + + When this macro is non-zero, the compiler will act as if + `STRICT_ALIGNMENT' were non-zero when generating code for block + moves. This can cause significantly more instructions to be + produced. Therefore, do not set this macro non-zero if unaligned + accesses only add a cycle or two to the time for a memory access. + + If the value of this macro is always zero, it need not be defined. */ + +/* #define SLOW_UNALIGNED_ACCESS 0 */ + +/* Define this macro to inhibit strength reduction of memory + addresses. (On some machines, such strength reduction seems to do + harm rather than good.) */ + +/* #define DONT_REDUCE_ADDR */ + +/* Define this macro if it is as good or better to call a constant + function address than to call an address kept in a register. + + Desirable on the 386 because a CALL with a constant address is + faster than one with a register address. */ + +#define NO_FUNCTION_CSE + +/* Define this macro if it is as good or better for a function to call + itself with an explicit address than to call an address kept in a + register. */ + +#define NO_RECURSIVE_FUNCTION_CSE + +/* A C statement (sans semicolon) to update the integer variable COST + based on the relationship between INSN that is dependent on + DEP_INSN through the dependence LINK. The default is to make no + adjustment to COST. This can be used for example to specify to + the scheduler that an output- or anti-dependence does not incur + the same cost as a data-dependence. */ + +#define ADJUST_COST(insn,link,dep_insn,cost) \ + { \ + rtx next_inst; \ + if (GET_CODE (dep_insn) == CALL_INSN) \ + (cost) = 0; \ + \ + else if (GET_CODE (dep_insn) == INSN \ + && GET_CODE (PATTERN (dep_insn)) == SET \ + && GET_CODE (SET_DEST (PATTERN (dep_insn))) == REG \ + && GET_CODE (insn) == INSN \ + && GET_CODE (PATTERN (insn)) == SET \ + && !reg_overlap_mentioned_p (SET_DEST (PATTERN (dep_insn)), \ + SET_SRC (PATTERN (insn)))) \ + { \ + (cost) = 0; \ + } \ + \ + else if (GET_CODE (insn) == JUMP_INSN) \ + { \ + (cost) = 0; \ + } \ + \ + if (TARGET_PENTIUM) \ + { \ + if (cost !=0 && is_fp_insn (insn) && is_fp_insn (dep_insn) \ + && !is_fp_dest (dep_insn)) \ + { \ + (cost) = 0; \ + } \ + \ + if (agi_dependent (insn, dep_insn)) \ + { \ + (cost) = 3; \ + } \ + else if (GET_CODE (insn) == INSN \ + && GET_CODE (PATTERN (insn)) == SET \ + && SET_DEST (PATTERN (insn)) == cc0_rtx \ + && (next_inst = next_nonnote_insn (insn)) \ + && GET_CODE (next_inst) == JUMP_INSN) \ + { /* compare probably paired with jump */ \ + (cost) = 0; \ + } \ + } \ + else \ + if (!is_fp_dest (dep_insn)) \ + { \ + if(!agi_dependent (insn, dep_insn)) \ + (cost) = 0; \ + else if (TARGET_486) \ + (cost) = 2; \ + } \ + else \ + if (is_fp_store (insn) && is_fp_insn (dep_insn) \ + && NEXT_INSN (insn) && NEXT_INSN (NEXT_INSN (insn)) \ + && NEXT_INSN (NEXT_INSN (NEXT_INSN (insn))) \ + && (GET_CODE (NEXT_INSN (insn)) == INSN) \ + && (GET_CODE (NEXT_INSN (NEXT_INSN (insn))) == JUMP_INSN) \ + && (GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))) == NOTE) \ + && (NOTE_LINE_NUMBER (NEXT_INSN (NEXT_INSN (NEXT_INSN (insn)))) \ + == NOTE_INSN_LOOP_END)) \ + { \ + (cost) = 3; \ + } \ + } + + +#define ADJUST_BLOCKAGE(last_insn,insn,blockage) \ +{ \ + if (is_fp_store (last_insn) && is_fp_insn (insn) \ + && NEXT_INSN (last_insn) && NEXT_INSN (NEXT_INSN (last_insn)) \ + && NEXT_INSN (NEXT_INSN (NEXT_INSN (last_insn))) \ + && (GET_CODE (NEXT_INSN (last_insn)) == INSN) \ + && (GET_CODE (NEXT_INSN (NEXT_INSN (last_insn))) == JUMP_INSN) \ + && (GET_CODE (NEXT_INSN (NEXT_INSN (NEXT_INSN (last_insn)))) == NOTE) \ + && (NOTE_LINE_NUMBER (NEXT_INSN (NEXT_INSN (NEXT_INSN (last_insn)))) \ + == NOTE_INSN_LOOP_END)) \ + { \ + (blockage) = 3; \ + } \ +} + /* Add any extra modes needed to represent the condition code. @@ -1519,6 +2355,10 @@ extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); /* Here we define machine-dependent flags and fields in cc_status (see `conditions.h'). */ +/* Set if the cc value was actually from the 80387 and + we are testing eax directly (i.e. no sahf) */ +#define CC_TEST_AX 020000 + /* Set if the cc value is actually in the 80387, so a floating point conditional branch must be output. */ #define CC_IN_80387 04000 @@ -1527,6 +2367,10 @@ extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); the state of equality is indicated by zero in the carry bit. */ #define CC_Z_IN_NOT_C 010000 +/* Set if the CC value was actually from the 80387 and loaded directly + into the eflags instead of via eax/sahf. */ +#define CC_FCOMI 040000 + /* Store in cc_status the expressions that the condition codes will describe after execution of an instruction whose pattern is EXP. @@ -1572,10 +2416,10 @@ extern struct rtx_def *(*i386_compare_gen)(), *(*i386_compare_gen_eq)(); /* Table of additional register names to use in user input. */ #define ADDITIONAL_REGISTER_NAMES \ -{ "eax", 0, "edx", 1, "ecx", 2, "ebx", 3, \ - "esi", 4, "edi", 5, "ebp", 6, "esp", 7, \ - "al", 0, "dl", 1, "cl", 2, "bl", 3, \ - "ah", 0, "dh", 1, "ch", 2, "bh", 3 } +{ { "eax", 0 }, { "edx", 1 }, { "ecx", 2 }, { "ebx", 3 }, \ + { "esi", 4 }, { "edi", 5 }, { "ebp", 6 }, { "esp", 7 }, \ + { "al", 0 }, { "dl", 1 }, { "cl", 2 }, { "bl", 3 }, \ + { "ah", 0 }, { "dh", 1 }, { "ch", 2 }, { "bh", 3 } } /* Note we are omitting these since currently I don't know how to get gcc to use these, since they want the same but different @@ -1609,6 +2453,22 @@ number as al, and ax. (n) == 7 ? 5 : \ (n) + 4) +/* Before the prologue, RA is at 0(%esp). */ +#define INCOMING_RETURN_ADDR_RTX \ + gen_rtx_MEM (VOIDmode, gen_rtx_REG (VOIDmode, STACK_POINTER_REGNUM)) + +/* After the prologue, RA is at -4(AP) in the current frame. */ +#define RETURN_ADDR_RTX(COUNT, FRAME) \ + ((COUNT) == 0 \ + ? gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, arg_pointer_rtx, GEN_INT(-4)))\ + : gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, (FRAME), GEN_INT(4)))) + +/* PC is dbx register 8; let's use that column for RA. */ +#define DWARF_FRAME_RETURN_COLUMN 8 + +/* Before the prologue, the top of the frame is at 4(%esp). */ +#define INCOMING_FRAME_SP_OFFSET 4 + /* This is how to output the definition of a user-level label named NAME, such as the label on a static function or variable NAME. */ @@ -1620,10 +2480,7 @@ number as al, and ax. #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ do { long l[2]; \ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \ - if (sizeof (int) == sizeof (long)) \ - fprintf (FILE, "%s 0x%x,0x%x\n", ASM_LONG, l[0], l[1]); \ - else \ - fprintf (FILE, "%s 0x%lx,0x%lx\n", ASM_LONG, l[0], l[1]); \ + fprintf (FILE, "%s 0x%lx,0x%lx\n", ASM_LONG, l[0], l[1]); \ } while (0) /* This is how to output a `long double' extended real constant. */ @@ -1632,10 +2489,7 @@ do { long l[2]; \ #define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \ do { long l[3]; \ REAL_VALUE_TO_TARGET_LONG_DOUBLE (VALUE, l); \ - if (sizeof (int) == sizeof (long)) \ - fprintf (FILE, "%s 0x%x,0x%x,0x%x\n", ASM_LONG, l[0], l[1], l[2]); \ - else \ - fprintf (FILE, "%s 0x%lx,0x%lx,0x%lx\n", ASM_LONG, l[0], l[1], l[2]); \ + fprintf (FILE, "%s 0x%lx,0x%lx,0x%lx\n", ASM_LONG, l[0], l[1], l[2]); \ } while (0) /* This is how to output an assembler line defining a `float' constant. */ @@ -1643,10 +2497,7 @@ do { long l[3]; \ #define ASM_OUTPUT_FLOAT(FILE,VALUE) \ do { long l; \ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \ - if (sizeof (int) == sizeof (long)) \ - fprintf ((FILE), "%s 0x%x\n", ASM_LONG, l); \ - else \ - fprintf ((FILE), "%s 0x%lx\n", ASM_LONG, l); \ + fprintf ((FILE), "%s 0x%lx\n", ASM_LONG, l); \ } while (0) /* Store in OUTPUT a string (made with alloca) containing @@ -1698,13 +2549,13 @@ do { long l; \ It need not be very fast code. */ #define ASM_OUTPUT_REG_PUSH(FILE,REGNO) \ - fprintf (FILE, "\tpushl e%s\n", reg_names[REGNO]) + fprintf (FILE, "\tpushl %%e%s\n", reg_names[REGNO]) /* This is how to output an insn to pop a register from the stack. It need not be very fast code. */ #define ASM_OUTPUT_REG_POP(FILE,REGNO) \ - fprintf (FILE, "\tpopl e%s\n", reg_names[REGNO]) + fprintf (FILE, "\tpopl %%e%s\n", reg_names[REGNO]) /* This is how to output an element of a case-vector that is absolute. */ @@ -1717,7 +2568,7 @@ do { long l; \ forward reference the differences. */ -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.word %s%d-%s%d\n",LPREFIX, VALUE,LPREFIX, REL) /* Define the parentheses used to group arithmetic operations @@ -1746,9 +2597,13 @@ do { long l; \ R -- print the prefix for register names. z -- print the opcode suffix for the size of the current operand. * -- print a star (in certain assembler syntax) - w -- print the operand as if it's a "word" (HImode) even if it isn't. - b -- print the operand as if it's a byte (QImode) even if it isn't. - c -- don't print special prefixes before constant operands. */ + P -- if PIC, print an @PLT suffix. + X -- don't print any sort of PIC '@' suffix for a symbol. + J -- print jump insn for arithmetic_comparison_operator. + s -- ??? something to do with double shifts. not actually used, afaik. + C -- print a conditional move suffix corresponding to the op code. + c -- likewise, but reverse the condition. + F,f -- likewise, but for floating-point. */ #define PRINT_OPERAND_PUNCT_VALID_P(CODE) \ ((CODE) == '*') @@ -1853,13 +2708,30 @@ extern char *qi_high_reg_name[]; we can use for operand syntax in the extended asm */ #define ASM_OPERAND_LETTER '#' - #define RET return "" -#define AT_SP(mode) (gen_rtx (MEM, (mode), stack_pointer_rtx)) +#define AT_SP(mode) (gen_rtx_MEM ((mode), stack_pointer_rtx)) + +/* Helper macros to expand a binary/unary operator if needed */ +#define IX86_EXPAND_BINARY_OPERATOR(OP, MODE, OPERANDS) \ +do { \ + if (!ix86_expand_binary_operator (OP, MODE, OPERANDS)) \ + FAIL; \ +} while (0) + +#define IX86_EXPAND_UNARY_OPERATOR(OP, MODE, OPERANDS) \ +do { \ + if (!ix86_expand_unary_operator (OP, MODE, OPERANDS,)) \ + FAIL; \ +} while (0) + /* Functions in i386.c */ extern void override_options (); extern void order_regs_for_local_alloc (); +extern char *output_strlen_unroll (); +extern struct rtx_def *i386_sext16_if_const (); +extern int i386_aligned_p (); +extern int i386_cc_probably_useless_p (); extern int i386_valid_decl_attribute_p (); extern int i386_valid_type_attribute_p (); extern int i386_return_pops_args (); @@ -1868,6 +2740,7 @@ extern void init_cumulative_args (); extern void function_arg_advance (); extern struct rtx_def *function_arg (); extern int function_arg_partial_nregs (); +extern char *output_strlen_unroll (); extern void output_op_from_reg (); extern void output_to_reg (); extern char *singlemove_string (); @@ -1880,6 +2753,10 @@ extern int symbolic_operand (); extern int call_insn_operand (); extern int expander_call_insn_operand (); extern int symbolic_reference_mentioned_p (); +extern int ix86_expand_binary_operator (); +extern int ix86_binary_operator_ok (); +extern int ix86_expand_unary_operator (); +extern int ix86_unary_operator_ok (); extern void emit_pic_move (); extern void function_prologue (); extern int simple_386_epilogue (); @@ -1902,17 +2779,40 @@ extern void save_386_machine_status (); extern void restore_386_machine_status (); extern void clear_386_stack_locals (); extern struct rtx_def *assign_386_stack_local (); +extern int is_mul (); +extern int is_div (); +extern int last_to_set_cc (); +extern int doesnt_set_condition_code (); +extern int sets_condition_code (); +extern int str_immediate_operand (); +extern int is_fp_insn (); +extern int is_fp_dest (); +extern int is_fp_store (); +extern int agi_dependent (); +extern int reg_mentioned_in_mem (); +extern char *output_int_conditional_move (); +extern char *output_fp_conditional_move (); +extern int ix86_can_use_return_insn_p (); + +#ifdef NOTYET +extern struct rtx_def *copy_all_rtx (); +extern void rewrite_address (); +#endif /* Variables in i386.c */ +extern char *ix86_cpu_string; /* for -mcpu= */ +extern char *ix86_arch_string; /* for -march= */ extern char *i386_reg_alloc_order; /* register allocation order */ extern char *i386_regparm_string; /* # registers to use to pass args */ extern char *i386_align_loops_string; /* power of two alignment for loops */ extern char *i386_align_jumps_string; /* power of two alignment for non-loop jumps */ extern char *i386_align_funcs_string; /* power of two alignment for functions */ +extern char *i386_branch_cost_string; /* values 1-5: see jump.c */ extern int i386_regparm; /* i386_regparm_string as a number */ extern int i386_align_loops; /* power of two alignment for loops */ extern int i386_align_jumps; /* power of two alignment for non-loop jumps */ extern int i386_align_funcs; /* power of two alignment for functions */ +extern int i386_branch_cost; /* values 1-5: see jump.c */ extern char *hi_reg_name[]; /* names for 16 bit regs */ extern char *qi_reg_name[]; /* names for 8 bit regs (low) */ extern char *qi_high_reg_name[]; /* names for 8 bit regs (high) */ @@ -1921,11 +2821,12 @@ extern struct rtx_def *i386_compare_op0; /* operand 0 for comparisons */ extern struct rtx_def *i386_compare_op1; /* operand 1 for comparisons */ /* External variables used */ -extern int optimize; /* optimization level */ -extern int obey_regdecls; /* TRUE if stupid register allocation */ +extern int optimize; /* optimization level */ +extern int obey_regdecls; /* TRUE if stupid register allocation */ /* External functions used */ extern struct rtx_def *force_operand (); + /* Local variables: diff --git a/contrib/gcc/config/i386/i386.md b/contrib/gcc/config/i386/i386.md index ff0119631cb4..f85992fd2ca3 100644 --- a/contrib/gcc/config/i386/i386.md +++ b/contrib/gcc/config/i386/i386.md @@ -1,5 +1,5 @@ -;; GCC machine description for Intel X86. -;; Copyright (C) 1988, 1994, 1995 Free Software Foundation, Inc. +; GCC machine description for Intel X86. +;; Copyright (C) 1988, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. ;; Mostly by William Schelter. ;; This file is part of GNU CC. @@ -17,8 +17,7 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU CC; see the file COPYING. If not, write to ;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - +;; Boston, MA 02111-1307, USA. */ ;; The original PO technology requires these to be ordered by speed, ;; so that assigner will pick the fastest. @@ -37,8 +36,8 @@ ;; 'L' Print the opcode suffix for a 32-bit integer opcode. ;; 'W' Print the opcode suffix for a 16-bit integer opcode. ;; 'B' Print the opcode suffix for an 8-bit integer opcode. -;; 'S' Print the opcode suffix for a 32-bit float opcode. ;; 'Q' Print the opcode suffix for a 64-bit float opcode. +;; 'S' Print the opcode suffix for a 32-bit float opcode. ;; 'T' Print the opcode suffix for an 80-bit extended real XFmode float opcode. ;; 'J' Print the appropriate jump operand. @@ -59,6 +58,72 @@ ;; operand 0 is the argument for `sin'. ;; 2 This is a `cos' operation. The mode of the UNSPEC is MODE_FLOAT. ;; operand 0 is the argument for `cos'. +;; 3 This is part of a `stack probe' operation. The mode of the UNSPEC is +;; always SImode. operand 0 is the size of the stack allocation. +;; 4 This is the source of a fake SET of the frame pointer which is used to +;; prevent insns referencing it being scheduled across the initial +;; decrement of the stack pointer. +;; 5 This is a `bsf' operation. + +;; This shadows the processor_type enumeration, so changes must be made +;; to i386.h at the same time. + +(define_attr "type" "integer,idiv,imul,fld,fpop,fpdiv,fpmul" + (const_string "integer")) + +;; Functional units + +; (define_function_unit NAME MULTIPLICITY SIMULTANEITY +; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) + +; pentiumpro has a reservation station with 5 ports +; port 0 has integer, float add, integer divide, float divide, float +; multiply, and shifter units. +; port 1 has integer, and jump units. +; port 2 has the load address generation unit +; ports 3 and 4 have the store address generation units + +; pentium has two integer pipelines, the main u pipe and the secondary v pipe. +; and a float pipeline + +;; Floating point + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "fpop") (eq_attr "cpu" "i386,i486")) + 5 5) + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "fpop") (eq_attr "cpu" "pentium,pentiumpro")) + 3 0) + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "fpmul") (eq_attr "cpu" "pentium")) + 7 0) + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "fpmul") (eq_attr "cpu" "pentiumpro")) + 5 0) + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "idiv") (eq_attr "cpu" "pentiumpro")) + 10 10) + +(define_function_unit "fp" 1 0 + (and (eq_attr "type" "imul") (eq_attr "cpu" "pentiumpro")) + 6 0) + +(define_function_unit "fp" 1 0 + (eq_attr "type" "fpdiv") + 10 10) + +(define_function_unit "fp" 1 0 + (eq_attr "type" "fld") + 1 0) + +(define_function_unit "integer" 1 0 + (and (eq_attr "type" "integer") (eq_attr "cpu" "!i386")) + 2 0) + ;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM". ;; But restricting MEM here would mean that gcc could not remove a redundant @@ -72,6 +137,12 @@ ;; actually generating RTL. The bCOND or sCOND (emitted immediately ;; after the tstM or cmp) will actually emit the tstM or cmpM. +;; Processor type -- this attribute must exactly match the processor_type +;; enumeration in i386.h. + +(define_attr "cpu" "i386,i486,pentium,pentiumpro" + (const (symbol_ref "ix86_cpu"))) + (define_insn "tstsi_1" [(set (cc0) (match_operand:SI 0 "nonimmediate_operand" "rm"))] @@ -93,6 +164,7 @@ { i386_compare_gen = gen_tstsi_1; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -117,6 +189,7 @@ { i386_compare_gen = gen_tsthi_1; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -141,6 +214,7 @@ { i386_compare_gen = gen_tstqi_1; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -174,6 +248,7 @@ { i386_compare_gen = gen_tstsf_cc; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -207,6 +282,7 @@ { i386_compare_gen = gen_tstdf_cc; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -228,7 +304,7 @@ return output_fp_cc0_set (insn); }") -;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode +;; Don't generate tstxf if generating IEEE code, since the `ftst' opcode ;; isn't IEEE compliant. (define_expand "tstxf" @@ -240,6 +316,7 @@ { i386_compare_gen = gen_tstxf_cc; i386_compare_op0 = operands[0]; + i386_compare_op1 = const0_rtx; DONE; }") @@ -251,15 +328,7 @@ (compare (match_operand:SI 0 "nonimmediate_operand" "mr,r") (match_operand:SI 1 "general_operand" "ri,mr")))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" - "* -{ - if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) - { - cc_status.flags |= CC_REVERSED; - return AS2 (cmp%L0,%0,%1); - } - return AS2 (cmp%L0,%1,%0); -}") + "* return AS2 (cmp%L0,%1,%0);") (define_expand "cmpsi" [(set (cc0) @@ -282,15 +351,7 @@ (compare (match_operand:HI 0 "nonimmediate_operand" "mr,r") (match_operand:HI 1 "general_operand" "ri,mr")))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" - "* -{ - if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) - { - cc_status.flags |= CC_REVERSED; - return AS2 (cmp%W0,%0,%1); - } - return AS2 (cmp%W0,%1,%0); -}") + "* return AS2 (cmp%W0,%1,%0);") (define_expand "cmphi" [(set (cc0) @@ -313,15 +374,7 @@ (compare (match_operand:QI 0 "nonimmediate_operand" "q,mq") (match_operand:QI 1 "general_operand" "qm,nq")))] "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" - "* -{ - if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM) - { - cc_status.flags |= CC_REVERSED; - return AS2 (cmp%B0,%0,%1); - } - return AS2 (cmp%B0,%1,%0); -}") + "* return AS2 (cmp%B0,%1,%0);") (define_expand "cmpqi" [(set (cc0) @@ -346,11 +399,10 @@ (define_insn "" [(set (cc0) (match_operator 2 "VOIDmode_compare_op" - [(match_operand:XF 0 "nonimmediate_operand" "f") - (match_operand:XF 1 "nonimmediate_operand" "f")])) + [(match_operand:XF 0 "register_operand" "f") + (match_operand:XF 1 "register_operand" "f")])) (clobber (match_scratch:HI 3 "=a"))] - "TARGET_80387 - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" + "TARGET_80387" "* return output_float_compare (insn, operands);") (define_insn "" @@ -383,6 +435,16 @@ "TARGET_80387" "* return output_float_compare (insn, operands);") +(define_insn "" + [(set (cc0) + (match_operator 2 "VOIDmode_compare_op" + [(float_extend:XF + (match_operand:DF 0 "nonimmediate_operand" "fm")) + (match_operand:XF 1 "register_operand" "f")])) + (clobber (match_scratch:HI 3 "=a"))] + "TARGET_80387" + "* return output_float_compare (insn, operands);") + (define_insn "" [(set (cc0) (match_operator 2 "VOIDmode_compare_op" @@ -393,6 +455,16 @@ "TARGET_80387" "* return output_float_compare (insn, operands);") +(define_insn "" + [(set (cc0) + (match_operator 2 "VOIDmode_compare_op" + [(float_extend:XF + (match_operand:SF 0 "nonimmediate_operand" "fm")) + (match_operand:XF 1 "register_operand" "f")])) + (clobber (match_scratch:HI 3 "=a"))] + "TARGET_80387" + "* return output_float_compare (insn, operands);") + (define_insn "" [(set (cc0) (compare:CCFPEQ (match_operand:XF 0 "register_operand" "f") @@ -451,6 +523,16 @@ "TARGET_80387" "* return output_float_compare (insn, operands);") +(define_insn "" + [(set (cc0) + (match_operator 2 "VOIDmode_compare_op" + [(float_extend:DF + (match_operand:SF 0 "register_operand" "f")) + (match_operand:DF 1 "nonimmediate_operand" "fm")])) + (clobber (match_scratch:HI 3 "=a"))] + "TARGET_80387" + "* return output_float_compare (insn, operands);") + (define_insn "" [(set (cc0) (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f") @@ -520,7 +602,7 @@ (define_expand "cmpxf" [(set (cc0) (compare (match_operand:XF 0 "register_operand" "") - (match_operand:XF 1 "nonimmediate_operand" "")))] + (match_operand:XF 1 "register_operand" "")))] "TARGET_80387" " { @@ -534,28 +616,30 @@ (define_expand "cmpdf" [(set (cc0) (compare (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "nonimmediate_operand" "")))] + (match_operand:DF 1 "general_operand" "")))] "TARGET_80387" " { i386_compare_gen = gen_cmpdf_cc; i386_compare_gen_eq = gen_cmpdf_ccfpeq; i386_compare_op0 = operands[0]; - i386_compare_op1 = operands[1]; + i386_compare_op1 = (immediate_operand (operands[1], DFmode)) + ? copy_to_mode_reg (DFmode, operands[1]) : operands[1]; DONE; }") (define_expand "cmpsf" [(set (cc0) (compare (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "nonimmediate_operand" "")))] + (match_operand:SF 1 "general_operand" "")))] "TARGET_80387" " { i386_compare_gen = gen_cmpsf_cc; i386_compare_gen_eq = gen_cmpsf_ccfpeq; i386_compare_op0 = operands[0]; - i386_compare_op1 = operands[1]; + i386_compare_op1 = (immediate_operand (operands[1], SFmode)) + ? copy_to_mode_reg (SFmode, operands[1]) : operands[1]; DONE; }") @@ -573,11 +657,7 @@ (match_operand:XF 1 "register_operand" ""))) (clobber (match_scratch:HI 2 ""))])] "TARGET_80387" - " -{ - if (! register_operand (operands[1], XFmode)) - operands[1] = copy_to_mode_reg (XFmode, operands[1]); -}") + "") (define_expand "cmpdf_cc" [(parallel [(set (cc0) @@ -624,7 +704,7 @@ (define_insn "" [(set (cc0) (and:SI (match_operand:SI 0 "general_operand" "%ro") - (match_operand:SI 1 "general_operand" "ri")))] + (match_operand:SI 1 "nonmemory_operand" "ri")))] "" "* { @@ -682,7 +762,7 @@ (define_insn "" [(set (cc0) (and:HI (match_operand:HI 0 "general_operand" "%ro") - (match_operand:HI 1 "general_operand" "ri")))] + (match_operand:HI 1 "nonmemory_operand" "ri")))] "" "* { @@ -715,6 +795,12 @@ } } + /* use 32-bit test instruction if there are no sign issues */ + if (GET_CODE (operands[1]) == CONST_INT + && !(INTVAL (operands[1]) & ~0x7fff) + && i386_aligned_p (operands[0])) + return AS2 (test%L0,%1,%k0); + if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) return AS2 (test%W0,%1,%0); @@ -723,8 +809,8 @@ (define_insn "" [(set (cc0) - (and:QI (match_operand:QI 0 "general_operand" "%qm") - (match_operand:QI 1 "general_operand" "qi")))] + (and:QI (match_operand:QI 0 "nonimmediate_operand" "%qm") + (match_operand:QI 1 "nonmemory_operand" "qi")))] "" "* { @@ -741,24 +827,23 @@ (define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") - (match_operand:SI 1 "general_operand" "g"))] - "TARGET_386" - "push%L0 %1") - -;; On a 486, it is faster to move MEM to a REG and then push, rather than -;; push MEM directly. + (match_operand:SI 1 "nonmemory_operand" "rn"))] + "flag_pic" + "* return AS1 (push%L0,%1);") (define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") (match_operand:SI 1 "nonmemory_operand" "ri"))] - "!TARGET_386 && TARGET_MOVE" - "push%L0 %1") + "!flag_pic" + "* return AS1 (push%L0,%1);") + +;; On a 386, it is faster to push MEM directly. (define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") - (match_operand:SI 1 "general_operand" "ri"))] - "!TARGET_386 && !TARGET_MOVE" - "push%L0 %1") + (match_operand:SI 1 "memory_operand" "m"))] + "TARGET_PUSH_MEMORY" + "* return AS1 (push%L0,%1);") ;; General case of fullword move. @@ -790,8 +875,10 @@ (define_insn "" [(set (match_operand:SI 0 "general_operand" "=g,r") - (match_operand:SI 1 "general_operand" "ri,m"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + (match_operand:SI 1 "general_operand" "rn,im"))] + "((!TARGET_MOVE || GET_CODE (operands[0]) != MEM) + || (GET_CODE (operands[1]) != MEM)) + && flag_pic" "* { rtx link; @@ -810,29 +897,50 @@ /* Fastest way to change a 0 to a 1. */ return AS1 (inc%L0,%0); - if (flag_pic && SYMBOLIC_CONST (operands[1])) + if (SYMBOLIC_CONST (operands[1])) return AS2 (lea%L0,%a1,%0); return AS2 (mov%L0,%1,%0); }") (define_insn "" - [(set (match_operand:HI 0 "push_operand" "=<") - (match_operand:HI 1 "general_operand" "g"))] - "TARGET_386" - "push%W0 %1") + [(set (match_operand:SI 0 "general_operand" "=g,r") + (match_operand:SI 1 "general_operand" "ri,m"))] + "((!TARGET_MOVE || GET_CODE (operands[0]) != MEM) + || (GET_CODE (operands[1]) != MEM)) + && !flag_pic" + "* +{ + rtx link; + if (operands[1] == const0_rtx && REG_P (operands[0])) + return AS2 (xor%L0,%0,%0); + + if (operands[1] == const1_rtx + && (link = find_reg_note (insn, REG_WAS_0, 0)) + /* Make sure the insn that stored the 0 is still present. */ + && ! INSN_DELETED_P (XEXP (link, 0)) + && GET_CODE (XEXP (link, 0)) != NOTE + /* Make sure cross jumping didn't happen here. */ + && no_labels_between_p (XEXP (link, 0), insn) + /* Make sure the reg hasn't been clobbered. */ + && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) + /* Fastest way to change a 0 to a 1. */ + return AS1 (inc%L0,%0); + + return AS2 (mov%L0,%1,%0); +}") (define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") (match_operand:HI 1 "nonmemory_operand" "ri"))] - "!TARGET_386 && TARGET_MOVE" - "push%W0 %1") + "" + "* return AS1 (push%W0,%1);") (define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") - (match_operand:HI 1 "general_operand" "ri"))] - "!TARGET_386 && !TARGET_MOVE" - "push%W0 %1") + (match_operand:HI 1 "memory_operand" "m"))] + "TARGET_PUSH_MEMORY" + "* return AS1 (push%W0,%1);") ;; On i486, an incl and movl are both faster than incw and movw. @@ -876,10 +984,21 @@ if (REG_P (operands[0])) { - if (REG_P (operands[1])) - return AS2 (mov%L0,%k1,%k0); - else if (CONSTANT_P (operands[1])) - return AS2 (mov%L0,%1,%k0); + if (i386_aligned_p (operands[1])) + { + operands[1] = i386_sext16_if_const (operands[1]); + return AS2 (mov%L0,%k1,%k0); + } + if (TARGET_PENTIUMPRO) + { + /* movzwl is faster than movw on the Pentium Pro, + * although not as fast as an aligned movl. */ +#ifdef INTEL_SYNTAX + return AS2 (movzx,%1,%k0); +#else + return AS2 (movz%W0%L0,%1,%k0); +#endif + } } return AS2 (mov%W0,%1,%0); @@ -932,27 +1051,17 @@ ;; the amount pushed up to a halfword. (define_insn "" [(set (match_operand:QI 0 "push_operand" "=<") - (match_operand:QI 1 "immediate_operand" "n"))] + (match_operand:QI 1 "const_int_operand" "n"))] "" - "* return AS1 (push%W0,%1);") - -(define_insn "" - [(set (match_operand:QI 0 "push_operand" "=<") - (match_operand:QI 1 "nonimmediate_operand" "q"))] - "!TARGET_MOVE" - "* -{ - operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); - return AS1 (push%W0,%1); -}") + "* return AS1(push%W0,%1);") (define_insn "" [(set (match_operand:QI 0 "push_operand" "=<") (match_operand:QI 1 "register_operand" "q"))] - "TARGET_MOVE" + "" "* { - operands[1] = gen_rtx (REG, HImode, REGNO (operands[1])); + operands[1] = gen_rtx_REG (HImode, REGNO (operands[1])); return AS1 (push%W0,%1); }") @@ -978,14 +1087,14 @@ }") (define_insn "" - [(set (match_operand:QI 0 "general_operand" "=q,*r,qm") - (match_operand:QI 1 "general_operand" "*g,q,qn"))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=q,*r,qm") + (match_operand:QI 1 "general_operand" "*g,*rn,qn"))] "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* { rtx link; if (operands[1] == const0_rtx && REG_P (operands[0])) - return AS2 (xor%B0,%0,%0); + return AS2 (xor%L0,%k0,%k0); if (operands[1] == const1_rtx && (link = find_reg_note (insn, REG_WAS_0, 0)) @@ -996,8 +1105,14 @@ && no_labels_between_p (XEXP (link, 0), insn) /* Make sure the reg hasn't been clobbered. */ && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) - /* Fastest way to change a 0 to a 1. */ - return AS1 (inc%B0,%0); + { + /* Fastest way to change a 0 to a 1. + If inc%B0 isn't allowed, use inc%L0. */ + if (NON_QI_REG_P (operands[0])) + return AS1 (inc%L0,%k0); + else + return AS1 (inc%B0,%0); + } /* If mov%B0 isn't allowed for one of these regs, use mov%L0. */ if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1])) @@ -1032,7 +1147,7 @@ }") (define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+qm,q")) + [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) (match_operand:QI 1 "general_operand" "*qn,m"))] "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* @@ -1042,6 +1157,7 @@ return AS2 (xor%B0,%0,%0); if (operands[1] == const1_rtx + && ! NON_QI_REG_P (operands[0]) && (link = find_reg_note (insn, REG_WAS_0, 0)) /* Make sure the insn that stored the 0 is still present. */ && ! INSN_DELETED_P (XEXP (link, 0)) @@ -1063,43 +1179,10 @@ return AS2 (mov%B0,%1,%0); }") -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - /* Special case memory->memory moves and pushes */ - if (TARGET_MOVE - && (reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], SFmode))) - { - rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], SFmode)) - ? gen_movsf_push - : gen_movsf_mem; - - emit_insn ((*genfunc) (operands[0], operands[1])); - DONE; - } - - /* If we are loading a floating point constant that isn't 0 or 1 into a register, - indicate we need the pic register loaded. This could be optimized into stores - of constants if the target eventually moves to memory, but better safe than - sorry. */ - if (flag_pic - && GET_CODE (operands[0]) != MEM - && GET_CODE (operands[1]) == CONST_DOUBLE - && !standard_80387_constant_p (operands[1])) - { - current_function_uses_pic_offset_table = 1; - } -}") - -(define_insn "movsf_push_nomove" +(define_insn "movsf_push" [(set (match_operand:SF 0 "push_operand" "=<,<") - (match_operand:SF 1 "general_operand" "gF,f"))] - "!TARGET_MOVE" + (match_operand:SF 1 "general_operand" "*rfF,m"))] + "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed" "* { if (STACK_REG_P (operands[1])) @@ -1119,64 +1202,62 @@ output_asm_insn (AS1 (fstp%S0,%0), xops); else output_asm_insn (AS1 (fst%S0,%0), xops); + RET; } - return AS1 (push%L1,%1); + + return AS1 (push%L0,%1); }") -(define_insn "movsf_push" - [(set (match_operand:SF 0 "push_operand" "=<,<,<,<") - (match_operand:SF 1 "general_operand" "rF,f,m,m")) - (clobber (match_scratch:SI 2 "=X,X,r,X"))] +(define_insn "movsf_push_memory" + [(set (match_operand:SF 0 "push_operand" "=<") + (match_operand:SF 1 "memory_operand" "m"))] + "TARGET_PUSH_MEMORY" + "* return AS1 (push%L0,%1);") + +(define_expand "movsf" + [(set (match_operand:SF 0 "general_operand" "") + (match_operand:SF 1 "general_operand" ""))] "" - "* + " { - if (STACK_REG_P (operands[1])) + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) { - rtx xops[3]; + operands[1] = force_reg (SFmode, operands[1]); + } - if (! STACK_TOP_P (operands[1])) - abort (); + /* If we are loading a floating point constant that isn't 0 or 1 + into a register, indicate we need the pic register loaded. This could + be optimized into stores of constants if the target eventually moves + to memory, but better safe than sorry. */ + else if ((reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) != MEM + && GET_CODE (operands[1]) == CONST_DOUBLE + && !standard_80387_constant_p (operands[1])) + { + rtx insn, note, fp_const; - xops[0] = AT_SP (SFmode); - xops[1] = GEN_INT (4); - xops[2] = stack_pointer_rtx; + fp_const = force_const_mem (SFmode, operands[1]); + if (flag_pic) + current_function_uses_pic_offset_table = 1; - output_asm_insn (AS2 (sub%L2,%1,%2), xops); + insn = emit_insn (gen_rtx_SET (SFmode, operands[0], fp_const)); + note = find_reg_note (insn, REG_EQUAL, NULL_RTX); - if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fstp%S0,%0), xops); + if (note) + XEXP (note, 0) = operands[1]; else - output_asm_insn (AS1 (fst%S0,%0), xops); - RET; - } - - else if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != REG) - return AS1 (push%L1,%1); - - else - { - output_asm_insn (AS2 (mov%L2,%1,%2), operands); - return AS1 (push%L2,%2); + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn)); } }") -;; Special memory<->memory pattern that combine will recreate from the -;; moves to pseudos. -(define_insn "movsf_mem" - [(set (match_operand:SF 0 "memory_operand" "=m") - (match_operand:SF 1 "memory_operand" "m")) - (clobber (match_scratch:SI 2 "=&r"))] - "" - "* -{ - output_asm_insn (AS2 (mov%L2,%1,%2), operands); - return AS2 (mov%L0,%2,%0); -}") - ;; For the purposes of regclass, prefer FLOAT_REGS. -(define_insn "movsf_normal" - [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm") +(define_insn "" + [(set (match_operand:SF 0 "nonimmediate_operand" "=*rfm,*rf,f,!*rm") (match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))] "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" "* @@ -1203,7 +1284,7 @@ if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1228,7 +1309,9 @@ /* Handle all SFmode moves not involving the 387 */ return singlemove_string (operands); -}") +}" + [(set_attr "type" "fld")]) + (define_insn "swapsf" [(set (match_operand:SF 0 "register_operand" "f") @@ -1244,50 +1327,17 @@ return AS1 (fxch,%0); }") -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - /* Special case memory->memory moves and pushes */ - if (TARGET_MOVE - && (reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DFmode))) - { - rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DFmode)) - ? gen_movdf_push - : gen_movdf_mem; - - emit_insn ((*genfunc) (operands[0], operands[1])); - DONE; - } - - /* If we are loading a floating point constant that isn't 0 or 1 into a register, - indicate we need the pic register loaded. This could be optimized into stores - of constants if the target eventually moves to memory, but better safe than - sorry. */ - if (flag_pic - && GET_CODE (operands[0]) != MEM - && GET_CODE (operands[1]) == CONST_DOUBLE - && !standard_80387_constant_p (operands[1])) - { - current_function_uses_pic_offset_table = 1; - } -}") - -(define_insn "movdf_push_nomove" +(define_insn "movdf_push" [(set (match_operand:DF 0 "push_operand" "=<,<") - (match_operand:DF 1 "general_operand" "gF,f"))] - "!TARGET_MOVE" + (match_operand:DF 1 "general_operand" "*rfF,o"))] + "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed" "* { if (STACK_REG_P (operands[1])) { rtx xops[3]; - xops[0] = AT_SP (SFmode); + xops[0] = AT_SP (DFmode); xops[1] = GEN_INT (8); xops[2] = stack_pointer_rtx; @@ -1300,56 +1350,65 @@ RET; } - else - return output_move_double (operands); + + if (which_alternative == 1) + return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 0, 0); + + return output_move_double (operands); }") -(define_insn "movdf_push" - [(set (match_operand:DF 0 "push_operand" "=<,<,<,<,<") - (match_operand:DF 1 "general_operand" "rF,f,o,o,o")) - (clobber (match_scratch:SI 2 "=X,X,&r,&r,X")) - (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))] +(define_insn "movdf_push_memory" + [(set (match_operand:DF 0 "push_operand" "=<") + (match_operand:DF 1 "memory_operand" "o"))] + "TARGET_PUSH_MEMORY" + "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode),0,0);") + +(define_expand "movdf" + [(set (match_operand:DF 0 "general_operand" "") + (match_operand:DF 1 "general_operand" ""))] "" - "* + " { - if (STACK_REG_P (operands[1])) + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) { - rtx xops[3]; + operands[1] = force_reg (DFmode, operands[1]); + } - xops[0] = AT_SP (SFmode); - xops[1] = GEN_INT (8); - xops[2] = stack_pointer_rtx; + /* If we are loading a floating point constant that isn't 0 or 1 into a + register, indicate we need the pic register loaded. This could be + optimized into stores of constants if the target eventually moves to + memory, but better safe than sorry. */ + else if ((reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) != MEM + && GET_CODE (operands[1]) == CONST_DOUBLE + && !standard_80387_constant_p (operands[1])) + { + rtx insn, note, fp_const; - output_asm_insn (AS2 (sub%L2,%1,%2), xops); + fp_const = force_const_mem (DFmode, operands[1]); + if (flag_pic) + current_function_uses_pic_offset_table = 1; - if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fstp%Q0,%0), xops); - else - output_asm_insn (AS1 (fst%Q0,%0), xops); + insn = emit_insn (gen_rtx_SET (DFmode, operands[0], fp_const)); + note = find_reg_note (insn, REG_EQUAL, NULL_RTX); - RET; + if (note) + XEXP (note, 0) = operands[1]; + else + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn)); } - - else if (GET_CODE (operands[1]) != MEM) - return output_move_double (operands); - - else - return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 2, 4); }") -(define_insn "movdf_mem" - [(set (match_operand:DF 0 "memory_operand" "=o,o") - (match_operand:DF 1 "memory_operand" "o,o")) - (clobber (match_scratch:SI 2 "=&r,&r")) - (clobber (match_scratch:SI 3 "=&r,X"))] - "" - "* return output_move_memory (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);") - ;; For the purposes of regclass, prefer FLOAT_REGS. -(define_insn "movdf_normal" - [(set (match_operand:DF 0 "general_operand" "=f,fm,!*rf,!*rm") +(define_insn "" + [(set (match_operand:DF 0 "nonimmediate_operand" "=f,fm,!*rf,!*rm") (match_operand:DF 1 "general_operand" "fmG,f,*rfm,*rfF"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) + || (GET_CODE (operands[1]) != MEM)" "* { int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; @@ -1374,7 +1433,7 @@ if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1399,7 +1458,10 @@ /* Handle all DFmode moves not involving the 387 */ return output_move_double (operands); -}") +}" + [(set_attr "type" "fld")]) + + (define_insn "swapdf" [(set (match_operand:DF 0 "register_operand" "f") @@ -1415,109 +1477,87 @@ return AS1 (fxch,%0); }") -(define_expand "movxf" - [(set (match_operand:XF 0 "general_operand" "") - (match_operand:XF 1 "general_operand" ""))] - "" - " -{ - /* Special case memory->memory moves and pushes */ - if (TARGET_MOVE - && (reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) == MEM - && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], XFmode))) - { - rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], XFmode)) - ? gen_movxf_push - : gen_movxf_mem; - - emit_insn ((*genfunc) (operands[0], operands[1])); - DONE; - } - - /* If we are loading a floating point constant that isn't 0 or 1 into a register, - indicate we need the pic register loaded. This could be optimized into stores - of constants if the target eventually moves to memory, but better safe than - sorry. */ - if (flag_pic - && GET_CODE (operands[0]) != MEM - && GET_CODE (operands[1]) == CONST_DOUBLE - && !standard_80387_constant_p (operands[1])) - { - current_function_uses_pic_offset_table = 1; - } -}") - - -(define_insn "movxf_push_nomove" +(define_insn "movxf_push" [(set (match_operand:XF 0 "push_operand" "=<,<") - (match_operand:XF 1 "general_operand" "gF,f"))] - "!TARGET_MOVE" + (match_operand:XF 1 "general_operand" "*rfF,o"))] + "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed" "* { if (STACK_REG_P (operands[1])) { rtx xops[3]; - xops[0] = AT_SP (SFmode); + xops[0] = AT_SP (XFmode); xops[1] = GEN_INT (12); xops[2] = stack_pointer_rtx; output_asm_insn (AS2 (sub%L2,%1,%2), xops); + output_asm_insn (AS1 (fstp%T0,%0), xops); if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) output_asm_insn (AS1 (fld%T0,%0), xops); RET; } - else - return output_move_double (operands); + + if (which_alternative == 1) + return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 0, 0); + + return output_move_double (operands); }") -(define_insn "movxf_push" - [(set (match_operand:XF 0 "push_operand" "=<,<,<,<,<") - (match_operand:XF 1 "general_operand" "rF,f,o,o,o")) - (clobber (match_scratch:SI 2 "=X,X,&r,&r,X")) - (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))] +(define_insn "movxf_push_memory" + [(set (match_operand:XF 0 "push_operand" "=<") + (match_operand:XF 1 "memory_operand" "o"))] + "TARGET_PUSH_MEMORY" + "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode),0,0);") + +(define_expand "movxf" + [(set (match_operand:XF 0 "general_operand" "") + (match_operand:XF 1 "general_operand" ""))] "" - "* + " { - if (STACK_REG_P (operands[1])) + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) { - rtx xops[3]; - - xops[0] = AT_SP (SFmode); - xops[1] = GEN_INT (12); - xops[2] = stack_pointer_rtx; + operands[1] = force_reg (XFmode, operands[1]); + } - output_asm_insn (AS2 (sub%L2,%1,%2), xops); - output_asm_insn (AS1 (fstp%T0,%0), xops); - if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fld%T0,%0), xops); + /* If we are loading a floating point constant that isn't 0 or 1 + into a register, indicate we need the pic register loaded. This could + be optimized into stores of constants if the target eventually moves + to memory, but better safe than sorry. */ + else if ((reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) != MEM + && GET_CODE (operands[1]) == CONST_DOUBLE + && !standard_80387_constant_p (operands[1])) + { + rtx insn, note, fp_const; - RET; - } + fp_const = force_const_mem (XFmode, operands[1]); + if (flag_pic) + current_function_uses_pic_offset_table = 1; - else if (GET_CODE (operands[1]) != MEM - || GET_CODE (operands[2]) != REG) - return output_move_double (operands); + insn = emit_insn (gen_rtx_SET (XFmode, operands[0], fp_const)); + note = find_reg_note (insn, REG_EQUAL, NULL_RTX); - else - return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 2, 4); + if (note) + XEXP (note, 0) = operands[1]; + else + REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn)); + } }") -(define_insn "movxf_mem" - [(set (match_operand:XF 0 "memory_operand" "=o,o") - (match_operand:XF 1 "memory_operand" "o,o")) - (clobber (match_scratch:SI 2 "=&r,&r")) - (clobber (match_scratch:SI 3 "=&r,X"))] - "" - "* return output_move_memory (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);") -(define_insn "movxf_normal" - [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm") +(define_insn "" + [(set (match_operand:XF 0 "nonimmediate_operand" "=f,fm,!*rf,!*rm") (match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) + || (GET_CODE (operands[1]) != MEM)" "* { int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; @@ -1542,7 +1582,7 @@ if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1570,7 +1610,7 @@ return output_move_double (operands); }") -(define_insn "swapxf" +(define_insn "swapxf" [(set (match_operand:XF 0 "register_operand" "f") (match_operand:XF 1 "register_operand" "f")) (set (match_dup 1) @@ -1585,36 +1625,40 @@ }") (define_insn "" - [(set (match_operand:DI 0 "push_operand" "=<,<,<,<") - (match_operand:DI 1 "general_operand" "riF,o,o,o")) - (clobber (match_scratch:SI 2 "=X,&r,&r,X")) - (clobber (match_scratch:SI 3 "=X,&r,X,X"))] + [(set (match_operand:DI 0 "push_operand" "=<") + (match_operand:DI 1 "general_operand" "riF"))] "" - "* -{ - if (GET_CODE (operands[1]) != MEM) - return output_move_double (operands); + "* return output_move_double (operands);") - else - return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode), 2, 4); -}") +(define_insn "" + [(set (match_operand:DI 0 "push_operand" "=<") + (match_operand:DI 1 "memory_operand" "o"))] + "TARGET_PUSH_MEMORY" + "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode),0,0);") -(define_insn "movdi" - [(set (match_operand:DI 0 "general_operand" "=o,o,r,rm") - (match_operand:DI 1 "general_operand" "o,o,m,riF")) - (clobber (match_scratch:SI 2 "=&r,&r,X,X")) - (clobber (match_scratch:SI 3 "=&r,X,X,X"))] +(define_expand "movdi" + [(set (match_operand:DI 0 "general_operand" "") + (match_operand:DI 1 "general_operand" ""))] "" - "* + " { - rtx low[2], high[2], xop[6]; - - if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - return output_move_double (operands); - else - return output_move_memory (operands, insn, GET_MODE_SIZE (DImode), 2, 4); + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) + { + operands[1] = force_reg (DImode, operands[1]); + } }") +(define_insn "" + [(set (match_operand:DI 0 "general_operand" "=g,r") + (match_operand:DI 1 "general_operand" "riF,m"))] + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) + || (GET_CODE (operands[1]) != MEM)" + "* return output_move_double (operands);") + ;;- conversion instructions ;;- NONE @@ -1623,21 +1667,39 @@ ;; See comments by `andsi' for when andl is faster than movzx. (define_insn "zero_extendhisi2" - [(set (match_operand:SI 0 "general_operand" "=r") - (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "rm")))] + [(set (match_operand:SI 0 "register_operand" "=r,&r,?r") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,rm,rm")))] "" "* -{ - if ((!TARGET_386 || REGNO (operands[0]) == 0) + { + rtx xops[2]; + + if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0) && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) { - rtx xops[2]; xops[0] = operands[0]; xops[1] = GEN_INT (0xffff); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; } + if (TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1])) + { + output_asm_insn (AS2 (xor%L0,%0,%0),operands); + output_asm_insn (AS2 (mov%W0,%1,%w0),operands); + RET; + } + + if (TARGET_ZERO_EXTEND_WITH_AND) + { + xops[0] = operands[0]; + xops[1] = GEN_INT (0xffff); + if (i386_aligned_p (operands[1])) + output_asm_insn (AS2 (mov%L0,%k1,%k0),operands); + else + output_asm_insn (AS2 (mov%W0,%1,%w0),operands); + output_asm_insn (AS2 (and%L0,%1,%k0), xops); + RET; + } #ifdef INTEL_SYNTAX return AS2 (movzx,%1,%0); @@ -1646,23 +1708,62 @@ #endif }") +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] + "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (match_dup 0) + (const_int 0)) + (set (strict_low_part (match_dup 2)) + (match_dup 1))] + "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));") + + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:HI 1 "memory_operand" "")))] + "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (strict_low_part (match_dup 2)) + (match_dup 1)) + (set (match_dup 0) + (and:SI (match_dup 0) + (const_int 65535)))] + "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));") + (define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "general_operand" "=r") - (zero_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "qm")))] + [(set (match_operand:HI 0 "register_operand" "=q,&q,?r") + (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))] "" "* -{ - if ((!TARGET_386 || REGNO (operands[0]) == 0) - && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) + { + rtx xops[2]; + + if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0) + && REG_P (operands[1]) + && REGNO (operands[0]) == REGNO (operands[1])) { - rtx xops[2]; xops[0] = operands[0]; xops[1] = GEN_INT (0xff); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; } - + if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0])) + { + if(!reg_overlap_mentioned_p(operands[0],operands[1])) + { + output_asm_insn (AS2 (xor%L0,%k0,%k0), operands); + output_asm_insn (AS2 (mov%B0,%1,%b0), operands); + } + else + { + xops[0] = operands[0]; + xops[1] = GEN_INT (0xff); + output_asm_insn (AS2 (mov%B0,%1,%b0),operands); + output_asm_insn (AS2 (and%L0,%1,%k0), xops); + } + RET; + } + #ifdef INTEL_SYNTAX return AS2 (movzx,%1,%0); #else @@ -1670,19 +1771,86 @@ #endif }") +(define_split + [(set (match_operand:HI 0 "register_operand" "") + (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] + "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND + && !reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (match_dup 0) + (const_int 0)) + (set (strict_low_part (match_dup 2)) + (match_dup 1))] + "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") + + +(define_split + [(set (match_operand:HI 0 "register_operand" "") + (zero_extend:HI (match_operand:QI 1 "memory_operand" "")))] + "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND + && reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (strict_low_part (match_dup 2)) + (match_dup 1)) + (set (match_dup 0) + (and:HI (match_dup 0) + (const_int 255)))] + "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") + +(define_split + [(set (match_operand:HI 0 "register_operand" "") + (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] + "reload_completed && TARGET_ZERO_EXTEND_WITH_AND" + [(set (match_dup 0) + (match_dup 2)) + (set (match_dup 0) + (and:HI (match_dup 0) + (const_int 255)))] + "if (GET_CODE (operands[1]) == SUBREG && SUBREG_WORD (operands[1]) == 0) + operands[1] = SUBREG_REG (operands[1]); + if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG + || REGNO (operands[0]) == REGNO (operands[1])) + FAIL; + operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));") + (define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "general_operand" "=r") - (zero_extend:SI - (match_operand:QI 1 "nonimmediate_operand" "qm")))] + [(set (match_operand:SI 0 "register_operand" "=q,&q,?r") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))] "" "* -{ - if ((!TARGET_386 || REGNO (operands[0]) == 0) - && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) + { + rtx xops[2]; + + if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0) + && REG_P (operands[1]) + && REGNO (operands[0]) == REGNO (operands[1])) + { + xops[0] = operands[0]; + xops[1] = GEN_INT (0xff); + output_asm_insn (AS2 (and%L0,%1,%k0), xops); + RET; + } + if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0])) + { + if(!reg_overlap_mentioned_p (operands[0], operands[1])) + { + output_asm_insn (AS2 (xor%L0,%0,%0),operands); + output_asm_insn (AS2 (mov%B0,%1,%b0),operands); + } + else + { + xops[0] = operands[0]; + xops[1] = GEN_INT (0xff); + output_asm_insn (AS2 (mov%B0,%1,%b0), operands); + output_asm_insn (AS2 (and%L0,%1,%k0), xops); + } + RET; + } + + if (TARGET_ZERO_EXTEND_WITH_AND && GET_CODE (operands[1]) == REG) { - rtx xops[2]; xops[0] = operands[0]; xops[1] = GEN_INT (0xff); + operands[1] = gen_rtx_REG (SImode, REGNO (operands[1])); + output_asm_insn (AS2 (mov%L0,%1,%0), operands); output_asm_insn (AS2 (and%L0,%1,%k0), xops); RET; } @@ -1694,23 +1862,77 @@ #endif }") +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] + "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND + && !reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (match_dup 0) + (const_int 0)) + (set (strict_low_part (match_dup 2)) + (match_dup 1))] + "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") + + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:QI 1 "memory_operand" "")))] + "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND + && reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (strict_low_part (match_dup 2)) + (match_dup 1)) + (set (match_dup 0) + (and:SI (match_dup 0) + (const_int 255)))] + "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") + +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] + "reload_completed && TARGET_ZERO_EXTEND_WITH_AND + && ! reg_overlap_mentioned_p (operands[0], operands[1])" + [(set (match_dup 0) + (match_dup 2)) + (set (match_dup 0) + (and:SI (match_dup 0) + (const_int 255)))] + "operands[2] = gen_rtx_REG (SImode, true_regnum (operands[1]));") + (define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI - (match_operand:SI 1 "register_operand" "0")))] + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?m") + (zero_extend:DI (match_operand:SI 1 "register_operand" "0,rm,r")))] "" "* -{ - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - return AS2 (xor%L0,%0,%0); + { + rtx high[2], low[2], xops[4]; + + if (REG_P (operands[0]) && REG_P (operands[1]) + && REGNO (operands[0]) == REGNO (operands[1])) + { + operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); + return AS2 (xor%L0,%0,%0); + } + + split_di (operands, 1, low, high); + xops[0] = low[0]; + xops[1] = operands[1]; + xops[2] = high[0]; + xops[3] = const0_rtx; + + output_asm_insn (AS2 (mov%L0,%1,%0), xops); + if (GET_CODE (low[0]) == MEM) + output_asm_insn (AS2 (mov%L2,%3,%2), xops); + else + output_asm_insn (AS2 (xor%L2,%2,%2), xops); + + RET; }") ;;- sign extension instructions (define_insn "extendsidi2" [(set (match_operand:DI 0 "register_operand" "=r") - (sign_extend:DI - (match_operand:SI 1 "register_operand" "0")))] + (sign_extend:DI (match_operand:SI 1 "register_operand" "0")))] "" "* { @@ -1724,7 +1946,7 @@ #endif } - operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); output_asm_insn (AS2 (mov%L0,%0,%1), operands); operands[0] = GEN_INT (31); @@ -1736,9 +1958,8 @@ ;; We use what the Unix assembler expects. (define_insn "extendhisi2" - [(set (match_operand:SI 0 "general_operand" "=r") - (sign_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "rm")))] + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))] "" "* { @@ -1758,9 +1979,8 @@ }") (define_insn "extendqihi2" - [(set (match_operand:HI 0 "general_operand" "=r") - (sign_extend:HI - (match_operand:QI 1 "nonimmediate_operand" "qm")))] + [(set (match_operand:HI 0 "register_operand" "=r") + (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))] "" "* { @@ -1776,9 +1996,8 @@ }") (define_insn "extendqisi2" - [(set (match_operand:SI 0 "general_operand" "=r") - (sign_extend:SI - (match_operand:QI 1 "nonimmediate_operand" "qm")))] + [(set (match_operand:SI 0 "register_operand" "=r") + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))] "" "* { @@ -1788,13 +2007,72 @@ return AS2 (movs%B0%L0,%1,%0); #endif }") + + +;; Truncation of long long -> 32 bit + +(define_expand "truncdisi2" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m") + (truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))] + "" + " +{ + /* Don't generate memory->memory moves, go through a register */ + if (TARGET_MOVE + && (reload_in_progress | reload_completed) == 0 + && GET_CODE (operands[0]) == MEM + && GET_CODE (operands[1]) == MEM) + { + rtx target = gen_reg_rtx (SImode); + emit_insn (gen_truncdisi2 (target, operands[1])); + emit_move_insn (operands[0], target); + DONE; + } +}") + +(define_insn "" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m") + (truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))] + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + "* +{ + rtx low[2], high[2], xops[2]; + + split_di (&operands[1], 1, low, high); + xops[0] = operands[0]; + xops[1] = low[0]; + if (!rtx_equal_p (xops[0], xops[1])) + output_asm_insn (AS2 (mov%L0,%1,%0), xops); + + RET; +}") + +(define_insn "" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m") + (truncate:SI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r") + (const_int 32))))] + "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" + "* +{ + rtx low[2], high[2], xops[2]; + + split_di (&operands[1], 1, low, high); + xops[0] = operands[0]; + xops[1] = high[0]; + if (!rtx_equal_p (xops[0], xops[1])) + output_asm_insn (AS2 (mov%L0,%1,%0), xops); + + RET; +}") + + ;; Conversions between float and double. (define_insn "extendsfdf2" - [(set (match_operand:DF 0 "general_operand" "=fm,f") + [(set (match_operand:DF 0 "nonimmediate_operand" "=fm,f") (float_extend:DF - (match_operand:SF 1 "general_operand" "f,fm")))] + (match_operand:SF 1 "nonimmediate_operand" "f,fm")))] "TARGET_80387" "* { @@ -1808,7 +2086,7 @@ if (NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1827,9 +2105,9 @@ }") (define_insn "extenddfxf2" - [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r") + [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r") (float_extend:XF - (match_operand:DF 1 "general_operand" "f,fm,!*r,f")))] + (match_operand:DF 1 "nonimmediate_operand" "f,fm,!*r,f")))] "TARGET_80387" "* { @@ -1843,7 +2121,7 @@ if (NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1862,9 +2140,9 @@ }") (define_insn "extendsfxf2" - [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r") + [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r") (float_extend:XF - (match_operand:SF 1 "general_operand" "f,fm,!*r,f")))] + (match_operand:SF 1 "nonimmediate_operand" "f,fm,!*r,f")))] "TARGET_80387" "* { @@ -1878,7 +2156,7 @@ if (NON_STACK_REG_P (operands[0])) { - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } @@ -1939,7 +2217,7 @@ }") (define_insn "truncxfsf2" - [(set (match_operand:SF 0 "general_operand" "=m,!*r") + [(set (match_operand:SF 0 "nonimmediate_operand" "=m,!*r") (float_truncate:SF (match_operand:XF 1 "register_operand" "f,f")))] "TARGET_80387" @@ -1954,7 +2232,7 @@ output_asm_insn (AS1 (fld,%y1), operands); stack_top_dies = 1; } - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } else if (GET_CODE (operands[0]) == MEM) @@ -1972,7 +2250,7 @@ }") (define_insn "truncxfdf2" - [(set (match_operand:DF 0 "general_operand" "=m,!*r") + [(set (match_operand:DF 0 "nonimmediate_operand" "=m,!*r") (float_truncate:DF (match_operand:XF 1 "register_operand" "f,f")))] "TARGET_80387" @@ -1987,7 +2265,7 @@ output_asm_insn (AS1 (fld,%y1), operands); stack_top_dies = 1; } - output_to_reg (operands[0], stack_top_dies); + output_to_reg (operands[0], stack_top_dies, 0); RET; } else if (GET_CODE (operands[0]) == MEM) @@ -2029,7 +2307,7 @@ operands[3] = gen_lowpart (SImode, operands[2]); operands[4] = gen_reg_rtx (XFmode); operands[5] = (rtx) assign_386_stack_local (SImode, 0); - operands[6] = (rtx) assign_386_stack_local (SImode, 1); + operands[6] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fixuns_truncdfsi2" @@ -2050,7 +2328,7 @@ operands[3] = gen_lowpart (SImode, operands[2]); operands[4] = gen_reg_rtx (DFmode); operands[5] = (rtx) assign_386_stack_local (SImode, 0); - operands[6] = (rtx) assign_386_stack_local (SImode, 1); + operands[6] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fixuns_truncsfsi2" @@ -2071,7 +2349,7 @@ operands[3] = gen_lowpart (SImode, operands[2]); operands[4] = gen_reg_rtx (SFmode); operands[5] = (rtx) assign_386_stack_local (SImode, 0); - operands[6] = (rtx) assign_386_stack_local (SImode, 1); + operands[6] = (rtx) assign_386_stack_local (DImode, 1); }") ;; Signed conversion to DImode. @@ -2091,7 +2369,7 @@ operands[1] = copy_to_mode_reg (XFmode, operands[1]); operands[2] = gen_reg_rtx (XFmode); operands[3] = (rtx) assign_386_stack_local (SImode, 0); - operands[4] = (rtx) assign_386_stack_local (SImode, 1); + operands[4] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fix_truncdfdi2" @@ -2109,7 +2387,7 @@ operands[1] = copy_to_mode_reg (DFmode, operands[1]); operands[2] = gen_reg_rtx (DFmode); operands[3] = (rtx) assign_386_stack_local (SImode, 0); - operands[4] = (rtx) assign_386_stack_local (SImode, 1); + operands[4] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fix_truncsfdi2" @@ -2127,37 +2405,37 @@ operands[1] = copy_to_mode_reg (SFmode, operands[1]); operands[2] = gen_reg_rtx (SFmode); operands[3] = (rtx) assign_386_stack_local (SImode, 0); - operands[4] = (rtx) assign_386_stack_local (SImode, 1); + operands[4] = (rtx) assign_386_stack_local (DImode, 1); }") ;; These match a signed conversion of either DFmode or SFmode to DImode. (define_insn "" - [(set (match_operand:DI 0 "general_operand" "=rm") - (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f")))) + [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") + (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "+f")))) (clobber (match_dup 1)) (clobber (match_operand:SI 2 "memory_operand" "m")) - (clobber (match_operand:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") (define_insn "" - [(set (match_operand:DI 0 "general_operand" "=rm") - (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f")))) + [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") + (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "+f")))) (clobber (match_dup 1)) (clobber (match_operand:SI 2 "memory_operand" "m")) - (clobber (match_operand:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") (define_insn "" - [(set (match_operand:DI 0 "general_operand" "=rm") - (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f")))) + [(set (match_operand:DI 0 "nonimmediate_operand" "=rm") + (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "+f")))) (clobber (match_dup 1)) (clobber (match_operand:SI 2 "memory_operand" "m")) - (clobber (match_operand:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") @@ -2175,7 +2453,7 @@ " { operands[2] = (rtx) assign_386_stack_local (SImode, 0); - operands[3] = (rtx) assign_386_stack_local (SImode, 1); + operands[3] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fix_truncdfsi2" @@ -2189,7 +2467,7 @@ " { operands[2] = (rtx) assign_386_stack_local (SImode, 0); - operands[3] = (rtx) assign_386_stack_local (SImode, 1); + operands[3] = (rtx) assign_386_stack_local (DImode, 1); }") (define_expand "fix_truncsfsi2" @@ -2203,32 +2481,32 @@ " { operands[2] = (rtx) assign_386_stack_local (SImode, 0); - operands[3] = (rtx) assign_386_stack_local (SImode, 1); + operands[3] = (rtx) assign_386_stack_local (DImode, 1); }") (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f")))) (clobber (match_operand:SI 2 "memory_operand" "m")) - (clobber (match_operand:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f")))) (clobber (match_operand:SI 2 "memory_operand" "m")) - (clobber (match_operand:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f")))) (clobber (match_operand:SI 2 "memory_operand" "m")) - (clobber (match_operand:SI 3 "memory_operand" "m")) + (clobber (match_operand:DI 3 "memory_operand" "m")) (clobber (match_scratch:SI 4 "=&q"))] "TARGET_80387" "* return output_fix_trunc (insn, operands);") @@ -2271,14 +2549,14 @@ (define_expand "floatdixf2" [(set (match_operand:XF 0 "register_operand" "") (float:XF (match_operand:DI 1 "nonimmediate_operand" "")))] - "TARGET_80387" + "TARGET_80387 && LONG_DOUBLE_TYPE_SIZE == 96" "") ;; This will convert from SImode or DImode to MODE_FLOAT. (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") - (float:XF (match_operand:DI 1 "general_operand" "rm")))] + (float:XF (match_operand:DI 1 "nonimmediate_operand" "rm")))] "TARGET_80387" "* { @@ -2346,7 +2624,7 @@ (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f,f") - (float:XF (match_operand:SI 1 "general_operand" "m,!*r")))] + (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,!*r")))] "TARGET_80387" "* { @@ -2380,11 +2658,11 @@ ;;- add instructions -(define_insn "adddi3" - [(set (match_operand:DI 0 "general_operand" "=&r,ro,o,&r,ro,o,&r,o,o,o") - (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,o,riF,o,or,riF,riF,o") - (match_operand:DI 2 "general_operand" "o,riF,o,0,0,0,oriF,riF,o,o"))) - (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r,X,&r,&r,&r"))] +(define_insn "addsidi3_1" + [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,!&r,!r,o,!o") + (plus:DI (match_operand:DI 1 "general_operand" "0,0,0,o,riF,riF,o") + (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,roi,roi,ri,ri")))) + (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,&r"))] "" "* { @@ -2392,14 +2670,10 @@ CC_STATUS_INIT; - if (rtx_equal_p (operands[0], operands[2])) - { - temp = operands[1]; - operands[1] = operands[2]; - operands[2] = temp; - } + split_di (operands, 2, low, high); + high[2] = const0_rtx; + low[2] = operands[2]; - split_di (operands, 3, low, high); if (!rtx_equal_p (operands[0], operands[1])) { xops[0] = high[0]; @@ -2407,7 +2681,7 @@ xops[2] = high[1]; xops[3] = low[1]; - if (GET_CODE (operands[0]) != MEM) + if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) { output_asm_insn (AS2 (mov%L1,%3,%1), xops); output_asm_insn (AS2 (mov%L0,%2,%0), xops); @@ -2427,90 +2701,280 @@ } } - if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG) - { - xops[0] = high[0]; - xops[1] = low[0]; - xops[2] = high[2]; - xops[3] = low[2]; - xops[4] = operands[3]; - - output_asm_insn (AS2 (mov%L4,%3,%4), xops); - output_asm_insn (AS2 (add%L1,%4,%1), xops); - output_asm_insn (AS2 (mov%L4,%2,%4), xops); - output_asm_insn (AS2 (adc%L0,%4,%0), xops); - } - - else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) - { - output_asm_insn (AS2 (add%L0,%2,%0), low); - output_asm_insn (AS2 (adc%L0,%2,%0), high); - } - - else - output_asm_insn (AS2 (add%L0,%2,%0), high); - + output_asm_insn (AS2 (add%L0,%2,%0), low); + output_asm_insn (AS2 (adc%L0,%2,%0), high); RET; }") -;; On a 486, it is faster to do movl/addl than to do a single leal if -;; operands[1] and operands[2] are both registers. - -(define_insn "addsi3" - [(set (match_operand:SI 0 "general_operand" "=?r,rm,r") - (plus:SI (match_operand:SI 1 "general_operand" "%r,0,0") - (match_operand:SI 2 "general_operand" "ri,ri,rm")))] +(define_insn "addsidi3_2" + [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,&r,!&r,&r,o,o,!o") + (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,o,ri,ri,i,r")) + (match_operand:DI 1 "general_operand" "0,0,0,iF,ro,roiF,riF,o,o"))) + (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,X,&r,&r"))] "" "* { - if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1])) - { - if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2])) - return AS2 (add%L0,%1,%0); + rtx low[3], high[3], xops[7], temp; - if (operands[2] == stack_pointer_rtx) - { - rtx temp; + CC_STATUS_INIT; - temp = operands[1]; - operands[1] = operands[2]; - operands[2] = temp; - } + split_di (operands, 2, low, high); + high[2] = const0_rtx; + low[2] = operands[2]; - if (operands[2] != stack_pointer_rtx) - { - CC_STATUS_INIT; - operands[1] = SET_SRC (PATTERN (insn)); - return AS2 (lea%L0,%a1,%0); - } + if (!rtx_equal_p (operands[0], operands[1])) + { + xops[0] = high[0]; + xops[1] = low[0]; + xops[2] = high[1]; + xops[3] = low[1]; - output_asm_insn (AS2 (mov%L0,%1,%0), operands); + if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + { + if (rtx_equal_p (low[0], operands[2])) + { + output_asm_insn (AS2 (mov%L0,%2,%0), high); + output_asm_insn (AS2 (add%L0,%1,%0), low); + output_asm_insn (AS2 (adc%L0,%1,%0), high); + RET; + } + if (rtx_equal_p (high[0], operands[2])) + { + if (GET_CODE (operands[0]) != MEM) + { + output_asm_insn (AS2 (mov%L0,%2,%0), low); + output_asm_insn (AS2 (mov%L0,%2,%0), high); + output_asm_insn (AS2 (add%L0,%1,%0), low); + output_asm_insn (AS2 (adc%L0,%1,%0), high); + } + else + { + /* It's too late to ask for a scratch now - but this + will probably not happen too often. */ + output_asm_insn (AS2 (add%L1,%2,%1), low); + output_asm_insn (AS2 (mov%L0,%1,%0), low); + output_asm_insn (AS2 (mov%L1,%2,%1), low); + output_asm_insn (AS2 (mov%L0,%2,%0), high); + output_asm_insn (AS2 (adc%L0,%1,%0), high); + output_asm_insn (AS2 (sub%L1,%0,%1), low); + output_asm_insn (AS1 (neg%L1,%1), low); + } + RET; + } + output_asm_insn (AS2 (mov%L1,%3,%1), xops); + output_asm_insn (AS2 (mov%L0,%2,%0), xops); + } + else + { + xops[4] = high[2]; + xops[5] = low[2]; + xops[6] = operands[3]; + output_asm_insn (AS2 (mov%L6,%3,%6), xops); + output_asm_insn (AS2 (add%L6,%5,%6), xops); + output_asm_insn (AS2 (mov%L1,%6,%1), xops); + output_asm_insn (AS2 (mov%L6,%2,%6), xops); + output_asm_insn (AS2 (adc%L6,%4,%6), xops); + output_asm_insn (AS2 (mov%L0,%6,%0), xops); + RET; + } + } + + output_asm_insn (AS2 (add%L0,%2,%0), low); + output_asm_insn (AS2 (adc%L0,%2,%0), high); + RET; +}") + +(define_insn "adddi3" + [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o") + (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o") + (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o"))) + (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))] + "" + "* +{ + rtx low[3], high[3], xops[7], temp; + + CC_STATUS_INIT; + + if (rtx_equal_p (operands[0], operands[2])) + { + temp = operands[1]; + operands[1] = operands[2]; + operands[2] = temp; } + split_di (operands, 3, low, high); + if (!rtx_equal_p (operands[0], operands[1])) + { + xops[0] = high[0]; + xops[1] = low[0]; + xops[2] = high[1]; + xops[3] = low[1]; + + if (GET_CODE (operands[0]) != MEM) + { + output_asm_insn (AS2 (mov%L1,%3,%1), xops); + output_asm_insn (AS2 (mov%L0,%2,%0), xops); + } + else + { + xops[4] = high[2]; + xops[5] = low[2]; + xops[6] = operands[3]; + output_asm_insn (AS2 (mov%L6,%3,%6), xops); + output_asm_insn (AS2 (add%L6,%5,%6), xops); + output_asm_insn (AS2 (mov%L1,%6,%1), xops); + output_asm_insn (AS2 (mov%L6,%2,%6), xops); + output_asm_insn (AS2 (adc%L6,%4,%6), xops); + output_asm_insn (AS2 (mov%L0,%6,%0), xops); + RET; + } + } + + if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG) + { + xops[0] = high[0]; + xops[1] = low[0]; + xops[2] = high[2]; + xops[3] = low[2]; + xops[4] = operands[3]; + + output_asm_insn (AS2 (mov%L4,%3,%4), xops); + output_asm_insn (AS2 (add%L1,%4,%1), xops); + output_asm_insn (AS2 (mov%L4,%2,%4), xops); + output_asm_insn (AS2 (adc%L0,%4,%0), xops); + } + + else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) + { + output_asm_insn (AS2 (add%L0,%2,%0), low); + output_asm_insn (AS2 (adc%L0,%2,%0), high); + } + + else + output_asm_insn (AS2 (add%L0,%2,%0), high); + + RET; +}") + +;; On a 486, it is faster to do movl/addl than to do a single leal if +;; operands[1] and operands[2] are both registers. + +(define_expand "addsi3" + [(set (match_operand:SI 0 "nonimmediate_operand" "") + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "") + (match_operand:SI 2 "general_operand" "")))] + "" + "IX86_EXPAND_BINARY_OPERATOR (PLUS, SImode, operands);") + +(define_insn "" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r") + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r") + (match_operand:SI 2 "general_operand" "rmi,ri,ri")))] + "ix86_binary_operator_ok (PLUS, SImode, operands)" + "* +{ + if (REG_P (operands[0]) && REG_P (operands[1]) + && (REG_P (operands[2]) || GET_CODE (operands[2]) == CONST_INT) + && REGNO (operands[0]) != REGNO (operands[1])) + { + if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2])) + return AS2 (add%L0,%1,%0); + + if (operands[2] == stack_pointer_rtx) + { + rtx temp; + + temp = operands[1]; + operands[1] = operands[2]; + operands[2] = temp; + } + + if (operands[2] != stack_pointer_rtx) + { + CC_STATUS_INIT; + operands[1] = SET_SRC (PATTERN (insn)); + return AS2 (lea%L0,%a1,%0); + } + } + + if (!rtx_equal_p (operands[0], operands[1])) + output_asm_insn (AS2 (mov%L0,%1,%0), operands); + if (operands[2] == const1_rtx) return AS1 (inc%L0,%0); if (operands[2] == constm1_rtx) return AS1 (dec%L0,%0); + /* subl $-128,%ebx is smaller than addl $128,%ebx. */ + if (GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) == 128) + { + /* This doesn't compute the carry bit in the same way + * as add%L0, but we use inc and dec above and they + * don't set the carry bit at all. If inc/dec don't need + * a CC_STATUS_INIT, this doesn't either... */ + operands[2] = GEN_INT (-128); + return AS2 (sub%L0,%2,%0); + } + return AS2 (add%L0,%2,%0); }") +;; addsi3 is faster, so put this after. + +(define_insn "movsi_lea" + [(set (match_operand:SI 0 "register_operand" "=r") + (match_operand:QI 1 "address_operand" "p"))] + "" + "* +{ + /* Adding a constant to a register is faster with an add. */ + /* ??? can this ever happen? */ + if (GET_CODE (operands[1]) == PLUS + && GET_CODE (XEXP (operands[1], 1)) == CONST_INT + && rtx_equal_p (operands[0], XEXP (operands[1], 0))) + { + operands[1] = XEXP (operands[1], 1); + + if (operands[1] == const1_rtx) + return AS1 (inc%L0,%0); + + if (operands[1] == constm1_rtx) + return AS1 (dec%L0,%0); + + return AS2 (add%L0,%1,%0); + } + + CC_STATUS_INIT; + return AS2 (lea%L0,%a1,%0); +}") + ;; ??? `lea' here, for three operand add? If leaw is used, only %bx, ;; %si and %di can appear in SET_SRC, and output_asm_insn might not be ;; able to handle the operand. But leal always works? -(define_insn "addhi3" - [(set (match_operand:HI 0 "general_operand" "=rm,r") - (plus:HI (match_operand:HI 1 "general_operand" "%0,0") - (match_operand:HI 2 "general_operand" "ri,rm")))] +(define_expand "addhi3" + [(set (match_operand:HI 0 "general_operand" "") + (plus:HI (match_operand:HI 1 "nonimmediate_operand" "") + (match_operand:HI 2 "general_operand" "")))] "" + "IX86_EXPAND_BINARY_OPERATOR (PLUS, HImode, operands);") + +(define_insn "" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") + (match_operand:HI 2 "general_operand" "ri,rm")))] + "ix86_binary_operator_ok (PLUS, HImode, operands)" "* { /* ??? what about offsettable memory references? */ - if (QI_REG_P (operands[0]) + if (!TARGET_PENTIUMPRO /* partial stalls are just too painful to risk. */ + && QI_REG_P (operands[0]) && GET_CODE (operands[2]) == CONST_INT - && (INTVAL (operands[2]) & 0xff) == 0) + && (INTVAL (operands[2]) & 0xff) == 0 + && i386_cc_probably_useless_p (insn)) { int byteval = (INTVAL (operands[2]) >> 8) & 0xff; CC_STATUS_INIT; @@ -2524,6 +2988,28 @@ return AS2 (add%B0,%2,%h0); } + /* Use a 32-bit operation when possible, to avoid the prefix penalty. */ + if (REG_P (operands[0]) + && i386_aligned_p (operands[2]) + && i386_cc_probably_useless_p (insn)) + { + CC_STATUS_INIT; + + if (GET_CODE (operands[2]) == CONST_INT) + { + HOST_WIDE_INT intval = 0xffff & INTVAL (operands[2]); + + if (intval == 1) + return AS1 (inc%L0,%k0); + + if (intval == 0xffff) + return AS1 (dec%L0,%k0); + + operands[2] = i386_sext16_if_const (operands[2]); + } + return AS2 (add%L0,%k2,%k0); + } + if (operands[2] == const1_rtx) return AS1 (inc%W0,%0); @@ -2535,11 +3021,18 @@ return AS2 (add%W0,%2,%0); }") -(define_insn "addqi3" - [(set (match_operand:QI 0 "general_operand" "=qm,q") - (plus:QI (match_operand:QI 1 "general_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qn,qmn")))] +(define_expand "addqi3" + [(set (match_operand:QI 0 "general_operand" "") + (plus:QI (match_operand:QI 1 "general_operand" "") + (match_operand:QI 2 "general_operand" "")))] "" + "IX86_EXPAND_BINARY_OPERATOR (PLUS, QImode, operands);") + +(define_insn "" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") + (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") + (match_operand:QI 2 "general_operand" "qn,qmn")))] + "ix86_binary_operator_ok (PLUS, QImode, operands)" "* { if (operands[2] == const1_rtx) @@ -2563,8 +3056,8 @@ ; ;(define_insn "" ; [(set (match_operand:SI 0 "push_operand" "=<") -; (plus:SI (match_operand:SI 1 "general_operand" "%r") -; (match_operand:SI 2 "general_operand" "ri")))] +; (plus:SI (match_operand:SI 1 "register_operand" "%r") +; (match_operand:SI 2 "nonmemory_operand" "ri")))] ; "" ; "* ;{ @@ -2572,46 +3065,18 @@ ; xops[0] = operands[0]; ; xops[1] = operands[1]; ; xops[2] = operands[2]; -; xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx); +; xops[3] = gen_rtx_MEM (SImode, stack_pointer_rtx); ; output_asm_insn (\"push%z1 %1\", xops); ; output_asm_insn (AS2 (add%z3,%2,%3), xops); ; RET; ;}") -;; addsi3 is faster, so put this after. - -(define_insn "movsi_lea" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:QI 1 "address_operand" "p"))] - "" - "* -{ - CC_STATUS_INIT; - /* Adding a constant to a register is faster with an add. */ - /* ??? can this ever happen? */ - if (GET_CODE (operands[1]) == PLUS - && GET_CODE (XEXP (operands[1], 1)) == CONST_INT - && rtx_equal_p (operands[0], XEXP (operands[1], 0))) - { - operands[1] = XEXP (operands[1], 1); - - if (operands[1] == const1_rtx) - return AS1 (inc%L0,%0); - - if (operands[1] == constm1_rtx) - return AS1 (dec%L0,%0); - - return AS2 (add%L0,%1,%0); - } - return AS2 (lea%L0,%a1,%0); -}") - ;; The patterns that match these are at the end of this file. (define_expand "addxf3" [(set (match_operand:XF 0 "register_operand" "") - (plus:XF (match_operand:XF 1 "nonimmediate_operand" "") - (match_operand:XF 2 "nonimmediate_operand" "")))] + (plus:XF (match_operand:XF 1 "register_operand" "") + (match_operand:XF 2 "register_operand" "")))] "TARGET_80387" "") @@ -2631,11 +3096,59 @@ ;;- subtract instructions +(define_insn "subsidi3" + [(set (match_operand:DI 0 "general_operand" "=&r,&ro,&r,!&r,o,o,!o") + (minus:DI (match_operand:DI 1 "general_operand" "0iF,0,roiF,roiF,riF,o,o") + (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,ri,i,r")))) + (clobber (match_scratch:SI 3 "=X,X,X,X,X,&r,&r"))] + "" + "* +{ + rtx low[3], high[3], xops[7]; + + CC_STATUS_INIT; + + split_di (operands, 2, low, high); + high[2] = const0_rtx; + low[2] = operands[2]; + + if (!rtx_equal_p (operands[0], operands[1])) + { + xops[0] = high[0]; + xops[1] = low[0]; + xops[2] = high[1]; + xops[3] = low[1]; + + if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + { + output_asm_insn (AS2 (mov%L1,%3,%1), xops); + output_asm_insn (AS2 (mov%L0,%2,%0), xops); + } + else + { + xops[4] = high[2]; + xops[5] = low[2]; + xops[6] = operands[3]; + output_asm_insn (AS2 (mov%L6,%3,%6), xops); + output_asm_insn (AS2 (sub%L6,%5,%6), xops); + output_asm_insn (AS2 (mov%L1,%6,%1), xops); + output_asm_insn (AS2 (mov%L6,%2,%6), xops); + output_asm_insn (AS2 (sbb%L6,%4,%6), xops); + output_asm_insn (AS2 (mov%L0,%6,%0), xops); + RET; + } + } + + output_asm_insn (AS2 (sub%L0,%2,%0), low); + output_asm_insn (AS2 (sbb%L0,%2,%0), high); + RET; +}") + (define_insn "subdi3" - [(set (match_operand:DI 0 "general_operand" "=&r,ro,&r,o,o") - (minus:DI (match_operand:DI 1 "general_operand" "0,0,roiF,riF,o") - (match_operand:DI 2 "general_operand" "o,riF,roiF,riF,o"))) - (clobber (match_scratch:SI 3 "=X,X,X,&r,&r"))] + [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,o,!&r,!o") + (minus:DI (match_operand:DI 1 "general_operand" "0,0,0iF,or,roiF,roiF") + (match_operand:DI 2 "general_operand" "or,riF,or,iF,roiF,roiF"))) + (clobber (match_scratch:SI 3 "=X,X,&r,&r,X,&r"))] "" "* { @@ -2698,33 +3211,65 @@ RET; }") -(define_insn "subsi3" - [(set (match_operand:SI 0 "general_operand" "=rm,r") - (minus:SI (match_operand:SI 1 "general_operand" "0,0") - (match_operand:SI 2 "general_operand" "ri,rm")))] +(define_expand "subsi3" + [(set (match_operand:SI 0 "nonimmediate_operand" "") + (minus:SI (match_operand:SI 1 "nonimmediate_operand" "") + (match_operand:SI 2 "general_operand" "")))] "" + "IX86_EXPAND_BINARY_OPERATOR (MINUS, SImode, operands);") + +(define_insn "" + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") + (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") + (match_operand:SI 2 "general_operand" "ri,rm")))] + "ix86_binary_operator_ok (MINUS, SImode, operands)" "* return AS2 (sub%L0,%2,%0);") -(define_insn "subhi3" - [(set (match_operand:HI 0 "general_operand" "=rm,r") - (minus:HI (match_operand:HI 1 "general_operand" "0,0") +(define_expand "subhi3" + [(set (match_operand:HI 0 "general_operand" "") + (minus:HI (match_operand:HI 1 "nonimmediate_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + "IX86_EXPAND_BINARY_OPERATOR (MINUS, HImode, operands);") + +(define_insn "" + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") (match_operand:HI 2 "general_operand" "ri,rm")))] + "ix86_binary_operator_ok (MINUS, HImode, operands)" + "* +{ + if (REG_P (operands[0]) + && i386_aligned_p (operands[2]) + && i386_cc_probably_useless_p (insn)) + { + CC_STATUS_INIT; + operands[2] = i386_sext16_if_const (operands[2]); + return AS2 (sub%L0,%k2,%k0); + } + return AS2 (sub%W0,%2,%0); +}") + +(define_expand "subqi3" + [(set (match_operand:QI 0 "general_operand" "") + (minus:QI (match_operand:QI 1 "general_operand" "") + (match_operand:QI 2 "general_operand" "")))] "" - "* return AS2 (sub%W0,%2,%0);") + "IX86_EXPAND_BINARY_OPERATOR (MINUS, QImode, operands);") -(define_insn "subqi3" - [(set (match_operand:QI 0 "general_operand" "=qm,q") - (minus:QI (match_operand:QI 1 "general_operand" "0,0") +(define_insn "" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") + (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") (match_operand:QI 2 "general_operand" "qn,qmn")))] - "" + "ix86_binary_operator_ok (MINUS, QImode, operands)" "* return AS2 (sub%B0,%2,%0);") ;; The patterns that match these are at the end of this file. (define_expand "subxf3" [(set (match_operand:XF 0 "register_operand" "") - (minus:XF (match_operand:XF 1 "nonimmediate_operand" "") - (match_operand:XF 2 "nonimmediate_operand" "")))] + (minus:XF (match_operand:XF 1 "register_operand" "") + (match_operand:XF 2 "register_operand" "")))] "TARGET_80387" "") @@ -2745,22 +3290,15 @@ ;;- multiply instructions ;(define_insn "mulqi3" -; [(set (match_operand:QI 0 "general_operand" "=a") -; (mult:QI (match_operand:QI 1 "general_operand" "%0") -; (match_operand:QI 2 "general_operand" "qm")))] +; [(set (match_operand:QI 0 "register_operand" "=a") +; (mult:QI (match_operand:QI 1 "register_operand" "%0") +; (match_operand:QI 2 "nonimmediate_operand" "qm")))] ; "" ; "imul%B0 %2,%0") -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=r") - (mult:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "r")))] - "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80" - "* return AS2 (imul%W0,%2,%0);") - (define_insn "mulhi3" - [(set (match_operand:HI 0 "general_operand" "=r,r") - (mult:HI (match_operand:HI 1 "general_operand" "%0,rm") + [(set (match_operand:HI 0 "register_operand" "=r,r") + (mult:HI (match_operand:HI 1 "nonimmediate_operand" "%0,rm") (match_operand:HI 2 "general_operand" "g,i")))] "" "* @@ -2771,18 +3309,12 @@ /* Assembler has weird restrictions. */ return AS2 (imul%W0,%2,%0); return AS3 (imul%W0,%2,%1,%0); -}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=r") - (mult:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "r")))] - "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80" - "* return AS2 (imul%L0,%2,%0);") +}" + [(set_attr "type" "imul")]) (define_insn "mulsi3" - [(set (match_operand:SI 0 "general_operand" "=r,r") - (mult:SI (match_operand:SI 1 "general_operand" "%0,rm") + [(set (match_operand:SI 0 "register_operand" "=r,r") + (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm") (match_operand:SI 2 "general_operand" "g,i")))] "" "* @@ -2793,35 +3325,40 @@ /* Assembler has weird restrictions. */ return AS2 (imul%L0,%2,%0); return AS3 (imul%L0,%2,%1,%0); -}") +}" + [(set_attr "type" "imul")]) (define_insn "umulqihi3" - [(set (match_operand:HI 0 "general_operand" "=a") - (mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) + [(set (match_operand:HI 0 "register_operand" "=a") + (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0")) (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))] "" - "mul%B0 %2") + "mul%B0 %2" + [(set_attr "type" "imul")]) (define_insn "mulqihi3" - [(set (match_operand:HI 0 "general_operand" "=a") - (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0")) + [(set (match_operand:HI 0 "register_operand" "=a") + (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0")) (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))] "" - "imul%B0 %2") + "imul%B0 %2" + [(set_attr "type" "imul")]) (define_insn "umulsidi3" [(set (match_operand:DI 0 "register_operand" "=A") (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))] "TARGET_WIDE_MULTIPLY" - "mul%L0 %2") + "mul%L0 %2" + [(set_attr "type" "imul")]) (define_insn "mulsidi3" [(set (match_operand:DI 0 "register_operand" "=A") (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))] "TARGET_WIDE_MULTIPLY" - "imul%L0 %2") + "imul%L0 %2" + [(set_attr "type" "imul")]) (define_insn "umulsi3_highpart" [(set (match_operand:SI 0 "register_operand" "=d") @@ -2830,7 +3367,8 @@ (const_int 32)))) (clobber (match_scratch:SI 3 "=a"))] "TARGET_WIDE_MULTIPLY" - "mul%L0 %2") + "mul%L0 %2" + [(set_attr "type" "imul")]) (define_insn "smulsi3_highpart" [(set (match_operand:SI 0 "register_operand" "=d") @@ -2839,27 +3377,28 @@ (const_int 32)))) (clobber (match_scratch:SI 3 "=a"))] "TARGET_WIDE_MULTIPLY" - "imul%L0 %2") + "imul%L0 %2" + [(set_attr "type" "imul")]) ;; The patterns that match these are at the end of this file. (define_expand "mulxf3" [(set (match_operand:XF 0 "register_operand" "") - (mult:XF (match_operand:XF 1 "nonimmediate_operand" "") - (match_operand:XF 2 "nonimmediate_operand" "")))] + (mult:XF (match_operand:XF 1 "register_operand" "") + (match_operand:XF 2 "register_operand" "")))] "TARGET_80387" "") (define_expand "muldf3" [(set (match_operand:DF 0 "register_operand" "") - (mult:DF (match_operand:DF 1 "nonimmediate_operand" "") + (mult:DF (match_operand:DF 1 "register_operand" "") (match_operand:DF 2 "nonimmediate_operand" "")))] "TARGET_80387" "") (define_expand "mulsf3" [(set (match_operand:SF 0 "register_operand" "") - (mult:SF (match_operand:SF 1 "nonimmediate_operand" "") + (mult:SF (match_operand:SF 1 "register_operand" "") (match_operand:SF 2 "nonimmediate_operand" "")))] "TARGET_80387" "") @@ -2867,38 +3406,39 @@ ;;- divide instructions (define_insn "divqi3" - [(set (match_operand:QI 0 "general_operand" "=a") - (div:QI (match_operand:HI 1 "general_operand" "0") - (match_operand:QI 2 "general_operand" "qm")))] + [(set (match_operand:QI 0 "register_operand" "=a") + (div:QI (match_operand:HI 1 "register_operand" "0") + (match_operand:QI 2 "nonimmediate_operand" "qm")))] "" "idiv%B0 %2") (define_insn "udivqi3" - [(set (match_operand:QI 0 "general_operand" "=a") - (udiv:QI (match_operand:HI 1 "general_operand" "0") - (match_operand:QI 2 "general_operand" "qm")))] + [(set (match_operand:QI 0 "register_operand" "=a") + (udiv:QI (match_operand:HI 1 "register_operand" "0") + (match_operand:QI 2 "nonimmediate_operand" "qm")))] "" - "div%B0 %2") + "div%B0 %2" + [(set_attr "type" "idiv")]) ;; The patterns that match these are at the end of this file. (define_expand "divxf3" [(set (match_operand:XF 0 "register_operand" "") - (div:XF (match_operand:XF 1 "nonimmediate_operand" "") - (match_operand:XF 2 "nonimmediate_operand" "")))] + (div:XF (match_operand:XF 1 "register_operand" "") + (match_operand:XF 2 "register_operand" "")))] "TARGET_80387" "") (define_expand "divdf3" [(set (match_operand:DF 0 "register_operand" "") - (div:DF (match_operand:DF 1 "nonimmediate_operand" "") - (match_operand:DF 2 "nonimmediate_operand" "")))] - "TARGET_80387" - "") - + (div:DF (match_operand:DF 1 "register_operand" "") + (match_operand:DF 2 "nonimmediate_operand" "")))] + "TARGET_80387" + "") + (define_expand "divsf3" [(set (match_operand:SF 0 "register_operand" "") - (div:SF (match_operand:SF 1 "nonimmediate_operand" "") + (div:SF (match_operand:SF 1 "register_operand" "") (match_operand:SF 2 "nonimmediate_operand" "")))] "TARGET_80387" "") @@ -2908,7 +3448,7 @@ (define_insn "divmodsi4" [(set (match_operand:SI 0 "register_operand" "=a") (div:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "rm"))) + (match_operand:SI 2 "nonimmediate_operand" "rm"))) (set (match_operand:SI 3 "register_operand" "=&d") (mod:SI (match_dup 1) (match_dup 2)))] "" @@ -2920,22 +3460,24 @@ output_asm_insn (\"cltd\", operands); #endif return AS1 (idiv%L0,%2); -}") +}" + [(set_attr "type" "idiv")]) (define_insn "divmodhi4" [(set (match_operand:HI 0 "register_operand" "=a") (div:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "rm"))) + (match_operand:HI 2 "nonimmediate_operand" "rm"))) (set (match_operand:HI 3 "register_operand" "=&d") (mod:HI (match_dup 1) (match_dup 2)))] "" - "cwtd\;idiv%W0 %2") + "cwtd\;idiv%W0 %2" + [(set_attr "type" "idiv")]) ;; ??? Can we make gcc zero extend operand[0]? (define_insn "udivmodsi4" [(set (match_operand:SI 0 "register_operand" "=a") (udiv:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "rm"))) + (match_operand:SI 2 "nonimmediate_operand" "rm"))) (set (match_operand:SI 3 "register_operand" "=&d") (umod:SI (match_dup 1) (match_dup 2)))] "" @@ -2943,13 +3485,14 @@ { output_asm_insn (AS2 (xor%L3,%3,%3), operands); return AS1 (div%L0,%2); -}") +}" + [(set_attr "type" "idiv")]) ;; ??? Can we make gcc zero extend operand[0]? (define_insn "udivmodhi4" [(set (match_operand:HI 0 "register_operand" "=a") (udiv:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "rm"))) + (match_operand:HI 2 "nonimmediate_operand" "rm"))) (set (match_operand:HI 3 "register_operand" "=&d") (umod:HI (match_dup 1) (match_dup 2)))] "" @@ -2957,7 +3500,8 @@ { output_asm_insn (AS2 (xor%W0,%3,%3), operands); return AS1 (div%W0,%2); -}") +}" + [(set_attr "type" "idiv")]) /* ;;this should be a valid double division which we may want to add @@ -2965,11 +3509,12 @@ (define_insn "" [(set (match_operand:SI 0 "register_operand" "=a") (udiv:DI (match_operand:DI 1 "register_operand" "a") - (match_operand:SI 2 "general_operand" "rm"))) + (match_operand:SI 2 "nonimmediate_operand" "rm"))) (set (match_operand:SI 3 "register_operand" "=d") (umod:SI (match_dup 1) (match_dup 2)))] "" - "div%L0 %2,%0") + "div%L0 %2,%0" + [(set_attr "type" "idiv")]) */ ;;- and instructions @@ -2989,21 +3534,33 @@ ;; The `r' in `rm' for operand 3 looks redundant, but it causes ;; optional reloads to be generated if op 3 is a pseudo in a stack slot. -;; ??? What if we only change one byte of an offsettable memory reference? (define_insn "andsi3" - [(set (match_operand:SI 0 "general_operand" "=r,r,rm,r") - (and:SI (match_operand:SI 1 "general_operand" "%rm,qm,0,0") - (match_operand:SI 2 "general_operand" "L,K,ri,rm")))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") + (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") + (match_operand:SI 2 "general_operand" "ri,rm")))] "" "* { - if (GET_CODE (operands[2]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) + HOST_WIDE_INT intval; + if (!rtx_equal_p (operands[0], operands[1]) + && rtx_equal_p (operands[0], operands[2])) { - if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0]) + rtx tmp; + tmp = operands[1]; + operands[1] = operands[2]; + operands[2] = tmp; + } + switch (GET_CODE (operands[2])) + { + case CONST_INT: + if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) + break; + intval = INTVAL (operands[2]); + /* zero-extend 16->32? */ + if (intval == 0xffff && REG_P (operands[0]) && (! REG_P (operands[1]) || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) - && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1]))) + && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1]))) { /* ??? tege: Should forget CC_STATUS only if we clobber a remembered operand. Fix that later. */ @@ -3015,11 +3572,12 @@ #endif } - if (INTVAL (operands[2]) == 0xff && REG_P (operands[0]) + /* zero extend 8->32? */ + if (intval == 0xff && REG_P (operands[0]) && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1])) && (! REG_P (operands[1]) || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) - && (TARGET_386 || ! rtx_equal_p (operands[0], operands[1]))) + && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1]))) { /* ??? tege: Should forget CC_STATUS only if we clobber a remembered operand. Fix that later. */ @@ -3031,47 +3589,110 @@ #endif } - if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff) == 0) - { - CC_STATUS_INIT; + /* Check partial bytes.. non-QI-regs are not available */ + if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) + break; - if (INTVAL (operands[2]) == 0xffffff00) + /* only low byte has zero bits? */ + if (~(intval | 0xff) == 0) + { + intval &= 0xff; + if (REG_P (operands[0])) { - operands[2] = const0_rtx; - return AS2 (mov%B0,%2,%b0); + if (intval == 0) + { + CC_STATUS_INIT; + return AS2 (xor%B0,%b0,%b0); + } + + /* we're better off with the 32-bit version if reg != EAX */ + /* the value is sign-extended in 8 bits */ + if (REGNO (operands[0]) != 0 && (intval & 0x80)) + break; } - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); + CC_STATUS_INIT; + + operands[2] = GEN_INT (intval); + + if (intval == 0) + return AS2 (mov%B0,%2,%b0); + return AS2 (and%B0,%2,%b0); } - if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff00) == 0) + /* only second byte has zero? */ + if (~(intval | 0xff00) == 0) { CC_STATUS_INIT; - if (INTVAL (operands[2]) == 0xffff00ff) + intval = (intval >> 8) & 0xff; + operands[2] = GEN_INT (intval); + if (intval == 0) { - operands[2] = const0_rtx; - return AS2 (mov%B0,%2,%h0); + if (REG_P (operands[0])) + return AS2 (xor%B0,%h0,%h0); + operands[0] = adj_offsettable_operand (operands[0], 1); + return AS2 (mov%B0,%2,%b0); } - operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); - return AS2 (and%B0,%2,%h0); + if (REG_P (operands[0])) + return AS2 (and%B0,%2,%h0); + + operands[0] = adj_offsettable_operand (operands[0], 1); + return AS2 (and%B0,%2,%b0); + } + + if (REG_P (operands[0])) + break; + + /* third byte has zero bits? */ + if (~(intval | 0xff0000) == 0) + { + intval = (intval >> 16) & 0xff; + operands[0] = adj_offsettable_operand (operands[0], 2); +byte_and_operation: + CC_STATUS_INIT; + operands[2] = GEN_INT (intval); + if (intval == 0) + return AS2 (mov%B0,%2,%b0); + return AS2 (and%B0,%2,%b0); + } + + /* fourth byte has zero bits? */ + if (~(intval | 0xff000000) == 0) + { + intval = (intval >> 24) & 0xff; + operands[0] = adj_offsettable_operand (operands[0], 3); + goto byte_and_operation; } - if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) == 0xffff0000) + /* Low word is zero? */ + if (intval == 0xffff0000) { +word_zero_and_operation: + CC_STATUS_INIT; operands[2] = const0_rtx; return AS2 (mov%W0,%2,%w0); } + + /* High word is zero? */ + if (intval == 0x0000ffff) + { + operands[0] = adj_offsettable_operand (operands[0], 2); + goto word_zero_and_operation; + } + + default: + break; } return AS2 (and%L0,%2,%0); }") (define_insn "andhi3" - [(set (match_operand:HI 0 "general_operand" "=rm,r") - (and:HI (match_operand:HI 1 "general_operand" "%0,0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "ri,rm")))] "" "* @@ -3110,14 +3731,46 @@ operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); return AS2 (and%B0,%2,%h0); } + + /* use 32-bit ops on registers when there are no sign issues.. */ + if (REG_P (operands[0])) + { + if (!(INTVAL (operands[2]) & ~0x7fff)) + return AS2 (and%L0,%2,%k0); + } + } + + if (REG_P (operands[0]) + && i386_aligned_p (operands[2])) + { + CC_STATUS_INIT; + /* If op[2] is constant, we should zero-extend it and */ + /* make a note that op[0] has been zero-extended, so */ + /* that we could use 32-bit ops on it forthwith, but */ + /* there is no such reg-note available. Instead we do */ + /* a sign extension as that can result in shorter asm */ + operands[2] = i386_sext16_if_const (operands[2]); + return AS2 (and%L0,%k2,%k0); + } + + /* Use a 32-bit word with the upper bits set, invalidate CC */ + if (GET_CODE (operands[2]) == CONST_INT + && i386_aligned_p (operands[0])) + { + HOST_WIDE_INT val = INTVAL (operands[2]); + CC_STATUS_INIT; + val |= ~0xffff; + if (val != INTVAL (operands[2])) + operands[2] = GEN_INT (val); + return AS2 (and%L0,%k2,%k0); } return AS2 (and%W0,%2,%0); }") (define_insn "andqi3" - [(set (match_operand:QI 0 "general_operand" "=qm,q") - (and:QI (match_operand:QI 1 "general_operand" "%0,0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") + (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") (match_operand:QI 2 "general_operand" "qn,qmn")))] "" "* return AS2 (and%B0,%2,%0);") @@ -3136,10 +3789,10 @@ "and%W0 %1,%0") (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=q") + [(set (match_operand:SI 0 "register_operand" "=q") (and:SI (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")) - (match_operand:SI 2 "general_operand" "0")))] + (match_operand:SI 2 "register_operand" "0")))] "GET_CODE (operands[2]) == CONST_INT && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))" "and%L0 %1,%0") @@ -3148,134 +3801,278 @@ ;;- Bit set (inclusive or) instructions -;; ??? What if we only change one byte of an offsettable memory reference? +;; This optimizes known byte-wide operations to memory, and in some cases +;; to QI registers.. Note that we don't want to use the QI registers too +;; aggressively, because often the 32-bit register instruction is the same +;; size, and likely to be faster on PentiumPro. (define_insn "iorsi3" - [(set (match_operand:SI 0 "general_operand" "=rm,r") - (ior:SI (match_operand:SI 1 "general_operand" "%0,0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") + (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") (match_operand:SI 2 "general_operand" "ri,rm")))] "" "* { - if (GET_CODE (operands[2]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) + HOST_WIDE_INT intval; + switch (GET_CODE (operands[2])) { - if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) - && (INTVAL (operands[2]) & ~0xff) == 0) - { - CC_STATUS_INIT; + case CONST_INT: - if (INTVAL (operands[2]) == 0xff) - return AS2 (mov%B0,%2,%b0); + if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) + break; + + /* don't try to optimize volatile accesses */ + if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) + break; - return AS2 (or%B0,%2,%b0); + intval = INTVAL (operands[2]); + if ((intval & ~0xff) == 0) + { + if (REG_P (operands[0])) + { + /* Do low byte access only for %eax or when high bit is set */ + if (REGNO (operands[0]) != 0 && !(intval & 0x80)) + break; + } + +byte_or_operation: + CC_STATUS_INIT; + + if (intval != INTVAL (operands[2])) + operands[2] = GEN_INT (intval); + + if (intval == 0xff) + return AS2 (mov%B0,%2,%b0); + + return AS2 (or%B0,%2,%b0); } - if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0) + /* second byte? */ + if ((intval & ~0xff00) == 0) { - CC_STATUS_INIT; - operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); + intval >>= 8; - if (INTVAL (operands[2]) == 0xff) - return AS2 (mov%B0,%2,%h0); + if (REG_P (operands[0])) + { + CC_STATUS_INIT; + operands[2] = GEN_INT (intval); + if (intval == 0xff) + return AS2 (mov%B0,%2,%h0); + + return AS2 (or%B0,%2,%h0); + } + + operands[0] = adj_offsettable_operand (operands[0], 1); + goto byte_or_operation; + } + + if (REG_P (operands[0])) + break; - return AS2 (or%B0,%2,%h0); + /* third byte? */ + if ((intval & ~0xff0000) == 0) + { + intval >>= 16; + operands[0] = adj_offsettable_operand (operands[0], 2); + goto byte_or_operation; } + + /* fourth byte? */ + if ((intval & ~0xff000000) == 0) + { + intval = (intval >> 24) & 0xff; + operands[0] = adj_offsettable_operand (operands[0], 3); + goto byte_or_operation; + } + + default: + break; } return AS2 (or%L0,%2,%0); }") (define_insn "iorhi3" - [(set (match_operand:HI 0 "general_operand" "=rm,r") - (ior:HI (match_operand:HI 1 "general_operand" "%0,0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "ri,rm")))] "" "* { - if (GET_CODE (operands[2]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) + HOST_WIDE_INT intval; + switch (GET_CODE (operands[2])) { - /* Can we ignore the upper byte? */ - if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) - && (INTVAL (operands[2]) & 0xff00) == 0) - { - CC_STATUS_INIT; - if (INTVAL (operands[2]) & 0xffff0000) - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); + case CONST_INT: - if (INTVAL (operands[2]) == 0xff) - return AS2 (mov%B0,%2,%b0); + if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) + break; + + /* don't try to optimize volatile accesses */ + if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) + break; + + intval = 0xffff & INTVAL (operands[2]); + + if ((intval & 0xff00) == 0) + { + if (REG_P (operands[0])) + { + /* Do low byte access only for %eax or when high bit is set */ + if (REGNO (operands[0]) != 0 && !(intval & 0x80)) + break; + } + +byte_or_operation: + CC_STATUS_INIT; - return AS2 (or%B0,%2,%b0); + if (intval == 0xff) + return AS2 (mov%B0,%2,%b0); + + return AS2 (or%B0,%2,%b0); } - /* Can we ignore the lower byte? */ - /* ??? what about offsettable memory references? */ - if (QI_REG_P (operands[0]) - && (INTVAL (operands[2]) & 0xff) == 0) + /* high byte? */ + if ((intval & 0xff) == 0) { - CC_STATUS_INIT; - operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); + intval >>= 8; + operands[2] = GEN_INT (intval); - if (INTVAL (operands[2]) == 0xff) - return AS2 (mov%B0,%2,%h0); + if (REG_P (operands[0])) + { + CC_STATUS_INIT; + if (intval == 0xff) + return AS2 (mov%B0,%2,%h0); + + return AS2 (or%B0,%2,%h0); + } - return AS2 (or%B0,%2,%h0); + operands[0] = adj_offsettable_operand (operands[0], 1); + + goto byte_or_operation; } + + default: + break; + } + + if (REG_P (operands[0]) + && i386_aligned_p (operands[2])) + { + CC_STATUS_INIT; + operands[2] = i386_sext16_if_const (operands[2]); + return AS2 (or%L0,%k2,%k0); + } + + if (GET_CODE (operands[2]) == CONST_INT + && i386_aligned_p (operands[0])) + { + CC_STATUS_INIT; + intval = 0xffff & INTVAL (operands[2]); + if (intval != INTVAL (operands[2])) + operands[2] = GEN_INT (intval); + return AS2 (or%L0,%2,%k0); } return AS2 (or%W0,%2,%0); }") (define_insn "iorqi3" - [(set (match_operand:QI 0 "general_operand" "=qm,q") - (ior:QI (match_operand:QI 1 "general_operand" "%0,0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") + (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") (match_operand:QI 2 "general_operand" "qn,qmn")))] "" "* return AS2 (or%B0,%2,%0);") ;;- xor instructions -;; ??? What if we only change one byte of an offsettable memory reference? (define_insn "xorsi3" - [(set (match_operand:SI 0 "general_operand" "=rm,r") - (xor:SI (match_operand:SI 1 "general_operand" "%0,0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") + (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") (match_operand:SI 2 "general_operand" "ri,rm")))] "" "* { - if (GET_CODE (operands[2]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) + HOST_WIDE_INT intval; + switch (GET_CODE (operands[2])) { - if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) - && (INTVAL (operands[2]) & ~0xff) == 0) - { - CC_STATUS_INIT; + case CONST_INT: - if (INTVAL (operands[2]) == 0xff) - return AS1 (not%B0,%b0); + if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) + break; - return AS2 (xor%B0,%2,%b0); + /* don't try to optimize volatile accesses */ + if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) + break; + + intval = INTVAL (operands[2]); + if ((intval & ~0xff) == 0) + { + if (REG_P (operands[0])) + { + /* Do low byte access only for %eax or when high bit is set */ + if (REGNO (operands[0]) != 0 && !(intval & 0x80)) + break; + } + +byte_xor_operation: + CC_STATUS_INIT; + + if (intval == 0xff) + return AS1 (not%B0,%b0); + + if (intval != INTVAL (operands[2])) + operands[2] = GEN_INT (intval); + return AS2 (xor%B0,%2,%b0); } - if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0) + /* second byte? */ + if ((intval & ~0xff00) == 0) { - CC_STATUS_INIT; - operands[2] = GEN_INT (INTVAL (operands[2]) >> 8); + intval >>= 8; - if (INTVAL (operands[2]) == 0xff) - return AS1 (not%B0,%h0); + if (REG_P (operands[0])) + { + CC_STATUS_INIT; + if (intval == 0xff) + return AS1 (not%B0,%h0); - return AS2 (xor%B0,%2,%h0); + operands[2] = GEN_INT (intval); + return AS2 (xor%B0,%2,%h0); + } + + operands[0] = adj_offsettable_operand (operands[0], 1); + + goto byte_xor_operation; } + + if (REG_P (operands[0])) + break; + + /* third byte? */ + if ((intval & ~0xff0000) == 0) + { + intval >>= 16; + operands[0] = adj_offsettable_operand (operands[0], 2); + goto byte_xor_operation; + } + + /* fourth byte? */ + if ((intval & ~0xff000000) == 0) + { + intval = (intval >> 24) & 0xff; + operands[0] = adj_offsettable_operand (operands[0], 3); + goto byte_xor_operation; + } + + default: + break; } return AS2 (xor%L0,%2,%0); }") (define_insn "xorhi3" - [(set (match_operand:HI 0 "general_operand" "=rm,r") - (xor:HI (match_operand:HI 1 "general_operand" "%0,0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") + (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "ri,rm")))] "" "* @@ -3305,23 +4102,143 @@ CC_STATUS_INIT; operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); - if (INTVAL (operands[2]) == 0xff) - return AS1 (not%B0,%h0); + if (INTVAL (operands[2]) == 0xff) + return AS1 (not%B0,%h0); + + return AS2 (xor%B0,%2,%h0); + } + } + + if (REG_P (operands[0]) + && i386_aligned_p (operands[2])) + { + CC_STATUS_INIT; + operands[2] = i386_sext16_if_const (operands[2]); + return AS2 (xor%L0,%k2,%k0); + } + + if (GET_CODE (operands[2]) == CONST_INT + && i386_aligned_p (operands[0])) + { + HOST_WIDE_INT intval; + CC_STATUS_INIT; + intval = 0xffff & INTVAL (operands[2]); + if (intval != INTVAL (operands[2])) + operands[2] = GEN_INT (intval); + return AS2 (xor%L0,%2,%k0); + } + + return AS2 (xor%W0,%2,%0); +}") + +(define_insn "xorqi3" + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") + (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") + (match_operand:QI 2 "general_operand" "qn,qm")))] + "" + "* return AS2 (xor%B0,%2,%0);") + +;; logical operations for DImode + + +(define_insn "anddi3" + [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o") + (and:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o") + (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o"))) + (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))] + "" + "#") + +(define_insn "iordi3" + [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o") + (ior:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o") + (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o"))) + (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))] + "" + "#") + +(define_insn "xordi3" + [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o") + (xor:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o") + (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o"))) + (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))] + "" + "#") + +(define_split + [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o") + (match_operator:DI 4 "ix86_logical_operator" + [(match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o") + (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")])) + (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))] + "reload_completed" + [(const_int 0)] + " +{ + rtx low[3], high[3], xops[7], temp; + rtx (*genfunc)() = (GET_CODE (operands[4]) == AND ? gen_andsi3 + : GET_CODE (operands[4]) == IOR ? gen_iorsi3 + : GET_CODE (operands[4]) == XOR ? gen_xorsi3 + : 0); + + if (rtx_equal_p (operands[0], operands[2])) + { + temp = operands[1]; + operands[1] = operands[2]; + operands[2] = temp; + } + + split_di (operands, 3, low, high); + if (!rtx_equal_p (operands[0], operands[1])) + { + xops[0] = high[0]; + xops[1] = low[0]; + xops[2] = high[1]; + xops[3] = low[1]; + + if (GET_CODE (operands[0]) != MEM) + { + emit_insn (gen_movsi (xops[1], xops[3])); + emit_insn (gen_movsi (xops[0], xops[2])); + } + else + { + xops[4] = high[2]; + xops[5] = low[2]; + xops[6] = operands[3]; + emit_insn (gen_movsi (xops[6], xops[3])); + emit_insn ((*genfunc) (xops[6], xops[6], xops[5])); + emit_insn (gen_movsi (xops[1], xops[6])); + emit_insn (gen_movsi (xops[6], xops[2])); + emit_insn ((*genfunc) (xops[6], xops[6], xops[4])); + emit_insn (gen_movsi (xops[0], xops[6])); + DONE; + } + } + + if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG) + { + xops[0] = high[0]; + xops[1] = low[0]; + xops[2] = high[2]; + xops[3] = low[2]; + xops[4] = operands[3]; + + emit_insn (gen_movsi (xops[4], xops[3])); + emit_insn ((*genfunc) (xops[1], xops[1], xops[4])); + emit_insn (gen_movsi (xops[4], xops[2])); + emit_insn ((*genfunc) (xops[0], xops[0], xops[4])); + } - return AS2 (xor%B0,%2,%h0); - } + else + { + emit_insn ((*genfunc) (low[0], low[0], low[2])); + emit_insn ((*genfunc) (high[0], high[0], high[2])); } - return AS2 (xor%W0,%2,%0); + DONE; }") -(define_insn "xorqi3" - [(set (match_operand:QI 0 "general_operand" "=qm,q") - (xor:QI (match_operand:QI 1 "general_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qn,qm")))] - "" - "* return AS2 (xor%B0,%2,%0);") - ;;- negation instructions (define_insn "negdi2" @@ -3345,50 +4262,50 @@ }") (define_insn "negsi2" - [(set (match_operand:SI 0 "general_operand" "=rm") - (neg:SI (match_operand:SI 1 "general_operand" "0")))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")))] "" "neg%L0 %0") (define_insn "neghi2" - [(set (match_operand:HI 0 "general_operand" "=rm") - (neg:HI (match_operand:HI 1 "general_operand" "0")))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))] "" "neg%W0 %0") (define_insn "negqi2" - [(set (match_operand:QI 0 "general_operand" "=qm") - (neg:QI (match_operand:QI 1 "general_operand" "0")))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")))] "" "neg%B0 %0") (define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (match_operand:SF 1 "general_operand" "0")))] + (neg:SF (match_operand:SF 1 "register_operand" "0")))] "TARGET_80387" "fchs") (define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (match_operand:DF 1 "general_operand" "0")))] + (neg:DF (match_operand:DF 1 "register_operand" "0")))] "TARGET_80387" "fchs") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] + (neg:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))] "TARGET_80387" "fchs") (define_insn "negxf2" [(set (match_operand:XF 0 "register_operand" "=f") - (neg:XF (match_operand:XF 1 "general_operand" "0")))] + (neg:XF (match_operand:XF 1 "register_operand" "0")))] "TARGET_80387" "fchs") (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") - (neg:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))] + (neg:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))] "TARGET_80387" "fchs") @@ -3396,44 +4313,48 @@ (define_insn "abssf2" [(set (match_operand:SF 0 "register_operand" "=f") - (abs:SF (match_operand:SF 1 "general_operand" "0")))] + (abs:SF (match_operand:SF 1 "register_operand" "0")))] "TARGET_80387" - "fabs") + "fabs" + [(set_attr "type" "fpop")]) (define_insn "absdf2" [(set (match_operand:DF 0 "register_operand" "=f") - (abs:DF (match_operand:DF 1 "general_operand" "0")))] + (abs:DF (match_operand:DF 1 "register_operand" "0")))] "TARGET_80387" - "fabs") + "fabs" + [(set_attr "type" "fpop")]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") - (abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))] + (abs:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))] "TARGET_80387" - "fabs") + "fabs" + [(set_attr "type" "fpop")]) (define_insn "absxf2" [(set (match_operand:XF 0 "register_operand" "=f") - (abs:XF (match_operand:XF 1 "general_operand" "0")))] + (abs:XF (match_operand:XF 1 "register_operand" "0")))] "TARGET_80387" - "fabs") + "fabs" + [(set_attr "type" "fpop")]) (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") - (abs:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))] + (abs:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))] "TARGET_80387" - "fabs") + "fabs" + [(set_attr "type" "fpop")]) (define_insn "sqrtsf2" [(set (match_operand:SF 0 "register_operand" "=f") - (sqrt:SF (match_operand:SF 1 "general_operand" "0")))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + (sqrt:SF (match_operand:SF 1 "register_operand" "0")))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" "fsqrt") (define_insn "sqrtdf2" [(set (match_operand:DF 0 "register_operand" "=f") - (sqrt:DF (match_operand:DF 1 "general_operand" "0")))] + (sqrt:DF (match_operand:DF 1 "register_operand" "0")))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math) " "fsqrt") @@ -3441,14 +4362,13 @@ (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (sqrt:DF (float_extend:DF - (match_operand:SF 1 "general_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + (match_operand:SF 1 "register_operand" "0"))))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" "fsqrt") (define_insn "sqrtxf2" [(set (match_operand:XF 0 "register_operand" "=f") - (sqrt:XF (match_operand:XF 1 "general_operand" "0")))] + (sqrt:XF (match_operand:XF 1 "register_operand" "0")))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && (TARGET_IEEE_FP || flag_fast_math) " "fsqrt") @@ -3456,94 +4376,84 @@ (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (float_extend:XF - (match_operand:DF 1 "general_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + (match_operand:DF 1 "register_operand" "0"))))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" "fsqrt") (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") (sqrt:XF (float_extend:XF - (match_operand:SF 1 "general_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + (match_operand:SF 1 "register_operand" "0"))))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" "fsqrt") (define_insn "sindf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fsin") (define_insn "sinsf2" [(set (match_operand:SF 0 "register_operand" "=f") (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fsin") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(float_extend:DF (match_operand:SF 1 "register_operand" "0"))] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fsin") (define_insn "sinxf2" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fsin") (define_insn "cosdf2" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fcos") (define_insn "cossf2" [(set (match_operand:SF 0 "register_operand" "=f") (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fcos") (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (unspec:DF [(float_extend:DF (match_operand:SF 1 "register_operand" "0"))] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fcos") (define_insn "cosxf2" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" "fcos") ;;- one complement instructions (define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "general_operand" "=rm") - (not:SI (match_operand:SI 1 "general_operand" "0")))] + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))] "" "not%L0 %0") (define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "general_operand" "=rm") - (not:HI (match_operand:HI 1 "general_operand" "0")))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))] "" "not%W0 %0") (define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "general_operand" "=qm") - (not:QI (match_operand:QI 1 "general_operand" "0")))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (not:QI (match_operand:QI 1 "nonimmediate_operand" "0")))] "" "not%B0 %0") @@ -3565,8 +4475,7 @@ ;; separately, making all shifts emit pairs of shift double and normal ;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to ;; support a 63 bit shift, each shift where the count is in a reg expands -;; to three pairs. If the overall shift is by N bits, then the first two -;; pairs shift by N / 2 and the last pair by N & 1. +;; to a pair of shifts, a branch, a shift by 32 and a label. ;; If the shift count is a constant, we need never emit more than one ;; shift pair, instead using moves and sign extension for counts greater @@ -3596,7 +4505,7 @@ [(set (match_operand:DI 0 "register_operand" "=&r") (ashift:DI (match_operand:DI 1 "register_operand" "0") (match_operand:QI 2 "const_int_operand" "J")))] - "" + "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')" "* { rtx xops[4], low[1], high[1]; @@ -3631,35 +4540,29 @@ (define_insn "ashldi3_non_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (ashift:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "c"))) - (clobber (match_dup 2))] + (match_operand:QI 2 "register_operand" "c")))] "" "* { - rtx xops[4], low[1], high[1]; + rtx xops[5], low[1], high[1]; CC_STATUS_INIT; split_di (operands, 1, low, high); xops[0] = operands[2]; - xops[1] = const1_rtx; + xops[1] = GEN_INT (32); xops[2] = low[0]; xops[3] = high[0]; - - output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ - - output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); - output_asm_insn (AS2 (sal%L2,%0,%2), xops); - output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); - output_asm_insn (AS2 (sal%L2,%0,%2), xops); - - xops[1] = GEN_INT (7); /* shift count & 1 */ - - output_asm_insn (AS2 (shr%B0,%1,%0), xops); + xops[4] = gen_label_rtx (); output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); output_asm_insn (AS2 (sal%L2,%0,%2), xops); - + output_asm_insn (AS2 (test%B0,%1,%b0), xops); + output_asm_insn (AS1 (je,%X4), xops); + output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */ + output_asm_insn (AS2 (xor%L2,%2,%2), xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (xops[4])); RET; }") @@ -3668,15 +4571,15 @@ ;; is smaller - use leal for now unless the shift count is 1. (define_insn "ashlsi3" - [(set (match_operand:SI 0 "general_operand" "=r,rm") - (ashift:SI (match_operand:SI 1 "general_operand" "r,0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm") + (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,0") (match_operand:SI 2 "nonmemory_operand" "M,cI")))] "" "* { if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1])) { - if (!TARGET_386 && INTVAL (operands[2]) == 1) + if (TARGET_DOUBLE_WITH_ADD && INTVAL (operands[2]) == 1) { output_asm_insn (AS2 (mov%L0,%1,%0), operands); return AS2 (add%L0,%1,%0); @@ -3690,8 +4593,8 @@ output_asm_insn (AS2 (mov%L0,%1,%0), operands); operands[1] = operands[0]; } - operands[1] = gen_rtx (MULT, SImode, operands[1], - GEN_INT (1 << INTVAL (operands[2]))); + operands[1] = gen_rtx_MULT (SImode, operands[1], + GEN_INT (1 << INTVAL (operands[2]))); return AS2 (lea%L0,%a1,%0); } } @@ -3706,8 +4609,8 @@ }") (define_insn "ashlhi3" - [(set (match_operand:HI 0 "general_operand" "=rm") - (ashift:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "nonmemory_operand" "cI")))] "" "* @@ -3722,8 +4625,8 @@ }") (define_insn "ashlqi3" - [(set (match_operand:QI 0 "general_operand" "=qm") - (ashift:QI (match_operand:QI 1 "general_operand" "0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI")))] "" "* @@ -3759,11 +4662,36 @@ DONE; }") +(define_insn "ashldi3_32" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m") + (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r") + (const_int 32)))] + "" + "* +{ + rtx low[2], high[2], xops[4]; + + split_di (operands, 2, low, high); + xops[0] = high[0]; + xops[1] = low[1]; + xops[2] = low[0]; + xops[3] = const0_rtx; + if (!rtx_equal_p (xops[0], xops[1])) + output_asm_insn (AS2 (mov%L0,%1,%0), xops); + + if (GET_CODE (low[0]) == MEM) + output_asm_insn (AS2 (mov%L2,%3,%2), xops); + else + output_asm_insn (AS2 (xor%L2,%2,%2), xops); + + RET; +}") + (define_insn "ashrdi3_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") (match_operand:QI 2 "const_int_operand" "J")))] - "" + "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')" "* { rtx xops[4], low[1], high[1]; @@ -3800,41 +4728,36 @@ (define_insn "ashrdi3_non_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "c"))) - (clobber (match_dup 2))] + (match_operand:QI 2 "register_operand" "c")))] "" "* { - rtx xops[4], low[1], high[1]; + rtx xops[5], low[1], high[1]; CC_STATUS_INIT; split_di (operands, 1, low, high); xops[0] = operands[2]; - xops[1] = const1_rtx; + xops[1] = GEN_INT (32); xops[2] = low[0]; xops[3] = high[0]; - - output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ - - output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (sar%L3,%0,%3), xops); - output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (sar%L3,%0,%3), xops); - - xops[1] = GEN_INT (7); /* shift count & 1 */ - - output_asm_insn (AS2 (shr%B0,%1,%0), xops); + xops[4] = gen_label_rtx (); output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); output_asm_insn (AS2 (sar%L3,%0,%3), xops); - + output_asm_insn (AS2 (test%B0,%1,%b0), xops); + output_asm_insn (AS1 (je,%X4), xops); + xops[1] = GEN_INT (31); + output_asm_insn (AS2 (mov%L2,%3,%2), xops); + output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */ + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (xops[4])); RET; }") (define_insn "ashrsi3" - [(set (match_operand:SI 0 "general_operand" "=rm") - (ashiftrt:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "nonmemory_operand" "cI")))] "" "* @@ -3846,8 +4769,8 @@ }") (define_insn "ashrhi3" - [(set (match_operand:HI 0 "general_operand" "=rm") - (ashiftrt:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "nonmemory_operand" "cI")))] "" "* @@ -3859,8 +4782,8 @@ }") (define_insn "ashrqi3" - [(set (match_operand:QI 0 "general_operand" "=qm") - (ashiftrt:QI (match_operand:QI 1 "general_operand" "0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI")))] "" "* @@ -3895,11 +4818,36 @@ DONE; }") +(define_insn "lshrdi3_32" + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m") + (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r") + (const_int 32)))] + "" + "* +{ + rtx low[2], high[2], xops[4]; + + split_di (operands, 2, low, high); + xops[0] = low[0]; + xops[1] = high[1]; + xops[2] = high[0]; + xops[3] = const0_rtx; + if (!rtx_equal_p (xops[0], xops[1])) + output_asm_insn (AS2 (mov%L0,%1,%0), xops); + + if (GET_CODE (low[0]) == MEM) + output_asm_insn (AS2 (mov%L2,%3,%2), xops); + else + output_asm_insn (AS2 (xor%L2,%2,%2), xops); + + RET; +}") + (define_insn "lshrdi3_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") (match_operand:QI 2 "const_int_operand" "J")))] - "" + "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')" "* { rtx xops[4], low[1], high[1]; @@ -3935,41 +4883,35 @@ (define_insn "lshrdi3_non_const_int" [(set (match_operand:DI 0 "register_operand" "=&r") (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "c"))) - (clobber (match_dup 2))] + (match_operand:QI 2 "register_operand" "c")))] "" "* { - rtx xops[4], low[1], high[1]; + rtx xops[5], low[1], high[1]; CC_STATUS_INIT; split_di (operands, 1, low, high); xops[0] = operands[2]; - xops[1] = const1_rtx; + xops[1] = GEN_INT (32); xops[2] = low[0]; xops[3] = high[0]; - - output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */ - - output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (shr%L3,%0,%3), xops); - output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (shr%L3,%0,%3), xops); - - xops[1] = GEN_INT (7); /* shift count & 1 */ - - output_asm_insn (AS2 (shr%B0,%1,%0), xops); + xops[4] = gen_label_rtx (); output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); output_asm_insn (AS2 (shr%L3,%0,%3), xops); - + output_asm_insn (AS2 (test%B0,%1,%b0), xops); + output_asm_insn (AS1 (je,%X4), xops); + output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */ + output_asm_insn (AS2 (xor%L3,%3,%3), xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (xops[4])); RET; }") (define_insn "lshrsi3" - [(set (match_operand:SI 0 "general_operand" "=rm") - (lshiftrt:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "nonmemory_operand" "cI")))] "" "* @@ -3981,8 +4923,8 @@ }") (define_insn "lshrhi3" - [(set (match_operand:HI 0 "general_operand" "=rm") - (lshiftrt:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "nonmemory_operand" "cI")))] "" "* @@ -3994,8 +4936,8 @@ }") (define_insn "lshrqi3" - [(set (match_operand:QI 0 "general_operand" "=qm") - (lshiftrt:QI (match_operand:QI 1 "general_operand" "0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI")))] "" "* @@ -4009,8 +4951,8 @@ ;;- rotate instructions (define_insn "rotlsi3" - [(set (match_operand:SI 0 "general_operand" "=rm") - (rotate:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "nonmemory_operand" "cI")))] "" "* @@ -4022,8 +4964,8 @@ }") (define_insn "rotlhi3" - [(set (match_operand:HI 0 "general_operand" "=rm") - (rotate:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "nonmemory_operand" "cI")))] "" "* @@ -4035,8 +4977,8 @@ }") (define_insn "rotlqi3" - [(set (match_operand:QI 0 "general_operand" "=qm") - (rotate:QI (match_operand:QI 1 "general_operand" "0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI")))] "" "* @@ -4048,8 +4990,8 @@ }") (define_insn "rotrsi3" - [(set (match_operand:SI 0 "general_operand" "=rm") - (rotatert:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "nonmemory_operand" "cI")))] "" "* @@ -4061,8 +5003,8 @@ }") (define_insn "rotrhi3" - [(set (match_operand:HI 0 "general_operand" "=rm") - (rotatert:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") + (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0") (match_operand:HI 2 "nonmemory_operand" "cI")))] "" "* @@ -4074,8 +5016,8 @@ }") (define_insn "rotrqi3" - [(set (match_operand:QI 0 "general_operand" "=qm") - (rotatert:QI (match_operand:QI 1 "general_operand" "0") + [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") + (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0") (match_operand:QI 2 "nonmemory_operand" "cI")))] "" "* @@ -4090,11 +5032,13 @@ ;; This usually looses. But try a define_expand to recognize a few case ;; we can do efficiently, such as accessing the "high" QImode registers, ;; %ah, %bh, %ch, %dh. +;; ??? Note this has a botch on the mode of operand 0, which needs to be +;; fixed if this is ever enabled. (define_insn "insv" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r") - (match_operand:SI 1 "general_operand" "i") - (match_operand:SI 2 "general_operand" "i")) - (match_operand:SI 3 "general_operand" "ri"))] + (match_operand:SI 1 "immediate_operand" "i") + (match_operand:SI 2 "immediate_operand" "i")) + (match_operand:SI 3 "nonmemory_operand" "ri"))] "" "* { @@ -4110,7 +5054,7 @@ } else { - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0])); + operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); if (INTVAL (operands[2])) output_asm_insn (AS2 (ror%L0,%2,%0), operands); output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands); @@ -4130,7 +5074,7 @@ [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "immediate_operand" "") (match_operand:SI 2 "immediate_operand" "")) - (match_operand:QI 3 "general_operand" "ri"))] + (match_operand:QI 3 "nonmemory_operand" "ri"))] "" " { @@ -4143,22 +5087,6 @@ && ! INTVAL (operands[1]) == 1) FAIL; }") - -;; ??? Are these constraints right? -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+&qo") - (const_int 8) - (const_int 8)) - (match_operand:QI 1 "general_operand" "qn"))] - "" - "* -{ - if (REG_P (operands[0])) - return AS2 (mov%B0,%1,%h0); - - operands[0] = adj_offsettable_operand (operands[0], 1); - return AS2 (mov%B0,%1,%0); -}") */ ;; On i386, the register count for a bit operation is *not* truncated, @@ -4173,11 +5101,11 @@ ;; General bit set and clear. (define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+rm") + [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+rm") (const_int 1) - (match_operand:SI 2 "general_operand" "r")) + (match_operand:SI 2 "register_operand" "r")) (match_operand:SI 3 "const_int_operand" "n"))] - "TARGET_386 && GET_CODE (operands[2]) != CONST_INT" + "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT" "* { CC_STATUS_INIT; @@ -4191,11 +5119,11 @@ ;; Bit complement. See comments on previous pattern. ;; ??? Is this really worthwhile? (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") (xor:SI (ashift:SI (const_int 1) - (match_operand:SI 1 "general_operand" "r")) - (match_operand:SI 2 "general_operand" "0")))] - "TARGET_386 && GET_CODE (operands[1]) != CONST_INT" + (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 2 "nonimmediate_operand" "0")))] + "TARGET_USE_BIT_TEST && GET_CODE (operands[1]) != CONST_INT" "* { CC_STATUS_INIT; @@ -4204,11 +5132,11 @@ }") (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") - (xor:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") + (xor:SI (match_operand:SI 1 "nonimmediate_operand" "0") (ashift:SI (const_int 1) - (match_operand:SI 2 "general_operand" "r"))))] - "TARGET_386 && GET_CODE (operands[2]) != CONST_INT" + (match_operand:SI 2 "register_operand" "r"))))] + "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT" "* { CC_STATUS_INIT; @@ -4229,7 +5157,7 @@ (define_insn "" [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r") (const_int 1) - (match_operand:SI 1 "general_operand" "r")))] + (match_operand:SI 1 "register_operand" "r")))] "GET_CODE (operands[1]) != CONST_INT" "* { @@ -4272,7 +5200,7 @@ ;; The CPU may access unspecified bytes around the actual target byte. (define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "general_operand" "rm") + [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m") (match_operand:SI 1 "const_int_operand" "n") (match_operand:SI 2 "const_int_operand" "n")))] "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])" @@ -4403,7 +5331,8 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (sete,%0); OUTPUT_JUMP (\"setg %0\", \"seta %0\", NULL_PTR); @@ -4435,7 +5364,8 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (sete,%0); OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\"); @@ -4467,7 +5397,8 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (sete,%0); OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\"); @@ -4499,7 +5430,8 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (setb,%0); OUTPUT_JUMP (\"setle %0\", \"setbe %0\", NULL_PTR); @@ -4553,6 +5485,14 @@ if (cc_prev_status.flags & CC_Z_IN_NOT_C) return \"jnc %l0\"; else + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x4000); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (jne,%l0); + } + return \"je %l0\"; }") @@ -4585,6 +5525,14 @@ if (cc_prev_status.flags & CC_Z_IN_NOT_C) return \"jc %l0\"; else + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x4000); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (je,%l0); + } + return \"jne %l0\"; }") @@ -4607,9 +5555,17 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (je,%l0); + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x4100); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (je,%l0); + } OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR); }") @@ -4651,9 +5607,17 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (je,%l0); + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x100); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (jne,%l0); + } OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\"); }") @@ -4695,9 +5659,16 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (je,%l0); - + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x100); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (je,%l0); + } OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\"); }") @@ -4739,8 +5710,16 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (jb,%l0); + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x4100); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (jne,%l0); + } OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR); }") @@ -4778,6 +5757,13 @@ if (cc_prev_status.flags & CC_Z_IN_NOT_C) return \"jc %l0\"; else + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x4000); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (je,%l0); + } return \"jne %l0\"; }") @@ -4793,6 +5779,13 @@ if (cc_prev_status.flags & CC_Z_IN_NOT_C) return \"jnc %l0\"; else + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x4000); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (jne,%l0); + } return \"je %l0\"; }") @@ -4805,9 +5798,16 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (jne,%l0); - + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x4100); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (jne,%l0); + } OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR); }") @@ -4829,8 +5829,16 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (jne,%l0); + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x100); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (je,%l0); + } OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\"); }") @@ -4853,9 +5861,16 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (jne,%l0); - + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x100); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (jne,%l0); + } OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\"); }") @@ -4877,9 +5892,17 @@ "" "* { - if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)) + if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387) + && ! (cc_prev_status.flags & CC_FCOMI)) return AS1 (jae,%l0); + if (cc_prev_status.flags & CC_TEST_AX) + { + operands[1] = gen_rtx_REG (SImode, 0); + operands[2] = GEN_INT (0x4100); + output_asm_insn (AS2 (testl,%2,%1), operands); + return AS1 (je,%l0); + } OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR); }") @@ -4901,7 +5924,7 @@ "jmp %l0") (define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "general_operand" "rm"))] + [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))] "" "* { @@ -4929,7 +5952,7 @@ (define_insn "" [(set (pc) (if_then_else (match_operator 0 "arithmetic_comparison_operator" - [(plus:SI (match_operand:SI 1 "general_operand" "+r,m") + [(plus:SI (match_operand:SI 1 "nonimmediate_operand" "+r,m") (match_operand:SI 2 "general_operand" "rmi,ri")) (const_int 0)]) (label_ref (match_operand 3 "" "")) @@ -4944,7 +5967,7 @@ if (operands[2] == constm1_rtx) output_asm_insn (AS1 (dec%L1,%1), operands); - else if (operands[1] == const1_rtx) + else if (operands[2] == const1_rtx) output_asm_insn (AS1 (inc%L1,%1), operands); else @@ -4956,7 +5979,7 @@ (define_insn "" [(set (pc) (if_then_else (match_operator 0 "arithmetic_comparison_operator" - [(minus:SI (match_operand:SI 1 "general_operand" "+r,m") + [(minus:SI (match_operand:SI 1 "nonimmediate_operand" "+r,m") (match_operand:SI 2 "general_operand" "rmi,ri")) (const_int 0)]) (label_ref (match_operand 3 "" "")) @@ -4980,6 +6003,110 @@ return AS1 (%J0,%l3); }") +(define_insn "" + [(set (pc) + (if_then_else (ne (match_operand:SI 0 "general_operand" "+g") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "" + "* +{ + CC_STATUS_INIT; + operands[2] = const1_rtx; + output_asm_insn (AS2 (sub%L0,%2,%0), operands); + return \"jnc %l1\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else (eq (match_operand:SI 0 "general_operand" "+g") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "" + "* +{ + CC_STATUS_INIT; + operands[2] = const1_rtx; + output_asm_insn (AS2 (sub%L0,%2,%0), operands); + return \"jc %l1\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else (ne (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "" + "* +{ + CC_STATUS_INIT; + output_asm_insn (AS1 (dec%L0,%0), operands); + return \"jnz %l1\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else (eq (match_operand:SI 0 "general_operand" "+g") + (const_int 1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))] + "" + "* +{ + CC_STATUS_INIT; + output_asm_insn (AS1 (dec%L0,%0), operands); + return \"jz %l1\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else (ne (match_operand:SI 0 "general_operand" "+g") + (const_int -1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "" + "* +{ + CC_STATUS_INIT; + output_asm_insn (AS1 (inc%L0,%0), operands); + return \"jnz %l1\"; +}") + +(define_insn "" + [(set (pc) + (if_then_else (eq (match_operand:SI 0 "general_operand" "+g") + (const_int -1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int 1)))] + "" + "* +{ + CC_STATUS_INIT; + output_asm_insn (AS1 (inc%L0,%0), operands); + return \"jz %l1\"; +}") + ;; Implement switch statements when generating PIC code. Switches are ;; implemented by `tablejump' when not using -fpic. @@ -4987,10 +6114,12 @@ (define_expand "casesi" [(set (match_dup 5) - (minus:SI (match_operand:SI 0 "general_operand" "") + (match_operand:SI 0 "general_operand" "")) + (set (match_dup 6) + (minus:SI (match_dup 5) (match_operand:SI 1 "general_operand" ""))) (set (cc0) - (compare:CC (match_dup 5) + (compare:CC (match_dup 6) (match_operand:SI 2 "general_operand" ""))) (set (pc) (if_then_else (gtu (cc0) @@ -5000,14 +6129,15 @@ (parallel [(set (pc) (minus:SI (reg:SI 3) - (mem:SI (plus:SI (mult:SI (match_dup 5) + (mem:SI (plus:SI (mult:SI (match_dup 6) (const_int 4)) (label_ref (match_operand 3 "" "")))))) - (clobber (match_scratch:SI 6 ""))])] + (clobber (match_scratch:SI 7 ""))])] "flag_pic" " { operands[5] = gen_reg_rtx (SImode); + operands[6] = gen_reg_rtx (SImode); current_function_uses_pic_offset_table = 1; }") @@ -5061,12 +6191,12 @@ output_asm_insn (AS2 (mov%L2,%3,%2), xops); output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops); output_asm_insn (AS1 (jmp,%*%2), xops); - ASM_OUTPUT_ALIGN_CODE (asm_out_file); + ASM_OUTPUT_ALIGN (asm_out_file, i386_align_jumps); RET; }") (define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "general_operand" "rm")) + [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm")) (use (label_ref (match_operand 1 "" "")))] "" "* @@ -5312,9 +6442,10 @@ coprocessor registers as containing a possible return value, simply pretend the untyped call returns a complex long double value. */ + emit_call_insn (TARGET_80387 - ? gen_call_value (gen_rtx (REG, XCmode, FIRST_FLOAT_REG), - operands[0], const0_rtx) + ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG), + operands[0], const0_rtx) : gen_call (operands[0], const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) @@ -5329,34 +6460,163 @@ point. */ emit_insn (gen_blockage ()); - DONE; + DONE; +}") + +;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and +;; all of memory. This blocks insns from being moved across this point. + +(define_insn "blockage" + [(unspec_volatile [(const_int 0)] 0)] + "" + "") + +;; Insn emitted into the body of a function to return from a function. +;; This is only done if the function's epilogue is known to be simple. +;; See comments for simple_386_epilogue in i386.c. + +(define_expand "return" + [(return)] + "ix86_can_use_return_insn_p ()" + "") + +(define_insn "return_internal" + [(return)] + "reload_completed" + "ret") + +(define_insn "return_pop_internal" + [(return) + (use (match_operand:SI 0 "const_int_operand" ""))] + "reload_completed" + "ret %0") + +(define_insn "nop" + [(const_int 0)] + "" + "nop") + +(define_expand "prologue" + [(const_int 1)] + "" + " +{ + ix86_expand_prologue (); + DONE; +}") + +;; The use of UNSPEC here is currently not necessary - a simple SET of ebp +;; to itself would be enough. But this way we are safe even if some optimizer +;; becomes too clever in the future. +(define_insn "prologue_set_stack_ptr" + [(set (reg:SI 7) + (minus:SI (reg:SI 7) (match_operand:SI 0 "immediate_operand" "i"))) + (set (reg:SI 6) (unspec:SI [(reg:SI 6)] 4))] + "" + "* +{ + rtx xops [2]; + + xops[0] = operands[0]; + xops[1] = stack_pointer_rtx; + output_asm_insn (AS2 (sub%L1,%0,%1), xops); + RET; +}") + +(define_insn "prologue_set_got" + [(set (match_operand:SI 0 "" "") + (unspec_volatile + [(plus:SI (match_dup 0) + (plus:SI (match_operand:SI 1 "symbolic_operand" "") + (minus:SI (pc) (match_operand 2 "" ""))))] 1))] + "" + "* +{ + char buffer[64]; + + if (TARGET_DEEP_BRANCH_PREDICTION) + { + sprintf (buffer, \"addl %s,%%0\", XSTR (operands[1], 0)); + output_asm_insn (buffer, operands); + } + else + { + sprintf (buffer, \"addl %s+[.-%%X2],%%0\", XSTR (operands[1], 0)); + output_asm_insn (buffer, operands); + } + RET; +}") + +(define_insn "prologue_get_pc" + [(set (match_operand:SI 0 "" "") + (unspec_volatile [(plus:SI (pc) (match_operand 1 "" ""))] 2))] + "" + "* +{ + char buffer[64]; + + output_asm_insn (AS1 (call,%X1), operands); + if (! TARGET_DEEP_BRANCH_PREDICTION) + { + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (operands[1])); + } + RET; }") -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] +(define_insn "prologue_get_pc_and_set_got" + [(unspec_volatile [(match_operand:SI 0 "" "")] 3)] "" - "") + "* +{ + operands[1] = gen_label_rtx (); + output_asm_insn (AS1 (call,%X1), operands); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (operands[1])); + output_asm_insn (AS1 (pop%L0,%0), operands); + output_asm_insn (\"addl $_GLOBAL_OFFSET_TABLE_+[.-%X1],%0\", operands); + RET; +}") -;; Insn emitted into the body of a function to return from a function. -;; This is only done if the function's epilogue is known to be simple. -;; See comments for simple_386_epilogue in i386.c. +(define_expand "epilogue" + [(const_int 1)] + "" + " +{ + ix86_expand_epilogue (); + DONE; +}") -(define_insn "return" - [(return)] - "simple_386_epilogue ()" +(define_insn "epilogue_set_stack_ptr" + [(set (reg:SI 7) (reg:SI 6)) + (clobber (reg:SI 6))] + "" "* { - function_epilogue (asm_out_file, get_frame_size ()); - RET; + rtx xops [2]; + + xops[0] = frame_pointer_rtx; + xops[1] = stack_pointer_rtx; + output_asm_insn (AS2 (mov%L0,%0,%1), xops); + RET; }") -(define_insn "nop" - [(const_int 0)] +(define_insn "leave" + [(const_int 2) + (clobber (reg:SI 6)) + (clobber (reg:SI 7))] "" - "nop") + "leave") + +(define_insn "pop" + [(set (match_operand:SI 0 "register_operand" "r") + (mem:SI (reg:SI 7))) + (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))] + "" + "* +{ + output_asm_insn (AS1 (pop%L0,%P0), operands); + RET; +}") (define_expand "movstrsi" [(parallel [(set (match_operand:BLK 0 "memory_operand" "") @@ -5380,8 +6640,8 @@ operands[5] = addr0; operands[6] = addr1; - operands[0] = gen_rtx (MEM, BLKmode, addr0); - operands[1] = gen_rtx (MEM, BLKmode, addr1); + operands[0] = change_address (operands[0], VOIDmode, addr0); + operands[1] = change_address (operands[1], VOIDmode, addr1); }") ;; It might seem that operands 0 & 1 could use predicate register_operand. @@ -5426,6 +6686,73 @@ RET; }") +(define_expand "clrstrsi" + [(set (match_dup 3) (const_int 0)) + (parallel [(set (match_operand:BLK 0 "memory_operand" "") + (const_int 0)) + (use (match_operand:SI 1 "const_int_operand" "")) + (use (match_operand:SI 2 "const_int_operand" "")) + (use (match_dup 3)) + (clobber (match_scratch:SI 4 "")) + (clobber (match_dup 5))])] + "" + " +{ + rtx addr0, addr1; + + if (GET_CODE (operands[1]) != CONST_INT) + FAIL; + + addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); + + operands[3] = gen_reg_rtx (SImode); + operands[5] = addr0; + + operands[0] = gen_rtx_MEM (BLKmode, addr0); +}") + +;; It might seem that operand 0 could use predicate register_operand. +;; But strength reduction might offset the MEM expression. So we let +;; reload put the address into %edi. + +(define_insn "" + [(set (mem:BLK (match_operand:SI 0 "address_operand" "D")) + (const_int 0)) + (use (match_operand:SI 1 "const_int_operand" "n")) + (use (match_operand:SI 2 "immediate_operand" "i")) + (use (match_operand:SI 3 "register_operand" "a")) + (clobber (match_scratch:SI 4 "=&c")) + (clobber (match_dup 0))] + "" + "* +{ + rtx xops[2]; + + output_asm_insn (\"cld\", operands); + if (GET_CODE (operands[1]) == CONST_INT) + { + if (INTVAL (operands[1]) & ~0x03) + { + xops[0] = GEN_INT ((INTVAL (operands[1]) >> 2) & 0x3fffffff); + xops[1] = operands[4]; + + output_asm_insn (AS2 (mov%L1,%0,%1), xops); +#ifdef INTEL_SYNTAX + output_asm_insn (\"rep stosd\", xops); +#else + output_asm_insn (\"rep\;stosl\", xops); +#endif + } + if (INTVAL (operands[1]) & 0x02) + output_asm_insn (\"stosw\", operands); + if (INTVAL (operands[1]) & 0x01) + output_asm_insn (\"stosb\", operands); + } + else + abort (); + RET; +}") + (define_expand "cmpstrsi" [(parallel [(set (match_operand:SI 0 "general_operand" "") (compare:SI (match_operand:BLK 1 "general_operand" "") @@ -5447,8 +6774,8 @@ operands[5] = addr1; operands[6] = addr2; - operands[1] = gen_rtx (MEM, BLKmode, addr1); - operands[2] = gen_rtx (MEM, BLKmode, addr2); + operands[1] = gen_rtx_MEM (BLKmode, addr1); + operands[2] = gen_rtx_MEM (BLKmode, addr2); }") @@ -5464,7 +6791,7 @@ ;; code to handle zero-length compares. (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=&r") + [(set (match_operand:SI 0 "register_operand" "=&r") (compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S")) (mem:BLK (match_operand:SI 2 "address_operand" "D")))) (use (match_operand:SI 3 "register_operand" "c")) @@ -5475,7 +6802,7 @@ "" "* { - rtx xops[4], label; + rtx xops[2], label; label = gen_label_rtx (); @@ -5485,16 +6812,13 @@ output_asm_insn (\"je %l0\", &label); xops[0] = operands[0]; - xops[1] = gen_rtx (MEM, QImode, - gen_rtx (PLUS, SImode, operands[1], constm1_rtx)); - xops[2] = gen_rtx (MEM, QImode, - gen_rtx (PLUS, SImode, operands[2], constm1_rtx)); - xops[3] = operands[3]; - - output_asm_insn (AS2 (movz%B1%L0,%1,%0), xops); - output_asm_insn (AS2 (movz%B2%L3,%2,%3), xops); - - output_asm_insn (AS2 (sub%L0,%3,%0), xops); + xops[1] = const1_rtx; + output_asm_insn (AS2 (sbb%L0,%0,%0), xops); + if (QI_REG_P (xops[0])) + output_asm_insn (AS2 (or%B0,%1,%b0), xops); + else + output_asm_insn (AS2 (or%L0,%1,%0), xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label)); RET; }") @@ -5515,7 +6839,7 @@ cc_status.flags |= CC_NOT_SIGNED; - xops[0] = gen_rtx (REG, QImode, 0); + xops[0] = gen_rtx_REG (QImode, 0); xops[1] = CONST0_RTX (QImode); output_asm_insn (\"cld\", operands); @@ -5523,101 +6847,64 @@ return \"repz\;cmps%B2\"; }") -(define_expand "ffssi2" - [(set (match_dup 2) - (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "")) - (const_int -1))) - (set (match_operand:SI 0 "general_operand" "") - (plus:SI (match_dup 2) (const_int 1)))] - "" - "operands[2] = gen_reg_rtx (SImode);") - + ;; Note, you cannot optimize away the branch following the bsfl by assuming ;; that the destination is not modified if the input is 0, since not all ;; x86 implementations do this. -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=&r") - (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "rm")) - (const_int -1)))] +(define_expand "ffssi2" + [(set (match_operand:SI 0 "general_operand" "") + (ffs:SI (match_operand:SI 1 "general_operand" "")))] "" - "* + " { - rtx xops[3]; - static int ffssi_label_number; - char buffer[30]; + rtx label = gen_label_rtx (), temp = gen_reg_rtx (SImode); - xops[0] = operands[0]; - xops[1] = operands[1]; - xops[2] = constm1_rtx; - output_asm_insn (AS2 (bsf%L0,%1,%0), xops); -#ifdef LOCAL_LABEL_PREFIX - sprintf (buffer, \"jnz %sLFFSSI%d\", - LOCAL_LABEL_PREFIX, ffssi_label_number); -#else - sprintf (buffer, \"jnz %sLFFSSI%d\", - \"\", ffssi_label_number); -#endif - output_asm_insn (buffer, xops); - output_asm_insn (AS2 (mov%L0,%2,%0), xops); -#ifdef LOCAL_LABEL_PREFIX - sprintf (buffer, \"%sLFFSSI%d:\", - LOCAL_LABEL_PREFIX, ffssi_label_number); -#else - sprintf (buffer, \"%sLFFSSI%d:\", - \"\", ffssi_label_number); -#endif - output_asm_insn (buffer, xops); + emit_insn (gen_ffssi_1 (temp, operands[1])); + emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, SImode, 0, 0); + emit_jump_insn (gen_bne (label)); + emit_move_insn (temp, constm1_rtx); + emit_label (label); + temp = expand_binop (SImode, add_optab, temp, const1_rtx, + operands[0], 0, OPTAB_WIDEN); - ffssi_label_number++; - return \"\"; + if (temp != operands[0]) + emit_move_insn (operands[0], temp); + DONE; }") -(define_expand "ffshi2" - [(set (match_dup 2) - (plus:HI (ffs:HI (match_operand:HI 1 "general_operand" "")) - (const_int -1))) - (set (match_operand:HI 0 "general_operand" "") - (plus:HI (match_dup 2) (const_int 1)))] +(define_insn "ffssi_1" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))] "" - "operands[2] = gen_reg_rtx (HImode);") + "* return AS2 (bsf%L0,%1,%0);") -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=&r") - (plus:HI (ffs:HI (match_operand:SI 1 "general_operand" "rm")) - (const_int -1)))] +(define_expand "ffshi2" + [(set (match_operand:SI 0 "general_operand" "") + (ffs:HI (match_operand:HI 1 "general_operand" "")))] "" - "* + " { - rtx xops[3]; - static int ffshi_label_number; - char buffer[30]; + rtx label = gen_label_rtx (), temp = gen_reg_rtx (HImode); - xops[0] = operands[0]; - xops[1] = operands[1]; - xops[2] = constm1_rtx; - output_asm_insn (AS2 (bsf%W0,%1,%0), xops); -#ifdef LOCAL_LABEL_PREFIX - sprintf (buffer, \"jnz %sLFFSHI%d\", - LOCAL_LABEL_PREFIX, ffshi_label_number); -#else - sprintf (buffer, \"jnz %sLFFSHI%d\", - \"\", ffshi_label_number); -#endif - output_asm_insn (buffer, xops); - output_asm_insn (AS2 (mov%W0,%2,%0), xops); -#ifdef LOCAL_LABEL_PREFIX - sprintf (buffer, \"%sLFFSHI%d:\", - LOCAL_LABEL_PREFIX, ffshi_label_number); -#else - sprintf (buffer, \"%sLFFSHI%d:\", - \"\", ffshi_label_number); -#endif - output_asm_insn (buffer, xops); + emit_insn (gen_ffshi_1 (temp, operands[1])); + emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, HImode, 0, 0); + emit_jump_insn (gen_bne (label)); + emit_move_insn (temp, constm1_rtx); + emit_label (label); + temp = expand_binop (HImode, add_optab, temp, const1_rtx, + operands[0], 0, OPTAB_WIDEN); - ffshi_label_number++; - return \"\"; + if (temp != operands[0]) + emit_move_insn (operands[0], temp); + DONE; }") + +(define_insn "ffshi_1" + [(set (match_operand:HI 0 "register_operand" "=r") + (unspec:HI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))] + "" + "* return AS2 (bsf%W0,%1,%0);") ;; These patterns match the binary 387 instructions for addM3, subM3, ;; mulM3 and divM3. There are three patterns for each of DFmode and @@ -5633,81 +6920,171 @@ [(match_operand:DF 1 "nonimmediate_operand" "0,fm") (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (match_operator:DF 3 "binary_387_op" - [(float:DF (match_operand:SI 1 "general_operand" "rm")) - (match_operand:DF 2 "general_operand" "0")]))] + [(float:DF (match_operand:SI 1 "nonimmediate_operand" "rm")) + (match_operand:DF 2 "register_operand" "0")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_387_op" - [(match_operand:XF 1 "nonimmediate_operand" "0,f") - (match_operand:XF 2 "nonimmediate_operand" "f,0")]))] + [(match_operand:XF 1 "register_operand" "0,f") + (match_operand:XF 2 "register_operand" "f,0")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") (match_operator:XF 3 "binary_387_op" - [(float:XF (match_operand:SI 1 "general_operand" "rm")) - (match_operand:XF 2 "general_operand" "0")]))] + [(float:XF (match_operand:SI 1 "nonimmediate_operand" "rm")) + (match_operand:XF 2 "register_operand" "0")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_387_op" - [(float_extend:XF (match_operand:SF 1 "general_operand" "fm,0")) - (match_operand:XF 2 "general_operand" "0,f")]))] + [(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) + (match_operand:XF 2 "register_operand" "0,f")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f") (match_operator:XF 3 "binary_387_op" - [(match_operand:XF 1 "general_operand" "0") - (float:XF (match_operand:SI 2 "general_operand" "rm"))]))] + [(match_operand:XF 1 "register_operand" "0") + (float:XF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:XF 0 "register_operand" "=f,f") (match_operator:XF 3 "binary_387_op" - [(match_operand:XF 1 "general_operand" "0,f") + [(match_operand:XF 1 "register_operand" "0,f") (float_extend:XF - (match_operand:SF 2 "general_operand" "fm,0"))]))] + (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f") (match_operator:DF 3 "binary_387_op" - [(float_extend:DF (match_operand:SF 1 "general_operand" "fm,0")) - (match_operand:DF 2 "general_operand" "0,f")]))] + [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) + (match_operand:DF 2 "register_operand" "0,f")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f") (match_operator:DF 3 "binary_387_op" - [(match_operand:DF 1 "general_operand" "0") - (float:DF (match_operand:SI 2 "general_operand" "rm"))]))] + [(match_operand:DF 1 "register_operand" "0") + (float:DF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:DF 0 "register_operand" "=f,f") (match_operator:DF 3 "binary_387_op" - [(match_operand:DF 1 "general_operand" "0,f") + [(match_operand:DF 1 "register_operand" "0,f") (float_extend:DF - (match_operand:SF 2 "general_operand" "fm,0"))]))] + (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f,f") @@ -5715,38 +7092,106 @@ [(match_operand:SF 1 "nonimmediate_operand" "0,fm") (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f") (match_operator:SF 3 "binary_387_op" - [(float:SF (match_operand:SI 1 "general_operand" "rm")) - (match_operand:SF 2 "general_operand" "0")]))] + [(float:SF (match_operand:SI 1 "nonimmediate_operand" "rm")) + (match_operand:SF 2 "register_operand" "0")]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_insn "" [(set (match_operand:SF 0 "register_operand" "=f") (match_operator:SF 3 "binary_387_op" - [(match_operand:SF 1 "general_operand" "0") - (float:SF (match_operand:SI 2 "general_operand" "rm"))]))] + [(match_operand:SF 1 "register_operand" "0") + (float:SF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))] "TARGET_80387" - "* return output_387_binary_op (insn, operands);") + "* return output_387_binary_op (insn, operands);" + [(set (attr "type") + (cond [(match_operand:DF 3 "is_mul" "") + (const_string "fpmul") + (match_operand:DF 3 "is_div" "") + (const_string "fpdiv") + ] + (const_string "fpop") + ) + )]) (define_expand "strlensi" [(parallel [(set (match_dup 4) (unspec:SI [(mem:BLK (match_operand:BLK 1 "general_operand" "")) - (match_operand:QI 2 "register_operand" "") + (match_operand:QI 2 "immediate_operand" "") (match_operand:SI 3 "immediate_operand" "")] 0)) (clobber (match_dup 1))]) (set (match_dup 5) (not:SI (match_dup 4))) (set (match_operand:SI 0 "register_operand" "") - (minus:SI (match_dup 5) - (const_int 1)))] + (plus:SI (match_dup 5) + (const_int -1)))] "" " { + if (TARGET_UNROLL_STRLEN && operands[2] == const0_rtx && optimize > 1) + { + rtx address; + rtx scratch; + + /* well it seems that some optimizer does not combine a call like + foo(strlen(bar), strlen(bar)); + when the move and the subtraction is done here. It does calculate + the length just once when these instructions are done inside of + output_strlen_unroll(). But I think since &bar[strlen(bar)] is + often used and I use one fewer register for the lifetime of + output_strlen_unroll() this is better. */ + scratch = gen_reg_rtx (SImode); + address = force_reg (SImode, XEXP (operands[1], 0)); + + /* move address to scratch-register + this is done here because the i586 can do the following and + in the same cycle with the following move. */ + if (GET_CODE (operands[3]) != CONST_INT || INTVAL (operands[3]) < 4) + emit_insn (gen_movsi (scratch, address)); + + emit_insn (gen_movsi (operands[0], address)); + + if(TARGET_USE_Q_REG) + emit_insn (gen_strlensi_unroll5 (operands[0], + operands[3], + scratch, + operands[0])); + else + emit_insn (gen_strlensi_unroll4 (operands[0], + operands[3], + scratch, + operands[0])); + + /* gen_strlensi_unroll[45] returns the address of the zero + at the end of the string, like memchr(), so compute the + length by subtracting the startaddress. */ + emit_insn (gen_subsi3 (operands[0], operands[0], address)); + DONE; + } + operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); operands[4] = gen_reg_rtx (SImode); operands[5] = gen_reg_rtx (SImode); @@ -5759,7 +7204,7 @@ (define_insn "" [(set (match_operand:SI 0 "register_operand" "=&c") (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D")) - (match_operand:QI 2 "register_operand" "a") + (match_operand:QI 2 "immediate_operand" "a") (match_operand:SI 3 "immediate_operand" "i")] 0)) (clobber (match_dup 1))] "" @@ -5773,3 +7218,601 @@ output_asm_insn (AS2 (mov%L0,%1,%0), xops); return \"repnz\;scas%B2\"; }") + +/* Conditional move define_insns. */ + +(define_expand "movsicc" + [(set (match_operand:SI 0 "register_operand" "") + (if_then_else:SI (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "nonimmediate_operand" "") + (match_operand:SI 3 "nonimmediate_operand" "")))] + "TARGET_CMOVE" + " +{ + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); +}") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (if_then_else:SI (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:SI 4 "nonimmediate_operand" "rm,rm,0,0") + (match_operand:SI 5 "nonimmediate_operand" "0,0,rm,rm")))] + "TARGET_CMOVE" + "#") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (if_then_else:SI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:SI 4 "nonimmediate_operand" "rm,rm,0,0") + (match_operand:SI 5 "nonimmediate_operand" "0,0,rm,rm")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT" + "#") + +(define_split + [(set (match_operand:SI 0 "register_operand" "=r,r") + (if_then_else:SI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (const_int 0)]) + (match_operand:SI 3 "nonimmediate_operand" "rm,0") + (match_operand:SI 4 "nonimmediate_operand" "0,rm")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (match_dup 2)) + (set (match_dup 0) + (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + "") + +(define_split + [(set (match_operand:SI 0 "register_operand" "=r,r") + (if_then_else:SI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (match_operand 3 "general_operand" "")]) + (match_operand:SI 4 "nonimmediate_operand" "rm,0") + (match_operand:SI 5 "nonimmediate_operand" "0,rm")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) (compare (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 4) (match_dup 5)))] + "") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (if_then_else:SI (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SI 2 "nonimmediate_operand" "rm,0") + (match_operand:SI 3 "nonimmediate_operand" "0,rm")))] + "TARGET_CMOVE && reload_completed" + "* return output_int_conditional_move (which_alternative, operands);") + +(define_expand "movhicc" + [(set (match_operand:HI 0 "register_operand" "") + (if_then_else:HI (match_operand 1 "comparison_operator" "") + (match_operand:HI 2 "nonimmediate_operand" "") + (match_operand:HI 3 "nonimmediate_operand" "")))] + "TARGET_CMOVE" + " +{ + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); +}") + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") + (if_then_else:HI (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:HI 4 "nonimmediate_operand" "rm,rm,0,0") + (match_operand:HI 5 "nonimmediate_operand" "0,0,rm,rm")))] + "TARGET_CMOVE" + "#") + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") + (if_then_else:HI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:HI 4 "nonimmediate_operand" "rm,rm,0,0") + (match_operand:HI 5 "nonimmediate_operand" "0,0,rm,rm")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT" + "#") + +(define_split + [(set (match_operand:HI 0 "register_operand" "=r,r") + (if_then_else:HI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (const_int 0)]) + (match_operand:HI 3 "nonimmediate_operand" "rm,0") + (match_operand:HI 4 "nonimmediate_operand" "0,rm")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (match_dup 2)) + (set (match_dup 0) + (if_then_else:HI (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + "") + +(define_split + [(set (match_operand:HI 0 "register_operand" "=r,r") + (if_then_else:HI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (match_operand 3 "general_operand" "")]) + (match_operand:HI 4 "nonimmediate_operand" "rm,0") + (match_operand:HI 5 "nonimmediate_operand" "0,rm")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (compare (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:HI (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 4) (match_dup 5)))] + "") + +(define_insn "" + [(set (match_operand:HI 0 "register_operand" "=r,r") + (if_then_else:HI (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:HI 2 "nonimmediate_operand" "rm,0") + (match_operand:HI 3 "nonimmediate_operand" "0,rm")))] + "TARGET_CMOVE && reload_completed" + "* return output_int_conditional_move (which_alternative, operands);") + +(define_expand "movsfcc" + [(set (match_operand:SF 0 "register_operand" "") + (if_then_else:SF (match_operand 1 "comparison_operator" "") + (match_operand:SF 2 "register_operand" "") + (match_operand:SF 3 "register_operand" "")))] + "TARGET_CMOVE" + " +{ + rtx temp; + + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + /* The floating point conditional move instructions don't directly + support conditions resulting from a signed integer comparison. */ + + switch (GET_CODE (operands[1])) + { + case LT: + case LE: + case GE: + case GT: + temp = emit_store_flag (gen_reg_rtx (QImode), + GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1, + VOIDmode, 0, 0); + + if (!temp) + FAIL; + + operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx); + break; + + default: + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); + break; + } +}") + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f,f,f,f") + (if_then_else:SF (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:SF 4 "register_operand" "f,f,0,0") + (match_operand:SF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f,f,f,f") + (if_then_else:SF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:SF 4 "register_operand" "f,f,0,0") + (match_operand:SF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_split + [(set (match_operand:SF 0 "register_operand" "=f,f") + (if_then_else:SF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (const_int 0)]) + (match_operand:SF 3 "register_operand" "f,0") + (match_operand:SF 4 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (match_dup 2)) + (set (match_dup 0) + (if_then_else:SF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + "") + +(define_split + [(set (match_operand:SF 0 "register_operand" "=f,f") + (if_then_else:SF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (match_operand 3 "general_operand" "")]) + (match_operand:SF 4 "register_operand" "f,0") + (match_operand:SF 5 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) (compare (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:SF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 4) (match_dup 5)))] + "") + +(define_insn "" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (if_then_else:SF (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SF 2 "register_operand" "f,0") + (match_operand:SF 3 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + "* return output_fp_conditional_move (which_alternative, operands);") + +(define_expand "movdfcc" + [(set (match_operand:DF 0 "register_operand" "") + (if_then_else:DF (match_operand 1 "comparison_operator" "") + (match_operand:DF 2 "register_operand" "") + (match_operand:DF 3 "register_operand" "")))] + "TARGET_CMOVE" + " +{ + rtx temp; + + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + /* The floating point conditional move instructions don't directly + support conditions resulting from a signed integer comparison. */ + + switch (GET_CODE (operands[1])) + { + case LT: + case LE: + case GE: + case GT: + temp = emit_store_flag (gen_reg_rtx (QImode), + GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1, + VOIDmode, 0, 0); + + if (!temp) + FAIL; + + operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx); + break; + + default: + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); + break; + } +}") + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f,f,f,f") + (if_then_else:DF (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:DF 4 "register_operand" "f,f,0,0") + (match_operand:DF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f,f,f,f") + (if_then_else:DF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:DF 4 "register_operand" "f,f,0,0") + (match_operand:DF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_split + [(set (match_operand:DF 0 "register_operand" "=f,f") + (if_then_else:DF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (const_int 0)]) + (match_operand:DF 3 "register_operand" "f,0") + (match_operand:DF 4 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (match_dup 2)) + (set (match_dup 0) + (if_then_else:DF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + "") + +(define_split + [(set (match_operand:DF 0 "register_operand" "=f,f") + (if_then_else:DF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (match_operand 3 "general_operand" "")]) + (match_operand:DF 4 "register_operand" "f,0") + (match_operand:DF 5 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) (compare (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:DF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 4) (match_dup 5)))] + "") + +(define_insn "" + [(set (match_operand:DF 0 "register_operand" "=f,f") + (if_then_else:DF (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:DF 2 "register_operand" "f,0") + (match_operand:DF 3 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + "* return output_fp_conditional_move (which_alternative, operands);") + +(define_expand "movxfcc" + [(set (match_operand:XF 0 "register_operand" "") + (if_then_else:XF (match_operand 1 "comparison_operator" "") + (match_operand:XF 2 "register_operand" "") + (match_operand:XF 3 "register_operand" "")))] + "TARGET_CMOVE" + " +{ + rtx temp; + + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + /* The floating point conditional move instructions don't directly + support conditions resulting from a signed integer comparison. */ + + switch (GET_CODE (operands[1])) + { + case LT: + case LE: + case GE: + case GT: + temp = emit_store_flag (gen_reg_rtx (QImode), + GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1, + VOIDmode, 0, 0); + + if (!temp) + FAIL; + + operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx); + break; + + default: + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); + break; + } +}") + +(define_insn "" + [(set (match_operand:XF 0 "register_operand" "=f,f,f,f") + (if_then_else:XF (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:XF 4 "register_operand" "f,f,0,0") + (match_operand:XF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_insn "" + [(set (match_operand:XF 0 "register_operand" "=f,f,f,f") + (if_then_else:XF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:XF 4 "register_operand" "f,f,0,0") + (match_operand:XF 5 "register_operand" "0,0,f,f")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT + && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE + && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" + "#") + +(define_split + [(set (match_operand:XF 0 "register_operand" "=f,f") + (if_then_else:XF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (const_int 0)]) + (match_operand:XF 3 "register_operand" "f,0") + (match_operand:XF 4 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (match_dup 2)) + (set (match_dup 0) + (if_then_else:XF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + "") + +(define_split + [(set (match_operand:XF 0 "register_operand" "=f,f") + (if_then_else:XF (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (match_operand 3 "general_operand" "")]) + (match_operand:XF 4 "register_operand" "f,0") + (match_operand:XF 5 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) (compare (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:XF (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 4) (match_dup 5)))] + "") + +(define_insn "" + [(set (match_operand:XF 0 "register_operand" "=f,f") + (if_then_else:XF (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:XF 2 "register_operand" "f,0") + (match_operand:XF 3 "register_operand" "0,f")))] + "TARGET_CMOVE && reload_completed" + "* return output_fp_conditional_move (which_alternative, operands);") + +(define_expand "movdicc" + [(set (match_operand:DI 0 "register_operand" "") + (if_then_else:DI (match_operand 1 "comparison_operator" "") + (match_operand:DI 2 "nonimmediate_operand" "") + (match_operand:DI 3 "nonimmediate_operand" "")))] + "TARGET_CMOVE" + " +{ + if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) + FAIL; + + operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), + GET_MODE (i386_compare_op0), + i386_compare_op0, i386_compare_op1); +}") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r,&r") + (if_then_else:DI (match_operator 1 "comparison_operator" + [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") + (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) + (match_operand:DI 4 "nonimmediate_operand" "ro,ro,0,0") + (match_operand:DI 5 "nonimmediate_operand" "0,0,ro,ro")))] + "TARGET_CMOVE" + "#") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r,&r") + (if_then_else:DI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "r,m,r,m") + (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) + (match_operand:DI 4 "nonimmediate_operand" "ro,ro,0,0") + (match_operand:DI 5 "nonimmediate_operand" "0,0,ro,ro")))] + "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT" + "#") + +(define_split + [(set (match_operand:DI 0 "register_operand" "=&r,&r") + (if_then_else:DI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (const_int 0)]) + (match_operand:DI 3 "nonimmediate_operand" "ro,0") + (match_operand:DI 4 "nonimmediate_operand" "0,ro")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) + (match_dup 2)) + (set (match_dup 0) + (if_then_else:DI (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 3) (match_dup 4)))] + "") + +(define_split + [(set (match_operand:DI 0 "register_operand" "=&r,&r") + (if_then_else:DI (match_operator 1 "comparison_operator" + [(match_operand 2 "nonimmediate_operand" "") + (match_operand 3 "general_operand" "")]) + (match_operand:DI 4 "nonimmediate_operand" "ro,0") + (match_operand:DI 5 "nonimmediate_operand" "0,ro")))] + "TARGET_CMOVE && reload_completed" + [(set (cc0) (compare (match_dup 2) (match_dup 3))) + (set (match_dup 0) + (if_then_else:DI (match_op_dup 1 [(cc0) (const_int 0)]) + (match_dup 4) (match_dup 5)))] + "") + +(define_insn "" + [(set (match_operand:DI 0 "register_operand" "=&r,&r") + (if_then_else:DI (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:DI 2 "nonimmediate_operand" "ro,0") + (match_operand:DI 3 "nonimmediate_operand" "0,ro")))] + "TARGET_CMOVE && reload_completed" + "* return output_int_conditional_move (which_alternative, operands);") + +(define_insn "strlensi_unroll" + [(set (match_operand:SI 0 "register_operand" "=&r,&r") + (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "r,r")) + (match_operand:SI 2 "immediate_operand" "i,i")] 0)) + (clobber (match_scratch:SI 3 "=&q,&r"))] + "optimize > 1" + "* return output_strlen_unroll (operands);") + +;; the only difference between the following patterns is the register preference +;; on a pentium using a q-register saves one clock cycle per 4 characters + +(define_insn "strlensi_unroll4" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0,0")) + (match_operand:SI 1 "immediate_operand" "i,i") + (match_operand:SI 2 "register_operand" "+q,!r")] 0)) + (clobber (match_dup 2))] + "(TARGET_USE_ANY_REG && optimize > 1)" + "* return output_strlen_unroll (operands);") + +(define_insn "strlensi_unroll5" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0")) + (match_operand:SI 1 "immediate_operand" "i") + (match_operand:SI 2 "register_operand" "+q")] 0)) + (clobber (match_dup 2))] + "(TARGET_USE_Q_REG && optimize > 1)" + "* return output_strlen_unroll (operands);" +) + +(define_insn "allocate_stack_worker" + [(unspec:SI [(match_operand:SI 0 "register_operand" "a")] 3) + (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0))) + (clobber (match_dup 0))] + "TARGET_STACK_PROBE" + "* return AS1(call,__alloca);") + +(define_expand "allocate_stack" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (reg:SI 7) (match_operand:SI 1 "general_operand" ""))) + (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 1)))] + "TARGET_STACK_PROBE" + " +{ +#ifdef CHECK_STACK_LIMIT + if (GET_CODE (operands[1]) == CONST_INT + && INTVAL (operands[1]) < CHECK_STACK_LIMIT) + emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, + operands[1])); + else +#endif + emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode, + operands[1]))); + + emit_move_insn (operands[0], virtual_stack_dynamic_rtx); + DONE; +}") + +(define_expand "exception_receiver" + [(const_int 0)] + "flag_pic" + " +{ + load_pic_register (1); + DONE; +}") diff --git a/contrib/gcc/config/i386/isc.h b/contrib/gcc/config/i386/isc.h index cf8c5f69277c..5c39896df017 100644 --- a/contrib/gcc/config/i386/isc.h +++ b/contrib/gcc/config/i386/isc.h @@ -19,7 +19,7 @@ #define LIB_SPEC "%{shlib:-lc_s} %{posix:-lcposix} %{Xp:-lcposix} -lc -lg" #undef CPP_SPEC -#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{Xp:-D_POSIX_SOURCE}" +#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE} %{Xp:-D_POSIX_SOURCE}" /* ISC 2.2 uses `char' for `wchar_t'. */ #undef WCHAR_TYPE @@ -37,7 +37,7 @@ #undef RETURN_POPS_ARGS #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - (TREE_CODE (FUNTYPE) == IDENTIFIER_NODE ? 0 \ + ((FUNDECL) && TREE_CODE (FUNDECL) == IDENTIFIER_NODE ? 0 \ : (TARGET_RTD \ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ @@ -87,3 +87,7 @@ } \ fputs ("\"\n", FILE); \ } while (0) + +/* Work around assembler forward label references generated in exception + handling code. */ +#define DWARF2_UNWIND_INFO 0 diff --git a/contrib/gcc/config/i386/linux-aout.h b/contrib/gcc/config/i386/linux-aout.h index 7e46c68b8ecc..de81d878317a 100644 --- a/contrib/gcc/config/i386/linux-aout.h +++ b/contrib/gcc/config/i386/linux-aout.h @@ -1,5 +1,5 @@ -/* Definitions for Intel 386 running Linux - Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc. +/* Definitions for Intel 386 running Linux-based GNU systems using a.out. + Copyright (C) 1992, 1994, 1995, 1997, 1998 Free Software Foundation, Inc. Contributed by H.J. Lu (hjl@nynexst.com) This file is part of GNU CC. @@ -25,17 +25,16 @@ Boston, MA 02111-1307, USA. */ #include #include /* some common stuff */ +#undef ASM_COMMENT_START +#define ASM_COMMENT_START "#" + /* Specify predefined symbols in preprocessor. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -Dlinux -Asystem(posix)" #undef CPP_SPEC -#if TARGET_CPU_DEFAULT == 2 -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!m386:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#else -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m486:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#endif +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" #undef SIZE_TYPE #define SIZE_TYPE "unsigned int" @@ -57,9 +56,8 @@ Boston, MA 02111-1307, USA. */ #if 1 /* We no longer link with libc_p.a or libg.a by default. If you - * want to profile or debug the Linux C library, please add - * -lc_p or -ggdb to LDFLAGS at the link time, respectively. - */ + want to profile or debug the GNU/Linux C library, please add + -lc_p or -ggdb to LDFLAGS at the link time, respectively. */ #define LIB_SPEC \ "%{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} %{!ggdb:-lc} %{ggdb:-lg}" #else diff --git a/contrib/gcc/config/i386/linux-oldld.h b/contrib/gcc/config/i386/linux-oldld.h index c3066ba13330..4e3085bc2caf 100644 --- a/contrib/gcc/config/i386/linux-oldld.h +++ b/contrib/gcc/config/i386/linux-oldld.h @@ -1,5 +1,6 @@ -/* Definitions for Intel 386 running Linux with pre-BFD a.out linkers - Copyright (C) 1995 Free Software Foundation, Inc. +/* Definitions for Intel 386 running Linux-based GNU systems with pre-BFD + a.out linkers. + Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. Contributed by Michael Meissner (meissner@cygnus.com) This file is part of GNU CC. @@ -25,17 +26,16 @@ Boston, MA 02111-1307, USA. */ #include #include /* some common stuff */ +#undef ASM_COMMENT_START +#define ASM_COMMENT_START "#" + /* Specify predefined symbols in preprocessor. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -Dlinux -Asystem(posix)" #undef CPP_SPEC -#if TARGET_CPU_DEFAULT == 2 -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!m386:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#else -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m486:-D__i486__} %{posix:-D_POSIX_SOURCE}" -#endif +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" #undef SIZE_TYPE #define SIZE_TYPE "unsigned int" @@ -57,9 +57,8 @@ Boston, MA 02111-1307, USA. */ #if 1 /* We no longer link with libc_p.a or libg.a by default. If you - * want to profile or debug the Linux C library, please add - * -lc_p or -ggdb to LDFLAGS at the link time, respectively. - */ + want to profile or debug the GNU/Linux C library, please add + lc_p or -ggdb to LDFLAGS at the link time, respectively. */ #define LIB_SPEC \ "%{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} %{!ggdb:-lc} %{ggdb:-lg}" #else diff --git a/contrib/gcc/config/i386/linux.h b/contrib/gcc/config/i386/linux.h index a0b49bab544e..8e84bb5be5ac 100644 --- a/contrib/gcc/config/i386/linux.h +++ b/contrib/gcc/config/i386/linux.h @@ -1,5 +1,5 @@ -/* Definitions for Intel 386 running Linux with ELF format - Copyright (C) 1994, 1995 Free Software Foundation, Inc. +/* Definitions for Intel 386 running Linux-based GNU systems with ELF format. + Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. Contributed by Eric Youngdale. Modified for stabs-in-ELF by H.J. Lu. @@ -37,16 +37,19 @@ Boston, MA 02111-1307, USA. */ #undef DEFAULT_PCC_STRUCT_RETURN #define DEFAULT_PCC_STRUCT_RETURN 1 +#undef ASM_COMMENT_START +#define ASM_COMMENT_START "#" + /* This is how to output an element of a case-vector that is relative. This is only used for PIC code. See comments by the `casesi' insn in i386.md for an explanation of the expression this outputs. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) /* Indicate that jump tables go in the text section. This is necessary when compiling PIC code. */ -#define JUMP_TABLES_IN_TEXT_SECTION +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) /* Copy this from the svr4 specifications... */ /* Define the register numbers to be used in Dwarf debugging information. @@ -147,44 +150,19 @@ Boston, MA 02111-1307, USA. */ #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE BITS_PER_WORD +/* The egcs-1.1 branch is the last time we will have -Di386. -D__i386__ is the thing to use. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-D__ELF__ -Dunix -Di386 -Dlinux -Asystem(unix) -Asystem(posix) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-D__ELF__ -Dunix -Di386 -D__i386__ -Dlinux -Asystem(posix)" #undef CPP_SPEC #ifdef USE_GNULIBC_1 -#if TARGET_CPU_DEFAULT == 2 -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{!m386:-D__i486__} %{posix:-D_POSIX_SOURCE}" +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" #else -#define CPP_SPEC "%{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{m486:-D__i486__} %{posix:-D_POSIX_SOURCE}" +#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" #endif -#else /* not USE_GNULIBC_1 */ -#define CPP_SPEC "%(cpp_cpu) %[cpp_cpu] %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" -#endif /* not USE_GNULIBC_1 */ -#undef LIBGCC_SPEC -#define LIBGCC_SPEC "-lgcc" - -#undef LIB_SPEC -#ifdef USE_GNULIBC_1 -#if 1 -/* We no longer link with libc_p.a or libg.a by default. If you - * want to profile or debug the Linux C library, please add - * -lc_p or -ggdb to LDFLAGS at the link time, respectively. - */ -#define LIB_SPEC \ - "%{!shared: %{mieee-fp:-lieee} %{p:-lgmon} %{pg:-lgmon} \ - %{!ggdb:-lc} %{ggdb:-lg}}" -#else -#define LIB_SPEC \ - "%{!shared: \ - %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \ - %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}" -#endif -#else -#define LIB_SPEC \ - "%{!shared: %{mieee-fp:-lieee} %{pthread:-lpthread} \ - %{profile:-lc_p} %{!profile: -lc}}" -#endif /* not USE_GNULIBC_1 */ +#undef CC1_SPEC +#define CC1_SPEC "%(cc1_cpu) %{profile:-p}" /* Provide a LINK_SPEC appropriate for Linux. Here we provide support for the special GCC options -static and -shared, which allow us to @@ -221,7 +199,7 @@ Boston, MA 02111-1307, USA. */ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \ %{static:-static}}}" #endif -#else /* not USE_GNULIBC_1 */ +#else #define LINK_SPEC "-m elf_i386 %{shared:-shared} \ %{!shared: \ %{!ibcs: \ @@ -229,7 +207,28 @@ Boston, MA 02111-1307, USA. */ %{rdynamic:-export-dynamic} \ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \ %{static:-static}}}" -#endif /* not USE_GNULIBC_1 */ +#endif /* Get perform_* macros to build libgcc.a. */ #include "i386/perform.h" + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of uninitialized global DECL named + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ + asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) + +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1< + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* I believe in reuse... */ +#include "i386/linux.h" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-D__ELF__ -Di386 -Dmoss -Asystem(posix) -Acpu(i386) -Amachine(i386)" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0.o%s" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtn.o%s" + +#undef LINK_SPEC + diff --git a/contrib/gcc/config/i386/netbsd.h b/contrib/gcc/config/i386/netbsd.h index 180ff3533f79..5978aec5c4b0 100644 --- a/contrib/gcc/config/i386/netbsd.h +++ b/contrib/gcc/config/i386/netbsd.h @@ -30,13 +30,6 @@ #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE 32 -#define HANDLE_SYSV_PRAGMA - -/* There are conflicting reports about whether this system uses - a different assembler syntax. wilson@cygnus.com says # is right. */ -#undef COMMENT_BEGIN -#define COMMENT_BEGIN "#" - #undef ASM_APP_ON #define ASM_APP_ON "#APP\n" @@ -51,18 +44,25 @@ i386.md for an explanation of the expression this outputs. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) /* Indicate that jump tables go in the text section. This is necessary when compiling PIC code. */ -#define JUMP_TABLES_IN_TEXT_SECTION +#define JUMP_TABLES_IN_TEXT_SECTION 1 /* Don't default to pcc-struct-return, because gcc is the only compiler, and we want to retain compatibility with older gcc versions. */ #define DEFAULT_PCC_STRUCT_RETURN 0 +/* i386 netbsd still uses old binutils that don't insert nops by default + when the .align directive demands to insert extra space in the text + segment. */ +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG)) + /* Profiling routines, partially copied from i386/osfrose.h. */ /* Redefine this to use %eax instead of %edx. */ @@ -78,3 +78,8 @@ fprintf (FILE, "\tcall mcount\n"); \ } \ } + +/* Until they use ELF or something that handles dwarf2 unwinds + and initialization stuff better. */ +#define DWARF2_UNWIND_INFO 0 + diff --git a/contrib/gcc/config/i386/next.h b/contrib/gcc/config/i386/next.h index c0d6d7296f18..65f74023999e 100644 --- a/contrib/gcc/config/i386/next.h +++ b/contrib/gcc/config/i386/next.h @@ -1,5 +1,5 @@ /* Target definitions for GNU compiler for Intel x86 CPU running NeXTSTEP - Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -124,8 +124,8 @@ Boston, MA 02111-1307, USA. */ GAS requires the %cl argument, so override unx386.h. */ -#undef AS3_SHIFT_DOUBLE -#define AS3_SHIFT_DOUBLE(a,b,c,d) AS3 (a,b,c,d) +#undef SHIFT_DOUBLE_OMITS_COUNT +#define SHIFT_DOUBLE_OMITS_COUNT 0 /* Print opcodes the way that GAS expects them. */ #define GAS_MNEMONICS 1 @@ -216,7 +216,7 @@ Boston, MA 02111-1307, USA. */ #undef RETURN_POPS_ARGS #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - (TREE_CODE (FUNTYPE) == IDENTIFIER_NODE \ + ((FUNDECL) && TREE_CODE (FUNDECL) == IDENTIFIER_NODE \ ? 0 \ : (TARGET_RTD \ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ @@ -224,3 +224,10 @@ Boston, MA 02111-1307, USA. */ == void_type_node))) ? (SIZE) : 0) /* END Calling Convention CHANGES */ + +/* NeXT still uses old binutils that don't insert nops by default + when the .align directive demands to insert extra space in the text + segment. */ +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG)) diff --git a/contrib/gcc/config/i386/openbsd.h b/contrib/gcc/config/i386/openbsd.h new file mode 100644 index 000000000000..1b56262d9a59 --- /dev/null +++ b/contrib/gcc/config/i386/openbsd.h @@ -0,0 +1,130 @@ +/* Configuration for an OpenBSD i386 target. + + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This is tested by i386gas.h. */ +#define YES_UNDERSCORES + +#include + +/* Get perform_* macros to build libgcc.a. */ +#include + +/* Get generic OpenBSD definitions. */ +#define OBSD_OLD_GAS +#include + +/* Run-time target specifications */ +#define CPP_PREDEFINES "-D__unix__ -D__i386__ -D__OpenBSD__ -Asystem(unix) -Asystem(OpenBSD) -Acpu(i386) -Amachine(i386)" + +/* Layout of source language data types. */ + +/* This must agree with */ +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE 32 + +/* Assembler format: overall framework. */ + +#undef ASM_APP_ON +#define ASM_APP_ON "#APP\n" + +#undef ASM_APP_OFF +#define ASM_APP_OFF "#NO_APP\n" + +/* The following macros were originally stolen from i386v4.h. + These have to be defined to get PIC code correct. */ + +/* Assembler format: dispatch tables. */ + +/* How to output an element of a case-vector that is relative. + This is only used for PIC code. See comments by the `casesi' insn in + i386.md for an explanation of the expression this outputs. */ +#undef ASM_OUTPUT_ADDR_DIFF_ELT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ + fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) + +/* Assembler format: sections. */ + +/* Indicate when jump tables go in the text section. This is + necessary when compiling PIC code. */ +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) + +/* Stack & calling: aggregate returns. */ + +/* Don't default to pcc-struct-return, because gcc is the only compiler, and + we want to retain compatibility with older gcc versions. */ +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* Assembler format: alignment output. */ + +/* Kludgy test: when gas is upgraded, it will have p2align, and no problems + with nops. */ +#ifndef HAVE_GAS_MAX_SKIP_P2ALIGN +/* i386 OpenBSD still uses an older gas that doesn't insert nops by default + when the .align directive demands to insert extra space in the text + segment. */ +#undef ASM_OUTPUT_ALIGN +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG)!=0) fprintf ((FILE), "\t.align %d,0x90\n", (LOG)) +#endif + +/* Stack & calling: profiling. */ + +/* OpenBSD's profiler recovers all information from the stack pointer. + The icky part is not here, but in machine/profile.h. */ +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ + fputs (flag_pic ? "\tcall mcount@PLT\n": "\tcall mcount\n", FILE); + +/* Assembler format: exception region output. */ + +/* All configurations that don't use elf must be explicit about not using + dwarf unwind information. egcs doesn't try too hard to check internal + configuration files... */ +#define DWARF2_UNWIND_INFO 0 + +/* Assembler format: alignment output. */ + +/* A C statement to output to the stdio stream FILE an assembler + command to advance the location counter to a multiple of 1< +#include "i386/sysv4.h" /* Base i386 target machine definitions */ +#define _sys_siglist sys_siglist +extern char *sys_siglist[]; + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 OSF/1)"); + +/* WORD_SWITCH_TAKES_ARG defined in svr4 is not correct. We also + need an extra -soname */ +#undef WORD_SWITCH_TAKES_ARG +#define WORD_SWITCH_TAKES_ARG(STR) \ + (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \ + || !strcmp (STR, "Tdata") || !strcmp (STR, "Ttext") \ + || !strcmp (STR, "Tbss") || !strcmp (STR, "soname")) + +/* Note, -fpic and -fPIC are equivalent */ +#undef CPP_SPEC +#define CPP_SPEC "\ +%{fpic: -D__SHARED__} %{fPIC: %{!fpic: -D__SHARED__}} \ +%{.S: %{!ansi:%{!traditional:%{!traditional-cpp:%{!ftraditional: -traditional}}}}} \ +%{.S: -D__LANGUAGE_ASSEMBLY %{!ansi:-DLANGUAGE_ASSEMBLY}} \ +%{.cc: -D__LANGUAGE_C_PLUS_PLUS} \ +%{.cxx: -D__LANGUAGE_C_PLUS_PLUS} \ +%{.C: -D__LANGUAGE_C_PLUS_PLUS} \ +%{.m: -D__LANGUAGE_OBJECTIVE_C} \ +%{!.S: -D__LANGUAGE_C %{!ansi:-DLANGUAGE_C}}" + +/* -mmcount or -mno-mcount should be used with -pg or -p */ +#undef CC1_SPEC +#define CC1_SPEC "%{p: %{!mmcount: %{!mno-mcount: -mno-mcount }}} \ +%{!p: %{pg: %{!mmcount: %{!mno-mcount: -mno-mcount }}}}" + +/* Note, -D__NO_UNDERSCORES__ -D__ELF__ are provided in the older version of + OSF/1 gcc. We keep them here, so that old /usr/include/i386/asm.h works. + */ +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ + "-D__NO_UNDERSCORES__ -D__ELF__ -DOSF -DOSF1 -Di386 -Dunix -Asystem(xpg4) -Asystem(osf1) -Acpu(i386) -Amachine(i386)" + +/* current OSF/1 doesn't provide separate crti.o and gcrti.o (and also, crtn.o + and gcrtn.o) for profile. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared: \ + %{!symbolic: \ + %{pg:gcrt0.o%s}%{!pg:%{p:mcrt0.o%s}%{!p:crt0.o%s}}}}\ + crti.o%s \ + crtbegin.o%s" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "crtend.o%s crtn.o%s" + +#undef ASM_SPEC +#define ASM_SPEC "%{v*: -v}" + +#undef LINK_SPEC +#define LINK_SPEC "%{v*: -v} \ + %{h*} %{z*} \ + %{dy:-call_shared} %{dn:-static} \ + %{static:-static} \ + %{shared:-shared} \ + %{call_shared:-call_shared} \ + %{symbolic:-Bsymbolic -shared -call_shared} \ + %{!dy: %{!dn: %{!static: %{!shared: %{!symbolic: \ + %{noshrlib: -static } \ + %{!noshrlib: -call_shared}}}}}}" + +#undef MD_EXEC_PREFIX +#define MD_EXEC_PREFIX "/usr/ccs/gcc/" + +#undef MD_STARTFILE_PREFIX +#define MD_STARTFILE_PREFIX "/usr/ccs/lib/" + +/* Define this macro meaning that gcc should find the library 'libgcc.a' + by hand, rather than passing the argument '-lgcc' to tell the linker + to do the search */ +#define LINK_LIBGCC_SPECIAL + +/* This goes with LINK_LIBGCC_SPECIAL, we need tell libgcc.a differently */ +#undef LIBGCC_SPEC +#define LIBGCC_SPEC "%{!shared:%{!symbolic:libgcc.a%s}}" + +/* A C statement to output assembler commands which will identify the object + file as having been compile with GNU CC. We don't need or want this for + OSF1. */ +#undef ASM_IDENTIFY_GCC +#define ASM_IDENTIFY_GCC(FILE) + +/* Identify the front-end which produced this file. To keep symbol + space down, and not confuse kdb, only do this if the language is + not C. */ +#define ASM_IDENTIFY_LANGUAGE(STREAM) \ +{ \ + if (strcmp (lang_identify (), "c") != 0) \ + output_lang_identify (STREAM); \ +} + +/* Specify size_t, ptrdiff_t, and wchar_t types. */ +#undef SIZE_TYPE +#undef PTRDIFF_TYPE +#undef WCHAR_TYPE +#undef WCHAR_TYPE_SIZE + +#define SIZE_TYPE "long unsigned int" +#define PTRDIFF_TYPE "int" +#define WCHAR_TYPE "unsigned int" +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +/* Turn off long double being 96 bits. */ +#undef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE 64 + +/* Work with OSF/1 profile */ +#define MASK_NO_MCOUNT 000200000000 /* profiling uses mcount_ptr */ + +#define TARGET_MCOUNT ((target_flags & MASK_NO_MCOUNT) == 0) + +#undef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES \ + { "mcount", -MASK_NO_MCOUNT}, \ + { "no-mcount", MASK_NO_MCOUNT}, + +/* This macro generates the assembly code for function entry. + FILE is a stdio stream to output the code to. + SIZE is an int: how many units of temporary storage to allocate. + Refer to the array `regs_ever_live' to determine which registers + to save; `regs_ever_live[I]' is nonzero if register number I + is ever used in the function. This macro is responsible for + knowing which registers should not be saved even if used. + + We override it here to allow for the new profiling code to go before + the prologue and the old mcount code to go after the prologue (and + after %ebx has been set up for ELF shared library support). */ +#if 0 +#define OSF_PROFILE_BEFORE_PROLOGUE \ + (!TARGET_MCOUNT \ + && !current_function_needs_context \ + && (!flag_pic \ + || !frame_pointer_needed \ + || (!current_function_uses_pic_offset_table \ + && !current_function_uses_const_pool))) +#else +#define OSF_PROFILE_BEFORE_PROLOGUE 0 +#endif +#undef FUNCTION_PROLOGUE +#define FUNCTION_PROLOGUE(FILE, SIZE) \ +do \ + { \ + char *prefix = ""; \ + char *lprefix = LPREFIX; \ + int labelno = profile_label_no; \ + \ + if (profile_flag && OSF_PROFILE_BEFORE_PROLOGUE) \ + { \ + if (!flag_pic) \ + { \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", lprefix, labelno); \ + fprintf (FILE, "\tcall *%s_mcount_ptr\n", prefix); \ + } \ + \ + else \ + { \ + static int call_no = 0; \ + \ + fprintf (FILE, "\tcall %sPc%d\n", lprefix, call_no); \ + fprintf (FILE, "%sPc%d:\tpopl %%eax\n", lprefix, call_no); \ + fprintf (FILE, "\taddl $_GLOBAL_OFFSET_TABLE_+[.-%sPc%d],%%eax\n", \ + lprefix, call_no++); \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%eax),%%edx\n", \ + lprefix, labelno); \ + fprintf (FILE, "\tmovl %s_mcount_ptr@GOT(%%eax),%%eax\n", \ + prefix); \ + fprintf (FILE, "\tcall *(%%eax)\n"); \ + } \ + } \ + \ + function_prologue (FILE, SIZE); \ + } \ +while (0) + +/* A C statement or compound statement to output to FILE some assembler code to + call the profiling subroutine `mcount'. Before calling, the assembler code + must load the address of a counter variable into a register where `mcount' + expects to find the address. The name of this variable is `LP' followed by + the number LABELNO, so you would generate the name using `LP%d' in a + `fprintf'. + + The details of how the address should be passed to `mcount' are determined + by your operating system environment, not by GNU CC. To figure them out, + compile a small program for profiling using the system's installed C + compiler and look at the assembler code that results. */ + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ +do \ + { \ + if (!OSF_PROFILE_BEFORE_PROLOGUE) \ + { \ + char *prefix = ""; \ + char *lprefix = LPREFIX; \ + int labelno = LABELNO; \ + \ + /* Note that OSF/rose blew it in terms of calling mcount, \ + since OSF/rose prepends a leading underscore, but mcount's \ + doesn't. At present, we keep this kludge for ELF as well \ + to allow old kernels to build profiling. */ \ + \ + if (flag_pic \ + && !current_function_uses_pic_offset_table \ + && !current_function_uses_const_pool) \ + abort (); \ + \ + if (TARGET_MCOUNT && flag_pic) \ + { \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \ + lprefix, labelno); \ + fprintf (FILE, "\tcall *%smcount@GOT(%%ebx)\n", prefix); \ + } \ + \ + else if (TARGET_MCOUNT) \ + { \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", lprefix, labelno); \ + fprintf (FILE, "\tcall %smcount\n", prefix); \ + } \ + \ + else if (flag_pic && frame_pointer_needed) \ + { \ + fprintf (FILE, "\tmovl 4(%%ebp),%%ecx\n"); \ + fprintf (FILE, "\tpushl %%ecx\n"); \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \ + lprefix, labelno); \ + fprintf (FILE, "\tmovl _mcount_ptr@GOT(%%ebx),%%eax\n"); \ + fprintf (FILE, "\tcall *(%%eax)\n"); \ + fprintf (FILE, "\tpopl %%eax\n"); \ + } \ + \ + else if (frame_pointer_needed) \ + { \ + fprintf (FILE, "\tmovl 4(%%ebp),%%ecx\n"); \ + fprintf (FILE, "\tpushl %%ecx\n"); \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", lprefix, labelno); \ + fprintf (FILE, "\tcall *_mcount_ptr\n"); \ + fprintf (FILE, "\tpopl %%eax\n"); \ + } \ + \ + else \ + abort (); \ + } \ + } \ +while (0) + +#if defined (CROSS_COMPILE) && defined (HOST_BITS_PER_INT) && defined (HOST_BITS_PER_LONG) && defined (HOST_BITS_PER_LONGLONG) +#if (HOST_BITS_PER_INT==32) && (HOST_BITS_PER_LONG==64) && (HOST_BITS_PER_LONGLONG==64) +#define REAL_ARITHMETIC +#endif +#endif diff --git a/contrib/gcc/config/i386/osf1elfgdb.h b/contrib/gcc/config/i386/osf1elfgdb.h new file mode 100644 index 000000000000..af6efa2d0def --- /dev/null +++ b/contrib/gcc/config/i386/osf1elfgdb.h @@ -0,0 +1,7 @@ +/* Target definitions for GNU compiler for Intel 80386 running OSF/1 1.3+ + with gas and gdb. */ + +/* Use stabs instead of DWARF debug format. */ +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#include "i386/osf1elf.h" diff --git a/contrib/gcc/config/i386/osfelf.h b/contrib/gcc/config/i386/osfelf.h index 7e71fe98f6b3..381ffc26313c 100644 --- a/contrib/gcc/config/i386/osfelf.h +++ b/contrib/gcc/config/i386/osfelf.h @@ -22,10 +22,10 @@ Boston, MA 02111-1307, USA. */ #include "config/i386/osfrose.h" #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-DOSF -DOSF1 -Dunix -Di386 -Asystem(unix) -Asystem(xpg4) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-DOSF -DOSF1 -Dunix -Asystem(xpg4)" #undef CPP_SPEC -#define CPP_SPEC "\ +#define CPP_SPEC "%(cpp_cpu) \ %{mrose: -D__ROSE__ %{!pic-none: -D__SHARED__}} \ %{!mrose: -D__ELF__ %{fpic: -D__SHARED__}} \ %{mno-underscores: -D__NO_UNDERSCORES__} \ diff --git a/contrib/gcc/config/i386/osfrose.h b/contrib/gcc/config/i386/osfrose.h index 3aae1e1b681c..9cfe187ea090 100644 --- a/contrib/gcc/config/i386/osfrose.h +++ b/contrib/gcc/config/i386/osfrose.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler. Intel 386 (OSF/1 with OSF/rose) version. - Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright (C) 1991, 1992, 1993, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -36,16 +36,7 @@ Boston, MA 02111-1307, USA. */ -z* options (for the linker). */ #define SWITCH_TAKES_ARG(CHAR) \ - ( (CHAR) == 'D' \ - || (CHAR) == 'U' \ - || (CHAR) == 'o' \ - || (CHAR) == 'e' \ - || (CHAR) == 'T' \ - || (CHAR) == 'u' \ - || (CHAR) == 'I' \ - || (CHAR) == 'm' \ - || (CHAR) == 'L' \ - || (CHAR) == 'A' \ + (DEFAULT_SWITCH_TAKES_ARG(CHAR) \ || (CHAR) == 'h' \ || (CHAR) == 'z') @@ -99,10 +90,10 @@ Boston, MA 02111-1307, USA. */ /* Change default predefines. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-DOSF -DOSF1 -Dunix -Di386 -Asystem(unix) -Asystem(xpg4) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-DOSF -DOSF1 -Dunix -Asystem(xpg4)" #undef CPP_SPEC -#define CPP_SPEC "\ +#define CPP_SPEC "%(cpp_cpu) \ %{!melf: -D__ROSE__ %{!pic-none: -D__SHARED__}} \ %{melf: -D__ELF__ %{fpic: -D__SHARED__}} \ %{mno-underscores: -D__NO_UNDERSCORES__} \ @@ -373,6 +364,12 @@ while (0) fprintf (FILE, "%s%s%d:\n", (TARGET_UNDERSCORES) ? "" : ".", \ PREFIX, NUM) +/* The prefix to add to user-visible assembler symbols. */ + +/* target_flags is not accessible by the preprocessor */ +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "_" + /* This is how to output a reference to a user-level label named NAME. */ #undef ASM_OUTPUT_LABELREF @@ -384,7 +381,7 @@ while (0) i386.md for an explanation of the expression this outputs. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) /* Output a definition */ @@ -407,10 +404,9 @@ while (0) alignment to be done at such a time. Most machine descriptions do not currently define the macro. */ -#undef ASM_OUTPUT_ALIGN_CODE -#define ASM_OUTPUT_ALIGN_CODE(STREAM) \ - fprintf (STREAM, "\t.align\t%d\n", \ - (!TARGET_LARGE_ALIGN && i386_align_jumps > 2) ? 2 : i386_align_jumps) +#undef LABEL_ALIGN_AFTER_BARRIER +#define LABEL_ALIGN_AFTER_BARRIER(LABEL) \ + ((!TARGET_LARGE_ALIGN && i386_align_jumps > 2) ? 2 : i386_align_jumps) /* A C expression to output text to align the location counter in the way that is desirable at the beginning of a loop. @@ -419,9 +415,8 @@ while (0) alignment to be done at such a time. Most machine descriptions do not currently define the macro. */ -#undef ASM_OUTPUT_LOOP_ALIGN -#define ASM_OUTPUT_LOOP_ALIGN(STREAM) \ - fprintf (STREAM, "\t.align\t%d\n", i386_align_loops) +#undef LOOP_ALIGN +#define LOOP_ALIGN(LABEL) (i386_align_loops) /* A C statement to output to the stdio stream STREAM an assembler command to advance the location counter to a multiple of 2 to the diff --git a/contrib/gcc/config/i386/ptx4-i.h b/contrib/gcc/config/i386/ptx4-i.h new file mode 100644 index 000000000000..1537b4a4ceee --- /dev/null +++ b/contrib/gcc/config/i386/ptx4-i.h @@ -0,0 +1,247 @@ +/* Target definitions for GNU compiler for Intel 80386 running Dynix/ptx v4 + Copyright (C) 1996 Free Software Foundation, Inc. + + Modified from sysv4.h + Originally written by Ron Guilmette (rfg@netcom.com). + Modified by Tim Wright (timw@sequent.com). + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "i386/i386.h" /* Base i386 target machine definitions */ +#include "i386/att.h" /* Use the i386 AT&T assembler syntax */ +#include "ptx4.h" /* Rest of definitions (non architecture dependent) */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 Sequent Dynix/ptx Version 4)"); + +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ + +#undef RETURN_IN_MEMORY +#define RETURN_IN_MEMORY(TYPE) \ + (TYPE_MODE (TYPE) == BLKmode) + +/* Define which macros to predefine. _SEQUENT_ is our extension. */ +/* This used to define X86, but james@bigtex.cactus.org says that + is supposed to be defined optionally by user programs--not by default. */ +#define CPP_PREDEFINES \ + "-Di386 -Dunix -D_SEQUENT_ -Asystem(unix) -Asystem(ptx4) -Acpu(i386) -Amachine(i386)" + +/* This is how to output assembly code to define a `float' constant. + We always have to use a .long pseudo-op to do this because the native + SVR4 ELF assembler is buggy and it generates incorrect values when we + try to use the .float pseudo-op instead. */ + +#undef ASM_OUTPUT_FLOAT +#define ASM_OUTPUT_FLOAT(FILE,VALUE) \ +do { long value; \ + REAL_VALUE_TO_TARGET_SINGLE ((VALUE), value); \ + if (sizeof (int) == sizeof (long)) \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value); \ + else \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value); \ + } while (0) + +/* This is how to output assembly code to define a `double' constant. + We always have to use a pair of .long pseudo-ops to do this because + the native SVR4 ELF assembler is buggy and it generates incorrect + values when we try to use the .double pseudo-op instead. */ + +#undef ASM_OUTPUT_DOUBLE +#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ +do { long value[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), value); \ + if (sizeof (int) == sizeof (long)) \ + { \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \ + } \ + else \ + { \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \ + } \ + } while (0) + + +#undef ASM_OUTPUT_LONG_DOUBLE +#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \ +do { long value[3]; \ + REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), value); \ + if (sizeof (int) == sizeof (long)) \ + { \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[1]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, value[2]); \ + } \ + else \ + { \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[0]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[1]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, value[2]); \ + } \ + } while (0) + +/* Output at beginning of assembler file. */ +/* The .file command should always begin the output. */ + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ + do { \ + output_file_directive (FILE, main_input_filename); \ + fprintf (FILE, "\t.version\t\"01.01\"\n"); \ + } while (0) + +/* Define the register numbers to be used in Dwarf debugging information. + The SVR4 reference port C compiler uses the following register numbers + in its Dwarf output code: + + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ + +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) \ +((n) == 0 ? 0 \ + : (n) == 1 ? 2 \ + : (n) == 2 ? 1 \ + : (n) == 3 ? 3 \ + : (n) == 4 ? 6 \ + : (n) == 5 ? 7 \ + : (n) == 6 ? 5 \ + : (n) == 7 ? 4 \ + : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ + : (-1)) + +/* The routine used to output sequences of byte values. We use a special + version of this for most svr4 targets because doing so makes the + generated assembly code more compact (and thus faster to assemble) + as well as more readable. Note that if we find subparts of the + character sequence which end with NUL (and which are shorter than + STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */ + +#undef ASM_OUTPUT_ASCII +#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \ + do \ + { \ + register unsigned char *_ascii_bytes = (unsigned char *) (STR); \ + register unsigned char *limit = _ascii_bytes + (LENGTH); \ + register unsigned bytes_in_chunk = 0; \ + for (; _ascii_bytes < limit; _ascii_bytes++) \ + { \ + register unsigned char *p; \ + if (bytes_in_chunk >= 64) \ + { \ + fputc ('\n', (FILE)); \ + bytes_in_chunk = 0; \ + } \ + for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \ + continue; \ + if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \ + { \ + if (bytes_in_chunk > 0) \ + { \ + fputc ('\n', (FILE)); \ + bytes_in_chunk = 0; \ + } \ + ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \ + _ascii_bytes = p; \ + } \ + else \ + { \ + if (bytes_in_chunk == 0) \ + fprintf ((FILE), "\t.byte\t"); \ + else \ + fputc (',', (FILE)); \ + fprintf ((FILE), "0x%02x", *_ascii_bytes); \ + bytes_in_chunk += 5; \ + } \ + } \ + if (bytes_in_chunk > 0) \ + fprintf ((FILE), "\n"); \ + } \ + while (0) + +/* This is how to output an element of a case-vector that is relative. + This is only used for PIC code. See comments by the `casesi' insn in + i386.md for an explanation of the expression this outputs. */ + +#undef ASM_OUTPUT_ADDR_DIFF_ELT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ + fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) + +/* Indicate that jump tables go in the text section. This is + necessary when compiling PIC code. */ + +#define JUMP_TABLES_IN_TEXT_SECTION 1 diff --git a/contrib/gcc/config/i386/rtems.h b/contrib/gcc/config/i386/rtems.h new file mode 100644 index 000000000000..60e6dc7c4197 --- /dev/null +++ b/contrib/gcc/config/i386/rtems.h @@ -0,0 +1,34 @@ +/* Definitions for rtems targeting an Intel i386 using coff. + Copyright (C) 1996, 1997 Free Software Foundation, Inc. + Contributed by Joel Sherrill (joel@OARcorp.com). + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "i386/i386-coff.h" + +/* Specify predefined symbols in preprocessor. */ + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -Drtems -D__rtems__ \ + -Asystem(rtems) -Acpu(i386) -Amachine(i386)" + +/* Generate calls to memcpy, memcmp and memset. */ +#ifndef TARGET_MEM_FUNCTIONS +#define TARGET_MEM_FUNCTIONS +#endif + diff --git a/contrib/gcc/config/i386/rtemself.h b/contrib/gcc/config/i386/rtemself.h new file mode 100644 index 000000000000..d9d97337aa95 --- /dev/null +++ b/contrib/gcc/config/i386/rtemself.h @@ -0,0 +1,169 @@ +/* Definitions for Intel 386 running Linux-based GNU systems with ELF format. + Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Eric Youngdale. + Modified for stabs-in-ELF by H.J. Lu. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define LINUX_DEFAULT_ELF + +/* A lie, I guess, but the general idea behind linux/ELF is that we are + supposed to be outputting something that will assemble under SVr4. + This gets us pretty close. */ +#include /* Base i386 target machine definitions */ +#include /* Use the i386 AT&T assembler syntax */ +#include /* some common stuff */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386 RTEMS with ELF)"); + +/* The svr4 ABI for the i386 says that records and unions are returned + in memory. */ +#undef DEFAULT_PCC_STRUCT_RETURN +#define DEFAULT_PCC_STRUCT_RETURN 1 + +/* This is how to output an element of a case-vector that is relative. + This is only used for PIC code. See comments by the `casesi' insn in + i386.md for an explanation of the expression this outputs. */ +#undef ASM_OUTPUT_ADDR_DIFF_ELT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ + fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) + +/* Indicate that jump tables go in the text section. This is + necessary when compiling PIC code. */ +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) + +/* Copy this from the svr4 specifications... */ +/* Define the register numbers to be used in Dwarf debugging information. + The SVR4 reference port C compiler uses the following register numbers + in its Dwarf output code: + 0 for %eax (gnu regno = 0) + 1 for %ecx (gnu regno = 2) + 2 for %edx (gnu regno = 1) + 3 for %ebx (gnu regno = 3) + 4 for %esp (gnu regno = 7) + 5 for %ebp (gnu regno = 6) + 6 for %esi (gnu regno = 4) + 7 for %edi (gnu regno = 5) + The following three DWARF register numbers are never generated by + the SVR4 C compiler or by the GNU compilers, but SDB on x86/svr4 + believes these numbers have these meanings. + 8 for %eip (no gnu equivalent) + 9 for %eflags (no gnu equivalent) + 10 for %trapno (no gnu equivalent) + It is not at all clear how we should number the FP stack registers + for the x86 architecture. If the version of SDB on x86/svr4 were + a bit less brain dead with respect to floating-point then we would + have a precedent to follow with respect to DWARF register numbers + for x86 FP registers, but the SDB on x86/svr4 is so completely + broken with respect to FP registers that it is hardly worth thinking + of it as something to strive for compatibility with. + The version of x86/svr4 SDB I have at the moment does (partially) + seem to believe that DWARF register number 11 is associated with + the x86 register %st(0), but that's about all. Higher DWARF + register numbers don't seem to be associated with anything in + particular, and even for DWARF regno 11, SDB only seems to under- + stand that it should say that a variable lives in %st(0) (when + asked via an `=' command) if we said it was in DWARF regno 11, + but SDB still prints garbage when asked for the value of the + variable in question (via a `/' command). + (Also note that the labels SDB prints for various FP stack regs + when doing an `x' command are all wrong.) + Note that these problems generally don't affect the native SVR4 + C compiler because it doesn't allow the use of -O with -g and + because when it is *not* optimizing, it allocates a memory + location for each floating-point variable, and the memory + location is what gets described in the DWARF AT_location + attribute for the variable in question. + Regardless of the severe mental illness of the x86/svr4 SDB, we + do something sensible here and we use the following DWARF + register numbers. Note that these are all stack-top-relative + numbers. + 11 for %st(0) (gnu regno = 8) + 12 for %st(1) (gnu regno = 9) + 13 for %st(2) (gnu regno = 10) + 14 for %st(3) (gnu regno = 11) + 15 for %st(4) (gnu regno = 12) + 16 for %st(5) (gnu regno = 13) + 17 for %st(6) (gnu regno = 14) + 18 for %st(7) (gnu regno = 15) +*/ +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) \ +((n) == 0 ? 0 \ + : (n) == 1 ? 2 \ + : (n) == 2 ? 1 \ + : (n) == 3 ? 3 \ + : (n) == 4 ? 6 \ + : (n) == 5 ? 7 \ + : (n) == 6 ? 5 \ + : (n) == 7 ? 4 \ + : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ + : (-1)) + +/* Output assembler code to FILE to increment profiler label # LABELNO + for profiling a function entry. */ + +#undef FUNCTION_PROFILER +#define FUNCTION_PROFILER(FILE, LABELNO) \ +{ \ + if (flag_pic) \ + { \ + fprintf (FILE, "\tleal %sP%d@GOTOFF(%%ebx),%%edx\n", \ + LPREFIX, (LABELNO)); \ + fprintf (FILE, "\tcall *mcount@GOT(%%ebx)\n"); \ + } \ + else \ + { \ + fprintf (FILE, "\tmovl $%sP%d,%%edx\n", LPREFIX, (LABELNO)); \ + fprintf (FILE, "\tcall mcount\n"); \ + } \ +} + +#undef SIZE_TYPE +#define SIZE_TYPE "unsigned int" + +#undef PTRDIFF_TYPE +#define PTRDIFF_TYPE "int" + +#undef WCHAR_TYPE +#define WCHAR_TYPE "long int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Di386 -Drtems -D__rtems__ \ + -Asystem(rtems) -Acpu(i386) -Amachine(i386)" + +/* Get perform_* macros to build libgcc.a. */ +#include "i386/perform.h" + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of uninitialized global DECL named + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ + asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0.o%s" + +#undef ENDFILE_SPEC + diff --git a/contrib/gcc/config/i386/sco.h b/contrib/gcc/config/i386/sco.h index 37dc03266984..016e0a00ce07 100644 --- a/contrib/gcc/config/i386/sco.h +++ b/contrib/gcc/config/i386/sco.h @@ -1,5 +1,5 @@ /* Definitions for Intel 386 running SCO Unix System V. - Copyright (C) 1988, 1992, 1994, 1995 Free Software Foundation, Inc. + Copyright (C) 1988, 1992, 1994, 1995 Free, 1996 Software Foundation, Inc. This file is part of GNU CC. @@ -55,10 +55,10 @@ Boston, MA 02111-1307, USA. */ /* Specify predefined symbols in preprocessor. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP -Asystem(unix) -Asystem(svr3) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP -Asystem(svr3)" #undef CPP_SPEC -#define CPP_SPEC "%{scointl:-DM_INTERNAT}" +#define CPP_SPEC "%(cpp_cpu) %{scointl:-DM_INTERNAT}" /* This spec is used for telling cpp whether char is signed or not. */ @@ -104,7 +104,7 @@ Boston, MA 02111-1307, USA. */ #undef RETURN_POPS_ARGS #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - (TREE_CODE (FUNTYPE) == IDENTIFIER_NODE ? 0 \ + ((FUNDECL) && TREE_CODE (FUNDECL) == IDENTIFIER_NODE ? 0 \ : (TARGET_RTD \ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ diff --git a/contrib/gcc/config/i386/sco4.h b/contrib/gcc/config/i386/sco4.h index fc389b4d1bcb..5d1ea471dbf8 100644 --- a/contrib/gcc/config/i386/sco4.h +++ b/contrib/gcc/config/i386/sco4.h @@ -63,11 +63,11 @@ Boston, MA 02111-1307, USA. */ #undef CPP_PREDEFINES #define CPP_PREDEFINES \ - "-Asystem(unix) -Asystem(svr3) -Acpu(i386) -Amachine(i386)" + "-Asystem(svr3)" #undef CPP_SPEC -#define CPP_SPEC \ - "-D_i386 -D_M_I386 -D_M_I86 -D_M_I86SM -D_M_SDATA -D_M_STEXT \ +#define CPP_SPEC "%(cpp_cpu) \ + -D_i386 -D_M_I386 -D_M_I86 -D_M_I86SM -D_M_SDATA -D_M_STEXT \ -D_unix -D_M_UNIX -D_M_XENIX \ -D_M_SYS5 -D_M_SYSV -D_M_SYS3 -D_M_SYSIII \ -D_M_COFF -D_M_BITFIELDS -D_M_WORDSWAP \ diff --git a/contrib/gcc/config/i386/sco4dbx.h b/contrib/gcc/config/i386/sco4dbx.h index 0387c2436c39..3d075b6a2e26 100644 --- a/contrib/gcc/config/i386/sco4dbx.h +++ b/contrib/gcc/config/i386/sco4dbx.h @@ -61,11 +61,11 @@ Boston, MA 02111-1307, USA. */ Specify predefined symbols in preprocessor. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Di386 -Dunix -Asystem(unix) -Asystem(svr3) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -Asystem(svr3)" #undef CPP_SPEC -#define CPP_SPEC \ - "-D_M_I386 -D_M_I86 -D_M_I86SM -D_M_SDATA -D_M_STEXT \ +#define CPP_SPEC "%(cpp_cpu) \ + -D_M_I386 -D_M_I86 -D_M_I86SM -D_M_SDATA -D_M_STEXT \ -D_M_UNIX -D_M_XENIX \ -D_M_SYS5 -D_M_SYSV -D_M_SYS3 -D_M_SYSIII \ -D_M_COFF -D_M_BITFIELDS -D_M_WORDSWAP \ diff --git a/contrib/gcc/config/i386/sco5.h b/contrib/gcc/config/i386/sco5.h new file mode 100644 index 000000000000..74fb891954bd --- /dev/null +++ b/contrib/gcc/config/i386/sco5.h @@ -0,0 +1,957 @@ +/* Definitions for Intel 386 running SCO Unix System V 3.2 Version 5. + Copyright (C) 1992, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Kean Johnston (hug@netcom.com) + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "i386/i386.h" /* Base i386 target definitions */ +#include "i386/att.h" /* Use AT&T i386 assembler syntax */ + +#undef TARGET_VERSION +#define TARGET_VERSION fprintf (stderr, " (i386, SCO OpenServer 5 Syntax)"); + +#undef LPREFIX +#define LPREFIX ".L" + +#undef ALIGN_ASM_OP +#define ALIGN_ASM_OP "\t.align" + +#undef ASCII_DATA_ASM_OP +#define ASCII_DATA_ASM_OP "\t.ascii" + +#undef ASM_BYTE_OP +#define ASM_BYTE_OP "\t.byte" + +#undef IDENT_ASM_OP +#define IDENT_ASM_OP "\t.ident" + +#undef COMMON_ASM_OP +#define COMMON_ASM_OP "\t.comm" + +#undef SET_ASM_OP +#define SET_ASM_OP "\t.set" + +#undef LOCAL_ASM_OP +#define LOCAL_ASM_OP "\t.local" + +#undef INT_ASM_OP +#define INT_ASM_OP "\t.long" + +#undef ASM_SHORT +#define ASM_SHORT "\t.value" + +#undef ASM_LONG +#define ASM_LONG "\t.long" + +#undef ASM_DOUBLE +#define ASM_DOUBLE "\t.double" + +#undef TYPE_ASM_OP +#define TYPE_ASM_OP "\t.type" + +#undef SIZE_ASM_OP +#define SIZE_ASM_OP "\t.size" + +#undef STRING_ASM_OP +#define STRING_ASM_OP "\t.string" + +#undef SKIP_ASM_OP +#define SKIP_ASM_OP "\t.zero" + +#undef GLOBAL_ASM_OP +#define GLOBAL_ASM_OP "\t.globl" + +#undef EH_FRAME_SECTION_ASM_OP +#define EH_FRAME_SECTION_ASM_OP_COFF "\t.section\t.ehfram, \"x\"" +#define EH_FRAME_SECTION_ASM_OP_ELF "\t.section\t.eh_frame, \"aw\"" +#define EH_FRAME_SECTION_ASM_OP \ + ((TARGET_ELF) ? EH_FRAME_SECTION_ASM_OP_ELF : EH_FRAME_SECTION_ASM_OP_COFF) + +/* Avoid problems (long sectino names, forward assembler refs) with DWARF + exception unwinding when we're generating COFF */ +#define DWARF2_UNWIND_INFO \ + ((TARGET_ELF) ? 1 : 0 ) + +#undef CONST_SECTION_ASM_OP +#define CONST_SECTION_ASM_OP_COFF "\t.section\t.rodata, \"x\"" +#define CONST_SECTION_ASM_OP_ELF "\t.section\t.rodata" +#define CONST_SECTION_ASM_OP \ + ((TARGET_ELF) ? CONST_SECTION_ASM_OP_ELF : CONST_SECTION_ASM_OP_COFF) + +#undef USE_CONST_SECTION +#define USE_CONST_SECTION_ELF 1 +#define USE_CONST_SECTION_COFF 0 +#define USE_CONST_SECTION \ + ((TARGET_ELF) ? USE_CONST_SECTION_ELF : USE_CONST_SECTION_COFF) + +#undef INIT_SECTION_ASM_OP +#define INIT_SECTION_ASM_OP_ELF "\t.section\t.init" +#define INIT_SECTION_ASM_OP_COFF "\t.section\t.init ,\"x\"" +#define INIT_SECTION_ASM_OP \ + ((TARGET_ELF) ? INIT_SECTION_ASM_OP_ELF : INIT_SECTION_ASM_OP_COFF) + +#undef CTORS_SECTION_ASM_OP +#define CTORS_SECTION_ASM_OP_ELF "\t.section\t.ctors,\"aw\"" +#define CTORS_SECTION_ASM_OP_COFF INIT_SECTION_ASM_OP_COFF +#define CTORS_SECTION_ASM_OP \ + ((TARGET_ELF) ? CTORS_SECTION_ASM_OP_ELF : CTORS_SECTION_ASM_OP_COFF) + +#undef DTORS_SECTION_ASM_OP +#define DTORS_SECTION_ASM_OP_ELF "\t.section\t.dtors, \"aw\"" +#define DTORS_SECTION_ASM_OP_COFF FINI_SECTION_ASM_OP_COFF +#define DTORS_SECTION_ASM_OP \ + ((TARGET_ELF) ? DTORS_SECTION_ASM_OP_ELF : DTORS_SECTION_ASM_OP_COFF) + +#undef FINI_SECTION_ASM_OP +#define FINI_SECTION_ASM_OP_ELF "\t.section\t.fini" +#define FINI_SECTION_ASM_OP_COFF "\t.section\t.fini, \"x\"" +#define FINI_SECTION_ASM_OP \ + ((TARGET_ELF) ? FINI_SECTION_ASM_OP_ELF : FINI_SECTION_ASM_OP_COFF) + +#undef BSS_SECTION_ASM_OP +#define BSS_SECTION_ASM_OP "\t.data" + +#undef TEXT_SECTION_ASM_OP +#define TEXT_SECTION_ASM_OP "\t.text" + +#undef DATA_SECTION_ASM_OP +#define DATA_SECTION_ASM_OP "\t.data" + +#undef TYPE_OPERAND_FMT +#define TYPE_OPERAND_FMT "@%s" + +#undef APPLY_RESULT_SIZE +#define APPLY_RESULT_SIZE \ +(TARGET_ELF) ? size : 116 + +#ifndef ASM_DECLARE_RESULT +#define ASM_DECLARE_RESULT(FILE, RESULT) +#endif + +#define SCO_DEFAULT_ASM_COFF(FILE,NAME) \ +do { \ + ASM_OUTPUT_LABEL (FILE, NAME); \ + } while (0) + +#undef ASM_DECLARE_FUNCTION_NAME +#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ + do { \ + if (TARGET_ELF) { \ + fprintf (FILE, "%s\t ", TYPE_ASM_OP); \ + assemble_name (FILE, NAME); \ + putc (',', FILE); \ + fprintf (FILE, TYPE_OPERAND_FMT, "function"); \ + putc ('\n', FILE); \ + ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \ + ASM_OUTPUT_LABEL(FILE, NAME); \ + } else \ + SCO_DEFAULT_ASM_COFF(FILE, NAME); \ +} while (0) + +#undef ASM_DECLARE_FUNCTION_SIZE +#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \ + do { \ + if (TARGET_ELF) { if (!flag_inhibit_size_directive) \ + { \ + fprintf (FILE, "%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, (FNAME)); \ + fprintf (FILE, ",.-"); \ + assemble_name (FILE, (FNAME)); \ + putc ('\n', FILE); \ + } } \ + } while (0) + +#undef ASM_DECLARE_OBJECT_NAME +#define ASM_DECLARE_OBJECT_NAME(FILE, NAME, DECL) \ + do { \ + if (TARGET_ELF) { \ + fprintf (FILE, "%s\t ", TYPE_ASM_OP); \ + assemble_name (FILE, NAME); \ + putc (',', FILE); \ + fprintf (FILE, TYPE_OPERAND_FMT, "object"); \ + putc ('\n', FILE); \ + size_directive_output = 0; \ + if (!flag_inhibit_size_directive && DECL_SIZE (DECL)) \ + { \ + size_directive_output = 1; \ + fprintf (FILE, "%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ + } \ + ASM_OUTPUT_LABEL(FILE, NAME); \ + } else \ + SCO_DEFAULT_ASM_COFF(FILE, NAME); \ + } while (0) + +#undef ASM_FILE_START_1 +#define ASM_FILE_START_1(FILE) + +#undef ASM_FILE_START +#define ASM_FILE_START(FILE) \ +do { \ + output_file_directive((FILE),main_input_filename); \ + fprintf ((FILE), "\t.version\t\"01.01\"\n"); \ +} while (0) + +#undef ASM_FILE_END +#define ASM_FILE_END(FILE) \ +do { \ + fprintf ((FILE), "%s\t\"GCC: (GNU) %s\"\n", \ + IDENT_ASM_OP, version_string); \ +} while (0) + +#undef ASM_FINISH_DECLARE_OBJECT +#define ASM_FINISH_DECLARE_OBJECT(FILE, DECL, TOP_LEVEL, AT_END) \ +do { \ + if (TARGET_ELF) { \ + char *name = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \ + if (!flag_inhibit_size_directive && DECL_SIZE (DECL) \ + && ! AT_END && TOP_LEVEL \ + && DECL_INITIAL (DECL) == error_mark_node \ + && !size_directive_output) \ + { \ + size_directive_output = 1; \ + fprintf (FILE, "%s\t ", SIZE_ASM_OP); \ + assemble_name (FILE, name); \ + fprintf (FILE, ",%d\n", int_size_in_bytes (TREE_TYPE (DECL))); \ + } \ + } \ +} while (0) + +#undef ASM_GENERATE_INTERNAL_LABEL +#define ASM_GENERATE_INTERNAL_LABEL(LABEL, PREFIX, NUM) \ +do { \ + if (TARGET_ELF) \ + sprintf (LABEL, "*.%s%d", (PREFIX), (NUM)); \ + else \ + sprintf (LABEL, ".%s%d", (PREFIX), (NUM)); \ +} while (0) + +#undef ASM_OUTPUT_ADDR_DIFF_ELT +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ +do { \ + if (TARGET_ELF) \ + fprintf (FILE, "%s _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", ASM_LONG, LPREFIX, VALUE); \ + else \ + fprintf (FILE, "\t.word %s%d-%s%d\n", LPREFIX,VALUE,LPREFIX,REL); \ +} while (0) + +#undef ASM_OUTPUT_ALIGNED_COMMON +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \ +do { \ + fprintf ((FILE), "%s\t", COMMON_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + if (TARGET_ELF) \ + fprintf ((FILE), ",%u,%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \ + else \ + fprintf ((FILE), ",%u\n", (SIZE)); \ +} while (0) + +#undef ASM_OUTPUT_ALIGNED_LOCAL +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \ +do { \ + if (TARGET_ELF) { \ + fprintf ((FILE), "%s\t", LOCAL_ASM_OP); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), "\n"); \ + ASM_OUTPUT_ALIGNED_COMMON (FILE, NAME, SIZE, ALIGN); \ + } else { \ + int align = exact_log2 (ALIGN); \ + if (align > 2) align = 2; \ + if (TARGET_SVR3_SHLIB) \ + data_section (); \ + else \ + bss_section (); \ + ASM_OUTPUT_ALIGN ((FILE), align == -1 ? 2 : align); \ + fprintf ((FILE), "%s\t", "\t.lcomm"); \ + assemble_name ((FILE), (NAME)); \ + fprintf ((FILE), ",%u\n", (SIZE)); \ + } \ +} while (0) + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of uninitialized global DECL named + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ +asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) + +#undef ESCAPES +#define ESCAPES \ +"\1\1\1\1\1\1\1\1btn\1fr\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\0\0\"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\0\0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\ +\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1" + +#undef STRING_LIMIT +#define STRING_LIMIT ((unsigned) 256) + +#undef ASM_OUTPUT_LIMITED_STRING +#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \ + do \ + { \ + register unsigned char *_limited_str = (unsigned char *) (STR); \ + register unsigned ch; \ + fprintf ((FILE), "%s\t\"", STRING_ASM_OP); \ + for (; (ch = *_limited_str); _limited_str++) \ + { \ + register int escape; \ + switch (escape = ESCAPES[ch]) \ + { \ + case 0: \ + putc (ch, (FILE)); \ + break; \ + case 1: \ + fprintf ((FILE), "\\%03o", ch); \ + break; \ + default: \ + putc ('\\', (FILE)); \ + putc (escape, (FILE)); \ + break; \ + } \ + } \ + fprintf ((FILE), "\"\n"); \ + } \ + while (0) + + +#undef ASM_OUTPUT_ASCII +#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \ +do { \ + register unsigned char *_ascii_bytes = (unsigned char *) (STR); \ + register unsigned char *limit = _ascii_bytes + (LENGTH); \ + register unsigned bytes_in_chunk = 0; \ + for (; _ascii_bytes < limit; _ascii_bytes++) \ + { \ + register unsigned char *p; \ + if (bytes_in_chunk >= 64) \ + { \ + fputc ('\n', (FILE)); \ + bytes_in_chunk = 0; \ + } \ + for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \ + continue; \ + if (p < limit && (p - _ascii_bytes) <= STRING_LIMIT) \ + { \ + if (bytes_in_chunk > 0) \ + { \ + fputc ('\n', (FILE)); \ + bytes_in_chunk = 0; \ + } \ + ASM_OUTPUT_LIMITED_STRING ((FILE), _ascii_bytes); \ + _ascii_bytes = p; \ + } \ + else \ + { \ + if (bytes_in_chunk == 0) \ + fprintf ((FILE), "%s\t", ASM_BYTE_OP); \ + else \ + fputc (',', (FILE)); \ + fprintf ((FILE), "0x%02x", *_ascii_bytes); \ + bytes_in_chunk += 5; \ + } \ + } \ + if (bytes_in_chunk > 0) \ + fprintf ((FILE), "\n"); \ +} while (0) + +/* Must use data section for relocatable constants when pic. */ +#undef SELECT_RTX_SECTION +#define SELECT_RTX_SECTION(MODE,RTX) \ +{ \ + if (TARGET_ELF) { \ + if (flag_pic && symbolic_operand (RTX)) \ + data_section (); \ + else \ + const_section (); \ + } else \ + readonly_data_section(); \ +} + +#undef ASM_OUTPUT_CASE_LABEL +#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,JUMPTABLE) \ +do { \ + if (TARGET_ELF) \ + ASM_OUTPUT_ALIGN ((FILE), 2); \ + ASM_OUTPUT_INTERNAL_LABEL((FILE),(PREFIX),(NUM)); \ +} while (0) + + +#undef ASM_OUTPUT_CONSTRUCTOR +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ +do { \ + if (TARGET_ELF) { \ + ctors_section (); \ + fprintf (FILE, "%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } else { \ + init_section (); \ + fprintf (FILE, "\tpushl $"); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); } \ + } while (0) + +#undef ASM_OUTPUT_DESTRUCTOR +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ +do { \ + if (TARGET_ELF) { \ + dtors_section (); \ + fprintf (FILE, "%s\t ", INT_ASM_OP); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } else { \ + fini_section (); \ + fprintf (FILE, "%s\t ", ASM_LONG); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); } \ + } while (0) + + +#undef ASM_OUTPUT_IDENT +#define ASM_OUTPUT_IDENT(FILE, NAME) \ + fprintf (FILE, "%s\t\"%s\"\n", IDENT_ASM_OP, NAME); + +#undef ASM_GLOBALIZE_LABEL +#define ASM_GLOBALIZE_LABEL(FILE,NAME) \ + (fprintf ((FILE), "%s ", GLOBAL_ASM_OP), assemble_name (FILE, NAME), fputs ("\n", FILE)) + +#undef ASM_OUTPUT_EXTERNAL_LIBCALL +#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, FUN) \ + if (TARGET_ELF) ASM_GLOBALIZE_LABEL (FILE, XSTR (FUN, 0)) + +#undef ASM_OUTPUT_INTERNAL_LABEL +#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \ + fprintf (FILE, ".%s%d:\n", PREFIX, NUM) + +/* The prefix to add to user-visible assembler symbols. */ + +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" + +/* + * Compensate for the difference between ELF and COFF assembler syntax. + * Otherwise, this is cribbed from ../svr4.h. + * We rename 'gcc_except_table' to the shorter name in preparation + * for the day when we're ready to do DWARF2 eh unwinding under COFF + */ +#undef ASM_OUTPUT_SECTION_NAME +#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ +do { \ + static struct section_info \ + { \ + struct section_info *next; \ + char *name; \ + enum sect_enum {SECT_RW, SECT_RO, SECT_EXEC} type; \ + } *sections; \ + struct section_info *s; \ + char *mode; \ + enum sect_enum type; \ + char *sname = NAME ; \ + if (strcmp(NAME, ".gcc_except_table") == 0) sname = ".gccexc" ; \ + \ + for (s = sections; s; s = s->next) \ + if (!strcmp (NAME, s->name)) \ + break; \ + \ + if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \ + type = SECT_EXEC, mode = (TARGET_ELF) ? "ax" : "x" ; \ + else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \ + type = SECT_RO, mode = "a"; \ + else \ + type = SECT_RW, mode = (TARGET_ELF) ? "aw" : "w" ; \ + \ + if (s == 0) \ + { \ + s = (struct section_info *) xmalloc (sizeof (struct section_info)); \ + s->name = xmalloc ((strlen (NAME) + 1) * sizeof (*NAME)); \ + strcpy (s->name, NAME); \ + s->type = type; \ + s->next = sections; \ + sections = s; \ + fprintf (FILE, ".section\t%s,\"%s\"%s\n", sname, mode, \ + (TARGET_ELF) ? ",@progbits" : "" ); \ + } \ + else \ + { \ + if (DECL && s->type != type) \ + error_with_decl (DECL, "%s causes a section type conflict"); \ + \ + fprintf (FILE, ".section\t%s\n", sname); \ + } \ +} while (0) + +#undef ASM_OUTPUT_SKIP +#define ASM_OUTPUT_SKIP(FILE,SIZE) \ +do { \ + if (TARGET_ELF) \ + fprintf (FILE, "%s\t%u\n", SKIP_ASM_OP, (SIZE)); \ + else \ + fprintf ((FILE), "%s\t.,.+%u\n", SET_ASM_OP, (SIZE)); \ +} while (0) + + +#undef CTOR_LIST_BEGIN +#define CTOR_LIST_BEGIN \ +do { \ + asm (CTORS_SECTION_ASM_OP); \ + if (TARGET_ELF) \ + STATIC func_ptr __CTOR_LIST__[1] = { (func_ptr) (-1) }; \ + else \ + asm ("pushl $0"); \ +} while (0) + +#undef CTOR_LIST_END +#define CTOR_LIST_END \ +do { \ + if (TARGET_ELF) { \ + asm (CTORS_SECTION_ASM_OP); \ + STATIC func_ptr __CTOR_LIST__[1] = { (func_ptr) (0) }; \ + } else { \ + CTOR_LIST_BEGIN; \ + } \ +} while (0) + +#undef DBX_BLOCKS_FUNCTION_RELATIVE +#define DBX_BLOCKS_FUNCTION_RELATIVE 1 + +#undef DBX_FUNCTION_FIRST +#define DBX_FUNCTION_FIRST 1 + +#undef DBX_REGISTER_NUMBER +#define DBX_REGISTER_NUMBER(n) \ +((TARGET_ELF) ? \ + ((n) == 0 ? 0 \ + : (n) == 1 ? 2 \ + : (n) == 2 ? 1 \ + : (n) == 3 ? 3 \ + : (n) == 4 ? 6 \ + : (n) == 5 ? 7 \ + : (n) == 6 ? 5 \ + : (n) == 7 ? 4 \ + : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \ + : (-1)) \ + : \ + ((n) == 0 ? 0 : \ + (n) == 1 ? 2 : \ + (n) == 2 ? 1 : \ + (n) == 3 ? 3 : \ + (n) == 4 ? 6 : \ + (n) == 5 ? 7 : \ + (n) == 6 ? 4 : \ + (n) == 7 ? 5 : \ + (n) + 4)) + +#undef DWARF_DEBUGGING_INFO +#undef SDB_DEBUGGING_INFO +#undef DBX_DEBUGGING_INFO +#undef PREFERRED_DEBUGGING_TYPE + +#define DWARF_DEBUGGING_INFO 1 +#define SDB_DEBUGGING_INFO 1 +#define DBX_DEBUGGING_INFO 1 +#define PREFERRED_DEBUGGING_TYPE \ + ((TARGET_ELF) ? DWARF_DEBUG: SDB_DEBUG) + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_const, in_init, in_fini, in_ctors, in_dtors + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + CONST_SECTION_FUNCTION \ + INIT_SECTION_FUNCTION \ + FINI_SECTION_FUNCTION \ + CTORS_SECTION_FUNCTION \ + DTORS_SECTION_FUNCTION + +#undef CONST_SECTION_FUNCTION +#define CONST_SECTION_FUNCTION \ +void \ +const_section () \ +{ \ + extern void text_section(); \ + if (!USE_CONST_SECTION) \ + text_section(); \ + else if (in_section != in_const) \ + { \ + fprintf (asm_out_file, "%s\n", CONST_SECTION_ASM_OP); \ + in_section = in_const; \ + } \ +} + +#undef FINI_SECTION_FUNCTION +#define FINI_SECTION_FUNCTION \ +void \ +fini_section () \ +{ \ + if ((!TARGET_ELF) && in_section != in_fini) \ + { \ + fprintf (asm_out_file, "%s\n", FINI_SECTION_ASM_OP); \ + in_section = in_fini; \ + } \ +} + +#undef INIT_SECTION_FUNCTION +#define INIT_SECTION_FUNCTION \ +void \ +init_section () \ +{ \ + if ((!TARGET_ELF) && in_section != in_init) \ + { \ + fprintf (asm_out_file, "%s\n", INIT_SECTION_ASM_OP); \ + in_section = in_init; \ + } \ +} + +#undef CTORS_SECTION_FUNCTION +#define CTORS_SECTION_FUNCTION \ +void \ +ctors_section () \ +{ \ + if (in_section != in_ctors) \ + { \ + fprintf (asm_out_file, "%s\n", CTORS_SECTION_ASM_OP); \ + in_section = in_ctors; \ + } \ +} + +#undef DTORS_SECTION_FUNCTION +#define DTORS_SECTION_FUNCTION \ +void \ +dtors_section () \ +{ \ + if (in_section != in_dtors) \ + { \ + fprintf (asm_out_file, "%s\n", DTORS_SECTION_ASM_OP); \ + in_section = in_dtors; \ + } \ +} + +#undef FRAME_POINTER_REQUIRED +#define FRAME_POINTER_REQUIRED \ + ((TARGET_ELF) ? 0 : \ + (current_function_calls_setjmp || current_function_calls_longjmp)) + +#undef JUMP_TABLES_IN_TEXT_SECTION +#define JUMP_TABLES_IN_TEXT_SECTION (TARGET_ELF && flag_pic) + +#undef LOCAL_LABEL_PREFIX +#define LOCAL_LABEL_PREFIX \ + ((TARGET_ELF) ? "" : ".") + +#undef MD_EXEC_PREFIX +#undef MD_STARTFILE_PREFIX +#define MD_EXEC_PREFIX "/usr/ccs/bin/" +#define MD_STARTFILE_PREFIX "/usr/ccs/lib/" + +#undef NON_SAVING_SETJMP +#define NON_SAVING_SETJMP \ + ((TARGET_ELF) ? 0 : \ + (current_function_calls_setjmp && current_function_calls_longjmp)) + +#undef NO_IMPLICIT_EXTERN_C +#define NO_IMPLICIT_EXTERN_C 1 + +/* JKJ FIXME - examine the ramifications of RETURN_IN_MEMORY and + RETURN_POPS_ARGS */ + +#undef RETURN_POPS_ARGS +#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ + ((TARGET_ELF) ? \ + (i386_return_pops_args (FUNDECL, FUNTYPE, SIZE)) : \ + (((FUNDECL) && (TREE_CODE (FUNDECL) == IDENTIFIER_NODE)) ? 0 \ + : (TARGET_RTD \ + && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ + || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ + == void_type_node))) ? (SIZE) \ + : 0)) + +#undef SELECT_SECTION +#define SELECT_SECTION(DECL,RELOC) \ +{ \ + if (TREE_CODE (DECL) == STRING_CST) \ + { \ + if (! flag_writable_strings) \ + const_section (); \ + else \ + data_section (); \ + } \ + else if (TREE_CODE (DECL) == VAR_DECL) \ + { \ + if ((TARGET_ELF && flag_pic && RELOC) \ + || !TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \ + || !DECL_INITIAL (DECL) \ + || (DECL_INITIAL (DECL) != error_mark_node \ + && !TREE_CONSTANT (DECL_INITIAL (DECL)))) \ + data_section (); \ + else \ + const_section (); \ + } \ + else \ + const_section (); \ +} + +#undef SWITCH_TAKES_ARG +#define SWITCH_TAKES_ARG(CHAR) \ + (DEFAULT_SWITCH_TAKES_ARG(CHAR) \ + || (CHAR) == 'h' \ + || (CHAR) == 'R' \ + || (CHAR) == 'Y' \ + || (CHAR) == 'z') + +#undef WORD_SWITCH_TAKES_ARG +#define WORD_SWITCH_TAKES_ARG(STR) \ + (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \ + && strcmp (STR, "Tdata") && strcmp (STR, "Ttext") \ + && strcmp (STR, "Tbss")) + +#undef TARGET_DEFAULT +#define TARGET_DEFAULT 0301 + +#undef HANDLE_SYSV_PRAGMA +#define HANDLE_SYSV_PRAGMA 1 + +#undef SCCS_DIRECTIVE +#define SCCS_DIRECTIVE 1 + +/* + * Define sizes and types + */ +#undef SIZE_TYPE +#undef PTRDIFF_TYPE +#undef WCHAR_TYPE +#undef WCHAR_TYPE_SIZE +#undef LONG_DOUBLE_TYPE_SIZE +#define LONG_DOUBLE_TYPE_SIZE 96 +#define SIZE_TYPE "unsigned int" +#define PTRDIFF_TYPE "int" +#define WCHAR_TYPE "long int" +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +/* + * New for multilib support. Set the default switches for multilib, + * which is -melf. + */ +#define MULTILIB_DEFAULTS { "melf" } + + +/* Please note that these specs may look messy but they are required in + order to emulate the SCO Development system as closely as possible. + With SCO Open Server 5.0, you now get the linker and assembler free, + so that is what these specs are targeted for. These utilities are + very argument sensitive: a space in the wrong place breaks everything. + So RMS, please forgive this mess. It works. + + Parameters which can be passed to gcc, and their SCO equivalents: + GCC Parameter SCO Equivalent + -ansi -a ansi + -posix -a posix + -Xpg4 -a xpg4 + -Xpg4plus -a xpg4plus + -Xods30 -a ods30 + + As with SCO, the default is XPG4 plus mode. SCO also allows you to + specify a C dialect with -Xt, -Xa, -Xc, -Xk and -Xm. These are passed + on to the assembler and linker in the same way that the SCO compiler + does. + + SCO also allows you to compile, link and generate either ELF or COFF + binaries. With gcc, unlike the SCO compiler, the default is ELF. + Specify -mcoff to gcc to produce COFF binaries. -fpic will get the + assembler and linker to produce PIC code. +*/ + +/* Set up assembler flags for PIC and ELF compilations */ +#undef ASM_SPEC + +#if USE_GAS + /* Leave ASM_SPEC undefined so we pick up the master copy from gcc.c + * Undef MD_EXEC_PREFIX becuase we don't know where GAS is, but it's not + * likely in /usr/ccs/bin/ + */ +#undef MD_EXEC_PREFIX +#else + +#define ASM_SPEC \ + "-b %{!mcoff:elf}%{mcoff:coff \ + %{static:%e-static not valid with -mcoff} \ + %{shared:%e-shared not valid with -mcoff} \ + %{symbolic:%e-symbolic not valid with -mcoff}} \ + %{Ym,*} %{Yd,*} %{Wa,*:%*} \ + %{!mcoff:-E%{Xa:a}%{!Xa:%{Xc:c}%{!Xc:%{Xk:k}%{!Xk:%{Xt:t}%{!Xt:a}}}},%{ansi:ansi}%{!ansi:%{posix:posix}%{!posix:%{Xpg4:xpg4}%{!Xpg4:%{Xpg4plus:XPG4PLUS}%{!Xpg4plus:%{Xods30:ods30}%{!Xods30:XPG4PLUS}}}}},ELF %{Qn:} %{!Qy:-Qn}}" +#endif + +/* Use crt1.o as a startup file and crtn.o as a closing file. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{shared: %{!mcoff: crti.o%s}} \ + %{!shared:\ + %{!symbolic: \ + %{pg:gcrt.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}} \ + %{ansi:values-Xc.o%s} \ + %{!ansi: \ + %{traditional:values-Xt.o%s} \ + %{!traditional: \ + %{Xa:values-Xa.o%s} \ + %{!Xa:%{Xc:values-Xc.o%s} \ + %{!Xc:%{Xk:values-Xk.o%s} \ + %{!Xk:%{Xt:values-Xt.o%s} \ + %{!Xt:values-Xa.o%s}}}}}} \ + %{mcoff:crtbeginS.o%s} %{!mcoff:crtbegin.o%s}" + +#undef ENDFILE_SPEC +#define ENDFILE_SPEC \ + "%{!mcoff:crtend.o%s} \ + %{mcoff:crtendS.o%s} \ + %{pg:gcrtn.o%s}%{!pg:crtn.o%s}" + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES \ + "-Asystem(svr3)" + +/* You are in a maze of GCC specs ... all alike */ + +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) \ + %{fpic:%{mcoff:%e-fpic is not valid with -mcoff}} \ + %{fPIC:%{mcoff:%e-fPIC is not valid with -mcoff}} \ + -D__i386 -D__unix -D_SCO_DS=1 -D_M_I386 -D_M_XENIX -D_M_UNIX \ + %{!Xods30:-D_STRICT_NAMES} \ + %{!ansi:%{!posix:%{!Xods30:-D_SCO_XPG_VERS=4}}} \ + %{ansi:-isystem include/ansi%s -isystem /usr/include/ansi -D_STRICT_ANSI} \ + %{!ansi: \ + %{posix:-isystem include/posix%s -isystem /usr/include/posix \ + -D_POSIX_C_SOURCE=2 -D_POSIX_SOURCE=1} \ + %{!posix:%{Xpg4:-isystem include/xpg4%s -isystem /usr/include/xpg4 \ + -D_XOPEN_SOURCE=1} \ + %{!Xpg4:-D_M_I86 -D_M_I86SM -D_M_INTERNAT -D_M_SDATA -D_M_STEXT \ + -D_M_BITFIELDS -D_M_SYS5 -D_M_SYSV -D_M_SYSIII \ + -D_M_WORDSWAP -Dunix -DM_I386 -DM_UNIX -DM_XENIX \ + %{Xods30:-isystem include/ods_30_compat%s \ + -isystem /usr/include/ods_30_compat \ + -D_SCO_ODS_30 -DM_I86 -DM_I86SM -DM_SDATA -DM_STEXT \ + -DM_BITFIELDS -DM_SYS5 -DM_SYSV -DM_INTERNAT -DM_SYSIII \ + -DM_WORDSWAP}}}} \ + %{scointl:-DM_INTERNAT -D_M_INTERNAT} \ + %{traditional:-D_KR -D_SVID -D_NO_PROTOTYPE} \ + %{!mcoff:-D_SCO_ELF} \ + %{mcoff:-D_M_COFF -D_SCO_COFF} \ + %{!mcoff:%{fpic:-D__PIC__ -D__pic__} \ + %{fPIC:%{!fpic:-D__PIC__ -D__pic__}}} \ + %{Xa:-D_SCO_C_DIALECT=1} \ + %{!Xa:%{Xc:-D_SCO_C_DIALECT=3} \ + %{!Xc:%{Xk:-D_SCO_C_DIALECT=4} \ + %{!Xk:%{Xt:-D_SCO_C_DIALECT=2} \ + %{!Xt:-D_SCO_C_DIALECT=1}}}} \ + %{traditional:-traditional -D_KR -D_NO_PROTOTYPE}" + +#undef LINK_SPEC +#define LINK_SPEC \ + "-b %{!mcoff:elf}%{mcoff:coff \ + %{static:%e-static not valid with -mcoff} \ + %{shared:%e-shared not valid with -mcoff} \ + %{symbolic:%e-symbolic not valid with -mcoff} \ + %{fpic:%e-fpic not valid with -mcoff} \ + %{fPIC:%e-fPIC not valid with -mcoff}} \ + -R%{Xa:a}%{!Xa:%{Xc:c}%{!Xc:%{Xk:k}%{!Xk:%{Xt:t}%{!Xt:a}}}},%{ansi:ansi}%{!ansi:%{posix:posix}%{!posix:%{Xpg4:xpg4}%{!Xpg4:%{Xpg4plus:XPG4PLUS}%{!Xpg4plus:%{Xods30:ods30}%{!Xods30:XPG4PLUS}}}}},%{mcoff:COFF}%{!mcoff:ELF} \ + %{Wl,*%*} %{YP,*} %{YL,*} %{YU,*} \ + %{!YP,*:%{p:-YP,/usr/ccs/libp:/lib/libp:/usr/lib/libp:/usr/ccs/lib:/lib:/usr/lib} \ + %{!p:-YP,/usr/ccs/lib:/lib:/usr/lib}} \ + %{h*} %{static:-dn -Bstatic} %{shared:-G -dy %{!z*:-z text}} \ + %{symbolic:-Bsymbolic -G -dy %{!z*:-z text}} %{z*} %{R*} %{Y*} \ + %{G:-G} %{!mcoff:%{Qn:} %{!Qy:-Qn}}" + +/* The SCO COFF linker gets confused on the difference between "-ofoo" + and "-o foo". So we just always force a single space. */ + +#define SWITCHES_NEED_SPACES "o" + +/* Library spec. If we are not building a shared library, provide the + standard libraries, as per the SCO compiler. */ + +#undef LIB_SPEC +#define LIB_SPEC \ + "%{shared:pic/libgcc.a%s}%{!shared:%{!symbolic:-lcrypt -lgen -lc}}" + +#undef LIBGCC_SPEC +#define LIBGCC_SPEC \ + "%{!shared:-lgcc}" + +#define MASK_COFF 010000000000 /* Mask for elf generation */ +#define TARGET_COFF (target_flags & MASK_COFF) +#define TARGET_ELF (!(target_flags & MASK_COFF)) + +#undef SUBTARGET_SWITCHES +#define SUBTARGET_SWITCHES \ + { "coff", MASK_COFF }, \ + { "elf", -MASK_COFF }, + +#define NO_DOLLAR_IN_LABEL + +/* +Here comes some major hackery to get the crt stuff to compile properly. +Since we can (and do) compile for both COFF and ELF environments, we +set things up accordingly, based on the pre-processor defines for ELF +and COFF. This is insane, but then I guess having one compiler with a +single back-end supporting two vastly different file format types is +a little insane too. But it is not impossible and we get a useful +compiler at the end of the day. Onward we go ... +*/ + +#if defined(CRT_BEGIN) || defined(CRT_END) || defined(IN_LIBGCC2) +# undef OBJECT_FORMAT_ELF +# undef HAVE_ATEXIT +# undef INIT_SECTION_ASM_OP +# undef FINI_SECTION_ASM_OP +# undef CTORS_SECTION_ASM_OP +# undef DTORS_SECTION_ASM_OP +# undef EH_FRAME_SECTION_ASM_OP +# undef CTOR_LIST_BEGIN +# undef CTOR_LIST_END +# undef DO_GLOBAL_CTORS_BODY + +# if defined (_SCO_ELF) +# define OBJECT_FORMAT_ELF +# define HAVE_ATEXIT 1 +# define INIT_SECTION_ASM_OP INIT_SECTION_ASM_OP_ELF +# define FINI_SECTION_ASM_OP FINI_SECTION_ASM_OP_ELF +# define DTORS_SECTION_ASM_OP DTORS_SECTION_ASM_OP_ELF +# define CTORS_SECTION_ASM_OP CTORS_SECTION_ASM_OP_ELF +# define EH_FRAME_SECTION_ASM_OP EH_FRAME_SECTION_ASM_OP_ELF +# else /* ! _SCO_ELF */ +# define INIT_SECTION_ASM_OP INIT_SECTION_ASM_OP_COFF +# define FINI_SECTION_ASM_OP FINI_SECTION_ASM_OP_COFF +# define DTORS_SECTION_ASM_OP DTORS_SECTION_ASM_OP_COFF +# define CTORS_SECTION_ASM_OP CTORS_SECTION_ASM_OP_COFF +# define EH_FRAME_SECTION_ASM_OP "" +# define CTOR_LIST_BEGIN asm (INIT_SECTION_ASM_OP); asm ("pushl $0") +# define CTOR_LIST_END CTOR_LIST_BEGIN +# define DO_GLOBAL_CTORS_BODY \ +do { \ + func_ptr *p, *beg = alloca(0); \ + for (p = beg; *p;) \ + (*p++) (); \ +} while (0) +# endif /* ! _SCO_ELF */ +#endif /* CRT_BEGIN !! CRT_END */ diff --git a/contrib/gcc/config/i386/sco5gas.h b/contrib/gcc/config/i386/sco5gas.h new file mode 100644 index 000000000000..de3e5d5570f1 --- /dev/null +++ b/contrib/gcc/config/i386/sco5gas.h @@ -0,0 +1,24 @@ +/* Definitions for Intel x86 running SCO OpenServer, running GNU assembler + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + + +/* Just set a single flag we can test for inside of sco5.h and include it. */ + +#define USE_GAS 1 diff --git a/contrib/gcc/config/i386/scodbx.h b/contrib/gcc/config/i386/scodbx.h index 1309735cf1e0..a2581d4257f1 100644 --- a/contrib/gcc/config/i386/scodbx.h +++ b/contrib/gcc/config/i386/scodbx.h @@ -1,6 +1,6 @@ /* Definitions for Intel 386 running SCO Unix System V, using dbx-in-coff encapsulation. - Copyright (C) 1992, 1995 Free Software Foundation, Inc. + Copyright (C) 1992, 1995, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -50,10 +50,10 @@ Boston, MA 02111-1307, USA. */ /* Specify predefined symbols in preprocessor. */ #undef CPP_PREDEFINES -#define CPP_PREDEFINES "-Dunix -Di386 -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP -Asystem(unix) -Asystem(svr3) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -DM_UNIX -DM_I386 -DM_COFF -DM_WORDSWAP -Asystem(svr3)" #undef CPP_SPEC -#define CPP_SPEC "%{scointl:-DM_INTERNAT}" +#define CPP_SPEC " -Acpu(i386) -Amachine(i386) %{scointl:-DM_INTERNAT}" /* This spec is used for telling cpp whether char is signed or not. */ @@ -75,7 +75,7 @@ Boston, MA 02111-1307, USA. */ #undef RETURN_POPS_ARGS #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) \ - (TREE_CODE (FUNTYPE) == IDENTIFIER_NODE ? 0 \ + ((FUNDECL) && TREE_CODE (FUNDECL) == IDENTIFIER_NODE ? 0 \ : (TARGET_RTD \ && (TYPE_ARG_TYPES (FUNTYPE) == 0 \ || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (FUNTYPE))) \ diff --git a/contrib/gcc/config/i386/seq-gas.h b/contrib/gcc/config/i386/seq-gas.h index 2ee071925bc7..796eaa24d622 100644 --- a/contrib/gcc/config/i386/seq-gas.h +++ b/contrib/gcc/config/i386/seq-gas.h @@ -39,8 +39,8 @@ GAS requires the %cl argument, so override i386/unix.h. */ -#undef AS3_SHIFT_DOUBLE -#define AS3_SHIFT_DOUBLE(a,b,c,d) AS3 (a,b,c,d) +#undef SHIFT_DOUBLE_OMITS_COUNT +#define SHIFT_DOUBLE_OMITS_COUNT 0 /* Print opcodes the way that GAS expects them. */ #define GAS_MNEMONICS 1 diff --git a/contrib/gcc/config/i386/seq-sysv3.h b/contrib/gcc/config/i386/seq-sysv3.h index e3182ee1a773..9e8388d47d74 100644 --- a/contrib/gcc/config/i386/seq-sysv3.h +++ b/contrib/gcc/config/i386/seq-sysv3.h @@ -40,17 +40,3 @@ /* Assembler pseudo-op for uninitialized shared local variables (.shbss). */ #undef SHARED_BSS_SECTION_ASM_OP #define SHARED_BSS_SECTION_ASM_OP ".section .shbss, \"bs\"" -#undef BSS_SECTION_FUNCTION -#define BSS_SECTION_FUNCTION \ -void \ -bss_section () \ -{ \ - if (in_section != in_bss) \ - { \ - if (flag_shared_data) \ - fprintf (asm_out_file, "%s\n", SHARED_BSS_SECTION_ASM_OP); \ - else \ - fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \ - in_section = in_bss; \ - } \ -} diff --git a/contrib/gcc/config/i386/sol2-c1.asm b/contrib/gcc/config/i386/sol2-c1.asm index 72fdfb87cc22..d08bcbd4aeca 100644 --- a/contrib/gcc/config/i386/sol2-c1.asm +++ b/contrib/gcc/config/i386/sol2-c1.asm @@ -1,6 +1,6 @@ ! crt1.s for Solaris 2, x86 -! Copyright (C) 1993 Free Software Foundation, Inc. +! Copyright (C) 1993, 1998 Free Software Foundation, Inc. ! Written By Fred Fish, Nov 1992 ! ! This file is free software; you can redistribute it and/or modify it @@ -149,7 +149,7 @@ _start: ! A dummy profiling support routine for non-profiling executables, ! in case we link in some objects that have been compiled for profiling. - .globl _mcount + .weak _mcount _mcount: ret .type _mcount,@function diff --git a/contrib/gcc/config/i386/sol2-gc1.asm b/contrib/gcc/config/i386/sol2-gc1.asm new file mode 100644 index 000000000000..24a1965f37e5 --- /dev/null +++ b/contrib/gcc/config/i386/sol2-gc1.asm @@ -0,0 +1,160 @@ +! gcrt1.s for Solaris 2, x86 + +! Copyright (C) 1993 Free Software Foundation, Inc. +! Written By Fred Fish, Nov 1992 +! +! This file is free software; you can redistribute it and/or modify it +! under the terms of the GNU General Public License as published by the +! Free Software Foundation; either version 2, or (at your option) any +! later version. +! +! In addition to the permissions in the GNU General Public License, the +! Free Software Foundation gives you unlimited permission to link the +! compiled version of this file with other programs, and to distribute +! those programs without any restriction coming from the use of this +! file. (The General Public License restrictions do apply in other +! respects; for example, they cover modification of the file, and +! distribution when not linked into another program.) +! +! This file is distributed in the hope that it will be useful, but +! WITHOUT ANY WARRANTY; without even the implied warranty of +! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +! General Public License for more details. +! +! You should have received a copy of the GNU General Public License +! along with this program; see the file COPYING. If not, write to +! the Free Software Foundation, 59 Temple Place - Suite 330, +! Boston, MA 02111-1307, USA. +! +! As a special exception, if you link this library with files +! compiled with GCC to produce an executable, this does not cause +! the resulting executable to be covered by the GNU General Public License. +! This exception does not however invalidate any other reasons why +! the executable file might be covered by the GNU General Public License. +! + +! This file takes control of the process from the kernel, as specified +! in section 3 of the System V Application Binary Interface, Intel386 +! Processor Supplement. It has been constructed from information obtained +! from the ABI, information obtained from single stepping existing +! Solaris executables through their startup code with gdb, and from +! information obtained by single stepping executables on other i386 SVR4 +! implementations. This file is the first thing linked into any executable. + +! This is a modified crt1.s by J.W.Hawtin 15/8/96, +! to allow program profiling, by calling monstartup on entry and _mcleanup +! on exit + + .file "gcrt1.s" + .ident "GNU C gcrt1.s" + .weak _DYNAMIC + .text + +! Start creating the initial frame by pushing a NULL value for the return +! address of the initial frame, and mark the end of the stack frame chain +! (the innermost stack frame) with a NULL value, per page 3-32 of the ABI. +! Initialize the first stack frame pointer in %ebp (the contents of which +! are unspecified at process initialization). + + .globl _start +_start: + pushl $0x0 + pushl $0x0 + movl %esp,%ebp + +! As specified per page 3-32 of the ABI, %edx contains a function +! pointer that should be registered with atexit(), for proper +! shared object termination. Just push it onto the stack for now +! to preserve it. We want to register _cleanup() first. + + pushl %edx + +! Check to see if there is an _cleanup() function linked in, and if +! so, register it with atexit() as the last thing to be run by +! atexit(). + + movl $_mcleanup,%eax + testl %eax,%eax + je .L1 + pushl $_mcleanup + call atexit + addl $0x4,%esp +.L1: + +! Now check to see if we have an _DYNAMIC table, and if so then +! we need to register the function pointer previously in %edx, but +! now conveniently saved on the stack as the argument to pass to +! atexit(). + + movl $_DYNAMIC,%eax + testl %eax,%eax + je .L2 + call atexit +.L2: + +! Register _fini() with atexit(). We will take care of calling _init() +! directly. + + pushl $_fini + call atexit + +! Start profiling + + pushl %ebp + movl %esp,%ebp + pushl $_etext + pushl $_start + call monstartup + addl $8,%esp + popl %ebp + +! Compute the address of the environment vector on the stack and load +! it into the global variable _environ. Currently argc is at 8 off +! the frame pointer. Fetch the argument count into %eax, scale by the +! size of each arg (4 bytes) and compute the address of the environment +! vector which is 16 bytes (the two zero words we pushed, plus argc, +! plus the null word terminating the arg vector) further up the stack, +! off the frame pointer (whew!). + + movl 8(%ebp),%eax + leal 16(%ebp,%eax,4),%edx + movl %edx,_environ + +! Push the environment vector pointer, the argument vector pointer, +! and the argument count on to the stack to set up the arguments +! for _init(), _fpstart(), and main(). Note that the environment +! vector pointer and the arg count were previously loaded into +! %edx and %eax respectively. The only new value we need to compute +! is the argument vector pointer, which is at a fixed address off +! the initial frame pointer. + + pushl %edx + leal 12(%ebp),%edx + pushl %edx + pushl %eax + +! Call _init(argc, argv, environ), _fpstart(argc, argv, environ), and +! main(argc, argv, environ). + + call _init + call __fpstart + call main + +! Pop the argc, argv, and environ arguments off the stack, push the +! value returned from main(), and call exit(). + + addl $12,%esp + pushl %eax + call exit + +! An inline equivalent of _exit, as specified in Figure 3-26 of the ABI. + + pushl $0x0 + movl $0x1,%eax + lcall $7,$0 + +! If all else fails, just try a halt! + + hlt + .type _start,@function + .size _start,.-_start diff --git a/contrib/gcc/config/i386/sol2.h b/contrib/gcc/config/i386/sol2.h index cc5ebca7d7e0..8fc3e6140e75 100644 --- a/contrib/gcc/config/i386/sol2.h +++ b/contrib/gcc/config/i386/sol2.h @@ -1,7 +1,6 @@ /* Target definitions for GNU compiler for Intel 80386 running Solaris 2 - Copyright (C) 1993, 1995 Free Software Foundation, Inc. - - Written by Fred Fish (fnf@cygnus.com). + Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. + Contributed by Fred Fish (fnf@cygnus.com). This file is part of GNU CC. @@ -31,17 +30,16 @@ Boston, MA 02111-1307, USA. */ executed. This macro forces the assembler to do the padding, since it knows what it is doing. */ -#define FORCE_INIT_SECTION_ALIGN do { asm (ALIGN_ASM_OP ## " 16"); } while (0) +#define FORCE_INIT_SECTION_ALIGN asm (ALIGN_ASM_OP ## " 16") #define FORCE_FINI_SECTION_ALIGN FORCE_INIT_SECTION_ALIGN /* Add "sun" to the list of symbols defined for SVR4. */ #undef CPP_PREDEFINES #define CPP_PREDEFINES \ - "-Di386 -Dunix -D__svr4__ -D__SVR4 -Dsun \ - -Asystem(unix) -Asystem(svr4) -Acpu(i386) -Amachine(i386)" + "-Dunix -D__svr4__ -D__SVR4 -Dsun -Asystem(svr4)" #undef CPP_SPEC -#define CPP_SPEC "\ +#define CPP_SPEC "%(cpp_cpu) \ %{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude}" #undef LIB_SPEC @@ -51,10 +49,21 @@ Boston, MA 02111-1307, USA. */ #undef ENDFILE_SPEC #define ENDFILE_SPEC "crtend.o%s %{pg:crtn.o%s}%{!pg:crtn.o%s}" +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{!shared: \ + %{!symbolic: \ + %{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s}%{!p:crt1.o%s}}}}\ + %{pg:gmon.o%s} crti.o%s \ + %{ansi:values-Xc.o%s} \ + %{!ansi: \ + %{traditional:values-Xt.o%s} \ + %{!traditional:values-Xa.o%s}} \ + crtbegin.o%s" + /* This should be the same as in svr4.h, except with -R added. */ #undef LINK_SPEC #define LINK_SPEC \ - "%{h*} %{V} %{v:%{!V:-V}} \ + "%{h*} %{v:-V} \ %{b} %{Wl,*:%*} \ %{static:-dn -Bstatic} \ %{shared:-G -dy -z text} \ @@ -63,12 +72,14 @@ Boston, MA 02111-1307, USA. */ %{YP,*} \ %{R*} \ %{compat-bsd: \ - %{!YP,*:%{p:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ - %{!p:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}} \ + %{!YP,*:%{pg:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ + %{!pg:%{p:-Y P,/usr/ucblib:/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ + %{!p:-Y P,/usr/ucblib:/usr/ccs/lib:/usr/lib}}} \ -R /usr/ucblib} \ %{!compat-bsd: \ - %{!YP,*:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ - %{!p:-Y P,/usr/ccs/lib:/usr/lib}}} \ + %{!YP,*:%{pg:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ + %{!pg:%{p:-Y P,/usr/ccs/lib/libp:/usr/lib/libp:/usr/ccs/lib:/usr/lib} \ + %{!p:-Y P,/usr/ccs/lib:/usr/lib}}}} \ %{Qy:} %{!Qn:-Qy}" /* This defines which switch letters take arguments. @@ -76,16 +87,9 @@ Boston, MA 02111-1307, USA. */ #undef SWITCH_TAKES_ARG #define SWITCH_TAKES_ARG(CHAR) \ - ( (CHAR) == 'D' \ - || (CHAR) == 'U' \ - || (CHAR) == 'o' \ - || (CHAR) == 'e' \ - || (CHAR) == 'u' \ - || (CHAR) == 'I' \ - || (CHAR) == 'm' \ - || (CHAR) == 'L' \ + (DEFAULT_SWITCH_TAKES_ARG(CHAR) \ || (CHAR) == 'R' \ - || (CHAR) == 'A' \ || (CHAR) == 'h' \ || (CHAR) == 'z') +#define STDC_0_IN_SYSTEM_HEADERS diff --git a/contrib/gcc/config/i386/sun386.h b/contrib/gcc/config/i386/sun386.h index 6e2680789bdb..4d4d66c181a0 100644 --- a/contrib/gcc/config/i386/sun386.h +++ b/contrib/gcc/config/i386/sun386.h @@ -1,5 +1,5 @@ /* Definitions for Sun assembler syntax for the Intel 80386. - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -131,10 +131,9 @@ do \ #define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \ sprintf ((BUF), "*.%s%d", (PREFIX), (NUMBER)) -/* This is how to output a reference to a user-level label named NAME. */ +/* The prefix to add to user-visible assembler symbols. */ -#define ASM_OUTPUT_LABELREF(FILE,NAME) \ - fprintf (FILE, "%s", NAME) +#define USER_LABEL_PREFIX "" /* This is how to output an internal numbered label where PREFIX is the class of label and NUM is the number within the class. */ diff --git a/contrib/gcc/config/i386/svr3.ifile b/contrib/gcc/config/i386/svr3.ifile index f0bb3a0f8dc0..32b3ddc2bf32 100644 --- a/contrib/gcc/config/i386/svr3.ifile +++ b/contrib/gcc/config/i386/svr3.ifile @@ -28,7 +28,10 @@ SECTIONS vfork = fork; /* I got tired of editing peoples sloppy code */ *(.fini) } - GROUP BIND( NEXT(0x400000) + (ADDR(.text) + (SIZEOF(.text)) % 0x1000)): + .stab BIND(ADDR(.text) + SIZEOF(.text)): { } + .stabstr BIND(ADDR(.stab) + SIZEOF(.stab)): { } + GROUP BIND( NEXT(0x400000) + + (ADDR(.stabstr) + (SIZEOF(.stabstr)) % 0x1000)): { .data : { __CTOR_LIST__ = . ; diff --git a/contrib/gcc/config/i386/svr3dbx.h b/contrib/gcc/config/i386/svr3dbx.h index d3348d552928..36c01cc3c21a 100644 --- a/contrib/gcc/config/i386/svr3dbx.h +++ b/contrib/gcc/config/i386/svr3dbx.h @@ -46,16 +46,13 @@ Boston, MA 02111-1307, USA. */ /* Align labels, etc. at 4-byte boundaries. For the 486, align to 16-byte boundary for sake of cache. */ -#undef ASM_OUTPUT_ALIGN_CODE -#define ASM_OUTPUT_ALIGN_CODE(FILE) \ - fprintf ((FILE), "\t.align %d,0x90\n", \ - 1 << i386_align_jumps) +#undef LABEL_ALIGN_AFTER_BARRIER +#define LABEL_ALIGN_AFTER_BARRIER(LABEL) (i386_align_jumps) /* Align start of loop at 4-byte boundary. */ -#undef ASM_OUTPUT_LOOP_ALIGN -#define ASM_OUTPUT_LOOP_ALIGN(FILE) \ - fprintf ((FILE), "\t.align %d,0x90\n", 1 << i386_align_loops); +#undef LOOP_ALIGN +#define LOOP_ALIGN(LABEL) (i386_align_loops) /* Additional overrides needed for dbx-in-coff gas, mostly taken from pbb.h */ @@ -66,17 +63,6 @@ Boston, MA 02111-1307, USA. */ */ #define CTOR_LISTS_DEFINED_EXTERNALLY -/* similar to default, but allows for the table defined by ld with svr3.ifile. - nptrs is always 0. So we need to instead check that __DTOR_LIST__[1] != 0. - The old check is left in so that the same macro can be used if and when - a future version of gas does support section directives. */ - -#define DO_GLOBAL_DTORS_BODY {int nptrs = *(int *)__DTOR_LIST__; int i; \ - if (nptrs == -1 || (__DTOR_LIST__[0] == 0 && __DTOR_LIST__[1] != 0)) \ - for (nptrs = 0; __DTOR_LIST__[nptrs + 1] != 0; nptrs++); \ - for (i = nptrs; i >= 1; i--) \ - __DTOR_LIST__[i] (); } - /* Use crt1.o as a startup file and crtn.o as a closing file. */ /* * The loader directive file svr3.ifile defines how to merge the constructor diff --git a/contrib/gcc/config/i386/svr3gas.h b/contrib/gcc/config/i386/svr3gas.h index 401c7661e272..a288b84e5240 100644 --- a/contrib/gcc/config/i386/svr3gas.h +++ b/contrib/gcc/config/i386/svr3gas.h @@ -1,5 +1,5 @@ /* Definitions for Intel 386 running system V, using gas. - Copyright (C) 1992 Free Software Foundation, Inc. + Copyright (C) 1992, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -139,29 +139,17 @@ do { \ #endif /* STACK_GROWS_DOWNWARD */ -/* Add extra sections .init and .fini, in addition to .bss from att386.h. */ +/* Add extra sections .rodata, .init and .fini. */ #undef EXTRA_SECTIONS -#define EXTRA_SECTIONS in_const, in_bss, in_init, in_fini +#define EXTRA_SECTIONS in_const, in_init, in_fini #undef EXTRA_SECTION_FUNCTIONS #define EXTRA_SECTION_FUNCTIONS \ CONST_SECTION_FUNCTION \ - BSS_SECTION_FUNCTION \ INIT_SECTION_FUNCTION \ FINI_SECTION_FUNCTION -#define BSS_SECTION_FUNCTION \ -void \ -bss_section () \ -{ \ - if (in_section != in_bss) \ - { \ - fprintf (asm_out_file, "\t%s\n", BSS_SECTION_ASM_OP); \ - in_section = in_bss; \ - } \ -} - #define INIT_SECTION_FUNCTION \ void \ init_section () \ diff --git a/contrib/gcc/config/i386/svr3z.ifile b/contrib/gcc/config/i386/svr3z.ifile index 4fdbb937c57b..4946051235e4 100644 --- a/contrib/gcc/config/i386/svr3z.ifile +++ b/contrib/gcc/config/i386/svr3z.ifile @@ -28,7 +28,10 @@ SECTIONS vfork = fork; /* I got tired of editing peoples sloppy code */ *(.fini) } - GROUP BIND( NEXT(0x400000) + (ADDR(.text) + (SIZEOF(.text)) % 0x1000)): + .stab BIND(ADDR(.text) + SIZEOF(.text)): { } + .stabstr BIND(ADDR(.stab) + SIZEOF(.stab)): { } + GROUP BIND( NEXT(0x400000) + + (ADDR(.stabstr) + (SIZEOF(.stabstr)) % 0x1000)): { .data : { __CTOR_LIST__ = . ; diff --git a/contrib/gcc/config/i386/sysv3.h b/contrib/gcc/config/i386/sysv3.h index 8c5cfc415876..ce898899011a 100644 --- a/contrib/gcc/config/i386/sysv3.h +++ b/contrib/gcc/config/i386/sysv3.h @@ -1,5 +1,5 @@ /* Definitions for Intel 386 running system V. - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -26,7 +26,7 @@ Boston, MA 02111-1307, USA. */ #include "svr3.h" /* Use the ATT assembler syntax. - This overrides at least one macro (ASM_OUTPUT_LABELREF) from svr3.h. */ + This overrides at least one macro (USER_LABEL_PREFIX) from svr3.h. */ #include "i386/att.h" @@ -42,9 +42,9 @@ Boston, MA 02111-1307, USA. */ /* Specify predefined symbols in preprocessor. */ -#define CPP_PREDEFINES "-Dunix -Di386 -Asystem(unix) -Asystem(svr3) -Acpu(i386) -Amachine(i386)" +#define CPP_PREDEFINES "-Dunix -Asystem(svr3)" -#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}" +#define CPP_SPEC "%(cpp_cpu) %{posix:-D_POSIX_SOURCE}" /* Writing `int' for a bitfield forces int alignment for the structure. */ diff --git a/contrib/gcc/config/i386/sysv4.h b/contrib/gcc/config/i386/sysv4.h index 92fcada03d59..e688f7b8c9f7 100644 --- a/contrib/gcc/config/i386/sysv4.h +++ b/contrib/gcc/config/i386/sysv4.h @@ -58,7 +58,7 @@ do { long value; \ /* This is how to output assembly code to define a `double' constant. We always have to use a pair of .long pseudo-ops to do this because the native SVR4 ELF assembler is buggy and it generates incorrect - values when we try to use the the .double pseudo-op instead. */ + values when we try to use the .double pseudo-op instead. */ #undef ASM_OUTPUT_DOUBLE #define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ @@ -236,10 +236,18 @@ do { long value[3]; \ i386.md for an explanation of the expression this outputs. */ #undef ASM_OUTPUT_ADDR_DIFF_ELT -#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, VALUE, REL) \ +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \ fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE) /* Indicate that jump tables go in the text section. This is necessary when compiling PIC code. */ -#define JUMP_TABLES_IN_TEXT_SECTION +#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic) + +/* A C statement (sans semicolon) to output to the stdio stream + FILE the assembler definition of uninitialized global DECL named + NAME whose size is SIZE bytes and alignment is ALIGN bytes. + Try to use asm_output_aligned_bss to implement this macro. */ + +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \ + asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN) diff --git a/contrib/gcc/config/i386/t-crtpic b/contrib/gcc/config/i386/t-crtpic index f5dd073a664e..ff81a9bef9ce 100644 --- a/contrib/gcc/config/i386/t-crtpic +++ b/contrib/gcc/config/i386/t-crtpic @@ -7,3 +7,4 @@ # routines in crtstuff.c. CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/contrib/gcc/config/i386/t-dgux b/contrib/gcc/config/i386/t-dgux new file mode 100644 index 000000000000..292331f22a9b --- /dev/null +++ b/contrib/gcc/config/i386/t-dgux @@ -0,0 +1,4 @@ +# +# target makefile for dgux +# +EXTRA_PARTS=crtbegin.o crtend.o diff --git a/contrib/gcc/config/i386/t-mingw32 b/contrib/gcc/config/i386/t-mingw32 new file mode 100644 index 000000000000..fe948c6d15ec --- /dev/null +++ b/contrib/gcc/config/i386/t-mingw32 @@ -0,0 +1,4 @@ +# +# collect2 doesn't work for i386-mingw32* yet. +# +USE_COLLECT2= diff --git a/contrib/gcc/config/i386/t-next b/contrib/gcc/config/i386/t-next index ec6373f9cea0..effa6953b9a7 100644 --- a/contrib/gcc/config/i386/t-next +++ b/contrib/gcc/config/i386/t-next @@ -7,3 +7,6 @@ OTHER_FIXINCLUDES_DIRS= /LocalDeveloper/Headers # is sometimes in /usr/include/ansi/limits.h. LIMITS_H_TEST = [ -f $(SYSTEM_HEADER_DIR)/limits.h -o -f $(SYSTEM_HEADER_DIR)/ansi/limits.h ] + +nextstep.o: $(srcdir)/config/nextstep.c $(CONFIG_H) flags.h tree.h + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/nextstep.c diff --git a/contrib/gcc/config/i386/t-osf b/contrib/gcc/config/i386/t-osf new file mode 100644 index 000000000000..c996e0c9e77b --- /dev/null +++ b/contrib/gcc/config/i386/t-osf @@ -0,0 +1,2 @@ +# If compiling with the osf gcc, avoid sharing code. +TCFLAGS = -pic-none diff --git a/contrib/gcc/config/i386/t-osf1elf b/contrib/gcc/config/i386/t-osf1elf new file mode 100644 index 000000000000..77c7df1a6dfd --- /dev/null +++ b/contrib/gcc/config/i386/t-osf1elf @@ -0,0 +1,18 @@ +# Assemble startup files. +crti.o: $(srcdir)/config/i386/osf1-ci.asm $(GCC_PASSES) + sed -e '/^!/d' <$(srcdir)/config/i386/osf1-ci.asm >crti.s + $(GCC_FOR_TARGET) -c -o crti.o crti.s +crtn.o: $(srcdir)/config/i386/osf1-cn.asm $(GCC_PASSES) + sed -e '/^!/d' <$(srcdir)/config/i386/osf1-cn.asm >crtn.s + $(GCC_FOR_TARGET) -c -o crtn.o crtn.s + +# The pushl in CTOR initialization interferes with frame pointer elimination. + +# We need to use -fPIC when we are using gcc to compile the routines in +# crtstuff.c. This is only really needed when we are going to use gcc/g++ +# to produce a shared library, but since we don't know ahead of time when +# we will be doing that, we just always use -fPIC when compiling the +# routines in crtstuff.c. + +CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/contrib/gcc/config/i386/t-sco5 b/contrib/gcc/config/i386/t-sco5 new file mode 100644 index 000000000000..f602066e9959 --- /dev/null +++ b/contrib/gcc/config/i386/t-sco5 @@ -0,0 +1,20 @@ +# The pushl in CTOR initialization interferes with frame pointer elimination. +CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer +CRTSTUFF_T_CFLAGS_S = -mcoff -fno-omit-frame-pointer + +# +# I am still a little unsure of the multilib architecture. The following +# 4 lines are based on advice from meissner@cygnus.com. +# +MULTILIB_OPTIONS = mcoff/fPIC +MULTILIB_DIRNAMES = coff pic +MULTILIB_EXCEPTIONS = *mcoff*/*fPIC* +MULTILIB_MATCHES = fPIC=fpic +MULTILIB_EXTRA_OPTS = + +LIBGCC=stmp-multilib +INSTALL_LIBGCC=install-multilib + +crti.o: $(srcdir)/config/i386/sol2-ci.asm $(GCC_PASSES) + sed -e '/^!/d' <$(srcdir)/config/i386/sol2-ci.asm >crti.s + $(GCC_FOR_TARGET) -c -o crti.o crti.s diff --git a/contrib/gcc/config/i386/t-sco5gas b/contrib/gcc/config/i386/t-sco5gas new file mode 100644 index 000000000000..2bca87be7a8b --- /dev/null +++ b/contrib/gcc/config/i386/t-sco5gas @@ -0,0 +1,20 @@ +# The pushl in CTOR initialization interferes with frame pointer elimination. +CRTSTUFF_T_CFLAGS = -fPIC -fno-omit-frame-pointer +CRTSTUFF_T_CFLAGS_S = -mcoff -fno-omit-frame-pointer + +# +# I am still a little unsure of the multilib architecture. The following +# 4 lines are based on advice from meissner@cygnus.com. +# +MULTILIB_OPTIONS = fPIC +MULTILIB_DIRNAMES = pic +MULTILIB_EXCEPTIONS = *fPIC* +MULTILIB_MATCHES = fPIC=fpic +MULTILIB_EXTRA_OPTS = + +LIBGCC=stmp-multilib +INSTALL_LIBGCC=install-multilib + +crti.o: $(srcdir)/config/i386/sol2-ci.asm $(GCC_PASSES) + sed -e '/^!/d' <$(srcdir)/config/i386/sol2-ci.asm >crti.s + $(GCC_FOR_TARGET) -c -o crti.o crti.s diff --git a/contrib/gcc/config/i386/t-sol2 b/contrib/gcc/config/i386/t-sol2 index f79f6ca05fbe..5dc59cc375ed 100644 --- a/contrib/gcc/config/i386/t-sol2 +++ b/contrib/gcc/config/i386/t-sol2 @@ -13,20 +13,28 @@ gmon.o: $(srcdir)/config/i386/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H) # Apparently Sun believes that assembler files don't need comments, because no # single ASCII character is valid (tried them all). So we manually strip out # the comments with sed. This bug may only be in the Early Access releases. -crt1.o: $(srcdir)/config/i386/sol2-c1.asm +gcrt1.o: $(srcdir)/config/i386/sol2-gc1.asm + sed -e '/^!/d' <$(srcdir)/config/i386/sol2-gc1.asm >gcrt1.s + $(AS) -o gcrt1.o gcrt1.s +crt1.o: $(srcdir)/config/i386/sol2-c1.asm $(GCC_PASSES) sed -e '/^!/d' <$(srcdir)/config/i386/sol2-c1.asm >crt1.s - $(AS) -o crt1.o crt1.s -crti.o: $(srcdir)/config/i386/sol2-ci.asm + $(GCC_FOR_TARGET) -c -o crt1.o crt1.s +crti.o: $(srcdir)/config/i386/sol2-ci.asm $(GCC_PASSES) sed -e '/^!/d' <$(srcdir)/config/i386/sol2-ci.asm >crti.s - $(AS) -o crti.o crti.s -crtn.o: $(srcdir)/config/i386/sol2-cn.asm + $(GCC_FOR_TARGET) -c -o crti.o crti.s +crtn.o: $(srcdir)/config/i386/sol2-cn.asm $(GCC_PASSES) sed -e '/^!/d' <$(srcdir)/config/i386/sol2-cn.asm >crtn.s - $(AS) -o crtn.o crtn.s + $(GCC_FOR_TARGET) -c -o crtn.o crtn.s # We need to use -fPIC when we are using gcc to compile the routines in # crtstuff.c. This is only really needed when we are going to use gcc/g++ # to produce a shared library, but since we don't know ahead of time when # we will be doing that, we just always use -fPIC when compiling the # routines in crtstuff.c. +# +# We must also enable optimization to avoid having any code appear after +# the call & alignment statement, but before we switch back to the +# .text section. -CRTSTUFF_T_CFLAGS = -fPIC +CRTSTUFF_T_CFLAGS = -fPIC -O2 +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/contrib/gcc/config/i386/t-winnt b/contrib/gcc/config/i386/t-winnt index e8e1a0af0504..1e3557c1822a 100644 --- a/contrib/gcc/config/i386/t-winnt +++ b/contrib/gcc/config/i386/t-winnt @@ -1,2 +1,6 @@ winnt.o: $(srcdir)/config/i386/winnt.c - $(CC) -I. -I$(srcdir) -I$(srcdir)/config -c $(srcdir)/config/i386/winnt.c + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/winnt.c +oldnames.o: $(srcdir)/config/winnt/oldnames.c + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/winnt/oldnames.c +spawnv.o: $(srcdir)/config/winnt/spawnv.c + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/winnt/spawnv.c diff --git a/contrib/gcc/config/i386/unix.h b/contrib/gcc/config/i386/unix.h index f38fe270d89e..47440ddd943d 100644 --- a/contrib/gcc/config/i386/unix.h +++ b/contrib/gcc/config/i386/unix.h @@ -45,7 +45,9 @@ Boston, MA 02111-1307, USA. */ count is in %cl. Some assemblers require %cl as an argument; some don't. This macro controls what to do: by default, don't print %cl. */ -#define AS3_SHIFT_DOUBLE(a,b,c,d) AS2 (a,c,d) +#define SHIFT_DOUBLE_OMITS_COUNT 1 +#define AS3_SHIFT_DOUBLE(a,b,c,d) \ + (SHIFT_DOUBLE_OMITS_COUNT ? AS2 (a,c,d) : AS3 (a,b,c,d)) /* Output the size-letter for an opcode. CODE is the letter used in an operand spec (L, B, W, S or Q). @@ -99,7 +101,6 @@ Boston, MA 02111-1307, USA. */ /* String containing the assembler's comment-starter. */ #define ASM_COMMENT_START "/" -#define COMMENT_BEGIN "/" /* Output to assembler file text saying following lines may contain character constants, extra white space, comments, etc. */ @@ -146,3 +147,45 @@ Boston, MA 02111-1307, USA. */ #define FUNCTION_VALUE_REGNO_P(N) \ ((N) == 0 || ((N)== FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387)) +/* Output code to add DELTA to the first argument, and then jump to FUNCTION. + Used for C++ multiple inheritance. */ +#define ASM_OUTPUT_MI_THUNK(FILE, THUNK_FNDECL, DELTA, FUNCTION) \ +do { \ + tree parm; \ + \ + if (i386_regparm > 0) \ + parm = TYPE_ARG_TYPES (TREE_TYPE (function)); \ + else \ + parm = NULL_TREE; \ + for (; parm; parm = TREE_CHAIN (parm)) \ + if (TREE_VALUE (parm) == void_type_node) \ + break; \ + fprintf (FILE, "\taddl $%d,%s\n", DELTA, \ + parm ? "%eax" \ + : aggregate_value_p (TREE_TYPE (TREE_TYPE (FUNCTION))) ? "8(%esp)" \ + : "4(%esp)"); \ + \ + if (flag_pic) \ + { \ + rtx xops[2]; \ + xops[0] = pic_offset_table_rtx; \ + xops[1] = (rtx) gen_label_rtx (); \ + \ + if (i386_regparm > 2) \ + abort (); \ + output_asm_insn ("push%L0 %0", xops); \ + output_asm_insn (AS1 (call,%P1), xops); \ + ASM_OUTPUT_INTERNAL_LABEL (FILE, "L", CODE_LABEL_NUMBER (xops[1])); \ + output_asm_insn (AS1 (pop%L0,%0), xops); \ + output_asm_insn ("addl $_GLOBAL_OFFSET_TABLE_+[.-%P1],%0", xops); \ + fprintf (FILE, "\tmovl "); \ + assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \ + fprintf (FILE, "@GOT(%%ebx),%%ecx\n\tpopl %%ebx\n\tjmp *%%ecx\n"); \ + } \ + else \ + { \ + fprintf (FILE, "\tjmp "); \ + assemble_name (FILE, XSTR (XEXP (DECL_RTL (FUNCTION), 0), 0)); \ + fprintf (FILE, "\n"); \ + } \ +} while (0) diff --git a/contrib/gcc/config/i386/vxi386.h b/contrib/gcc/config/i386/vxi386.h new file mode 100644 index 000000000000..1044286215b6 --- /dev/null +++ b/contrib/gcc/config/i386/vxi386.h @@ -0,0 +1,23 @@ +/* Definitions of target machine for GNU compiler. VxWorks i386 version. + Copyright (C) 1998 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "i386/i386-aout.h" + +#define HANDLE_SYSV_PRAGMA diff --git a/contrib/gcc/config/i386/winnt.c b/contrib/gcc/config/i386/winnt.c index 3a7ebf1ba5d3..0058eb76499b 100644 --- a/contrib/gcc/config/i386/winnt.c +++ b/contrib/gcc/config/i386/winnt.c @@ -1,6 +1,6 @@ /* Subroutines for insn-output.c for Windows NT. Contributed by Douglas Rupp (drupp@cs.washington.edu) - Copyright (C) 1995 Free Software Foundation, Inc. + Copyright (C) 1995, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -19,8 +19,8 @@ along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include #include "config.h" +#include "system.h" #include "rtl.h" #include "regs.h" #include "hard-reg-set.h" @@ -28,6 +28,342 @@ Boston, MA 02111-1307, USA. */ #include "tree.h" #include "flags.h" +/* i386/PE specific attribute support. + + i386/PE has two new attributes: + dllexport - for exporting a function/variable that will live in a dll + dllimport - for importing a function/variable from a dll + + Microsoft allows multiple declspecs in one __declspec, separating + them with spaces. We do NOT support this. Instead, use __declspec + multiple times. +*/ + +/* Return nonzero if ATTR is a valid attribute for DECL. + ATTRIBUTES are any existing attributes and ARGS are the arguments + supplied with ATTR. */ + +int +i386_pe_valid_decl_attribute_p (decl, attributes, attr, args) + tree decl; + tree attributes; + tree attr; + tree args; +{ + if (args == NULL_TREE) + { + if (is_attribute_p ("dllexport", attr)) + return 1; + if (is_attribute_p ("dllimport", attr)) + return 1; + } + + return i386_valid_decl_attribute_p (decl, attributes, attr, args); +} + +/* Return nonzero if ATTR is a valid attribute for TYPE. + ATTRIBUTES are any existing attributes and ARGS are the arguments + supplied with ATTR. */ + +int +i386_pe_valid_type_attribute_p (type, attributes, attr, args) + tree type; + tree attributes; + tree attr; + tree args; +{ + if (args == NULL_TREE + && (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)) + { + if (is_attribute_p ("dllexport", attr)) + return 1; + if (is_attribute_p ("dllimport", attr)) + return 1; + } + + return i386_valid_type_attribute_p (type, attributes, attr, args); +} + +/* Merge attributes in decls OLD and NEW. + + This handles the following situation: + + __declspec (dllimport) int foo; + int foo; + + The second instance of `foo' nullifies the dllimport. */ + +tree +i386_pe_merge_decl_attributes (old, new) + tree old, new; +{ + tree a; + int delete_dllimport_p; + + old = DECL_MACHINE_ATTRIBUTES (old); + new = DECL_MACHINE_ATTRIBUTES (new); + + /* What we need to do here is remove from `old' dllimport if it doesn't + appear in `new'. dllimport behaves like extern: if a declaration is + marked dllimport and a definition appears later, then the object + is not dllimport'd. */ + + if (lookup_attribute ("dllimport", old) != NULL_TREE + && lookup_attribute ("dllimport", new) == NULL_TREE) + delete_dllimport_p = 1; + else + delete_dllimport_p = 0; + + a = merge_attributes (old, new); + + if (delete_dllimport_p) + { + tree prev,t; + + /* Scan the list for dllimport and delete it. */ + for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t)) + { + if (is_attribute_p ("dllimport", TREE_PURPOSE (t))) + { + if (prev == NULL_TREE) + a = TREE_CHAIN (a); + else + TREE_CHAIN (prev) = TREE_CHAIN (t); + break; + } + } + } + + return a; +} + +/* Return the type that we should use to determine if DECL is + imported or exported. */ + +static tree +associated_type (decl) + tree decl; +{ + tree t = NULL_TREE; + + /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer + to the containing class. So we look at the 'this' arg. */ + if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) + { + /* Artificial methods are not affected by the import/export status of + their class unless they are virtual. */ + if (! DECL_ARTIFICIAL (decl) || DECL_VINDEX (decl)) + t = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))); + } + else if (DECL_CONTEXT (decl) + && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't') + t = DECL_CONTEXT (decl); + + return t; +} + +/* Return non-zero if DECL is a dllexport'd object. */ + +int +i386_pe_dllexport_p (decl) + tree decl; +{ + tree exp; + + if (TREE_CODE (decl) != VAR_DECL + && TREE_CODE (decl) != FUNCTION_DECL) + return 0; + exp = lookup_attribute ("dllexport", DECL_MACHINE_ATTRIBUTES (decl)); + if (exp) + return 1; + + /* Class members get the dllexport status of their class. */ + if (associated_type (decl)) + { + exp = lookup_attribute ("dllexport", + TYPE_ATTRIBUTES (associated_type (decl))); + if (exp) + return 1; + } + + return 0; +} + +/* Return non-zero if DECL is a dllimport'd object. */ + +int +i386_pe_dllimport_p (decl) + tree decl; +{ + tree imp; + + if (TREE_CODE (decl) == FUNCTION_DECL + && TARGET_NOP_FUN_DLLIMPORT) + return 0; + + if (TREE_CODE (decl) != VAR_DECL + && TREE_CODE (decl) != FUNCTION_DECL) + return 0; + imp = lookup_attribute ("dllimport", DECL_MACHINE_ATTRIBUTES (decl)); + if (imp) + return 1; + + /* Class members get the dllimport status of their class. */ + if (associated_type (decl)) + { + imp = lookup_attribute ("dllimport", + TYPE_ATTRIBUTES (associated_type (decl))); + if (imp) + return 1; + } + + return 0; +} + +/* Return non-zero if SYMBOL is marked as being dllexport'd. */ + +int +i386_pe_dllexport_name_p (symbol) + char *symbol; +{ + return symbol[0] == '@' && symbol[1] == 'e' && symbol[2] == '.'; +} + +/* Return non-zero if SYMBOL is marked as being dllimport'd. */ + +int +i386_pe_dllimport_name_p (symbol) + char *symbol; +{ + return symbol[0] == '@' && symbol[1] == 'i' && symbol[2] == '.'; +} + +/* Mark a DECL as being dllexport'd. + Note that we override the previous setting (eg: dllimport). */ + +void +i386_pe_mark_dllexport (decl) + tree decl; +{ + char *oldname, *newname; + rtx rtlname; + tree idp; + + rtlname = XEXP (DECL_RTL (decl), 0); + if (GET_CODE (rtlname) == SYMBOL_REF) + oldname = XSTR (rtlname, 0); + else if (GET_CODE (rtlname) == MEM + && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) + oldname = XSTR (XEXP (rtlname, 0), 0); + else + abort (); + if (i386_pe_dllimport_name_p (oldname)) + oldname += 9; + else if (i386_pe_dllexport_name_p (oldname)) + return; /* already done */ + + newname = alloca (strlen (oldname) + 4); + sprintf (newname, "@e.%s", oldname); + + /* We pass newname through get_identifier to ensure it has a unique + address. RTL processing can sometimes peek inside the symbol ref + and compare the string's addresses to see if two symbols are + identical. */ + idp = get_identifier (newname); + + XEXP (DECL_RTL (decl), 0) = + gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); +} + +/* Mark a DECL as being dllimport'd. */ + +void +i386_pe_mark_dllimport (decl) + tree decl; +{ + char *oldname, *newname; + tree idp; + rtx rtlname, newrtl; + + rtlname = XEXP (DECL_RTL (decl), 0); + if (GET_CODE (rtlname) == SYMBOL_REF) + oldname = XSTR (rtlname, 0); + else if (GET_CODE (rtlname) == MEM + && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) + oldname = XSTR (XEXP (rtlname, 0), 0); + else + abort (); + if (i386_pe_dllexport_name_p (oldname)) + { + error ("`%s' declared as both exported to and imported from a DLL.", + IDENTIFIER_POINTER (DECL_NAME (decl))); + return; + } + else if (i386_pe_dllimport_name_p (oldname)) + { + /* Already done, but force correct linkage since the redeclaration + might have omitted explicit extern. Sigh. */ + if (TREE_CODE (decl) == VAR_DECL + /* ??? Is this test for vtables needed? */ + && !DECL_VIRTUAL_P (decl)) + { + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + } + return; + } + + /* ??? One can well ask why we're making these checks here, + and that would be a good question. */ + + /* Imported variables can't be initialized. Note that C++ classes + are marked initial, so we need to check. */ + if (TREE_CODE (decl) == VAR_DECL + && !DECL_VIRTUAL_P (decl) + && (DECL_INITIAL (decl) + && ! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))) + { + error_with_decl (decl, "initialized variable `%s' is marked dllimport"); + return; + } + /* Nor can they be static. */ + if (TREE_CODE (decl) == VAR_DECL + /* ??? Is this test for vtables needed? */ + && !DECL_VIRTUAL_P (decl) + && 0 /*???*/) + { + error_with_decl (decl, "static variable `%s' is marked dllimport"); + return; + } + + /* `extern' needn't be specified with dllimport. + Specify `extern' now and hope for the best. Sigh. */ + if (TREE_CODE (decl) == VAR_DECL + /* ??? Is this test for vtables needed? */ + && !DECL_VIRTUAL_P (decl)) + { + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + } + + newname = alloca (strlen (oldname) + 11); + sprintf (newname, "@i._imp__%s", oldname); + + /* We pass newname through get_identifier to ensure it has a unique + address. RTL processing can sometimes peek inside the symbol ref + and compare the string's addresses to see if two symbols are + identical. */ + idp = get_identifier (newname); + + newrtl = gen_rtx (MEM, Pmode, + gen_rtx (SYMBOL_REF, Pmode, + IDENTIFIER_POINTER (idp))); + XEXP (DECL_RTL (decl), 0) = newrtl; + + /* Can't treat a pointer to this as a constant address */ + DECL_NON_ADDR_CONST_P (decl) = 1; +} + /* Return string which is the former assembler name modified with a suffix consisting of an atsign (@) followed by the number of bytes of arguments */ @@ -37,6 +373,8 @@ gen_stdcall_suffix (decl) tree decl; { int total = 0; + /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead + of DECL_ASSEMBLER_NAME. */ char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); char *newsym; @@ -44,13 +382,19 @@ gen_stdcall_suffix (decl) if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl)))) == void_type_node) { - tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); + tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl)); - while (TREE_VALUE (formal_type) != void_type_node) - { - total += TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); - formal_type = TREE_CHAIN (formal_type); - } + while (TREE_VALUE (formal_type) != void_type_node) + { + int parm_size + = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type))); + /* Must round up to include padding. This is done the same + way as in store_one_arg. */ + parm_size = ((parm_size + PARM_BOUNDARY - 1) + / PARM_BOUNDARY * PARM_BOUNDARY); + total += parm_size; + formal_type = TREE_CHAIN (formal_type); + } } newsym = xmalloc (strlen (asmname) + 10); @@ -58,3 +402,169 @@ gen_stdcall_suffix (decl) return IDENTIFIER_POINTER (get_identifier (newsym)); } +/* Cover function to implement ENCODE_SECTION_INFO. */ + +void +i386_pe_encode_section_info (decl) + tree decl; +{ + /* This bit is copied from i386.h. */ + if (optimize > 0 && TREE_CONSTANT (decl) + && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST)) + { + rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd' + ? TREE_CST_RTL (decl) : DECL_RTL (decl)); + SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; + } + + if (TREE_CODE (decl) == FUNCTION_DECL) + if (lookup_attribute ("stdcall", + TYPE_ATTRIBUTES (TREE_TYPE (decl)))) + XEXP (DECL_RTL (decl), 0) = + gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl)); + + /* Mark the decl so we can tell from the rtl whether the object is + dllexport'd or dllimport'd. */ + + if (i386_pe_dllexport_p (decl)) + i386_pe_mark_dllexport (decl); + else if (i386_pe_dllimport_p (decl)) + i386_pe_mark_dllimport (decl); + /* It might be that DECL has already been marked as dllimport, but a + subsequent definition nullified that. The attribute is gone but + DECL_RTL still has @i._imp__foo. We need to remove that. Ditto + for the DECL_NON_ADDR_CONST_P flag. */ + else if ((TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == VAR_DECL) + && DECL_RTL (decl) != NULL_RTX + && GET_CODE (DECL_RTL (decl)) == MEM + && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM + && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF + && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0))) + { + char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0); + tree idp = get_identifier (oldname + 9); + rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); + + XEXP (DECL_RTL (decl), 0) = newrtl; + + DECL_NON_ADDR_CONST_P (decl) = 0; + + /* We previously set TREE_PUBLIC and DECL_EXTERNAL. + We leave these alone for now. */ + } +} + +/* Cover function for UNIQUE_SECTION. */ + +void +i386_pe_unique_section (decl, reloc) + tree decl; + int reloc; +{ + int len; + char *name,*string,*prefix; + + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + /* Strip off any encoding in fnname. */ + STRIP_NAME_ENCODING (name, name); + + /* The object is put in, for example, section .text$foo. + The linker will then ultimately place them in .text + (everything from the $ on is stripped). Don't put + read-only data in .rdata section to avoid a PE linker + bug when .rdata$* grouped sections are used in code + without a .rdata section. */ + if (TREE_CODE (decl) == FUNCTION_DECL) + prefix = ".text$"; + else if (DECL_READONLY_SECTION (decl, reloc)) +#ifdef READONLY_DATA_SECTION + prefix = ".rdata$"; +#else + prefix = ".text$"; +#endif + else + prefix = ".data$"; + len = strlen (name) + strlen (prefix); + string = alloca (len + 1); + sprintf (string, "%s%s", prefix, name); + + DECL_SECTION_NAME (decl) = build_string (len, string); +} + +/* The Microsoft linker requires that every function be marked as + DT_FCN. When using gas on cygwin32, we must emit appropriate .type + directives. */ + +#include "gsyms.h" + +/* Mark a function appropriately. This should only be called for + functions for which we are not emitting COFF debugging information. + FILE is the assembler output file, NAME is the name of the + function, and PUBLIC is non-zero if the function is globally + visible. */ + +void +i386_pe_declare_function_type (file, name, public) + FILE *file; + char *name; + int public; +{ + fprintf (file, "\t.def\t"); + assemble_name (file, name); + fprintf (file, ";\t.scl\t%d;\t.type\t%d;\t.endef\n", + public ? (int) C_EXT : (int) C_STAT, + (int) DT_FCN << N_BTSHFT); +} + +/* Keep a list of external functions. */ + +struct extern_list +{ + struct extern_list *next; + char *name; +}; + +static struct extern_list *extern_head; + +/* Assemble an external function reference. We need to keep a list of + these, so that we can output the function types at the end of the + assembly. We can't output the types now, because we might see a + definition of the function later on and emit debugging information + for it then. */ + +void +i386_pe_record_external_function (name) + char *name; +{ + struct extern_list *p; + + p = (struct extern_list *) permalloc (sizeof *p); + p->next = extern_head; + p->name = name; + extern_head = p; +} + +/* This is called at the end of assembly. For each external function + which has not been defined, we output a declaration now. */ + +void +i386_pe_asm_file_end (file) + FILE *file; +{ + struct extern_list *p; + + for (p = extern_head; p != NULL; p = p->next) + { + tree decl; + + decl = get_identifier (p->name); + + /* Positively ensure only one declaration for any given symbol. */ + if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl)) + { + TREE_ASM_WRITTEN (decl) = 1; + i386_pe_declare_function_type (file, p->name, TREE_PUBLIC (decl)); + } + } +} diff --git a/contrib/gcc/config/i386/x-dgux b/contrib/gcc/config/i386/x-dgux new file mode 100644 index 000000000000..322bfe3ae911 --- /dev/null +++ b/contrib/gcc/config/i386/x-dgux @@ -0,0 +1,11 @@ +# +# host is ix86 running dgux +# +CC = /bin/gcc +X_CFLAGS = -O -mstandard -mlegend +BOOT_CFLAGS = -O2 -g -mstandard -mlegend $(CFLAGS) +CLIB = -lw32 +RANLIB = true +USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) +STMP_FIXPROTO = + diff --git a/contrib/gcc/config/i386/x-osf1elf b/contrib/gcc/config/i386/x-osf1elf new file mode 100644 index 000000000000..146738107f6e --- /dev/null +++ b/contrib/gcc/config/i386/x-osf1elf @@ -0,0 +1,8 @@ +# Defaults for OSF/1 1.3+ +CC = $(OLDCC) +CLIB = -lld +INSTALL = installbsd -c +OLDCC = /usr/ccs/gcc/gcc +X_CFLAGS = -static + +# FIXPROTO_DEFINES = -D_XOPEN_SOURCE diff --git a/contrib/gcc/config/i386/x-osfrose b/contrib/gcc/config/i386/x-osfrose index a419bdb78226..2c5e3ba13c76 100644 --- a/contrib/gcc/config/i386/x-osfrose +++ b/contrib/gcc/config/i386/x-osfrose @@ -7,8 +7,9 @@ BUILD = CC = $(OLDCC) CLIB = -lld -X_CFLAGS = $(DEB_OPT) $(MSTATS) $(SHLIB) $(X_DEFINES) -X_CFLAGS_NODEBUG = $(NO_DEBUG) $(MSTATS) $(OPT) $(PROFILE) $(SHLIB) $(X_DEFINES) $(XCFLAGS) +X_CFLAGS = $(DEB_OPT) $(MSTATS) $(X_DEFINES) +X_CFLAGS_NODEBUG = $(NO_DEBUG) $(MSTATS) $(OPT) $(PROFILE) $(X_DEFINES) $(XCFLAGS) +XCFLAGS = $(SHLIB) CPP_ABORT = # -Dabort=fancy_abort CPPFLAGS = $(CPP_ABORT) $(SYSTEM_INCLUDES) DEB_OPT = $(OPT) $(DEBUG) $(PROFILE) @@ -16,7 +17,6 @@ DEBUG = DEBUG_COLLECT = # -DDEBUG CCLIBFLAGS = -O -DNO_HALF_PIC GCC_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) -B./ -DPOSIX -DNO_HALF_PIC -INSTALL = installbsd -c LDFLAGS = MSTATS = # -mstats OLDCC = /usr/ccs/gcc/gcc @@ -25,7 +25,3 @@ PROFILE = SHLIB = -pic-none SYSTEM_INCLUDES = # -I${BUILD}/usr/include X_DEFINES = -Dvfork=fork - -libdir = /usr/ccs -mandir = /usr/ccs/gcc/$(target)/$(version) -bindir = /usr/ccs/gcc/$(target)/$(version) diff --git a/contrib/gcc/config/i386/x-sco5 b/contrib/gcc/config/i386/x-sco5 new file mode 100644 index 000000000000..e13ed7425404 --- /dev/null +++ b/contrib/gcc/config/i386/x-sco5 @@ -0,0 +1,10 @@ +RANLIB = : +RANLIB_TEST = false +CC = cc +OLDCC = cc +CCLIBFLAGS = +# We avoid the ALLOCA in -lPW becuase it gives us an evil index() +ALLOCA = alloca.o + +# See all the declarations. +FIXPROTO_DEFINES = -D_XOPEN_SOURCE -D_POSIX_C_SOURCE=2 diff --git a/contrib/gcc/config/i386/xm-aix.h b/contrib/gcc/config/i386/xm-aix.h index 5e5d40281a16..4cbd36ef518f 100644 --- a/contrib/gcc/config/i386/xm-aix.h +++ b/contrib/gcc/config/i386/xm-aix.h @@ -1,37 +1,2 @@ -/* Configuration for GNU C-compiler for IBM PS/2 running AIX/386. - Copyright (C) 1988, 1993 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define USG - #undef TRUE #undef FALSE - -#include "i386/xm-i386.h" - -#define bcopy(a,b,c) memcpy (b,a,c) -#define bzero(a,b) memset (a,0,b) -#define bcmp(a,b,c) memcmp (a,b,c) - -/* If not compiled with GNU C, use the portable alloca. */ -#ifndef __GNUC__ -#define USE_C_ALLOCA -#endif - -#define HAVE_PUTENV diff --git a/contrib/gcc/config/i386/xm-bsd386.h b/contrib/gcc/config/i386/xm-bsd386.h index 9deb7ef6c651..6b8eee7db039 100644 --- a/contrib/gcc/config/i386/xm-bsd386.h +++ b/contrib/gcc/config/i386/xm-bsd386.h @@ -1,6 +1,3 @@ /* Configuration for GCC for Intel i386 running BSDI's BSD/386 as host. */ #include "i386/xm-i386.h" - -#define HAVE_STRERROR - diff --git a/contrib/gcc/config/i386/xm-dgux.h b/contrib/gcc/config/i386/xm-dgux.h new file mode 100644 index 000000000000..5bdb9be0ebb4 --- /dev/null +++ b/contrib/gcc/config/i386/xm-dgux.h @@ -0,0 +1,12 @@ + +/* Configuration for GCC for Intel i386 running DG/ux */ + +/* looks just like sysv4 for now */ + +#include "i386/xm-i386.h" +#include "xm-svr4.h" + +/* If not compiled with GNU C, use the portable alloca. */ +#ifndef __GNUC__ +#define USE_C_ALLOCA +#endif diff --git a/contrib/gcc/config/i386/xm-dos.h b/contrib/gcc/config/i386/xm-dos.h index 1dd0c013b1d6..a734a81b94eb 100644 --- a/contrib/gcc/config/i386/xm-dos.h +++ b/contrib/gcc/config/i386/xm-dos.h @@ -1,8 +1,5 @@ #include "i386/xm-i386.h" -/* Inhibit cccp.c's definition of putenv. */ -#define HAVE_PUTENV - /* Use semicolons to separate elements of a path. */ #define PATH_SEPARATOR ';' @@ -15,6 +12,3 @@ #define MKTEMP_EACH_FILE 1 #define NO_PRECOMPILES 1 - -/* sys_errlist proto in cccp.c doesn't match djgpp */ -#define HAVE_STRERROR diff --git a/contrib/gcc/config/i386/xm-isc.h b/contrib/gcc/config/i386/xm-isc.h index 7a0a47c4df58..e686c5ec9d4d 100644 --- a/contrib/gcc/config/i386/xm-isc.h +++ b/contrib/gcc/config/i386/xm-isc.h @@ -1,5 +1,3 @@ -#include "i386/xm-sysv3.h" - #ifndef REAL_ARITHMETIC #define REAL_VALUE_ATOF(x, mode) strtod ((x), (char **)0) extern double strtod (); diff --git a/contrib/gcc/config/i386/xm-linux.h b/contrib/gcc/config/i386/xm-linux.h index 42f097ddc6cc..713bf3b2817a 100644 --- a/contrib/gcc/config/i386/xm-linux.h +++ b/contrib/gcc/config/i386/xm-linux.h @@ -1,5 +1,5 @@ -/* Configuration for GCC for Intel i386 running Linux. - Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. +/* Configuration for GCC for Intel i386 running Linux-based GNU systems. + Copyright (C) 1993, 1994, 1995, 1997 Free Software Foundation, Inc. Contributed by H.J. Lu (hjl@nynexst.com) This file is part of GNU CC. diff --git a/contrib/gcc/config/i386/xm-mingw32.h b/contrib/gcc/config/i386/xm-mingw32.h new file mode 100644 index 000000000000..d818142d9e52 --- /dev/null +++ b/contrib/gcc/config/i386/xm-mingw32.h @@ -0,0 +1,42 @@ +/* Configuration for GNU C-compiler for hosting on Windows32. + using GNU tools and the Windows32 API Library. + Copyright (C) 1997, 1998 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#ifndef USG +#define USG 1 +#endif + +#ifndef ONLY_INT_FIELD +#define ONLY_INT_FIELDS 1 +#endif + +#ifndef USE_PROTOTYPES +#define USE_PROTOTYPES 1 +#endif + +#define NO_SYS_SIGLIST 1 +#define environ _environ + +/* Even though we support "/", allow "\" since everybody tests both. */ +#define DIR_SEPARATOR '\\' +#define EXECUTABLE_SUFFIX ".exe" + +#undef PATH_SEPARATOR +#define PATH_SEPARATOR ';' diff --git a/contrib/gcc/config/i386/xm-openbsd.h b/contrib/gcc/config/i386/xm-openbsd.h new file mode 100644 index 000000000000..1a79e83bc4a4 --- /dev/null +++ b/contrib/gcc/config/i386/xm-openbsd.h @@ -0,0 +1,23 @@ +/* Configuration file for i386 hosts running OpenBSD. + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include +#include + diff --git a/contrib/gcc/config/i386/xm-os2.h b/contrib/gcc/config/i386/xm-os2.h index 5ff2899cfd54..aed925e993c5 100644 --- a/contrib/gcc/config/i386/xm-os2.h +++ b/contrib/gcc/config/i386/xm-os2.h @@ -1,7 +1,7 @@ /* Configuration for GNU compiler for an Intel i386 or later processor running OS/2 2.x. - Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. - Contributed by Samuel Figueroa (figueroa@cs.nyu.edu) + Copyright (C) 1993, 1994, 1995, 1997, 1998 Free Software Foundation, Inc. + Contributed by Samuel Figueroa (figueroa@apple.com) This file is part of GNU CC. @@ -28,20 +28,24 @@ Boston, MA 02111-1307, USA. */ #include /* this defines alloca */ #define USG #define ONLY_INT_FIELDS -#define HAVE_PUTENV #define USE_PROTOTYPES 1 -#define bcmp(a,b,c) memcmp (a,b,c) -#define bcopy(a,b,c) memcpy (b,a,c) -#define bzero(a,b) memset (a,0,b) -#define index strchr -#define rindex strrchr #define strcasecmp stricmp #define kill(a,b) raise(b) #define mktemp tmpnam #else +#ifdef __EMX__ +#define EMX +#define USG +#define BSTRING +#define HAVE_PUTENV +#define HAVE_VPRINTF +#define HAVE_STRERROR +#define strcasecmp stricmp +#else #define ____386BSD____ int spawnv (int modeflag, char *path, char *argv[]); int spawnvp (int modeflag, char *path, char *argv[]); +#endif /* __EMX__ */ #endif /* __IBMC__ */ #ifndef PATH_SEPARATOR @@ -52,6 +56,14 @@ int spawnvp (int modeflag, char *path, char *argv[]); #endif #define EXECUTABLE_SUFFIX ".exe" + +/* The EMX compiler uses regular .o files */ +#ifndef __EMX__ #define OBJECT_SUFFIX ".obj" +#endif + +/* This is required to make temporary file names unique on file + systems which severely restrict the length of file names. */ +#define MKTEMP_EACH_FILE #include "i386/xm-i386.h" diff --git a/contrib/gcc/config/i386/xm-osf.h b/contrib/gcc/config/i386/xm-osf.h index fda50d98f554..4cbd36ef518f 100644 --- a/contrib/gcc/config/i386/xm-osf.h +++ b/contrib/gcc/config/i386/xm-osf.h @@ -1,32 +1,2 @@ -/* Configuration for GNU C-compiler for 386 running OSF/1 - Copyright (C) 1994 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - #undef TRUE #undef FALSE - -#include "i386/xm-i386.h" - -#define bcopy(a,b,c) memcpy (b,a,c) -#define bzero(a,b) memset (a,0,b) -#define bcmp(a,b,c) memcmp (a,b,c) - -#define HAVE_PUTENV -#define HAVE_VPRINTF - diff --git a/contrib/gcc/config/i386/xm-osf1elf.h b/contrib/gcc/config/i386/xm-osf1elf.h new file mode 100644 index 000000000000..69ca9c14c007 --- /dev/null +++ b/contrib/gcc/config/i386/xm-osf1elf.h @@ -0,0 +1,6 @@ +/* Configuration for GCC for Intel i386 running OSF/1 1.3. */ + +#ifndef HZ +#include +#define HZ DEFAULT_CLK_TCK +#endif diff --git a/contrib/gcc/config/i386/xm-sco.h b/contrib/gcc/config/i386/xm-sco.h index 01a63d90e004..ad634499d30b 100644 --- a/contrib/gcc/config/i386/xm-sco.h +++ b/contrib/gcc/config/i386/xm-sco.h @@ -1,18 +1,9 @@ /* Configuration for GCC for Intel i386 running SCO. */ -#include "i386/xm-sysv3.h" - -/* On SCO 3.2.1, ldexp rejects values outside [0.5, 1). */ - -#define BROKEN_LDEXP - /* Big buffers improve performance. */ #define IO_BUFFER_SIZE (0x8000 - 1024) -/* SCO has a very small ARG_MAX. */ -#define SMALL_ARG_MAX - #ifndef __GNUC__ /* The SCO compiler gets it wrong, and treats enumerated bitfields as signed quantities, making it impossible to use an 8-bit enum diff --git a/contrib/gcc/config/i386/xm-sco5.h b/contrib/gcc/config/i386/xm-sco5.h new file mode 100644 index 000000000000..6b22b1d549fd --- /dev/null +++ b/contrib/gcc/config/i386/xm-sco5.h @@ -0,0 +1,7 @@ +/* Configuration for GCC for Intel i386 running SCO. */ + +/* Big buffers improve performance. */ + +#define IO_BUFFER_SIZE (0x8000 - 1024) + + diff --git a/contrib/gcc/config/i386/xm-sun.h b/contrib/gcc/config/i386/xm-sun.h index d2e714ecf5cd..de7c2013b3ef 100644 --- a/contrib/gcc/config/i386/xm-sun.h +++ b/contrib/gcc/config/i386/xm-sun.h @@ -1,5 +1,5 @@ /* Configuration for GNU C-compiler for Intel 80386 running SunOS 4.0. - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -21,7 +21,3 @@ Boston, MA 02111-1307, USA. */ #define USG #include "i386/xm-i386.h" - -#define bcopy(a,b,c) memcpy (b,a,c) -#define bzero(a,b) memset (a,0,b) -#define bcmp(a,b,c) memcmp (a,b,c) diff --git a/contrib/gcc/config/i386/xm-sysv4.h b/contrib/gcc/config/i386/xm-sysv4.h index 49d52b4e7f3b..1365064a5a64 100644 --- a/contrib/gcc/config/i386/xm-sysv4.h +++ b/contrib/gcc/config/i386/xm-sysv4.h @@ -1,16 +1,5 @@ /* Configuration for GCC for Intel i386 running System V Release 4. */ -#include "i386/xm-i386.h" -#include "xm-svr4.h" - -/* If not compiled with GNU C, use the portable alloca. */ -#ifndef __GNUC__ -#define USE_C_ALLOCA -#endif #ifdef __HIGHC__ #include /* for MetaWare High-C on NCR System 3000 */ #endif - -/* Univel, at least, has a small ARG_MAX. Defining this is harmless - except for causing extra stat calls in the driver program. */ -#define SMALL_ARG_MAX diff --git a/contrib/gcc/config/i386/xm-vsta.h b/contrib/gcc/config/i386/xm-vsta.h index bb333aeae678..735d1d51943b 100644 --- a/contrib/gcc/config/i386/xm-vsta.h +++ b/contrib/gcc/config/i386/xm-vsta.h @@ -1,26 +1,2 @@ -/* Configuration for GNU C-compiler for Intel 80386. - Copyright (C) 1994 Free Software Foundation, Inc. - -This file is part of GNU CC. - -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ - -#define NO_STAB_H - -#include "i386/xm-i386.h" - /* Use semicolons to separate elements of a path. */ #define PATH_SEPARATOR ';' -- cgit v1.2.3