Bring s390 backend back in sync with branch.
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 11 Aug 2001 20:56:12 +0000 (20:56 +0000)
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 11 Aug 2001 20:56:12 +0000 (20:56 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@44810 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/s390/fixdfdi.h
gcc/config/s390/linux.h
gcc/config/s390/linux64.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md

index 77f37b0..18244a1 100644 (file)
@@ -1,3 +1,51 @@
+2001-08-11  Ulrich Weigand  <uweigand@de.ibm.com>
+       * config/s390/s390.c (targetm): Define TARGET_ASM_OPEN_PAREN
+       and TARGET_ASM_CLOSE_PAREN.
+       (regclass_map): CC register belongs to class NO_REGS.
+       (legitimize_pic_address): Don't generate unnecessary moves 
+       (to avoid confusing loop optimization).
+       (check_and_change_labels): Replace jump_long by indirect_jump.
+       (s390_final_chunkify): Don't start a new literal pool on section 
+       switch in 64-bit code.
+       (s390_va_start, s390_va_arg): Fixed incorrect sizes for 64-bit.
+       
+       * config/s390/s390.h (TARGET_SWITCHES): Renamed debug_arg to debug.
+       (MAX_BITS_PER_WORD, MAX_LONG_TYPE_SIZE): Set to 64 (for 64-bit).
+       (HARD_REGNO_MODE_OK, RETURN_IN_MEMORY): Support complex integer 
+       modes correctly.
+       (reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS): Remove CC_REGS.
+       (EH_RETURN_HANDLER_RTX): Fixed incorrect offset for 64-bit.
+       (CONST_COSTS): Fixed incorrect costs.
+
+       * config/s390/s390.md (fixuns_trunc[sd]f[sd]i2, udivsi3, umodsi3):
+       Use emit_jump instead of emit_jump_insn (gen_jump).
+       (divsi3, modsi3): Clobber low word of divmoddisi3 before shifting 
+       (to avoid confusing flow analysis).
+       (tablejump, tablejump1, tablejump2): Removed.  Replaced by casesi.
+       (casesi, casesi_jump): New.
+       (jump_long): Removed.  Functionality merged into indirect_jump.
+       (indirect_jump): Accept address_operand, not just register_operand.
+       (cjump_long, icjump_long): Use same logic as indirect_jump.
+       (builtin_setjmp_setup, builtin_setjmp_receiver, builtin_longjmp):
+       Fixed broken setjmp/longjmp handling.
+       (do_builtin_setjmp_setup): Removed.
+
+       * config/s390/linux.h (ASM_OUTPUT_DOUBLE_INT): Work around
+       broken GNU as versions that don't accept .quad with large
+       negative values.  Use hexadecimal output instead.
+       (ASM_OUTPUT_ADDR_DIFF_ELT): Adapt to new casesi insn.
+       (ASM_OPEN_PAREN, ASM_CLOSE_PAREN, FUNCTION_PROLOGUE,
+       FUNCTION_EPILOGUE): Removed.  Now in targetm.
+
+       * config/s390/linux64.h (CALL_USED_REGISTERS): Add CC register.
+
+       * config/s390/fixdfdi.h: Add missing copyright statement.
+       Fix type conflicts on 64-bit.  Add missing SFmode routines.
+
+       * s390.c, s390.h, s390.md, linux.h, linux64.h: Fixed incorrect
+       email address.
+
 2001-08-11  Richard Henderson  <rth@redhat.com>
 
        * rtl.h (REG_EH_RETHROW): Remove.
index 3e1ad49..4f1fb35 100644 (file)
@@ -1,3 +1,25 @@
+/* Definitions of target machine for GNU compiler, for IBM S/390
+   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+   Contributed by Hartmut Penner (hpenner@de.ibm.com) and
+                  Ulrich Weigand (uweigand@de.ibm.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.  */ 
+
 #ifdef L_fixunsdfdi
 #define EXPD(fp)       (((fp.l.upper) >> 20) & 0x7FF)
 #define EXCESSD                1022
 #define SIGND(fp)      ((fp.l.upper) & SIGNBIT)
 #define MANTD_LL(fp)   ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
 #define FRACD_LL(fp)   (fp.ll & (HIDDEND_LL-1))
-#define HIDDEND_LL     ((long long)1 << 52)
+#define HIDDEND_LL     ((UDItype_x)1 << 52)
+
+typedef int DItype_x __attribute__ ((mode (DI)));
+typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
+typedef int SItype_x __attribute__ ((mode (SI)));
+typedef unsigned int USItype_x __attribute__ ((mode (SI)));
 
 union double_long {
     double d;
     struct {
-      long upper;
-      unsigned long lower;
+      SItype_x upper;
+      USItype_x lower;
     } l;
-    long long ll;
+    UDItype_x ll;
 };
 
 
 /* convert double to unsigned int */
-unsigned long long
+UDItype_x
 __fixunsdfdi (double a1)
 {
     register union double_long dl1;
     register int exp;
-    register long long l;
+    register UDItype_x l;
 
     dl1.d = a1;
 
@@ -71,24 +98,29 @@ __fixunsdfdi (double a1)
 #define SIGND(fp)      ((fp.l.upper) & SIGNBIT)
 #define MANTD_LL(fp)   ((fp.ll & (HIDDEND_LL-1)) | HIDDEND_LL)
 #define FRACD_LL(fp)   (fp.ll & (HIDDEND_LL-1))
-#define HIDDEND_LL     ((long long)1 << 52)
+#define HIDDEND_LL     ((UDItype_x)1 << 52)
+
+typedef int DItype_x __attribute__ ((mode (DI)));
+typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
+typedef int SItype_x __attribute__ ((mode (SI)));
+typedef unsigned int USItype_x __attribute__ ((mode (SI)));
 
 union double_long {
     double d;
     struct {
-      long upper;
-      unsigned long lower;
+      SItype_x upper;
+      USItype_x lower;
     } l;
-    long long ll;
+    UDItype_x ll;
 };
 
 /* convert double to int */
-long long
+DItype_x
 __fixdfdi (double a1)
 {
     register union double_long dl1;
     register int exp;
-    register long long l;
+    register DItype_x l;
 
     dl1.d = a1;
 
@@ -132,3 +164,138 @@ __fixdfdi (double a1)
 #endif
 #undef L_fixdfdi
 
+#ifdef L_fixunssfdi
+#define EXP(fp)         (((fp.l) >> 23) & 0xFF)
+#define EXCESS          126
+#define SIGNBIT         0x80000000
+#define SIGN(fp)        ((fp.l) & SIGNBIT)
+#define HIDDEN          (1 << 23)
+#define MANT(fp)        (((fp.l) & 0x7FFFFF) | HIDDEN)
+#define FRAC(fp)        ((fp.l) & 0x7FFFFF)
+
+typedef int DItype_x __attribute__ ((mode (DI)));
+typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
+typedef int SItype_x __attribute__ ((mode (SI)));
+typedef unsigned int USItype_x __attribute__ ((mode (SI)));
+
+union float_long
+  {
+    float f;
+    USItype_x l;
+  };
+
+/* convert float to unsigned int */
+UDItype_x
+__fixunssfdi (float a1)
+{
+    register union float_long fl1;
+    register int exp;
+    register UDItype_x l;
+
+    fl1.f = a1;
+
+    /* +/- 0, denormalized, negativ */
+
+    if (!EXP (fl1) || SIGN(fl1))
+      return 0;
+
+    exp = EXP (fl1) - EXCESS - 24;
+
+    /* number < 1 */
+
+    if (exp < -24)
+      return 0;
+
+    /* NaN */
+
+    if ((EXP(fl1) == 0xff) && (FRAC(fl1) != 0)) /* NaN */
+      return 0x0ULL;
+
+    /* Number big number & + inf */
+
+    if (exp >= 41) {
+      return 0xFFFFFFFFFFFFFFFFULL;
+    }
+
+    l = MANT(fl1);
+
+    if (exp > 0)
+      l <<= exp;
+    else 
+      l >>= -exp;
+
+    return l;
+}
+#define __fixunssfdi ___fixunssfdi
+#endif
+#undef L_fixunssfdi
+
+#ifdef L_fixsfdi
+#define EXP(fp)         (((fp.l) >> 23) & 0xFF)
+#define EXCESS          126
+#define SIGNBIT         0x80000000
+#define SIGN(fp)        ((fp.l) & SIGNBIT)
+#define HIDDEN          (1 << 23)
+#define MANT(fp)        (((fp.l) & 0x7FFFFF) | HIDDEN)
+#define FRAC(fp)        ((fp.l) & 0x7FFFFF)
+
+typedef int DItype_x __attribute__ ((mode (DI)));
+typedef unsigned int UDItype_x __attribute__ ((mode (DI)));
+typedef int SItype_x __attribute__ ((mode (SI)));
+typedef unsigned int USItype_x __attribute__ ((mode (SI)));
+
+union float_long
+  {
+    float f;
+    USItype_x l;
+  };
+
+/* convert double to int */
+DItype_x
+__fixsfdi (float a1)
+{
+    register union float_long fl1;
+    register int exp;
+    register DItype_x l;
+
+    fl1.f = a1;
+
+    /* +/- 0, denormalized */
+
+    if (!EXP (fl1))
+      return 0;
+
+    exp = EXP (fl1) - EXCESS - 24;
+
+    /* number < 1 */
+
+    if (exp < -24)
+      return 0;
+
+    /* NaN */
+
+    if ((EXP(fl1) == 0xff) && (FRAC(fl1) != 0)) /* NaN */
+      return 0x8000000000000000ULL;
+
+    /* Number big number & +/- inf */
+
+    if (exp >= 40) {
+       l = (long long)1<<63;
+       if (!SIGN(fl1))
+           l--;
+       return l;
+    }
+
+    l = MANT(fl1);
+
+    if (exp > 0)
+      l <<= exp;
+    else 
+      l >>= -exp;
+
+    return (SIGN (fl1) ? -l : l);
+}
+#define __fixsfdi ___fixsfdi
+#endif
+#undef L_fixsfdi
+
index 36ae80d..0e5d179 100644 (file)
@@ -1,7 +1,7 @@
 /* Definitions for Linux for S/390.
    Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-                  Ulrich Weigand (weigand@de.ibm.com).
+                  Ulrich Weigand (uweigand@de.ibm.com).
 
 This file is part of GNU CC.
 
@@ -138,10 +138,14 @@ Boston, MA 02111-1307, USA.  */
   sprintf ((OUTPUT), "%s.%d", (NAME), (LABELNO)))
 
 
-#define ASM_OUTPUT_DOUBLE_INT(FILE, VALUE)      \
-do { fprintf (FILE, "%s\t", ASM_QUAD);          \
-  output_addr_const (FILE,(VALUE));             \
-  putc ('\n',FILE);                             \
+#define ASM_OUTPUT_DOUBLE_INT(FILE, VALUE)                             \
+do { fprintf ((FILE), "%s\t", ASM_QUAD);                               \
+  /* Work around bug in some GNU as versions */                                \
+  if (GET_CODE (VALUE) == CONST_INT && INTVAL (VALUE) < INT_MIN)       \
+    fprintf ((FILE), HOST_WIDE_INT_PRINT_HEX, INTVAL (x));             \
+  else                                                                 \
+    output_addr_const ((FILE), (VALUE));                               \
+  putc ('\n', (FILE));                                                 \
  } while (0)
 
 
@@ -180,22 +184,14 @@ do { fprintf (FILE, "%s\t", ASM_LONG);          \
 /* This is how to output an element of a case-vector that is absolute.  */
 
 #define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE)                   \
-  fprintf (FILE, "%s %s%d\n", TARGET_64BIT?ASM_QUAD:ASM_LONG,  \
+  fprintf (FILE, "%s\t%s%d\n", TARGET_64BIT?ASM_QUAD:ASM_LONG,         \
           LPREFIX, VALUE)
 
 /* This is how to output an element of a case-vector that is relative.  */
 
 #define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL)               \
-  fprintf (FILE, "%s %s%d-.LT%X_%X\n" ,TARGET_64BIT?ASM_QUAD:ASM_LONG,         \
-          LPREFIX, VALUE, s390_function_count,s390_pool_count)
-
-/* Define the parentheses used to group arithmetic operations
-   in assembler code.  */
-
-#undef ASM_OPEN_PAREN
-#undef ASM_CLOSE_PAREN
-#define ASM_OPEN_PAREN ""
-#define ASM_CLOSE_PAREN ""
+  fprintf (FILE, "%s\t%s%d-%s%d\n", TARGET_64BIT?ASM_QUAD:ASM_LONG,    \
+          LPREFIX, VALUE, LPREFIX, REL)
 
 
 
@@ -293,24 +289,6 @@ do {                                                                    \
 
 #define DBX_REGISTER_NUMBER(REGNO) (REGNO)
 
-/*
- * This macro generates the assembly code for function entry.
- */
-
-#define FUNCTION_PROLOGUE(FILE, LSIZE) s390_function_prologue (FILE, LSIZE)
-
-/* This macro generates the assembly code for function exit, on machines
-   that need it.  If FUNCTION_EPILOGUE is not defined then individual
-   return instructions are generated for each return statement.  Args are
-   same as for FUNCTION_PROLOGUE.
-  
-   The function epilogue should not depend on the current stack pointer!
-   It should use the frame pointer only.  This is mandatory because
-   of alloca; we also take advantage of it to omit stack adjustments
-   before returning.  */
-
-#define FUNCTION_EPILOGUE(FILE, LSIZE) s390_function_epilogue(FILE, LSIZE)
-
 /* Select section for constant in constant pool. 
    We are in the right section. 
    undef for 64 bit mode (linux64.h).
index ab518c2..36fa1c7 100644 (file)
@@ -1,7 +1,7 @@
 /* Definitions for Linux for s/390 zSeries
    Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-                  Ulrich Weigand (weigand@de.ibm.com).
+                  Ulrich Weigand (uweigand@de.ibm.com).
 This file is part of GNU CC.
 
 GNU CC is free software; you can redistribute it and/or modify
@@ -77,6 +77,6 @@ Boston, MA 02111-1307, USA.  */
   1, 1, 1, 1,                                  \
   0, 0, 0, 0,                                  \
   0, 0, 0, 0,                                  \
-  1 }
+  1, 1 }
 
 #endif
index c80dc2a..33307a8 100644 (file)
@@ -1,7 +1,7 @@
 /* Subroutines used for code generation on IBM S/390 and zSeries
    Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-                  Ulrich Weigand (weigand@de.ibm.com).
+                  Ulrich Weigand (uweigand@de.ibm.com).
 
 This file is part of GNU CC.
 
@@ -53,6 +53,12 @@ Boston, MA 02111-1307, USA.  */
 #undef  TARGET_ASM_FUNCTION_EPILOGUE 
 #define TARGET_ASM_FUNCTION_EPILOGUE s390_function_epilogue
 
+#undef  TARGET_ASM_OPEN_PAREN
+#define TARGET_ASM_OPEN_PAREN ""
+
+#undef  TARGET_ASM_CLOSE_PAREN
+#define TARGET_ASM_CLOSE_PAREN ""
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 extern int reload_completed;
@@ -173,7 +179,7 @@ enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
   FP_REGS,      FP_REGS,   FP_REGS,   FP_REGS,
   FP_REGS,      FP_REGS,   FP_REGS,   FP_REGS,
   FP_REGS,      FP_REGS,   FP_REGS,   FP_REGS,
-  ADDR_REGS,    CC_REGS 
+  ADDR_REGS,    NO_REGS 
 };
 
 
@@ -959,11 +965,6 @@ legitimize_pic_address (orig, reg)
                   case 112:
                   case 114:
                     new = force_const_mem (SImode, orig);
-                    if (reg != 0)
-                      {
-                        emit_move_insn (reg, new);
-                        new = reg;
-                      }
                     break;
 
                   /* @GOTENT is OK as is.  */
@@ -1080,11 +1081,6 @@ legitimize_pic_address (orig, reg)
                 abort();
 
               new = force_const_mem (SImode, orig);
-              if (reg != 0)
-                {
-                  emit_move_insn (reg, new);
-                  new = reg;
-                }
             }
 
           /* Otherwise, compute the sum.  */
@@ -1700,7 +1696,7 @@ check_and_change_labels (rtx insn, int *ltorg_uids)
                }
              
              emit_insn_before (gen_movsi (temp_reg, target), insn);
-             tmp = emit_jump_insn_before (gen_jump_long (jump), insn);
+             tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
              remove_insn (insn);
              INSN_ADDRESSES_NEW (tmp, -1);
              return tmp;
@@ -1736,7 +1732,7 @@ check_and_change_labels (rtx insn, int *ltorg_uids)
                  label1 = gen_label_rtx ();
                  emit_jump_insn_before (gen_icjump (label1, XEXP (body, 0)), insn);
                  emit_insn_before (gen_movsi (temp_reg, target), insn);
-                 tmp = emit_jump_insn_before (gen_jump_long (jump), insn);
+                 tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
                  INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
                  remove_insn (insn);
                  return tmp;
@@ -1770,7 +1766,7 @@ check_and_change_labels (rtx insn, int *ltorg_uids)
                  label1 = gen_label_rtx ();
                  emit_jump_insn_before (gen_cjump (label1, XEXP (body, 0)), insn);
                  emit_insn_before (gen_movsi (temp_reg, target), insn);
-                 tmp = emit_jump_insn_before (gen_jump_long (jump), insn);
+                 tmp = emit_jump_insn_before (gen_indirect_jump (jump), insn);
                  INSN_ADDRESSES_NEW (emit_label_before (label1, insn), -1);
                  remove_insn (insn);
                  return tmp;
@@ -1862,7 +1858,7 @@ s390_final_chunkify (int chunkify)
              warning ("no code label found");
            }
        } 
-      else if (GET_CODE (PATTERN (insn)) == ASM_INPUT) 
+      else if (GET_CODE (PATTERN (insn)) == ASM_INPUT && !TARGET_64BIT
        {
          asms = XSTR (PATTERN (insn),0);
          
@@ -2732,7 +2728,7 @@ s390_va_start (int stdarg_p, tree valist, rtx nextarg)
   off = INTVAL (current_function_arg_offset_rtx);
   off = off < 0 ? 0 : off;
   if (! stdarg_p)
-    off = off > 0 ? off - 4 : off;
+    off = off > 0 ? off - UNITS_PER_WORD : off;
   if (TARGET_DEBUG_ARG)
     fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
             n_gpr, n_fpr, off);
@@ -2809,7 +2805,7 @@ s390_va_arg (tree valist, tree type)
       indirect_p = 1;
       reg = gpr;
       n_reg = 1;
-      sav_ofs = 8;
+      sav_ofs = 2 * UNITS_PER_WORD;
       sav_scale = UNITS_PER_WORD;
       size = UNITS_PER_WORD;
       max_reg = 4;
@@ -2826,7 +2822,7 @@ s390_va_arg (tree valist, tree type)
       indirect_p = 0;
       reg = fpr;
       n_reg = 1;
-      sav_ofs = 16 * UNITS_PER_WORD;;
+      sav_ofs = 16 * UNITS_PER_WORD;
       sav_scale = 8;
       /* TARGET_64BIT has up to 4 parameter in fprs */
       max_reg = TARGET_64BIT ? 3 : 1;
index 8cb03e8..fb98ba8 100644 (file)
@@ -1,7 +1,7 @@
 /* Definitions of target machine for GNU compiler, for IBM S/390
    Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-                  Ulrich Weigand (weigand@de.ibm.com).
+                  Ulrich Weigand (uweigand@de.ibm.com).
 This file is part of GNU CC.
 
 GNU CC is free software; you can redistribute it and/or modify
@@ -54,8 +54,8 @@ extern int target_flags;
   { "no-backchain", -2,N_("Don't set backchain (faster, but debug harder")}, \
   { "small-exec",    4,N_("Use bras for execucable < 64k")},           \
   { "no-small-exec",-4,N_("Don't use bras")},                         \
-  { "debug_arg",     8,N_("Additional debug prints")},                \
-  { "no-debug_arg", -8,N_("Don't print additional debug prints")},     \
+  { "debug",         8,N_("Additional debug prints")},                \
+  { "no-debug",     -8,N_("Don't print additional debug prints")},     \
   { "64",           16,N_("64 bit mode")},                            \
   { "31",          -16,N_("31 bit mode")},                             \
   { "mvcle",        32,N_("mvcle use")},                              \
@@ -95,7 +95,7 @@ extern int current_function_outgoing_args_size;
 /* Width in bits of a "word", which is the contents of a machine register.  */
 
 #define BITS_PER_WORD (TARGET_64BIT ? 64 : 32)
-#define MAX_BITS_PER_WORD 32
+#define MAX_BITS_PER_WORD 64
 
 /* Width of a word, in units (bytes).  */
 
@@ -121,7 +121,7 @@ extern int current_function_outgoing_args_size;
    target machine.  If you don't define this, the default is one
    word.  */
 #define LONG_TYPE_SIZE (TARGET_64BIT ? 64 : 32)
-#define MAX_LONG_TYPE_SIZE 32
+#define MAX_LONG_TYPE_SIZE 64
 
 /* A C expression for the size in bits of the type `long long' on the
    target machine.  If you don't define this, the default is two
@@ -330,8 +330,7 @@ do                                                          \
    (GET_MODE_CLASS(MODE) == MODE_FLOAT ||                           \
     GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT) :                   \
    INT_REGNO_P(REGNO)?                                              \
-    (!((TARGET_64BIT && (MODE) == TImode) ||                        \
-     (!TARGET_64BIT && (MODE) == DImode)) || ((REGNO) & 1) == 0 ) : \
+    (HARD_REGNO_NREGS(REGNO, MODE) == 1 || !((REGNO) & 1)) :        \
    CC_REGNO_P(REGNO)?                                               \
      GET_MODE_CLASS (MODE) == MODE_CC :                             \
    0)
@@ -427,7 +426,7 @@ while (0)
 enum reg_class
 {
   NO_REGS, ADDR_REGS, GENERAL_REGS,
-  FP_REGS, CC_REGS, ALL_REGS, LIM_REG_CLASSES
+  FP_REGS, ALL_REGS, LIM_REG_CLASSES
 };
 
 #define N_REG_CLASSES (int) LIM_REG_CLASSES
@@ -435,7 +434,7 @@ enum reg_class
 /* Give names of register classes as strings for dump file.  */
 
 #define REG_CLASS_NAMES                                                 \
-{ "NO_REGS","ADDR_REGS", "GENERAL_REGS", "FP_REGS", "CC_REGS", "ALL_REGS" }
+{ "NO_REGS","ADDR_REGS", "GENERAL_REGS", "FP_REGS", "ALL_REGS" }
 
 /* Define which registers fit in which classes.  This is an initializer for
    a vector of HARD_REG_SET of length N_REG_CLASSES.
@@ -447,7 +446,6 @@ enum reg_class
   { 0x0000fffe, 0x00000001 },  /* ADDR_REGS */         \
   { 0x0000ffff, 0x00000001 },  /* GENERAL_REGS */      \
   { 0xffff0000, 0x00000000 },  /* FP_REGS */           \
-  { 0x00000000, 0x00000002 },  /* CC_REGS */           \
   { 0xffffffff, 0x00000003 },  /* ALL_REGS */          \
 }
 
@@ -591,7 +589,8 @@ extern enum reg_class regclass_map[];       /* smalled class containing REGNO   */
 #define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 6 : INVALID_REGNUM)
 #define EH_RETURN_STACKADJ_RTX  gen_rtx_REG (Pmode, 10)
 #define EH_RETURN_HANDLER_RTX \
-  gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, -40))
+  gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, \
+                                     TARGET_64BIT? -48 : -40))
 
 /* Define this if pushing a word on the stack makes the stack pointer a
    smaller address.  */
@@ -767,10 +766,10 @@ CUMULATIVE_ARGS;
 /* The definition of this macro implies that there are cases where
    a scalar value cannot be returned in registers.  */
 
-#define RETURN_IN_MEMORY(type)                 \
-  (TYPE_MODE (type) == BLKmode ||              \
-   TYPE_MODE (type) == DCmode  ||              \
-   TYPE_MODE (type) == SCmode)
+#define RETURN_IN_MEMORY(type)                                 \
+  (TYPE_MODE (type) == BLKmode ||                              \
+   GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_INT  ||   \
+   GET_MODE_CLASS (TYPE_MODE (type)) == MODE_COMPLEX_FLOAT)
 
 /* Mode of stack savearea.
    FUNCTION is VOIDmode because calling convention maintains SP.
@@ -1569,11 +1568,11 @@ do {                                                                       \
        if ((OUTER_CODE == PLUS) &&                              \
           ((INTVAL (RTX) > 32767) ||                           \
           (INTVAL (RTX) < -32768)))                            \
-         return 3;                                              \
+         return COSTS_N_INSNS (3);                              \
   case LABEL_REF:                                               \
   case SYMBOL_REF:                                              \
   case CONST_DOUBLE:                                            \
-    return 1;                                                   \
+    return 0;                                                   \
 
 
 /* Like `CONST_COSTS' but applies to nonconstant RTL expressions.
index 5c6b183..31a5097 100644 (file)
@@ -1,7 +1,7 @@
 ;;- Machine description for GNU compiler -- S/390 / zSeries version.
 ;;  Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
 ;;  Contributed by Hartmut Penner (hpenner@de.ibm.com) and
-;;                 Ulrich Weigand (weigand@de.ibm.com).
+;;                 Ulrich Weigand (uweigand@de.ibm.com).
 ;; This file is part of GNU CC.
 
 ;; GNU CC is free software; you can redistribute it and/or modify
   emit_insn (gen_subdf3 (temp, operands[1], force_const_mem (DFmode,
        CONST_DOUBLE_FROM_REAL_VALUE (0x10000000000000000ULL, DFmode))));
   emit_insn (gen_fix_truncdfdi2_ieee (operands[0], temp, GEN_INT(7)));
-  emit_jump_insn (gen_jump (label2));
+  emit_jump (label2);
 
   emit_label (label1);
   emit_insn (gen_fix_truncdfdi2_ieee (operands[0], operands[1], GEN_INT(5)));
   emit_insn (gen_subdf3 (temp, operands[1], force_const_mem (DFmode,
        CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, DFmode))));
   emit_insn (gen_fix_truncdfsi2_ieee (operands[0], temp, GEN_INT (7)));
-  emit_jump_insn (gen_jump (label2));
+  emit_jump (label2);
 
   emit_label (label1);
   emit_insn (gen_fix_truncdfsi2_ieee (operands[0], operands[1], GEN_INT (5)));
   emit_insn (gen_subsf3 (temp, operands[1], force_const_mem (SFmode,
        CONST_DOUBLE_FROM_REAL_VALUE (0x10000000000000000ULL, SFmode))));
   emit_insn (gen_fix_truncsfdi2_ieee (operands[0], temp, GEN_INT(7)));
-  emit_jump_insn (gen_jump (label2));
+  emit_jump (label2);
 
   emit_label (label1);
   emit_insn (gen_fix_truncsfdi2_ieee (operands[0], operands[1], GEN_INT(5)));
   emit_insn (gen_subsf3 (temp, operands[1], force_const_mem (SFmode,
        CONST_DOUBLE_FROM_REAL_VALUE (0x100000000ULL, SFmode))));
   emit_insn (gen_fix_truncsfsi2_ieee (operands[0], temp, GEN_INT (7)));
-  emit_jump_insn (gen_jump (label2));
+  emit_jump (label2);
 
   emit_label (label1);
   emit_insn (gen_fix_truncsfsi2_ieee (operands[0], operands[1], GEN_INT (5)));
   else
     operands[2] = force_reg (SImode, operands[2]);
 
-  emit_insn (gen_rtx_CLOBBER (DImode, tmp));
+  emit_insn (gen_rtx_CLOBBER (SImode, gen_rtx_SUBREG (SImode, tmp, 4)));
   emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), operands[1]);
   emit_insn (gen_ashrdi3 (tmp, tmp, GEN_INT (32))); 
   emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
   else
     operands[2] = force_reg (SImode, operands[2]);
 
-  emit_insn (gen_rtx_CLOBBER (DImode, tmp));
+  emit_insn (gen_rtx_CLOBBER (SImode, gen_rtx_SUBREG (SImode, tmp, 4)));
   emit_insn (gen_movsi (gen_rtx_SUBREG (SImode, tmp, 0), operands[1]));
   emit_insn (gen_ashrdi3 (tmp, tmp, GEN_INT (32))); 
   emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
       emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
       emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
       emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
-      emit_jump_insn (gen_jump (label3));
+      emit_jump (label3);
       emit_label (label1);
       emit_move_insn (dr_1, operands[1]);
-      emit_jump_insn (gen_jump (label3));
+      emit_jump (label3);
       emit_label (label2);
       emit_move_insn (dr_1, const1_rtx);
       emit_label (label3);
       emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 0), const0_rtx);
       emit_move_insn (gen_rtx_SUBREG (SImode, tmp, 4), operands[1]);
       emit_insn (gen_divmoddisi3 (tmp, tmp, operands[2]));
-      emit_jump_insn (gen_jump (label3));
+      emit_jump (label3);
       emit_label (label1);
       emit_move_insn (dr_0, const0_rtx);
-      emit_jump_insn (gen_jump (label3));
+      emit_jump (label3);
       emit_label (label2);
       emit_insn (gen_subsi3 (dr_0, dr_0, operands[2]));
       emit_label (label3);
       (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
       (const_int 4) (const_int 6)))])
 
-(define_insn "cjump_long"
+(define_insn "*cjump_long"
  [(set (pc)
        (if_then_else
          (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
-        (match_operand 0 "memory_operand" "m")
+        (match_operand 0 "address_operand" "p")
         (pc)))]
   ""
-  "b%C1\\t%0"
-  [(set_attr "op_type" "RX")])
+  "*
+{
+  if (get_attr_op_type (insn) == OP_TYPE_RR)
+    return \"b%C1r\\t%0\";
+  else
+    return \"b%C1\\t%a0\";
+}"
+  [(set (attr "op_type") 
+        (if_then_else (match_operand 0 "register_operand" "")
+                      (const_string "RR") (const_string "RX")))
+   (set_attr "atype" "mem")])
 
 
 ;;
      (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
      (const_int 4) (const_int 6)))])
 
-(define_insn "icjump_long"
+(define_insn "*icjump_long"
  [(set (pc)
        (if_then_else
          (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
-        (pc)
-        (match_operand 0 "memory_operand" "m")))]
+         (pc)
+        (match_operand 0 "address_operand" "p")))]
   ""
-  "b%D1\\t%0"
-  [(set_attr "op_type" "RX")])
+  "*
+{
+  if (get_attr_op_type (insn) == OP_TYPE_RR)
+    return \"b%D1r\\t%0\";
+  else
+    return \"b%D1\\t%a0\";
+}"
+  [(set (attr "op_type") 
+        (if_then_else (match_operand 0 "register_operand" "")
+                      (const_string "RR") (const_string "RX")))
+   (set_attr "atype" "mem")])
 
 
 ;;
 ;
 
 (define_insn "indirect_jump"
 [(set (pc) (match_operand 0 "register_operand" "a"))]
[(set (pc) (match_operand 0 "address_operand" "p"))]
   ""
-  "br\\t%0"
-  [(set_attr "op_type" "RX")])
-
-(define_insn "jump_long"
-  [(set (pc) (match_operand 0 "address_operand" "p"))]
-  ""
-  "b\\t%a0"
-  [(set_attr "op_type" "RX")
-   (set_attr "atype"   "mem")])
-
+  "*
+{
+  if (get_attr_op_type (insn) == OP_TYPE_RR)
+    return \"br\\t%0\";
+  else
+    return \"b\\t%a0\";
+}"
+  [(set (attr "op_type") 
+        (if_then_else (match_operand 0 "register_operand" "")
+                      (const_string "RR") (const_string "RX")))
+   (set_attr "atype" "mem")])
 
 ;
-; tablejump instruction pattern(s).
+; casesi instruction pattern(s).
 ;
 
-(define_expand "tablejump"
-  [(parallel
-    [(set (pc) (match_operand 0 "register_operand" "a"))
-     (use (label_ref (match_operand 1 "" "")))])]
+(define_insn "casesi_jump"
+ [(set (pc) (match_operand 0 "address_operand" "p"))
+   (use (label_ref (match_operand 1 "" "")))]
   ""
-  "
+  "*
 {
-  if (flag_pic)
-    {
-      rtx base;
-      base = gen_rtx_REG (Pmode, BASE_REGISTER);
-      base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 101);
-      operands[0] = gen_rtx_PLUS (Pmode, base, operands[0]);
-    }
-}")
+  if (get_attr_op_type (insn) == OP_TYPE_RR)
+    return \"br\\t%0\";
+  else
+    return \"b\\t%a0\";
+}"
+  [(set (attr "op_type") 
+        (if_then_else (match_operand 0 "register_operand" "")
+                      (const_string "RR") (const_string "RX")))
+   (set_attr "atype" "mem")])
 
-(define_insn "*tablejump1"
-  [(set (pc) (match_operand 0 "register_operand" "a"))
-   (use (label_ref (match_operand 1 "" "")))]
+(define_expand "casesi"
+  [(match_operand:SI 0 "general_operand" "")
+   (match_operand:SI 1 "general_operand" "")
+   (match_operand:SI 2 "general_operand" "")
+   (label_ref (match_operand 3 "" ""))
+   (label_ref (match_operand 4 "" ""))]
   ""
-  "br\\t%0"
-  [(set_attr "op_type" "RX")])
+  "
+{
+   rtx index  = gen_reg_rtx (SImode);
+   rtx base   = gen_reg_rtx (Pmode);
+   rtx target = gen_reg_rtx (Pmode);
+
+   emit_move_insn (index, operands[0]);
+   emit_insn (gen_subsi3 (index, index, operands[1]));
+   emit_cmp_and_jump_insns (index, operands[2], GTU, NULL_RTX, SImode, 1,
+                            0, operands[4]);
+
+   if (Pmode != SImode)
+     index = convert_to_mode (Pmode, index, 1);
+   if (GET_CODE (index) != REG)
+     index = copy_to_mode_reg (Pmode, index);
+
+   if (TARGET_64BIT)
+       emit_insn (gen_ashldi3 (index, index, GEN_INT (3)));
+   else
+       emit_insn (gen_ashlsi3 (index, index, GEN_INT (2)));
 
-(define_insn "*tablejump2"
-  [(set (pc) (match_operand 0 "address_operand" "p"))
-   (use (label_ref (match_operand 1 "" "")))]
-  ""
-  "b\\t%a0"
-  [(set_attr "op_type" "RX")
-   (set_attr "atype"   "mem")])
+   emit_move_insn (base, gen_rtx_LABEL_REF (Pmode, operands[3]));
+
+   index = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, base, index));
+   emit_move_insn (target, index);
+
+   if (flag_pic)
+     target = gen_rtx_PLUS (Pmode, base, target);
+   emit_jump_insn (gen_casesi_jump (target, operands[3]));
+
+   DONE;
+}")
 
 
 ;;
   ""
   "
 {
-  emit_insn (gen_do_builtin_setjmp_setup (operands[0]));
+  rtx base = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4 * GET_MODE_SIZE (Pmode)));
+  rtx basereg = gen_rtx_REG (Pmode, BASE_REGISTER);
+
+  emit_move_insn (base, basereg);
   DONE;
 }")
 
 (define_expand "builtin_setjmp_receiver"
   [(unspec_volatile [(label_ref (match_operand 0 "" ""))] 2)]
-  ""
+  "flag_pic"
   "
 {
-  emit_insn (gen_blockage ());
+  rtx gotreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
+  rtx got = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\");
+  SYMBOL_REF_FLAG (got) = 1;
+
+  emit_move_insn (gotreg, got);
+  emit_insn (gen_rtx_USE (VOIDmode, gotreg));
   DONE;
 }")
 
-(define_expand "do_builtin_setjmp_setup"
-  [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "a")
-                  (const_int 12)))
-      (reg:SI 12))
-   (set (mem:SI (plus:SI (match_dup 0)
-                  (const_int 16)))
-      (reg:SI 13)) ]
-  ""
-  "")
-
 (define_expand "builtin_longjmp"
   [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)]
   ""
 {
   /* The elements of the buffer are, in order:  */
   rtx fp = gen_rtx_MEM (Pmode, operands[0]);
-  rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4));
-  rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 8));
-  rtx gotv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 12));
-  rtx basev = gen_rtx_MEM (Pmode, plus_constant (operands[0], 16));
-  rtx base = gen_rtx_REG (Pmode, 13);
-  rtx got = gen_rtx_REG (Pmode, 12);
+  rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], GET_MODE_SIZE (Pmode)));
+  rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2 * GET_MODE_SIZE (Pmode)));
+  rtx base = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4 * GET_MODE_SIZE (Pmode)));
+  rtx basereg = gen_rtx_REG (Pmode, BASE_REGISTER);
   rtx jmp = gen_rtx_REG (Pmode, 14);
 
   emit_move_insn (jmp, lab);
-  emit_move_insn (got, gotv);
-  emit_move_insn (base, basev);
+  emit_move_insn (basereg, base);
   emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
   emit_move_insn (hard_frame_pointer_rtx, fp);
 
   emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
   emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
-  emit_insn (gen_rtx_USE (VOIDmode, got));
-  emit_insn (gen_rtx_USE (VOIDmode, base));
+  emit_insn (gen_rtx_USE (VOIDmode, basereg));
   emit_indirect_jump (jmp);
   DONE;
 }")