diff options
Diffstat (limited to 'gnu/usr.bin/gcc/config/i386')
78 files changed, 9035 insertions, 1395 deletions
diff --git a/gnu/usr.bin/gcc/config/i386/386bsd.h b/gnu/usr.bin/gcc/config/i386/386bsd.h index cdab5f57c88..c93279ffb00 100644 --- a/gnu/usr.bin/gcc/config/i386/386bsd.h +++ b/gnu/usr.bin/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" diff --git a/gnu/usr.bin/gcc/config/i386/aix386ng.h b/gnu/usr.bin/gcc/config/i386/aix386ng.h index 5d09fc30509..ec283a4fa4e 100644 --- a/gnu/usr.bin/gcc/config/i386/aix386ng.h +++ b/gnu/usr.bin/gcc/config/i386/aix386ng.h @@ -1,6 +1,6 @@ /* Definitions for IBM PS2 running AIX/386. - From: Minh Tran-Le <TRANLE@intellicorp.com> - Copyright (C) 1988 Free Software Foundation, Inc. + Copyright (C) 1988, 1996 Free Software Foundation, Inc. + Contributed by Minh Tran-Le <TRANLE@intellicorp.com>. 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,9 +44,9 @@ 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 \ +#define CPP_SPEC "%(cpp_cpu) %[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 @@ -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/gnu/usr.bin/gcc/config/i386/att.h b/gnu/usr.bin/gcc/config/i386/att.h index f8bbb764306..e5c2d9c7e99 100644 --- a/gnu/usr.bin/gcc/config/i386/att.h +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/bsd.h b/gnu/usr.bin/gcc/config/i386/bsd.h index 6bf7399dc31..d50be3664c1 100644 --- a/gnu/usr.bin/gcc/config/i386/bsd.h +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/bsd386.h b/gnu/usr.bin/gcc/config/i386/bsd386.h index 935a2e06404..d64fe59e2ac 100644 --- a/gnu/usr.bin/gcc/config/i386/bsd386.h +++ b/gnu/usr.bin/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,7 @@ #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 " #" diff --git a/gnu/usr.bin/gcc/config/i386/cygwin32.asm b/gnu/usr.bin/gcc/config/i386/cygwin32.asm new file mode 100644 index 00000000000..4ac4c91a3b1 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/cygwin32.asm @@ -0,0 +1,32 @@ +/* stuff needed for libgcc1 on win32. */ + +#ifdef L_chkstk + + .global ___chkstk + .global __alloca +___chkstk: +__alloca: + pushl %ecx /* save temp */ + movl %esp,%ecx /* get sp */ + addl $0x8,%ecx /* and point to return addr */ + +probe: cmpl $0x1000,%eax /* > 4k ?*/ + jb done + + subl $0x1000,%ecx /* yes, move pointer down 4k*/ + orl $0x0,(%ecx) /* probe there */ + subl $0x1000,%eax /* decrement count */ + jmp probe /* and do it again */ + +done: subl %eax,%ecx + orl $0x0,(%ecx) /* less that 4k, just peek here */ + + movl %esp,%eax + movl %ecx,%esp /* decrement stack */ + + movl (%eax),%ecx /* recover saved temp */ + movl 4(%eax),%eax /* get return address */ + jmp *%eax + + +#endif diff --git a/gnu/usr.bin/gcc/config/i386/cygwin32.h b/gnu/usr.bin/gcc/config/i386/cygwin32.h new file mode 100644 index 00000000000..952d8488b34 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/cygwin32.h @@ -0,0 +1,207 @@ +/* Operating system specific defines to be used when targeting GCC for + hosting on Windows NT 3.x, using a Unix style C library and tools, + 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. + Copyright (C) 1995, 1996, 1997 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 YES_UNDERSCORES + +#define DBX_DEBUGGING_INFO +#define SDB_DEBUGGING_INFO +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#include "i386/gas.h" +#include "dbxcoff.h" + +#ifdef CPP_PREDEFINES +#undef CPP_PREDEFINES +#endif + +#define CPP_PREDEFINES "-Di386 -D_WIN32 \ + -DPOSIX -D__CYGWIN32__ -DWINNT -D_X86_=1 -D__STDC__=1\ + -D__stdcall=__attribute__((__stdcall__)) \ + -D__cdecl=__attribute__((__cdecl__)) \ + -Asystem(winnt) -Acpu(i386) -Amachine(i386)" + +#undef CPP_SPEC +#define CPP_SPEC "-remap %(cpp_cpu) %[cpp_cpu] %{posix:-D_POSIX_SOURCE}" + +/* We have to dynamic link to get to the system DLLs. All of libc, libm and + the Unix stuff is in cygwin.dll. The import library is called + 'libcygwin.a'. For Windows applications, include more libraries, but + always include kernel32. We'd like to specific subsystem windows to + ld, but that doesn't work just yet. */ + +#undef LIB_SPEC +#define LIB_SPEC "-lcygwin %{mwindows:-luser32 -lgdi32 -lcomdlg32} -lkernel32" + +#define LINK_SPEC "%{mwindows:--subsystem windows}" + +/* Normally, -lgcc is not needed since everything in it is in the DLL, but we + want to allow things to be added to it when installing new versions of + GCC without making a new CYGWIN.DLL, so we leave it. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "crt0%O%s" + +#define SIZE_TYPE "unsigned int" +#define PTRDIFF_TYPE "int" +#define WCHAR_UNSIGNED 1 +#define WCHAR_TYPE_SIZE 16 +#define WCHAR_TYPE "short unsigned int" +#define HAVE_ATEXIT 1 + +#undef EXTRA_SECTIONS +#define EXTRA_SECTIONS in_ctor, in_dtor + +#undef EXTRA_SECTION_FUNCTIONS +#define EXTRA_SECTION_FUNCTIONS \ + CTOR_SECTION_FUNCTION \ + DTOR_SECTION_FUNCTION + +#define CTOR_SECTION_FUNCTION \ +void \ +ctor_section () \ +{ \ + if (in_section != in_ctor) \ + { \ + fprintf (asm_out_file, "\t.section .ctor\n"); \ + in_section = in_ctor; \ + } \ +} + +#define DTOR_SECTION_FUNCTION \ +void \ +dtor_section () \ +{ \ + if (in_section != in_dtor) \ + { \ + fprintf (asm_out_file, "\t.section .dtor\n"); \ + in_section = in_dtor; \ + } \ +} + +#define ASM_OUTPUT_CONSTRUCTOR(FILE,NAME) \ + do { \ + ctor_section (); \ + fprintf (FILE, "%s\t", ASM_LONG); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +#define ASM_OUTPUT_DESTRUCTOR(FILE,NAME) \ + do { \ + dtor_section (); \ + fprintf (FILE, "%s\t", ASM_LONG); \ + assemble_name (FILE, NAME); \ + fprintf (FILE, "\n"); \ + } while (0) + +/* Define this macro if references to a symbol must be treated + differently depending on something about the variable or + function named by the symbol (such as what section it is in). + + On i386, if using PIC, mark a SYMBOL_REF for a non-global symbol + so that we may access it directly in the GOT. + + On i386 running Windows NT, modify the assembler name with a suffix + consisting of an atsign (@) followed by string of digits that represents + the number of bytes of arguments passed to the function, if it has the + attribute STDCALL. */ + +#ifdef ENCODE_SECTION_INFO +#undef ENCODE_SECTION_INFO +#define ENCODE_SECTION_INFO(DECL) \ +do \ + { \ + if (flag_pic) \ + { \ + rtx rtl = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \ + ? TREE_CST_RTL (DECL) : DECL_RTL (DECL)); \ + SYMBOL_REF_FLAG (XEXP (rtl, 0)) \ + = (TREE_CODE_CLASS (TREE_CODE (DECL)) != 'd' \ + || ! TREE_PUBLIC (DECL)); \ + } \ + 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)); \ + } \ +while (0) +#endif + +/* Emit code to check the stack when allocating more that 4000 + bytes in one go. */ + +#define CHECK_STACK_LIMIT 4000 + +/* By default, target has a 80387, uses IEEE compatible arithmetic, + and returns float values in the 387 and needs stack probes */ +#undef TARGET_DEFAULT + +#define TARGET_DEFAULT \ + (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE) + +/* 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.align %d\n", 1<<(LOG)) + +/* Define this macro if in some cases global symbols from one translation + unit may not be bound to undefined symbols in another translation unit + without user intervention. For instance, under Microsoft Windows + symbols must be explicitly imported from shared libraries (DLLs). */ +#define MULTIPLE_SYMBOL_SPACES + +#define UNIQUE_SECTION_P(DECL) DECL_ONE_ONLY (DECL) +extern void i386_pe_unique_section (); +#define UNIQUE_SECTION(DECL,RELOC) i386_pe_unique_section (DECL, RELOC) + +#define SUPPORTS_ONE_ONLY 1 + +/* A C statement to output something to the assembler file to switch to section + NAME for object DECL which is either a FUNCTION_DECL, a VAR_DECL or + NULL_TREE. Some target formats do not support arbitrary sections. Do not + define this macro in such cases. */ +#undef ASM_OUTPUT_SECTION_NAME +#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \ +do { \ + if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL) \ + fprintf (STREAM, "\t.section %s,\"x\"\n", (NAME)); \ + else if ((DECL) && DECL_READONLY_SECTION (DECL, RELOC)) \ + fprintf (STREAM, "\t.section %s,\"\"\n", (NAME)); \ + else \ + fprintf (STREAM, "\t.section %s,\"w\"\n", (NAME)); \ + /* Functions may have been compiled at various levels of \ + optimization so we can't use `same_size' here. Instead, \ + have the linker pick one. */ \ + if ((DECL) && DECL_ONE_ONLY (DECL)) \ + fprintf (STREAM, "\t.linkonce %s\n", \ + TREE_CODE (DECL) == FUNCTION_DECL \ + ? "discard" : "same_size"); \ +} while (0) + +#undef ASM_COMMENT_START +#define ASM_COMMENT_START " #" diff --git a/gnu/usr.bin/gcc/config/i386/dgux.c b/gnu/usr.bin/gcc/config/i386/dgux.c new file mode 100644 index 00000000000..ff36135380c --- /dev/null +++ b/gnu/usr.bin/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 <time.h> +#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_ : "<nofile>", 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_ : "<nofile>", 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/gnu/usr.bin/gcc/config/i386/dgux.h b/gnu/usr.bin/gcc/config/i386/dgux.h new file mode 100644 index 00000000000..974052ed819 --- /dev/null +++ b/gnu/usr.bin/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 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) \ + do { \ + extern int flag_signed_bitfields; \ + flag_signed_bitfields = 0; \ + abort_helper (); \ + optimization_options (LEVEL); \ + } 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 <varargs.h> and <stdarg.h> 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/gnu/usr.bin/gcc/config/i386/freebsd-elf.h b/gnu/usr.bin/gcc/config/i386/freebsd-elf.h new file mode 100644 index 00000000000..252ebf5cf84 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/freebsd-elf.h @@ -0,0 +1,187 @@ +/* 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. + +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 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. */ +#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, 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 + +/* 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 "int" + +#undef WCHAR_TYPE_SIZE +#define WCHAR_TYPE_SIZE BITS_PER_WORD + +#undef CPP_PREDEFINES +#define CPP_PREDEFINES "-Dunix -D__ELF__ -D__FreeBSD__=2 -Asystem(FreeBSD)" + +#undef CPP_SPEC +#define CPP_SPEC "%(cpp_cpu) %[cpp_cpu] %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}" + +#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 + +/* 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}}}" + +/* Get perform_* macros to build libgcc.a. */ diff --git a/gnu/usr.bin/gcc/config/i386/freebsd.h b/gnu/usr.bin/gcc/config/i386/freebsd.h index c4e9991c62f..b02c31c5729 100644 --- a/gnu/usr.bin/gcc/config/i386/freebsd.h +++ b/gnu/usr.bin/gcc/config/i386/freebsd.h @@ -1,6 +1,6 @@ /* Definitions of target machine for GNU compiler for Intel 80386 running FreeBSD. - Copyright (C) 1988, 1992, 1994 Free Software Foundation, Inc. + Copyright (C) 1988, 1992, 1994, 1996, 1997 Free Software Foundation, Inc. Contributed by Poul-Henning Kamp <phk@login.dkuug.dk> This file is part of GNU CC. @@ -56,11 +56,6 @@ Boston, MA 02111-1307, USA. */ #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" @@ -229,9 +224,9 @@ do { \ #ifdef FREEBSD_NATIVE #define INCLUDE_DEFAULTS { \ - { "/usr/include", 0 }, \ - { "/usr/include/g++", 1 }, \ - { 0, 0} \ + { "/usr/include", 0, 0, 0 }, \ + { "/usr/include/g++", "G++", 1, 1 }, \ + { 0, 0, 0, 0} \ } #undef MD_EXEC_PREFIX diff --git a/gnu/usr.bin/gcc/config/i386/gas.h b/gnu/usr.bin/gcc/config/i386/gas.h index d02015723ba..fbfba7456be 100644 --- a/gnu/usr.bin/gcc/config/i386/gas.h +++ b/gnu/usr.bin/gcc/config/i386/gas.h @@ -1,5 +1,5 @@ -/* Definitions for Intel 386 running system V with gnu tools - Copyright (C) 1988, 1993, 1994 Free Software Foundation, Inc. +/* Definitions for Intel 386 using GAS. + Copyright (C) 1988, 1993, 1994, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -56,8 +56,8 @@ Boston, MA 02111-1307, USA. */ /* Specify predefined symbols in preprocessor. */ -#define CPP_PREDEFINES "-Dunix -Di386 -Asystem(unix) -Acpu(i386) -Amachine(i386)" -#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}" +#define CPP_PREDEFINES "-Dunix" +#define CPP_SPEC "%(cpp_cpu) %[cpp_cpu] %{posix:-D_POSIX_SOURCE}" /* Allow #sccs in preprocessor. */ @@ -71,12 +71,19 @@ Boston, MA 02111-1307, USA. */ #define TARGET_MEM_FUNCTIONS -#if 0 /* People say gas uses the log as the arg to .align. */ -/* When using gas, .align N aligns to an N-byte boundary. */ +/* In the past there was confusion as to what the argument to .align was + in GAS. For the last several years the rule has been this: for a.out + file formats that argument is LOG, and for all other file formats the + argument is 1<<LOG. + However, GAS now has .p2align and .balign pseudo-ops so to remove any + doubt or guess work, and since this file is used for both a.out and other + file formats, we use one of them. */ + +#if 0 /* ??? However, not every port uses binutils 2.6 yet. */ #undef ASM_OUTPUT_ALIGN -#define ASM_OUTPUT_ALIGN(FILE,LOG) \ - if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG)) +#define ASM_OUTPUT_ALIGN(FILE,LOG) \ + if ((LOG)!=0) fprintf ((FILE), "\t.balign %d\n", 1<<(LOG)) #endif /* Align labels, etc. at 4-byte boundaries. @@ -126,8 +133,8 @@ Boston, MA 02111-1307, USA. */ 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/gnu/usr.bin/gcc/config/i386/gmon-sol2.c b/gnu/usr.bin/gcc/config/i386/gmon-sol2.c new file mode 100644 index 00000000000..c0743958f90 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/gmon-sol2.c @@ -0,0 +1,402 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Re rework of the solaris 2 version of gmon by J.W.Hawtin 12/8/1996 + * Does not work right yet. + */ + +/* + * This is a modified gmon.c by J.W.Hawtin <J.W.Hawtin@lboro.ac.uk>, + * 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.4 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 my 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 <unistd.h> + +#endif +#ifdef DEBUG +#include <stdio.h> +#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; + + /* + * 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); + + /* + * 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/gnu/usr.bin/gcc/config/i386/gnu.h b/gnu/usr.bin/gcc/config/i386/gnu.h index 1ad5df991e4..bdce3ed000b 100644 --- a/gnu/usr.bin/gcc/config/i386/gnu.h +++ b/gnu/usr.bin/gcc/config/i386/gnu.h @@ -6,14 +6,16 @@ #undef CPP_PREDEFINES #define CPP_PREDEFINES GNU_CPP_PREDEFINES("i386") +#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/gnu/usr.bin/gcc/config/i386/go32-rtems.h b/gnu/usr.bin/gcc/config/i386/go32-rtems.h new file mode 100644 index 00000000000..282465b249b --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/go32-rtems.h @@ -0,0 +1,32 @@ +/* Configuration for an i386 running RTEMS on top of MS-DOS with + djgpp/go32 v1.x. + + Copyright (C) 1996 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/go32.h" + +/* Specify predefined symbols in preprocessor. */ + +#ifdef CPP_PREDEFINES +#undef CPP_PREDEFINES +#endif +#define CPP_PREDEFINES "-Dunix -Di386 -DGO32 -DMSDOS -Drtems -D__rtems__ \ + -Asystem(unix) -Asystem(msdos) -Acpu(i386) -Amachine(i386) -Asystem(rtems)" diff --git a/gnu/usr.bin/gcc/config/i386/go32.h b/gnu/usr.bin/gcc/config/i386/go32.h index 5618a0dd0fb..80a0e875c43 100644 --- a/gnu/usr.bin/gcc/config/i386/go32.h +++ b/gnu/usr.bin/gcc/config/i386/go32.h @@ -1,5 +1,9 @@ /* Configuration for an i386 running MS-DOS with djgpp/go32. */ +#include "dbxcoff.h" + +#define NO_STAB_H /* DJGPP has no stab.h */ + /* Don't assume anything about the header files. */ #define NO_IMPLICIT_EXTERN_C @@ -53,7 +57,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 +71,29 @@ 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 it's own version of __main, so don't define one + in libgcc, nor call one in main(). */ +#define HAS_INIT_SECTION diff --git a/gnu/usr.bin/gcc/config/i386/i386.c b/gnu/usr.bin/gcc/config/i386/i386.c index 48c58a09d8e..a4ec3b6a3f2 100644 --- a/gnu/usr.bin/gcc/config/i386/i386.c +++ b/gnu/usr.bin/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, 95, 96, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -16,7 +16,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. */ #include <stdio.h> #include <setjmp.h> @@ -33,6 +33,7 @@ Boston, MA 02111-1307, USA. */ #include "insn-attr.h" #include "tree.h" #include "flags.h" +#include "except.h" #include "function.h" #ifdef EXTRA_CONSTRAINT @@ -44,11 +45,69 @@ Boston, MA 02111-1307, USA. */ even if the conditional was untrue. */ #endif +#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 (); @@ -80,24 +139,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=<xxx> */ +char *ix86_arch_string; /* for -march=<xxx> */ + /* 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,15 +193,34 @@ int i386_align_funcs; /* power of two alignment for functions */ void override_options () { - int ch, i, regno; + int ch, i, j, regno; char *p; 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++) @@ -137,23 +239,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); @@ -164,7 +318,7 @@ override_options () else i386_align_loops = 2; - /* 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); @@ -175,7 +329,7 @@ override_options () else i386_align_jumps = def_align; - /* 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 +339,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 @@ -205,7 +374,8 @@ order_regs_for_local_alloc () { int i, ch, order, regno; - /* 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++) @@ -226,59 +396,112 @@ 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) + int level; +{ + /* 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)); } + + 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 @@ -315,17 +538,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; @@ -380,31 +603,28 @@ i386_return_pops_args (fundecl, funtype, size) tree fundecl; tree funtype; int size; -{ - int rtd = TARGET_RTD; - - if (TREE_CODE (funtype) == IDENTIFIER_NODE) +{ + int rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE); + + /* 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; + + if (rtd + && (TYPE_ARG_TYPES (funtype) == NULL_TREE + || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) + == void_type_node))) + return size; + } + + /* Lose any fake structure return argument. */ + if (aggregate_value_p (TREE_TYPE (funtype))) + return GET_MODE_SIZE (Pmode); + return 0; - - /* Cdecl functions override -mrtd, and never pop the stack */ - if (lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) - return 0; - - /* 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 (aggregate_value_p (TREE_TYPE (funtype))) - return GET_MODE_SIZE (Pmode); - } - - return 0; } @@ -416,7 +636,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 +647,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 +664,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 +677,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 +702,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 +745,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: @@ -548,7 +768,7 @@ function_arg (cum, mode, type, named) 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) @@ -575,7 +795,6 @@ function_arg_partial_nregs (cum, mode, type, named) { 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 +828,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); output_asm_insn (AS1 (push%L0,%0), &high); } + 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,19 +850,25 @@ 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) { @@ -651,6 +877,7 @@ output_to_reg (dest, dies) else output_asm_insn (AS1 (fist%z3,%y0), xops); } + else if (GET_MODE_CLASS (GET_MODE (dest)) == MODE_FLOAT) { if (dies) @@ -666,19 +893,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); + 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); + 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 +942,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 +974,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 +994,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 +1005,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. */ @@ -918,8 +1161,11 @@ 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); else if (optype0 == OFFSOP) @@ -960,13 +1206,12 @@ 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]); middlehalf[1] = adj_offsettable_operand (operands[1], size-8); latehalf[1] = adj_offsettable_operand (operands[1], size-4); @@ -977,17 +1222,18 @@ compadr: 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 +1241,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 +1256,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 +1280,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 +1329,6 @@ compadr: return ""; } - #define MAX_TMPS 2 /* max temporary registers used */ @@ -1095,13 +1342,13 @@ 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; int offset = 0; @@ -1110,7 +1357,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 +1393,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 +1410,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 +1421,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 +1441,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 +1452,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 +1461,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 +1486,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 +1529,6 @@ output_move_memory (operands, insn, length, tmp_start, n_operands) return ""; } - int standard_80387_constant_p (x) @@ -1289,7 +1544,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 +1576,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 +1588,7 @@ output_move_const_single (operands) REAL_VALUE_TO_TARGET_SINGLE (r, l); operands[1] = GEN_INT (l); } + return singlemove_string (operands); } @@ -1348,11 +1605,13 @@ symbolic_operand (op, mode) 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; } @@ -1374,9 +1633,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; } @@ -1392,9 +1652,10 @@ expander_call_insn_operand (op, mode) && (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,6 +1671,7 @@ 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; @@ -1440,6 +1702,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,7 +1710,197 @@ symbolic_reference_mentioned_p (op) return 0; } -/* This function generates the assembly code for function entry. +/* 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. */ + +int +ix86_expand_binary_operator (code, mode, operands) + enum rtx_code code; + enum machine_mode mode; + rtx operands[]; +{ + rtx insn; + int i; + int modified; + + /* Recognize <var1> = <value> <op> <var1> for commutative operators */ + if (GET_RTX_CLASS (code) == 'c' + && (rtx_equal_p (operands[0], operands[2]) + || immediate_operand (operands[1], mode))) + { + rtx temp = operands[1]; + operands[1] = operands[2]; + operands[2] = temp; + } + + /* 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]); + + if (GET_CODE (operands[2]) == MEM) + operands[2] = force_reg (GET_MODE (operands[2]), operands[2]); + + if (GET_CODE (operands[1]) == CONST_INT && code == MINUS) + { + rtx temp = gen_reg_rtx (GET_MODE (operands[0])); + + emit_move_insn (temp, operands[1]); + operands[1] = temp; + return TRUE; + } + } + + 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 ((! 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; + } + + if (GET_CODE (operands[2]) == MEM) + { + operands[2] = force_reg (GET_MODE (operands[2]), operands[2]); + modified = TRUE; + } + + if (GET_CODE (operands[1]) == CONST_INT && code == MINUS) + { + rtx temp = gen_reg_rtx (GET_MODE (operands[0])); + + 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; + 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[]; +{ + rtx insn; + + /* 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; + enum machine_mode mode; + rtx operands[2]; +{ + 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 + with the return address of the caller and then returns. */ + +void +asm_output_function_prefix (file, name) + FILE *file; + char *name; +{ + 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 (); + sprintf (pic_label_name, "LPR%d", pic_label_no++); + LABEL_NAME (pic_label_rtx) = pic_label_name; + } + + prologue_node = make_node (FUNCTION_DECL); + DECL_RESULT (prologue_node) = 0; +#ifdef ASM_DECLARE_FUNCTION_NAME + ASM_DECLARE_FUNCTION_NAME (file, pic_label_name, prologue_node); +#endif + 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. */ @@ -1456,23 +1909,188 @@ function_prologue (file, size) FILE *file; int size; { + 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 (); + sprintf (pic_label_name, "LPR%d", 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,%P1), 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 (size); + xops[2] = GEN_INT (tsize); + if (frame_pointer_needed) { - output_asm_insn ("push%L1 %1", xops); - output_asm_insn (AS2 (mov%L0,%0,%1), xops); + 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 (size) - output_asm_insn (AS2 (sub%L0,%2,%0), xops); + 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!! @@ -1483,39 +2101,69 @@ function_prologue (file, size) 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 (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) - { - xops[0] = pic_offset_table_rtx; - xops[1] = (rtx) gen_label_rtx (); - - 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); - } + 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. + 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. */ + 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 -simple_386_epilogue () +ix86_can_use_return_insn_p () { int regno; int nregs = 0; @@ -1540,7 +2188,6 @@ 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. */ @@ -1550,18 +2197,32 @@ function_epilogue (file, size) FILE *file; int size; { + 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; int offset; 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,25 +2231,37 @@ 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++) @@ -1596,9 +2269,14 @@ function_epilogue (file, size) || (regno == PIC_OFFSET_TABLE_REGNUM && pic_reg_used)) { xops[0] = gen_rtx (REG, SImode, regno); - output_asm_insn ("pop%L0 %0", xops); + + 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]) @@ -1606,30 +2284,62 @@ function_epilogue (file, size) { 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. */ + xops[0] = GEN_INT (tsize); - xops[0] = GEN_INT (size); - output_asm_insn (AS2 (add%L2,%0,%2), xops); + 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); + } + +#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) { @@ -1643,17 +2353,37 @@ function_epilogue (file, size) { /* ??? 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); + + 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 + { + if (do_rtl) + emit_jump_insn (gen_return_pop_internal (xops[1])); + else + output_asm_insn ("ret %1", xops); } - 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 +2433,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 +2453,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 +2470,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 +2486,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 +2500,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 +2516,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 +2530,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 +2551,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 +2580,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 +2628,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. @@ -1934,14 +2678,14 @@ legitimize_pic_address (orig, reg) 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)); + 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,12 +2715,12 @@ 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 @@ -1987,11 +2731,10 @@ emit_pic_move (operands, mode) 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. @@ -2025,7 +2768,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 +2782,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 +2810,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,11 +2827,13 @@ 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 @@ -2173,7 +2919,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 @@ -2253,20 +2998,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 +3026,132 @@ 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: + fputs ("ge", file); + return; + + case GT: + fputs ("g", file); + return; + + case LE: + fputs ("le", file); + return; + + case LT: + 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) @@ -2406,6 +3267,33 @@ print_operand (file, x, code) } 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: { char str[50]; @@ -2415,10 +3303,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,25 +3322,34 @@ 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); } + /* 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); @@ -2507,38 +3406,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 +3455,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 +3487,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 +3498,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; @@ -2645,6 +3541,7 @@ 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. @@ -2656,29 +3553,37 @@ notice_update_cc (exp) 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 +3591,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 +3606,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. */ @@ -2725,14 +3631,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 (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 @@ -2761,9 +3674,7 @@ split_di (operands, num, lo_half, hi_half) hi_half[num] = gen_rtx (REG, SImode, REGNO (operands[num]) + 1); } else if (CONSTANT_P (operands[num])) - { - split_double (operands[num], &lo_half[num], &hi_half[num]); - } + split_double (operands[num], &lo_half[num], &hi_half[num]); else if (offsettable_memref_p (operands[num])) { lo_half[num] = operands[num]; @@ -2797,7 +3708,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. */ @@ -2908,12 +3818,13 @@ 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]))) @@ -2935,12 +3846,13 @@ 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])) @@ -2983,8 +3895,8 @@ 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]) + || (GET_MODE (operands[0]) == DImode && ! stack_top_dies)) abort (); xops[0] = GEN_INT (12); @@ -2997,7 +3909,8 @@ 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) @@ -3024,7 +3937,22 @@ 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 (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 +3968,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 +3998,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 +4011,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); } @@ -3092,7 +4043,32 @@ output_fp_cc0_set (insn) 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,12 +4078,22 @@ 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 (); @@ -3168,7 +4154,8 @@ output_fp_cc0_set (insn) default: abort (); } - RET; + + return ""; } #define MAX_386_STACK_LOCALS 2 @@ -3243,3 +4230,810 @@ 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; +{ + return (GET_CODE (op) == MULT); +} + +int is_div(op,mode) + register rtx op; + enum machine_mode mode; +{ + 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; +{ + 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 (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; + } + + 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 ""; +} diff --git a/gnu/usr.bin/gcc/config/i386/i386.h b/gnu/usr.bin/gcc/config/i386/i386.h index b00b0e509c5..6fb08a120d2 100644 --- a/gnu/usr.bin/gcc/config/i386/i386.h +++ b/gnu/usr.bin/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, 1997 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,77 @@ extern int target_flags; #define SUBTARGET_SWITCHES #define SUBTARGET_OPTIONS +/* Define this to change the optimizations performed by default. */ +#define OPTIMIZATION_OPTIONS(LEVEL) optimization_options(LEVEL) + +/* 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 + +#ifndef CPP_CPU_SPEC +#ifdef __STDC__ +#if TARGET_CPU_DEFAULT == 1 +#define CPP_CPU_DEFAULT "-Di486" +#else +#if TARGET_CPU_DEFAULT == 2 +#define CPP_CPU_DEFAULT "-Di586" +#else +#if TARGET_CPU_DEFAULT == 3 +#define CPP_CPU_DEFAULT "-Di686" +#else +#define CPP_CPU_DEFAULT "" +#endif +#endif +#endif /* TARGET_CPU_DEFAULT */ + +#define CPP_CPU_SPEC "\ +-Di386 " CPP_CPU_DEFAULT " -Asystem(unix) -Acpu(i386) -Amachine(i386) \ +%{mcpu=i486:-Di486} %{m486:-Di486} \ +%{mpentium:-Dpentium -Di586} %{mcpu=pentium:-Dpentium -Di586} \ +%{mpentiumpro:-Dpentiumpro -Di686} %{mcpu=pentiumpro:-Dpentiumpro -Di686}" + +#else +#define CPP_CPU_SPEC "\ +-Di386 -Asystem(unix) -Acpu(i386) -Amachine(i386) \ +%{mcpu=i486:-Di486} %{m486:-Di486} \ +%{mpentium:-Dpentium -Di586} %{mcpu=pentium:-Dpentium -Di586} \ +%{mpentiumpro:-Dpentiumpro -Di686} %{mcpu=pentiumpro:-Dpentiumpro -Di686}" +#endif /* __STDC__ */ +#endif /* CPP_CPU_SPEC */ + +#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_cpu", CPP_CPU_SPEC }, \ + { "cc1_cpu", CC1_CPU_SPEC }, \ + SUBTARGET_EXTRA_SPECS /* target machine storage layout */ @@ -265,6 +424,9 @@ extern int target_flags; aligned on 64 bit boundaries. */ #define BIGGEST_ALIGNMENT (TARGET_ALIGN_DOUBLE ? 64 : 32) +/* align DFmode constants and nonaggregates */ +#define ALIGN_DFmode (!TARGET_386) + /* Set this non-zero if move instructions will actually fail to work when given unaligned data. */ #define STRICT_ALIGNMENT 0 @@ -274,6 +436,12 @@ extern int target_flags; /* Required on the 386 since it doesn't have bitfield insns. */ #define PCC_BITFIELD_TYPE_MATTERS 1 +/* An integer expression for the size in bits of the largest integer + machine mode that should actually be used. All integer machine modes of + this size or smaller can be used for structures and unions with the + appropriate sizes. */ +#define MAX_FIXED_MODE_SIZE 32 + /* Maximum power of 2 that code can be aligned to. */ #define MAX_CODE_ALIGN 6 /* 64 byte alignment */ @@ -292,6 +460,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 @@ -414,8 +583,9 @@ extern int target_flags; : 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. @@ -424,17 +594,6 @@ extern int target_flags; #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) - /* Specify the registers used for certain standard purposes. The values of these macros are register numbers. */ @@ -459,7 +618,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 @@ -567,7 +726,7 @@ enum reg_class 0x3, /* AD_REGS */ \ 0xf, /* Q_REGS */ \ 0x10, 0x20, /* SIREG, DIREG */ \ - 0x07f, /* INDEX_REGS */ \ + 0x7f, /* INDEX_REGS */ \ 0x100ff, /* GENERAL_REGS */ \ 0x0100, 0x0200, /* FP_TOP_REG, FP_SECOND_REG */ \ 0xff00, /* FLOAT_REGS */ \ @@ -584,7 +743,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,6 +817,7 @@ 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. @@ -825,7 +985,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 +1018,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 +1055,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 +1150,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[5] = stack_pointer_rtx; \ - xops[6] = GEN_INT (4); \ 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 +1433,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. */ @@ -1094,8 +1524,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 (); \ @@ -1245,6 +1676,8 @@ do { \ 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 +1712,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 = %s\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)); \ @@ -1369,22 +1811,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 +1854,192 @@ 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: \ 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); \ + else \ + 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 +2052,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) 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 +2271,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 +2283,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. @@ -1609,6 +2369,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. */ @@ -1698,13 +2474,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. */ @@ -1853,13 +2629,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)) +/* 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 +2661,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 +2674,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 +2700,37 @@ 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 (); + +#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=<xxx> */ +extern char *ix86_arch_string; /* for -march=<xxx> */ 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 +2739,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/gnu/usr.bin/gcc/config/i386/i386.md b/gnu/usr.bin/gcc/config/i386/i386.md index ff0119631cb..ea72a98a65e 100644 --- a/gnu/usr.bin/gcc/config/i386/i386.md +++ b/gnu/usr.bin/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, 1994, 1995, 1996, 1997 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,71 @@ ;; 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. + +;; 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 +136,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"))] @@ -228,7 +298,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" @@ -346,11 +416,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 "" @@ -386,6 +455,16 @@ (define_insn "" [(set (cc0) (match_operator 2 "VOIDmode_compare_op" + [(float_extend:XF + (match_operand:DF 1 "nonimmediate_operand" "fm")) + (match_operand:XF 0 "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" [(match_operand:XF 0 "register_operand" "f") (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm"))])) @@ -453,6 +532,16 @@ (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") (match_operand:DF 1 "register_operand" "f"))) (clobber (match_scratch:HI 2 "=a"))] @@ -520,7 +609,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 +623,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 +664,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 +711,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 +769,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 +802,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 +816,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")))] "" "* { @@ -742,22 +835,22 @@ (define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") (match_operand:SI 1 "general_operand" "g"))] - "TARGET_386" + "TARGET_PUSH_MEMORY" "push%L0 %1") -;; On a 486, it is faster to move MEM to a REG and then push, rather than +;; If not a 386, it is faster to move MEM to a REG and then push, rather than ;; push MEM directly. (define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") (match_operand:SI 1 "nonmemory_operand" "ri"))] - "!TARGET_386 && TARGET_MOVE" + "!TARGET_PUSH_MEMORY && TARGET_MOVE" "push%L0 %1") (define_insn "" [(set (match_operand:SI 0 "push_operand" "=<") - (match_operand:SI 1 "general_operand" "ri"))] - "!TARGET_386 && !TARGET_MOVE" + (match_operand:SI 1 "nonmemory_operand" "ri"))] + "!TARGET_PUSH_MEMORY && !TARGET_MOVE" "push%L0 %1") ;; General case of fullword move. @@ -819,19 +912,19 @@ (define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") (match_operand:HI 1 "general_operand" "g"))] - "TARGET_386" + "TARGET_PUSH_MEMORY" "push%W0 %1") (define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") (match_operand:HI 1 "nonmemory_operand" "ri"))] - "!TARGET_386 && TARGET_MOVE" + "!TARGET_PUSH_MEMORY && TARGET_MOVE" "push%W0 %1") (define_insn "" [(set (match_operand:HI 0 "push_operand" "=<") - (match_operand:HI 1 "general_operand" "ri"))] - "!TARGET_386 && !TARGET_MOVE" + (match_operand:HI 1 "nonmemory_operand" "ri"))] + "!TARGET_PUSH_MEMORY && !TARGET_MOVE" "push%W0 %1") ;; On i486, an incl and movl are both faster than incw and movw. @@ -876,10 +969,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,13 +1036,13 @@ ;; 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"))] + (match_operand:QI 1 "register_operand" "q"))] "!TARGET_MOVE" "* { @@ -978,14 +1082,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,r,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)) @@ -1032,7 +1136,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)" "* @@ -1083,16 +1187,28 @@ 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 + /* 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 ((reload_in_progress | reload_completed) == 0 && GET_CODE (operands[0]) != MEM && GET_CODE (operands[1]) == CONST_DOUBLE && !standard_80387_constant_p (operands[1])) { - current_function_uses_pic_offset_table = 1; + rtx insn, note, fp_const; + + fp_const = force_const_mem (SFmode, operands[1]); + if (flag_pic) + current_function_uses_pic_offset_table = 1; + + insn = emit_insn (gen_rtx (SET, SFmode, operands[0], fp_const)); + note = find_reg_note (insn, REG_EQUAL, NULL_RTX); + + if (note) + XEXP (note, 0) = operands[1]; + else + REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1], REG_NOTES (insn)); } }") @@ -1176,7 +1292,7 @@ ;; For the purposes of regclass, prefer FLOAT_REGS. (define_insn "movsf_normal" - [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm") + [(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 +1319,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 +1344,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") @@ -1264,16 +1382,28 @@ 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 + /* 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 ((reload_in_progress | reload_completed) == 0 && GET_CODE (operands[0]) != MEM && GET_CODE (operands[1]) == CONST_DOUBLE && !standard_80387_constant_p (operands[1])) { - current_function_uses_pic_offset_table = 1; + rtx insn, note, fp_const; + + fp_const = force_const_mem (DFmode, operands[1]); + if (flag_pic) + current_function_uses_pic_offset_table = 1; + + insn = emit_insn (gen_rtx (SET, DFmode, operands[0], fp_const)); + note = find_reg_note (insn, REG_EQUAL, NULL_RTX); + + if (note) + XEXP (note, 0) = operands[1]; + else + REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1], REG_NOTES (insn)); } }") @@ -1346,10 +1476,11 @@ "* 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 +1505,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 +1530,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") @@ -1435,16 +1569,28 @@ 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 + /* 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 ((reload_in_progress | reload_completed) == 0 && GET_CODE (operands[0]) != MEM && GET_CODE (operands[1]) == CONST_DOUBLE && !standard_80387_constant_p (operands[1])) { - current_function_uses_pic_offset_table = 1; + rtx insn, note, fp_const; + + fp_const = force_const_mem (XFmode, operands[1]); + if (flag_pic) + current_function_uses_pic_offset_table = 1; + + insn = emit_insn (gen_rtx (SET, XFmode, operands[0], fp_const)); + note = find_reg_note (insn, REG_EQUAL, NULL_RTX); + + if (note) + XEXP (note, 0) = operands[1]; + else + REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1], REG_NOTES (insn)); } }") @@ -1514,10 +1660,11 @@ "" "* 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 +1689,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 +1717,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) @@ -1623,21 +1770,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_rtx (CONST_INT, VOIDmode, 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 +1811,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_rtx (CONST_INT, VOIDmode, 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,22 +1874,89 @@ #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])) { - 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,%0,%0),operands); + output_asm_insn (AS2 (mov%B0,%1,%b0),operands); + } + else + { + xops[0] = operands[0]; + xops[1] = gen_rtx (CONST_INT, VOIDmode, 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) + { + xops[0] = operands[0]; + xops[1] = gen_rtx (CONST_INT, VOIDmode, 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; + } #ifdef INTEL_SYNTAX return AS2 (movzx,%1,%0); @@ -1694,23 +1965,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")))] "" "* { @@ -1736,9 +2061,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 +2082,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 +2099,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 +2110,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 +2189,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 +2208,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 +2224,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 +2243,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 +2259,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 +2320,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 +2335,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 +2353,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 +2368,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 +2410,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 +2431,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 +2452,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 +2472,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 +2490,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 +2508,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") + [(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") + [(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") + [(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 +2556,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 +2570,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 +2584,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 +2652,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 +2727,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 +2761,137 @@ ;;- add instructions +(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"))] + "" + "* +{ + rtx low[3], high[3], xops[7], temp; + + 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 (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 "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"))] + "" + "* +{ + rtx low[3], high[3], xops[7], temp; + + 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) + { + 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,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"))] + [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,!&r,!o,!o") + (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0iF,or,riF,o") + (match_operand:DI 2 "general_operand" "o,riF,or,or,oriF,o"))) + (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r"))] "" "* { @@ -2456,14 +2963,23 @@ ;; 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_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]) && REGNO (operands[0]) != REGNO (operands[1])) + 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); @@ -2483,34 +2999,85 @@ operands[1] = SET_SRC (PATTERN (insn)); return AS2 (lea%L0,%a1,%0); } - - output_asm_insn (AS2 (mov%L0,%1,%0), operands); } + 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 +3091,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 +3124,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 +3159,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")))] ; "" ; "* ;{ @@ -2578,40 +3174,12 @@ ; 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 +3199,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 +3314,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 +3393,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 +3412,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 +3428,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 +3470,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 +3480,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 +3509,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 +3551,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 +3563,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 +3588,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 +3603,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 +3612,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 +3637,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])) + { + rtx tmp; + tmp = operands[1]; + operands[1] = operands[2]; + operands[2] = tmp; + } + switch (GET_CODE (operands[2])) { - if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0]) + 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 +3675,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 +3692,107 @@ #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; + } } 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 +3831,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 +3889,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,37 +3901,87 @@ ;;- 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; + + 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); - return AS2 (or%B0,%2,%b0); + 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); + } - return AS2 (or%B0,%2,%h0); + operands[0] = adj_offsettable_operand (operands[0], 1); + goto byte_or_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_or_operation; + } + + /* fourth byte? */ + if ((intval & ~0xff000000) == 0) + { + intval = (intval >> 24) & 0xff; + operands[0] = adj_offsettable_operand (operands[0], 3); + goto byte_or_operation; } } @@ -3186,87 +3989,172 @@ }") (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; + + if (intval == 0xff) + return AS2 (mov%B0,%2,%b0); - return AS2 (or%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); + } + + operands[0] = adj_offsettable_operand (operands[0], 1); - return AS2 (or%B0,%2,%h0); + goto byte_or_operation; } } + 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; } } @@ -3274,8 +4162,8 @@ }") (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")))] "" "* @@ -3312,12 +4200,31 @@ } } + 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 "general_operand" "=qm,q") - (xor:QI (match_operand:QI 1 "general_operand" "%0,0") + [(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);") @@ -3345,50 +4252,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 +4303,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 +4352,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 +4366,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 +4465,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 +4495,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,34 +4530,28 @@ (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]; + static HOST_WIDE_INT ashldi_label_number; 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); - 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); + asm_fprintf (asm_out_file, \"\\tje %LLASHLDI%d\\n\", ashldi_label_number); + output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */ + output_asm_insn (AS2 (xor%L2,%2,%2), xops); + asm_fprintf (asm_out_file, \"%LLASHLDI%d:\\n\", ashldi_label_number++); RET; }") @@ -3668,15 +4561,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); @@ -3706,8 +4599,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 +4615,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 +4652,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 +4718,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]; + static HOST_WIDE_INT ashrdi_label_number; 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); - 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); + asm_fprintf (asm_out_file, \"\\tje %LLASHRDI%d\\n\", ashrdi_label_number); + 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_fprintf (asm_out_file, \"%LLASHRDI%d:\\n\", ashrdi_label_number++); 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 +4759,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 +4772,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 +4808,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 +4873,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]; + static HOST_WIDE_INT lshrdi_label_number; 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); - 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); + asm_fprintf (asm_out_file, \"\\tje %LLLSHRDI%d\\n\", lshrdi_label_number); + output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */ + output_asm_insn (AS2 (xor%L3,%3,%3), xops); + asm_fprintf (asm_out_file, \"%LLLSHRDI%d:\\n\", lshrdi_label_number++); 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 +4913,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 +4926,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 +4941,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 +4954,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 +4967,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 +4980,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 +4993,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 +5006,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 +5022,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"))] "" "* { @@ -4130,7 +5064,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 +5077,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 +5091,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 +5109,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 +5122,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 +5147,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 +5190,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 +5321,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 +5354,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 +5387,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 +5420,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 +5475,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 +5515,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 +5545,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 +5597,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 +5649,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 +5700,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 +5747,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 +5769,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 +5788,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 +5819,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 +5851,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 +5882,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 +5914,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 +5942,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 +5957,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 +5969,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 +5993,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 +6104,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 +6119,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; }") @@ -5066,7 +6186,7 @@ }") (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,6 +6432,7 @@ 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) @@ -5344,19 +6465,148 @@ ;; This is only done if the function's epilogue is known to be simple. ;; See comments for simple_386_epilogue in i386.c. -(define_insn "return" +(define_expand "return" [(return)] - "simple_386_epilogue ()" + "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))] + "" "* { - function_epilogue (asm_out_file, get_frame_size ()); + rtx xops [2]; + + xops[0] = operands[0]; + xops[1] = stack_pointer_rtx; + output_asm_insn (AS2 (sub%L1,%0,%1), xops); RET; }") -(define_insn "nop" - [(const_int 0)] +(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))] "" - "nop") + "* +{ + 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+[.-%%P2],%%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,%P1), operands); + if (! TARGET_DEEP_BRANCH_PREDICTION) + { + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (operands[1])); + } + RET; +}") + +(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,%P1), 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_+[.-%P1],%0\", operands); + RET; +}") + +(define_expand "epilogue" + [(const_int 1)] + "" + " +{ + ix86_expand_epilogue (); + DONE; +}") + +(define_insn "epilogue_set_stack_ptr" + [(set (reg:SI 7) (reg:SI 6)) + (clobber (reg:SI 6))] + "" + "* +{ + 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 "leave" + [(const_int 2) + (clobber (reg:SI 6)) + (clobber (reg:SI 7))] + "" + "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 +6630,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 +6676,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" "") @@ -5464,7 +6781,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 +6792,7 @@ "" "* { - rtx xops[4], label; + rtx xops[2], label; label = gen_label_rtx (); @@ -5485,16 +6802,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; }") @@ -5523,6 +6837,7 @@ return \"repz\;cmps%B2\"; }") + (define_expand "ffssi2" [(set (match_dup 2) (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "")) @@ -5537,8 +6852,8 @@ ;; 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")) + [(set (match_operand:SI 0 "register_operand" "=&r") + (plus:SI (ffs:SI (match_operand:SI 1 "nonimmediate_operand" "rm")) (const_int -1)))] "" "* @@ -5570,6 +6885,7 @@ output_asm_insn (buffer, xops); ffssi_label_number++; + CC_STATUS_INIT; return \"\"; }") @@ -5583,8 +6899,8 @@ "operands[2] = gen_reg_rtx (HImode);") (define_insn "" - [(set (match_operand:HI 0 "general_operand" "=&r") - (plus:HI (ffs:HI (match_operand:SI 1 "general_operand" "rm")) + [(set (match_operand:HI 0 "register_operand" "=&r") + (plus:HI (ffs:HI (match_operand:SI 1 "nonimmediate_operand" "rm")) (const_int -1)))] "" "* @@ -5616,6 +6932,7 @@ output_asm_insn (buffer, xops); ffshi_label_number++; + CC_STATUS_INIT; return \"\"; }") @@ -5633,81 +6950,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 +7122,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 +7234,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 +7248,454 @@ output_asm_insn (AS2 (mov%L0,%1,%0), xops); return \"repnz\;scas%B2\"; }") + +/* Conditional move define_insns. */ + +(define_expand "movsicc" + [(match_dup 4) + (parallel [(set (match_operand 0 "register_operand" "") + (if_then_else:SI (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "general_operand" "") + (match_operand:SI 3 "general_operand" ""))) + (clobber (match_scratch:SI 4 "=&r"))])] + "TARGET_CMOVE" + " +{ + operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1); +}") + +(define_expand "movhicc" + [(match_dup 4) + (parallel [(set (match_operand 0 "register_operand" "") + (if_then_else:HI (match_operand 1 "comparison_operator" "") + (match_operand:HI 2 "general_operand" "") + (match_operand:HI 3 "general_operand" ""))) + (clobber (match_scratch:SI 4 "=&r"))])] + "TARGET_CMOVE" + " +{ + operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1); +}") + +(define_insn "movsicc_1" + [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,&r,rm") + (if_then_else:SI (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SI 2 "general_operand" "rm,0,rm,g") + (match_operand:SI 3 "general_operand" "0,rm,rm,g"))) + (clobber (match_scratch:SI 4 "X,X,X,=&r"))] + "TARGET_CMOVE" + "* +{ + if (which_alternative == 0) + { + /* r <- cond ? arg : r */ + output_asm_insn (AS2 (cmov%C1,%2,%0), operands); + } + else if (which_alternative == 1) + { + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (cmov%c1,%3,%0), operands); + } + else if (which_alternative == 2) + { + /* r <- cond ? arg1 : arg2 */ + output_asm_insn (AS2 (cmov%C1,%2,%0), operands); + output_asm_insn (AS2 (cmov%c1,%3,%0), operands); + } + else if (which_alternative == 3) + { + /* r <- cond ? arg1 : arg2 */ + rtx xops[3]; + + xops[0] = gen_label_rtx (); + xops[1] = gen_label_rtx (); + xops[2] = operands[1]; + + output_asm_insn (\"j%c2 %l0\", xops); + if (! rtx_equal_p (operands[0], operands[2])) + if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM) + { + output_asm_insn (AS2 (mov%z2,%2,%4), operands); + output_asm_insn (AS2 (mov%z2,%4,%0), operands); + } + else + output_asm_insn (AS2 (mov%z0,%2,%0), operands); + output_asm_insn (\"jmp %l1\", xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0])); + if (! rtx_equal_p (operands[0], operands[3])) + { + if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM) + { + output_asm_insn (AS2 (mov%z2,%3,%4), operands); + output_asm_insn (AS2 (mov%z2,%4,%0), operands); + } + else + output_asm_insn (AS2 (mov%z0,%3,%0), operands); + } + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1])); + } + RET; +}") + +(define_insn "movhicc_1" + [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,&r,rm") + (if_then_else:HI (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:HI 2 "general_operand" "rm,0,rm,g") + (match_operand:HI 3 "general_operand" "0,rm,rm,g"))) + (clobber (match_scratch:SI 4 "X,X,X,=&r"))] + "TARGET_CMOVE" + "* +{ + if (which_alternative == 0) + { + /* r <- cond ? arg : r */ + output_asm_insn (AS2 (cmov%C1,%2,%0), operands); + } + else if (which_alternative == 1) + { + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (cmov%c1,%3,%0), operands); + } + else if (which_alternative == 2) + { + /* r <- cond ? arg1 : arg2 */ + output_asm_insn (AS2 (cmov%C1,%2,%0), operands); + output_asm_insn (AS2 (cmov%c1,%3,%0), operands); + } + else if (which_alternative == 3) + { + /* r <- cond ? arg1 : arg2 */ + rtx xops[3]; + + xops[0] = gen_label_rtx (); + xops[1] = gen_label_rtx (); + xops[2] = operands[1]; + + output_asm_insn (\"j%c2 %l0\", xops); + if (! rtx_equal_p (operands[0], operands[2])) + if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM) + { + output_asm_insn (AS2 (mov%z2,%2,%4), operands); + output_asm_insn (AS2 (mov%z2,%4,%0), operands); + } + else + output_asm_insn (AS2 (mov%z0,%2,%0), operands); + output_asm_insn (\"jmp %l1\", xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0])); + if (! rtx_equal_p (operands[0], operands[3])) + { + if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM) + { + output_asm_insn (AS2 (mov%z2,%3,%4), operands); + output_asm_insn (AS2 (mov%z2,%4,%0), operands); + } + else + output_asm_insn (AS2 (mov%z0,%3,%0), operands); + } + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1])); + } + RET; +}") + +(define_expand "movsfcc" + [(match_dup 4) + (set (match_operand 0 "general_operand" "") + (if_then_else:SF (match_operand 1 "comparison_operator" "") + (match_operand:SF 2 "general_operand" "") + (match_operand:SF 3 "general_operand" "")))] + "TARGET_CMOVE" + " +{ + int i; + + for (i = 2; i <= 3; i++) + { + if ((reload_in_progress | reload_completed) == 0 + && CONSTANT_P (operands[i])) + { + operands[i] = force_const_mem (SFmode, operands[i]); + } + } + operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1); +}") + +(define_expand "movdfcc" + [(match_dup 4) + (set (match_operand 0 "register_operand" "t") + (if_then_else:DF (match_operand 1 "comparison_operator" "") + (match_operand:DF 2 "general_operand" "") + (match_operand:DF 3 "general_operand" "")))] + "TARGET_CMOVE" + " +{ + int i; + + for (i = 2; i <= 3; i++) + { + if ((reload_in_progress | reload_completed) == 0 + && CONSTANT_P (operands[i])) + { + operands[i] = force_const_mem (DFmode, operands[i]); + } + } + operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1); +}") + +(define_expand "movxfcc" + [(match_dup 4) + (set (match_operand 0 "register_operand" "t") + (if_then_else:XF (match_operand 1 "comparison_operator" "") + (match_operand:XF 2 "general_operand" "") + (match_operand:XF 3 "general_operand" "")))] + "TARGET_CMOVE" + " +{ + int i; + + for (i = 2; i <= 3; i++) + { + if ((reload_in_progress | reload_completed) == 0 + && CONSTANT_P (operands[i])) + { + operands[i] = force_const_mem (XFmode, operands[i]); + } + } + operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1); +}") + +(define_insn "movsfcc_1" + [(set (match_operand:SF 0 "general_operand" "=f,=f,=f,=f") + (if_then_else:SF (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:SF 2 "general_operand" "0,f,f,fFm") + (match_operand:SF 3 "general_operand" "f,0,f,fFm")))] + "TARGET_CMOVE" + "* +{ + if (which_alternative == 0) + { + /* r <- cond ? arg : r */ + output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); + } + else if (which_alternative == 1) + { + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); + } + else if (which_alternative == 2) + { + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); + output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); + } + else if (which_alternative == 3) + { + /* r <- cond ? arg1 : arg2 */ + rtx xops[3]; + + xops[0] = gen_label_rtx (); + xops[1] = gen_label_rtx (); + xops[2] = operands[1]; + + output_asm_insn (\"j%f2 %l0\", xops); + if (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM) + output_asm_insn (AS1 (fld%z2,%y2), operands); + else + { + operands[2] = XEXP (operands[2], 0); + output_asm_insn (AS1 (fld%z2,%y2), operands); + } + output_asm_insn (\"jmp %l1\", xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0])); + if (STACK_REG_P (operands[3]) || GET_CODE (operands[0]) == MEM) + output_asm_insn (AS1 (fld%z3,%y3), operands); + else + { + operands[3] = XEXP (operands[3], 0); + output_asm_insn (AS1 (fld%z3,%y3), operands); + } + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1])); +} + RET; +}") + +(define_insn "movdfcc_1" + [(set (match_operand:DF 0 "general_operand" "=f,=f,=f,=f") + (if_then_else:DF (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:DF 2 "general_operand" "0,f,f,fFm") + (match_operand:DF 3 "general_operand" "f,0,f,fFm")))] + "TARGET_CMOVE" + "* +{ + if (which_alternative == 0) + { + /* r <- cond ? arg : r */ + output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); + } + else if (which_alternative == 1) + { + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); + } + else if (which_alternative == 2) + { + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); + output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); + } + else if (which_alternative == 3) + { + /* r <- cond ? arg1 : arg2 */ + rtx xops[3]; + + xops[0] = gen_label_rtx (); + xops[1] = gen_label_rtx (); + xops[2] = operands[1]; + + output_asm_insn (\"j%f2 %l0\", xops); + if (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM) + output_asm_insn (AS1 (fld%z2,%y2), operands); + else + { + operands[2] = XEXP (operands[2], 0); + output_asm_insn (AS1 (fld%z2,%y2), operands); + } + output_asm_insn (\"jmp %l1\", xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0])); + if (STACK_REG_P (operands[3]) || GET_CODE (operands[0]) == MEM) + output_asm_insn (AS1 (fld%z3,%y3), operands); + else + { + operands[3] = XEXP (operands[3], 0); + output_asm_insn (AS1 (fld%z3,%y3), operands); + } + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1])); +} + RET; +}") + +(define_insn "movxfcc_1" + [(set (match_operand:XF 0 "register_operand" "=f,=f,=f,=f") + (if_then_else:XF (match_operator 1 "comparison_operator" + [(cc0) (const_int 0)]) + (match_operand:XF 2 "register_operand" "0,f,f,fFm") + (match_operand:XF 3 "register_operand" "f,0,f,fFm")))] + "TARGET_CMOVE" + "* +{ + if (which_alternative == 0) + { + /* r <- cond ? arg : r */ + output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); + } + else if (which_alternative == 1) + { + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); + } + else if (which_alternative == 2) + { + /* r <- cond ? r : arg */ + output_asm_insn (AS2 (fcmov%F1,%2,%0), operands); + output_asm_insn (AS2 (fcmov%f1,%3,%0), operands); + } + else if (which_alternative == 3) + { + /* r <- cond ? arg1 : arg2 */ + rtx xops[3]; + + xops[0] = gen_label_rtx (); + xops[1] = gen_label_rtx (); + xops[2] = operands[1]; + + output_asm_insn (\"j%f2 %l0\", xops); + if (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM) + output_asm_insn (AS1 (fld%z2,%y2), operands); + else + { + operands[2] = XEXP (operands[2], 0); + output_asm_insn (AS1 (fld%z2,%y2), operands); + } + output_asm_insn (\"jmp %l1\", xops); + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0])); + if (STACK_REG_P (operands[3]) || GET_CODE (operands[0]) == MEM) + output_asm_insn (AS1 (fld%z3,%y3), operands); + else + { + operands[3] = XEXP (operands[3], 0); + output_asm_insn (AS1 (fld%z3,%y3), operands); + } + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1])); +} + RET; +}") + +(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 "nonlocal_goto_receiver" + [(const_int 0)] + "flag_pic" + " +{ + load_pic_register (1); + DONE; +}") diff --git a/gnu/usr.bin/gcc/config/i386/isc.h b/gnu/usr.bin/gcc/config/i386/isc.h index cf8c5f69277..d0b2dcc7a55 100644 --- a/gnu/usr.bin/gcc/config/i386/isc.h +++ b/gnu/usr.bin/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) %[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/gnu/usr.bin/gcc/config/i386/linux-aout.h b/gnu/usr.bin/gcc/config/i386/linux-aout.h index 7e46c68b8ec..8bf3daa5613 100644 --- a/gnu/usr.bin/gcc/config/i386/linux-aout.h +++ b/gnu/usr.bin/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 Free Software Foundation, Inc. Contributed by H.J. Lu (hjl@nynexst.com) This file is part of GNU CC. @@ -28,14 +28,10 @@ Boston, MA 02111-1307, USA. */ /* 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) %[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 +53,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/gnu/usr.bin/gcc/config/i386/linux-oldld.h b/gnu/usr.bin/gcc/config/i386/linux-oldld.h index c3066ba1333..9c6c21f79d4 100644 --- a/gnu/usr.bin/gcc/config/i386/linux-oldld.h +++ b/gnu/usr.bin/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 Free Software Foundation, Inc. Contributed by Michael Meissner (meissner@cygnus.com) This file is part of GNU CC. @@ -28,14 +29,10 @@ Boston, MA 02111-1307, USA. */ /* 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) %[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 +54,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/gnu/usr.bin/gcc/config/i386/linux.h b/gnu/usr.bin/gcc/config/i386/linux.h index f077de57efb..df27c603603 100644 --- a/gnu/usr.bin/gcc/config/i386/linux.h +++ b/gnu/usr.bin/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 Free Software Foundation, Inc. Contributed by Eric Youngdale. Modified for stabs-in-ELF by H.J. Lu. @@ -30,7 +30,7 @@ Boston, MA 02111-1307, USA. */ #include <linux.h> /* some common stuff */ #undef TARGET_VERSION -#define TARGET_VERSION fprintf (stderr, " (i386 Linux/ELF)"); +#define TARGET_VERSION fprintf (stderr, " (i386 GNU/Linux with ELF)"); /* The svr4 ABI for the i386 says that records and unions are returned in memory. */ @@ -148,32 +148,19 @@ Boston, MA 02111-1307, USA. */ #define WCHAR_TYPE_SIZE BITS_PER_WORD #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 -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}" +#ifdef USE_GNULIBC_1 +#define CPP_SPEC "%(cpp_cpu) %[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) %[cpp_cpu] %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}" #endif -#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 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 +#undef CC1_SPEC +#define CC1_SPEC "%(cc1_cpu) %{profile:-p}" -/* Provide a LINK_SPEC appropriate for Linux. Here we provide support +/* Provide a LINK_SPEC appropriate for GNU/Linux. 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 @@ -190,6 +177,7 @@ Boston, MA 02111-1307, USA. */ /* If ELF is the default format, we should not use /lib/elf. */ #undef LINK_SPEC +#ifdef USE_GNULIBC_1 #ifndef LINUX_DEFAULT_ELF #define LINK_SPEC "-m elf_i386 %{shared:-shared} \ %{!shared: \ @@ -207,6 +195,23 @@ Boston, MA 02111-1307, USA. */ %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \ %{static:-static}}}" #endif +#else +#define LINK_SPEC "-m elf_i386 %{shared:-shared} \ + %{!shared: \ + %{!ibcs: \ + %{!static: \ + %{rdynamic:-export-dynamic} \ + %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \ + %{static:-static}}}" +#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) diff --git a/gnu/usr.bin/gcc/config/i386/lynx.h b/gnu/usr.bin/gcc/config/i386/lynx.h index 4ac00a052ba..73111f916a5 100644 --- a/gnu/usr.bin/gcc/config/i386/lynx.h +++ b/gnu/usr.bin/gcc/config/i386/lynx.h @@ -1,5 +1,5 @@ /* Definitions for Intel 386 running LynxOS. - Copyright (C) 1993, 1995 Free Software Foundation, Inc. + Copyright (C) 1993, 1995, 1996 Free Software Foundation, Inc. This file is part of GNU CC. @@ -24,12 +24,12 @@ Boston, MA 02111-1307, USA. */ #undef CPP_PREDEFINES #define CPP_PREDEFINES "-Dunix -Di386 -DI386 -DLynx -DIBITS32 -Asystem(unix) -Asystem(lynx) -Acpu(i386) -Amachine(i386)" -/* This is how to output a reference to a user-level label named NAME. */ +/* The prefix to add to user-visible assembler symbols. */ /* Override the svr3 convention of adding a leading underscore. */ -#undef ASM_OUTPUT_LABELREF -#define ASM_OUTPUT_LABELREF(FILE,NAME) fprintf (FILE, "%s", NAME) +#undef USER_LABEL_PREFIX +#define USER_LABEL_PREFIX "" /* Apparently LynxOS clobbers ebx when you call into the OS. */ diff --git a/gnu/usr.bin/gcc/config/i386/mingw32.h b/gnu/usr.bin/gcc/config/i386/mingw32.h new file mode 100644 index 00000000000..984a3692c30 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/mingw32.h @@ -0,0 +1,93 @@ +/* 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. + Copyright (C) 1997 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. */ + +/* Most of this is the same as for Cygwin32, except for changing some + specs. */ + +#include "i386/cygwin32.h" + +#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__cdecl=__attribute__((__cdecl__)) \ + -Asystem(winnt) -Acpu(i386) -Amachine(i386)" + +/* Specific a different directory for the standard include files. */ +#undef STANDARD_INCLUDE_DIR +#define STANDARD_INCLUDE_DIR "/usr/mingw32/include" + +#define STANDARD_INCLUDE_COMPONENT "MINGW32" + +/* For Windows applications, include more libraries, but always include + kernel32. */ +#undef LIB_SPEC +#define LIB_SPEC \ +"%{mwindows:-luser32 -lgdi32 -lcomdlg32} -lkernel32 -ladvapi32 -lshell32" + +/* Include in the mingw32 libraries with libgcc */ +#undef LIBGCC_SPEC +#define LIBGCC_SPEC "-lmingw32 -lgcc -lmoldname -lcrtdll" + +/* Specify a different entry point when linking a DLL */ +#undef LINK_SPEC +#define LINK_SPEC \ +"%{mwindows:--subsystem windows} %{mdll:--dll -e _DllMainCRTStartup@12}" + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "%{mdll:dllcrt1%O%s} %{!mdll:crt1%O%s}" + +#define MATH_LIBRARY "-lcrtdll" + +/* Output STRING, a string representing a filename, to FILE. We canonicalize + it to be in MS-DOS format. */ +#define OUTPUT_QUOTED_STRING(FILE, STRING) \ +do { \ + char c; \ + \ + putc ('\"', asm_file); \ + if (STRING[1] == ':' \ + && (STRING[2] == '/' || STRING[2] == '\\')) \ + { \ + putc ('/', asm_file); \ + putc ('/', asm_file); \ + putc (*string, asm_file); \ + string += 2; \ + } \ + \ + while ((c = *string++) != 0) \ + { \ + if (c == '\\') \ + c = '/'; \ + \ + if (c == '\"') \ + putc ('\\', asm_file); \ + putc (c, asm_file); \ + } \ + \ + putc ('\"', asm_file); \ +} while (0) + +/* Dwarf2 exception information does not work on this system for some + unknown reason, so turn it off. */ +#undef INCOMING_RETURN_ADDR_RTX diff --git a/gnu/usr.bin/gcc/config/i386/moss.h b/gnu/usr.bin/gcc/config/i386/moss.h new file mode 100644 index 00000000000..dadf3d86af2 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/moss.h @@ -0,0 +1,34 @@ +/* Definitions for Intel 386 running MOSS + Copyright (C) 1996 Free Software Foundation, Inc. + Contributed by Bryan Ford <baford@cs.utah.edu> + +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/gnu/usr.bin/gcc/config/i386/netbsd.h b/gnu/usr.bin/gcc/config/i386/netbsd.h index bb5aba20ff4..527a76bfadd 100644 --- a/gnu/usr.bin/gcc/config/i386/netbsd.h +++ b/gnu/usr.bin/gcc/config/i386/netbsd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: netbsd.h,v 1.2 1996/04/29 07:09:47 niklas Exp $ */ +/* $OpenBSD: netbsd.h,v 1.3 1998/03/03 21:24:49 niklas Exp $ */ /* This goes away when the math-emulator is fixed */ #define TARGET_CPU_DEFAULT 0400 /* TARGET_NO_FANCY_MATH_387 */ @@ -32,11 +32,6 @@ #undef WCHAR_TYPE_SIZE #define WCHAR_TYPE_SIZE 32 -/* 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" diff --git a/gnu/usr.bin/gcc/config/i386/next.h b/gnu/usr.bin/gcc/config/i386/next.h index c0d6d7296f1..8dd46f5cd41 100644 --- a/gnu/usr.bin/gcc/config/i386/next.h +++ b/gnu/usr.bin/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 \ diff --git a/gnu/usr.bin/gcc/config/i386/osfelf.h b/gnu/usr.bin/gcc/config/i386/osfelf.h index 7e71fe98f6b..4604a341175 100644 --- a/gnu/usr.bin/gcc/config/i386/osfelf.h +++ b/gnu/usr.bin/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) %[cpp_cpu] \ %{mrose: -D__ROSE__ %{!pic-none: -D__SHARED__}} \ %{!mrose: -D__ELF__ %{fpic: -D__SHARED__}} \ %{mno-underscores: -D__NO_UNDERSCORES__} \ diff --git a/gnu/usr.bin/gcc/config/i386/osfrose.h b/gnu/usr.bin/gcc/config/i386/osfrose.h index 3aae1e1b681..fd4c3a8eb28 100644 --- a/gnu/usr.bin/gcc/config/i386/osfrose.h +++ b/gnu/usr.bin/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) %[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 diff --git a/gnu/usr.bin/gcc/config/i386/ptx4-i.h b/gnu/usr.bin/gcc/config/i386/ptx4-i.h new file mode 100644 index 00000000000..fdf21a471f1 --- /dev/null +++ b/gnu/usr.bin/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 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, 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 diff --git a/gnu/usr.bin/gcc/config/i386/rtems.h b/gnu/usr.bin/gcc/config/i386/rtems.h new file mode 100644 index 00000000000..b31ceb9f799 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/rtems.h @@ -0,0 +1,28 @@ +/* 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)" diff --git a/gnu/usr.bin/gcc/config/i386/sco.h b/gnu/usr.bin/gcc/config/i386/sco.h index 37dc0326698..9c94a766a83 100644 --- a/gnu/usr.bin/gcc/config/i386/sco.h +++ b/gnu/usr.bin/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) %[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/gnu/usr.bin/gcc/config/i386/sco4.h b/gnu/usr.bin/gcc/config/i386/sco4.h index fc389b4d1bc..1b17d674cd5 100644 --- a/gnu/usr.bin/gcc/config/i386/sco4.h +++ b/gnu/usr.bin/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) %[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/gnu/usr.bin/gcc/config/i386/sco4dbx.h b/gnu/usr.bin/gcc/config/i386/sco4dbx.h index 0387c2436c3..6ff5714c56b 100644 --- a/gnu/usr.bin/gcc/config/i386/sco4dbx.h +++ b/gnu/usr.bin/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) %[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/gnu/usr.bin/gcc/config/i386/sco5.h b/gnu/usr.bin/gcc/config/i386/sco5.h new file mode 100644 index 00000000000..5306000e2a0 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/sco5.h @@ -0,0 +1,967 @@ +/* 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 section 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, 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_DOUBLE +#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \ +do { \ + long value[2]; \ + REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), value); \ + if (TARGET_ELF) { \ + 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]); \ + } \ + } else { \ + if (sizeof (int) == sizeof (long)) \ + fprintf (FILE, "%s 0x%x,0x%x\n", ASM_LONG, value[0], value[1]); \ + else \ + fprintf (FILE, "%s 0x%lx,0x%lx\n", ASM_LONG,value[0],value[1]);} \ +} while (0) + +#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) + +#undef ASM_OUTPUT_LONG_DOUBLE +#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \ +do { \ + long l[3]; \ + REAL_VALUE_TO_TARGET_LONG_DOUBLE ((VALUE), l); \ + if (TARGET_ELF) { \ + if (sizeof (int) == sizeof (long)) \ + { \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, l[0]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, l[1]); \ + fprintf((FILE), "%s\t0x%x\n", ASM_LONG, l[2]); \ + } \ + else \ + { \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, l[0]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, l[1]); \ + fprintf((FILE), "%s\t0x%lx\n", ASM_LONG, l[2]); \ + } \ + } else { \ + 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]);} \ +} 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 "" + +#undef ASM_OUTPUT_SECTION_NAME +#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \ +do { \ + char *snam = NAME ; \ + if (strcmp(NAME, ".gcc_except_table") == 0) snam = ".gccexc" ; \ + if (TARGET_ELF) \ + fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, \ + (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "ax" : \ + (DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "aw"); \ + else \ + fprintf (FILE, ".section\t%s,\"%s\"\n", snam, \ + (DECL) && TREE_CODE (DECL) == FUNCTION_DECL ? "x" : \ + (DECL) && DECL_READONLY_SECTION (DECL, RELOC) ? "a" : "w"); \ +} 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 1 + +#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 elf binaries. -fpic will get the + assembler and linker to produce PIC code. +*/ + +/* Set up assembler flags for PIC and ELF compilations */ +#undef ASM_SPEC +#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}}" + +/* Use crt1.o as a startup file and crtn.o as a closing file. */ + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC \ + "%{!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) %[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 +# 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/gnu/usr.bin/gcc/config/i386/scodbx.h b/gnu/usr.bin/gcc/config/i386/scodbx.h index 1309735cf1e..a2581d4257f 100644 --- a/gnu/usr.bin/gcc/config/i386/scodbx.h +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/seq-gas.h b/gnu/usr.bin/gcc/config/i386/seq-gas.h index 2ee071925bc..796eaa24d62 100644 --- a/gnu/usr.bin/gcc/config/i386/seq-gas.h +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/seq-sysv3.h b/gnu/usr.bin/gcc/config/i386/seq-sysv3.h index e3182ee1a77..9e8388d47d7 100644 --- a/gnu/usr.bin/gcc/config/i386/seq-sysv3.h +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/sol2-gc1.asm b/gnu/usr.bin/gcc/config/i386/sol2-gc1.asm new file mode 100644 index 00000000000..8983a672ac2 --- /dev/null +++ b/gnu/usr.bin/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 <J.W.Hawtin@lboro.ac.uk> 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/gnu/usr.bin/gcc/config/i386/sol2.h b/gnu/usr.bin/gcc/config/i386/sol2.h index cc5ebca7d7e..64172359c4e 100644 --- a/gnu/usr.bin/gcc/config/i386/sol2.h +++ b/gnu/usr.bin/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 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) %[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}%{!pg: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} \ @@ -76,16 +85,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/gnu/usr.bin/gcc/config/i386/sol2dbg.h b/gnu/usr.bin/gcc/config/i386/sol2dbg.h new file mode 100644 index 00000000000..9d09c8fd043 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/sol2dbg.h @@ -0,0 +1,16 @@ +/* Target definitions for GNU compiler for Intel 80386 running Solaris + with gas and gdb. + This file is added into the directory .../gcc-2.../config/i386 + Workability without "#undef DWARF_DEBUGGING_INFO" is not tested. */ + +/* Use stabs instead of DWARF debug format. */ +#ifdef PREFERRED_DEBUGGING_TYPE +#undef PREFERRED_DEBUGGING_TYPE +#endif +#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG + +#include "i386/sol2.h" + +#ifdef DWARF_DEBUGGING_INFO +#undef DWARF_DEBUGGING_INFO +#endif diff --git a/gnu/usr.bin/gcc/config/i386/sun386.h b/gnu/usr.bin/gcc/config/i386/sun386.h index 6e2680789bd..4d4d66c181a 100644 --- a/gnu/usr.bin/gcc/config/i386/sun386.h +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/svr3.ifile b/gnu/usr.bin/gcc/config/i386/svr3.ifile index f0bb3a0f8dc..32b3ddc2bf3 100644 --- a/gnu/usr.bin/gcc/config/i386/svr3.ifile +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/svr3dbx.h b/gnu/usr.bin/gcc/config/i386/svr3dbx.h index d3348d55292..c394747ab9a 100644 --- a/gnu/usr.bin/gcc/config/i386/svr3dbx.h +++ b/gnu/usr.bin/gcc/config/i386/svr3dbx.h @@ -66,17 +66,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/gnu/usr.bin/gcc/config/i386/svr3gas.h b/gnu/usr.bin/gcc/config/i386/svr3gas.h index 401c7661e27..a288b84e524 100644 --- a/gnu/usr.bin/gcc/config/i386/svr3gas.h +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/svr3z.ifile b/gnu/usr.bin/gcc/config/i386/svr3z.ifile index 4fdbb937c57..4946051235e 100644 --- a/gnu/usr.bin/gcc/config/i386/svr3z.ifile +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/sysv3.h b/gnu/usr.bin/gcc/config/i386/sysv3.h index 8c5cfc41587..b6a1fcc8e2a 100644 --- a/gnu/usr.bin/gcc/config/i386/sysv3.h +++ b/gnu/usr.bin/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) %[cpp_cpu] %{posix:-D_POSIX_SOURCE}" /* Writing `int' for a bitfield forces int alignment for the structure. */ diff --git a/gnu/usr.bin/gcc/config/i386/sysv4.h b/gnu/usr.bin/gcc/config/i386/sysv4.h index 92fcada03d5..3f69827fd54 100644 --- a/gnu/usr.bin/gcc/config/i386/sysv4.h +++ b/gnu/usr.bin/gcc/config/i386/sysv4.h @@ -243,3 +243,11 @@ do { long value[3]; \ necessary when compiling PIC code. */ #define JUMP_TABLES_IN_TEXT_SECTION + +/* 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/gnu/usr.bin/gcc/config/i386/t-crtpic b/gnu/usr.bin/gcc/config/i386/t-crtpic index f5dd073a664..ff81a9bef9c 100644 --- a/gnu/usr.bin/gcc/config/i386/t-crtpic +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/t-cygwin32 b/gnu/usr.bin/gcc/config/i386/t-cygwin32 new file mode 100644 index 00000000000..4be2477fbc9 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-cygwin32 @@ -0,0 +1,7 @@ +LIBGCC1 = libgcc1-asm.a +CROSS_LIBGCC1 = libgcc1-asm.a +LIB1ASMSRC = i386/cygwin32.asm +LIB1ASMFUNCS = _chkstk + +winnt.o: $(srcdir)/config/i386/winnt.c + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/winnt.c diff --git a/gnu/usr.bin/gcc/config/i386/t-dgux b/gnu/usr.bin/gcc/config/i386/t-dgux new file mode 100644 index 00000000000..292331f22a9 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-dgux @@ -0,0 +1,4 @@ +# +# target makefile for dgux +# +EXTRA_PARTS=crtbegin.o crtend.o diff --git a/gnu/usr.bin/gcc/config/i386/t-freebsd b/gnu/usr.bin/gcc/config/i386/t-freebsd new file mode 100644 index 00000000000..5164669d1ac --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-freebsd @@ -0,0 +1,5 @@ +# Don't run fixproto +STMP_FIXPROTO = +# Use only native include files +USER_H = $(EXTRA_HEADERS) $(LANG_EXTRA_HEADERS) + diff --git a/gnu/usr.bin/gcc/config/i386/t-go32 b/gnu/usr.bin/gcc/config/i386/t-go32 new file mode 100644 index 00000000000..6160b7ec945 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-go32 @@ -0,0 +1,2 @@ +LIBGCC1 = libgcc1.null +CROSS_LIBGCC1 = libgcc1.null diff --git a/gnu/usr.bin/gcc/config/i386/t-next b/gnu/usr.bin/gcc/config/i386/t-next index ec6373f9cea..effa6953b9a 100644 --- a/gnu/usr.bin/gcc/config/i386/t-next +++ b/gnu/usr.bin/gcc/config/i386/t-next @@ -7,3 +7,6 @@ OTHER_FIXINCLUDES_DIRS= /LocalDeveloper/Headers # <limits.h> 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/gnu/usr.bin/gcc/config/i386/t-osf b/gnu/usr.bin/gcc/config/i386/t-osf new file mode 100644 index 00000000000..c996e0c9e77 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-osf @@ -0,0 +1,2 @@ +# If compiling with the osf gcc, avoid sharing code. +TCFLAGS = -pic-none diff --git a/gnu/usr.bin/gcc/config/i386/t-sco5 b/gnu/usr.bin/gcc/config/i386/t-sco5 new file mode 100644 index 00000000000..fd3d6c63b8e --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/t-sco5 @@ -0,0 +1,16 @@ +# 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 diff --git a/gnu/usr.bin/gcc/config/i386/t-sol2 b/gnu/usr.bin/gcc/config/i386/t-sol2 index f79f6ca05fb..f47905ae65d 100644 --- a/gnu/usr.bin/gcc/config/i386/t-sol2 +++ b/gnu/usr.bin/gcc/config/i386/t-sol2 @@ -13,15 +13,18 @@ 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++ @@ -30,3 +33,4 @@ crtn.o: $(srcdir)/config/i386/sol2-cn.asm # routines in crtstuff.c. CRTSTUFF_T_CFLAGS = -fPIC +TARGET_LIBGCC2_CFLAGS = -fPIC diff --git a/gnu/usr.bin/gcc/config/i386/t-winnt b/gnu/usr.bin/gcc/config/i386/t-winnt index e8e1a0af050..1e3557c1822 100644 --- a/gnu/usr.bin/gcc/config/i386/t-winnt +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/unix.h b/gnu/usr.bin/gcc/config/i386/unix.h index f38fe270d89..c74911c7107 100644 --- a/gnu/usr.bin/gcc/config/i386/unix.h +++ b/gnu/usr.bin/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,47 @@ 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, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION))); \ + fprintf (FILE, "@GOT(%%ebx),%%ecx\n\tpopl %%ebx\n\tjmp *%%ecx\n"); \ + } \ + else \ + { \ + fprintf (FILE, "\tjmp "); \ + assemble_name \ + (FILE, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (FUNCTION))); \ + fprintf (FILE, "\n"); \ + } \ +} while (0) diff --git a/gnu/usr.bin/gcc/config/i386/winnt.c b/gnu/usr.bin/gcc/config/i386/winnt.c index 3a7ebf1ba5d..ac26a1a7190 100644 --- a/gnu/usr.bin/gcc/config/i386/winnt.c +++ b/gnu/usr.bin/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 <stdio.h> #include "config.h" +#include <stdio.h> #include "rtl.h" #include "regs.h" #include "hard-reg-set.h" @@ -44,13 +44,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 +64,30 @@ gen_stdcall_suffix (decl) return IDENTIFIER_POINTER (get_identifier (newsym)); } +/* 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)); + + /* 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). */ + if (TREE_CODE (decl) == FUNCTION_DECL) + prefix = ".text$"; + else if (DECL_READONLY_SECTION (decl, reloc)) + prefix = ".rdata$"; + 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); +} diff --git a/gnu/usr.bin/gcc/config/i386/x-cygwin32 b/gnu/usr.bin/gcc/config/i386/x-cygwin32 new file mode 100644 index 00000000000..5e796a0e916 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/x-cygwin32 @@ -0,0 +1,4 @@ +# Don't run fixproto +STMP_FIXPROTO = +# Don't need collect2 +USE_COLLECT2 = diff --git a/gnu/usr.bin/gcc/config/i386/x-dgux b/gnu/usr.bin/gcc/config/i386/x-dgux new file mode 100644 index 00000000000..322bfe3ae91 --- /dev/null +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/x-osfrose b/gnu/usr.bin/gcc/config/i386/x-osfrose index a419bdb7822..27c36fe4fe7 100644 --- a/gnu/usr.bin/gcc/config/i386/x-osfrose +++ b/gnu/usr.bin/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) @@ -25,7 +26,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/gnu/usr.bin/gcc/config/i386/x-sco5 b/gnu/usr.bin/gcc/config/i386/x-sco5 new file mode 100644 index 00000000000..276d74045ed --- /dev/null +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/xm-aix.h b/gnu/usr.bin/gcc/config/i386/xm-aix.h index 5e5d40281a1..ea9202112a1 100644 --- a/gnu/usr.bin/gcc/config/i386/xm-aix.h +++ b/gnu/usr.bin/gcc/config/i386/xm-aix.h @@ -1,5 +1,5 @@ /* Configuration for GNU C-compiler for IBM PS/2 running AIX/386. - Copyright (C) 1988, 1993 Free Software Foundation, Inc. + Copyright (C) 1988, 1993, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -25,13 +25,7 @@ Boston, MA 02111-1307, USA. */ #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/gnu/usr.bin/gcc/config/i386/xm-bsd386.h b/gnu/usr.bin/gcc/config/i386/xm-bsd386.h index 9deb7ef6c65..6b8eee7db03 100644 --- a/gnu/usr.bin/gcc/config/i386/xm-bsd386.h +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/xm-cygwin32.h b/gnu/usr.bin/gcc/config/i386/xm-cygwin32.h new file mode 100644 index 00000000000..98327f24b1d --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/xm-cygwin32.h @@ -0,0 +1,26 @@ +/* Configuration for GNU C-compiler for hosting on Windows NT. + using a unix style C library. + Copyright (C) 1995, 1996, 1997 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 +#define EXECUTABLE_SUFFIX ".exe" + +/* Even though we support "/", allow "\" since everybody tests both. */ +#define DIR_SEPARATOR '\\' diff --git a/gnu/usr.bin/gcc/config/i386/xm-dgux.h b/gnu/usr.bin/gcc/config/i386/xm-dgux.h new file mode 100644 index 00000000000..5bdb9be0ebb --- /dev/null +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/xm-dos.h b/gnu/usr.bin/gcc/config/i386/xm-dos.h index 1dd0c013b1d..a734a81b94e 100644 --- a/gnu/usr.bin/gcc/config/i386/xm-dos.h +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/xm-go32.h b/gnu/usr.bin/gcc/config/i386/xm-go32.h new file mode 100644 index 00000000000..d8182132ac6 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/xm-go32.h @@ -0,0 +1,28 @@ +/* Configuration for GNU C-compiler for Intel 80386 running GO32. + Copyright (C) 1988, 1996 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 __MSDOS__ 1 + +#define NO_STAB_H + +#include "i386/xm-i386.h" + +/* Use semicolons to separate elements of a path. */ +#define PATH_SEPARATOR ';' diff --git a/gnu/usr.bin/gcc/config/i386/xm-linux.h b/gnu/usr.bin/gcc/config/i386/xm-linux.h index 42f097ddc6c..713bf3b2817 100644 --- a/gnu/usr.bin/gcc/config/i386/xm-linux.h +++ b/gnu/usr.bin/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/gnu/usr.bin/gcc/config/i386/xm-mingw32.h b/gnu/usr.bin/gcc/config/i386/xm-mingw32.h new file mode 100644 index 00000000000..47356f568d1 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/xm-mingw32.h @@ -0,0 +1,45 @@ +/* Configuration for GNU C-compiler for hosting on Windows32. + using GNU tools and the Windows32 API Library. + Copyright (C) 1997 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 + +#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 link(a,b) -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/gnu/usr.bin/gcc/config/i386/xm-os2.h b/gnu/usr.bin/gcc/config/i386/xm-os2.h index 5ff2899cfd5..f74bee5ebb2 100644 --- a/gnu/usr.bin/gcc/config/i386/xm-os2.h +++ b/gnu/usr.bin/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 Free Software Foundation, Inc. + Contributed by Samuel Figueroa (figueroa@apple.com) This file is part of GNU CC. @@ -28,13 +28,7 @@ Boston, MA 02111-1307, USA. */ #include <stdlib.h> /* 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 diff --git a/gnu/usr.bin/gcc/config/i386/xm-osf.h b/gnu/usr.bin/gcc/config/i386/xm-osf.h index fda50d98f55..cd06b56b6ad 100644 --- a/gnu/usr.bin/gcc/config/i386/xm-osf.h +++ b/gnu/usr.bin/gcc/config/i386/xm-osf.h @@ -1,5 +1,5 @@ /* Configuration for GNU C-compiler for 386 running OSF/1 - Copyright (C) 1994 Free Software Foundation, Inc. + Copyright (C) 1994, 1997 Free Software Foundation, Inc. This file is part of GNU CC. @@ -22,11 +22,3 @@ Boston, MA 02111-1307, USA. */ #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/gnu/usr.bin/gcc/config/i386/xm-sco.h b/gnu/usr.bin/gcc/config/i386/xm-sco.h index 01a63d90e00..472ce047cf8 100644 --- a/gnu/usr.bin/gcc/config/i386/xm-sco.h +++ b/gnu/usr.bin/gcc/config/i386/xm-sco.h @@ -20,3 +20,6 @@ #define ONLY_INT_FIELDS 1 #define CODE_FIELD_BUG 1 #endif + +/* SCO lacks sys_siglist. */ +#define NO_SYS_SIGLIST diff --git a/gnu/usr.bin/gcc/config/i386/xm-sco5.h b/gnu/usr.bin/gcc/config/i386/xm-sco5.h new file mode 100644 index 00000000000..99bc53c2bc5 --- /dev/null +++ b/gnu/usr.bin/gcc/config/i386/xm-sco5.h @@ -0,0 +1,18 @@ +/* Configuration for GCC for Intel i386 running SCO. */ + +#include "i386/xm-sysv3.h" + +/* Big buffers improve performance. */ + +#define IO_BUFFER_SIZE (0x8000 - 1024) +/* OpenServer provides no sys_siglist, + but does offer the same data under another name. */ +#define sys_siglist _sys_siglist +#undef SYS_SIGLIST_DECLARED +#define SYS_SIGLIST_DECLARED + +/* If not compiled with GNU C, use the portable alloca. */ +#ifndef __GNUC__ +#define USE_C_ALLOCA +#endif + diff --git a/gnu/usr.bin/gcc/config/i386/xm-sun.h b/gnu/usr.bin/gcc/config/i386/xm-sun.h index d2e714ecf5c..de7c2013b3e 100644 --- a/gnu/usr.bin/gcc/config/i386/xm-sun.h +++ b/gnu/usr.bin/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) |