i386.c (ix86_cmodel_string, [...]): Define.
authorJan Hubicka <jh@suse.cz>
Wed, 14 Mar 2001 21:35:58 +0000 (22:35 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 14 Mar 2001 21:35:58 +0000 (21:35 +0000)
* i386.c (ix86_cmodel_string, ix86_cmodel): Define.
(override_options): Parse cmodel string.
(x86_64_sign_extended_value, x86_64_zero_extended_value): New.
* i386.h (TARGET_OPTIONS): Add "cmodel".
(EXTRA_CONSTRAINT): Recognize 'e' and 'Z'.
(enum cmodel): New.
(ix86_cmodel_string, ix86_cmodel): Declare.

Spot by Matt Kraai:
* i386.h (GENERAL_REG_P): Add missing REG_P.

From-SVN: r40474

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h

index e68a5faf1350b98fbf89b7946fb101628cf4d927..d4997cb2af59f3a9a71844360e33862f92bb0908 100644 (file)
@@ -1,3 +1,18 @@
+Wed Mar 14 22:26:10 CET 2001  Jan Hubicka  <jh@suse.cz>
+
+       * i386.c (ix86_cmodel_string, ix86_cmodel): Define.
+       (override_options): Parse cmodel string.
+       (x86_64_sign_extended_value, x86_64_zero_extended_value): New.
+       * i386.h (TARGET_OPTIONS): Add "cmodel".
+       (EXTRA_CONSTRAINT): Recognize 'e' and 'Z'.
+       (enum cmodel): New.
+       (ix86_cmodel_string, ix86_cmodel): Declare.
+
+Wed Mar 14 22:26:54 CET 2001  Jan Hubicka  <jh@suse.cz>
+
+       Spot by Matt Kraai:
+       * i386.h (GENERAL_REG_P): Add missing REG_P.
+
 2001-03-14  Laurynas Biveinis  <lauras@softhome.net>
 
        * configure.in: Use $gcc_cv_as instead of $as.
index 70fd21d384a2804e54ab4ee920531a14775dcf95..16dfe454b3976f59ea11432c211ff49ee033d21e 100644 (file)
@@ -487,6 +487,11 @@ struct ix86_frame
   HOST_WIDE_INT stack_pointer_offset;
 };
 
+/* Code model option as passed by user.  */
+const char *ix86_cmodel_string;
+/* Parsed value.  */
+enum cmodel ix86_cmodel;
+
 /* which cpu are we scheduling for */
 enum processor_type ix86_cpu;
 
@@ -659,6 +664,35 @@ override_options ()
   ix86_arch = PROCESSOR_I386;
   ix86_cpu = (enum processor_type) TARGET_CPU_DEFAULT;
 
+  if (ix86_cmodel_string != 0)
+    {
+      if (!strcmp (ix86_cmodel_string, "small"))
+       ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+      else if (flag_pic)
+       sorry ("Code model %s not supported in PIC mode", ix86_cmodel_string);
+      else if (!strcmp (ix86_cmodel_string, "32"))
+       ix86_cmodel = CM_32;
+      else if (!strcmp (ix86_cmodel_string, "kernel") && !flag_pic)
+       ix86_cmodel = CM_KERNEL;
+      else if (!strcmp (ix86_cmodel_string, "medium") && !flag_pic)
+       ix86_cmodel = CM_MEDIUM;
+      else if (!strcmp (ix86_cmodel_string, "large") && !flag_pic)
+       ix86_cmodel = CM_LARGE;
+      else
+       error ("bad value (%s) for -mcmodel= switch", ix86_cmodel_string);
+    }
+  else
+    {
+      ix86_cmodel = CM_32;
+      if (TARGET_64BIT)
+       ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+    }
+  if ((TARGET_64BIT == 0) != (ix86_cmodel == CM_32))
+    error ("Code model `%s' not supported in the %s bit mode.",
+          ix86_cmodel_string, TARGET_64BIT ? "64" : "32");
+  if (ix86_cmodel == CM_LARGE)
+    sorry ("Code model `large' not supported yet.");
+
   if (ix86_arch_string != 0)
     {
       for (i = 0; i < pta_size; i++)
@@ -1793,6 +1827,171 @@ ix86_can_use_return_insn_p ()
   ix86_compute_frame_layout (&frame);
   return frame.to_allocate == 0 && frame.nregs == 0;
 }
+\f
+/* Return 1 if VALUE can be stored in the sign extended immediate field.  */
+int
+x86_64_sign_extended_value (value)
+     rtx value;
+{
+  switch (GET_CODE (value))
+    {
+      /* CONST_DOUBLES never match, since HOST_BITS_PER_WIDE_INT is known
+         to be at least 32 and this all acceptable constants are
+        represented as CONST_INT.  */
+      case CONST_INT:
+       if (HOST_BITS_PER_WIDE_INT == 32)
+         return 1;
+       else
+         {
+           HOST_WIDE_INT val = trunc_int_for_mode (INTVAL (value), DImode);
+           return (HOST_WIDE_INT)(int)val == val;
+         }
+       break;
+
+      /* For certain code models, the symbolic references are known to fit.  */
+      case SYMBOL_REF:
+       return ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL;
+
+      /* For certain code models, the code is near as well.  */
+      case LABEL_REF:
+       return ix86_cmodel != CM_LARGE && ix86_cmodel != CM_SMALL_PIC;
+
+      /* We also may accept the offsetted memory references in certain special
+         cases.  */
+      case CONST:
+       if (GET_CODE (XEXP (value, 0)) == UNSPEC
+           && XVECLEN (XEXP (value, 0), 0) == 1
+           && XINT (XEXP (value, 0), 1) ==  15)
+         return 1;
+       else if (GET_CODE (XEXP (value, 0)) == PLUS)
+         {
+           rtx op1 = XEXP (XEXP (value, 0), 0);
+           rtx op2 = XEXP (XEXP (value, 0), 1);
+           HOST_WIDE_INT offset;
+
+           if (ix86_cmodel == CM_LARGE)
+             return 0;
+           if (GET_CODE (op2) != CONST_INT)
+             return 0;
+           offset = trunc_int_for_mode (INTVAL (op2), DImode);
+           switch (GET_CODE (op1))
+             {
+               case SYMBOL_REF:
+                 /* For CM_SMALL assume that latest object is 1MB before
+                    end of 31bits boundary.  We may also accept pretty
+                    large negative constants knowing that all objects are
+                    in the positive half of address space.  */
+                 if (ix86_cmodel == CM_SMALL
+                     && offset < 1024*1024*1024
+                     && trunc_int_for_mode (offset, SImode) == offset)
+                   return 1;
+                 /* For CM_KERNEL we know that all object resist in the
+                    negative half of 32bits address space.  We may not
+                    accept negative offsets, since they may be just off
+                    and we may accept pretty large possitive ones.  */
+                 if (ix86_cmodel == CM_KERNEL
+                     && offset > 0
+                     && trunc_int_for_mode (offset, SImode) == offset)
+                   return 1;
+                 break;
+               case LABEL_REF:
+                 /* These conditions are similar to SYMBOL_REF ones, just the
+                    constraints for code models differ.  */
+                 if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
+                     && offset < 1024*1024*1024
+                     && trunc_int_for_mode (offset, SImode) == offset)
+                   return 1;
+                 if (ix86_cmodel == CM_KERNEL
+                     && offset > 0
+                     && trunc_int_for_mode (offset, SImode) == offset)
+                   return 1;
+                 break;
+               default:
+                 return 0;
+             }
+         }
+       return 0;
+      default:
+       return 0;
+    }
+}
+
+/* Return 1 if VALUE can be stored in the zero extended immediate field.  */
+int
+x86_64_zero_extended_value (value)
+     rtx value;
+{
+  switch (GET_CODE (value))
+    {
+      case CONST_DOUBLE:
+       if (HOST_BITS_PER_WIDE_INT == 32)
+         return  (GET_MODE (value) == VOIDmode
+                  && !CONST_DOUBLE_HIGH (value));
+       else
+         return 0;
+      case CONST_INT:
+       if (HOST_BITS_PER_WIDE_INT == 32)
+         return INTVAL (value) >= 0;
+       else
+         return !(INTVAL (value) & ~(HOST_WIDE_INT)0xffffffff);
+       break;
+
+      /* For certain code models, the symbolic references are known to fit.  */
+      case SYMBOL_REF:
+       return ix86_cmodel == CM_SMALL;
+
+      /* For certain code models, the code is near as well.  */
+      case LABEL_REF:
+       return ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM;
+
+      /* We also may accept the offsetted memory references in certain special
+         cases.  */
+      case CONST:
+       if (GET_CODE (XEXP (value, 0)) == PLUS)
+         {
+           rtx op1 = XEXP (XEXP (value, 0), 0);
+           rtx op2 = XEXP (XEXP (value, 0), 1);
+
+           if (ix86_cmodel == CM_LARGE)
+             return 0;
+           switch (GET_CODE (op1))
+             {
+               case SYMBOL_REF:
+                   return 0;
+                 /* For small code model we may accept pretty large possitive
+                    offsets, since one bit is available for free.  Negative
+                    offsets are limited by the size of NULL pointer area
+                    specified by the ABI.  */
+                 if (ix86_cmodel == CM_SMALL
+                     && GET_CODE (op2) == CONST_INT
+                     && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
+                     && (trunc_int_for_mode (INTVAL (op2), SImode)
+                         == INTVAL (op2)))
+                   return 1;
+                 /* ??? For the kernel, we may accept adjustment of
+                    -0x10000000, since we know that it will just convert
+                    negative address space to possitive, but perhaps this
+                    is not worthwhile.  */
+                 break;
+               case LABEL_REF:
+                 /* These conditions are similar to SYMBOL_REF ones, just the
+                    constraints for code models differ.  */
+                 if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
+                     && GET_CODE (op2) == CONST_INT
+                     && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
+                     && (trunc_int_for_mode (INTVAL (op2), SImode)
+                         == INTVAL (op2)))
+                   return 1;
+                 break;
+               default:
+                 return 0;
+             }
+         }
+       return 0;
+      default:
+       return 0;
+    }
+}
 
 /* Value should be nonzero if functions must have frame pointers.
    Zero means the frame pointer need not be set up (and parms may
index df06a2f3378fcce2979f0dc3557daf803089ce65..02c6e2a03cc1fb62774aa9cbd5f334f71957eb66 100644 (file)
@@ -393,6 +393,8 @@ extern int ix86_arch;
     N_("Attempt to keep stack aligned to this power of 2") },  \
   { "branch-cost=",    &ix86_branch_cost_string,               \
     N_("Branches are this expensive (1-5, arbitrary units)") },        \
+  { "cmodel=", &ix86_cmodel_string,                            \
+    N_("Use given x86-64 code model") },                       \
   SUBTARGET_OPTIONS                                            \
 }
 
@@ -1138,7 +1140,7 @@ enum reg_class
   ((n) < 8 || REX_INT_REGNO_P (n))
 
 #define GENERAL_REG_P(X) \
-  (REG_P (X) && GENERAL_REGNO_P (X))
+  (REG_P (X) && GENERAL_REGNO_P (REGNO (X)))
 
 #define ANY_QI_REG_P(X) (TARGET_64BIT ? GENERAL_REG_P(X) : QI_REG_P (X))
 
@@ -1247,6 +1249,23 @@ enum reg_class
   ((C) == 'G' ? standard_80387_constant_p (VALUE) \
    : ((C) == 'H' ? standard_sse_constant_p (VALUE) : 0))
 
+/* A C expression that defines the optional machine-dependent
+   constraint letters that can be used to segregate specific types of
+   operands, usually memory references, for the target machine.  Any
+   letter that is not elsewhere defined and not matched by
+   `REG_CLASS_FROM_LETTER' may be used.  Normally this macro will not
+   be defined.
+
+   If it is required for a particular target machine, it should
+   return 1 if VALUE corresponds to the operand type represented by
+   the constraint letter C.  If C is not defined as an extra
+   constraint, the value returned should be 0 regardless of VALUE.  */
+
+#define EXTRA_CONSTRAINT(VALUE, C)                             \
+  ((C) == 'e' ? x86_64_sign_extended_value (VALUE)             \
+   : (C) == 'Z' ? x86_64_zero_extended_value (VALUE)           \
+   : 0)
+
 /* Place additional restrictions on the register class to use when it
    is necessary to be able to hold a value of mode MODE in a reload
    register for which class CLASS would ordinarily be used. */
@@ -3051,6 +3070,31 @@ do { long l;                                             \
 #define SPECIAL_MODE_PREDICATES \
   "ext_register_operand",
 \f
+/* CM_32 is used by 32bit ABI
+   CM_SMALL is small model assuming that all code and data fits in the first
+   31bits of address space.
+   CM_KERNEL is model assuming that all code and data fits in the negative
+   31bits of address space.
+   CM_MEDIUM is model assuming that code fits in the first 31bits of address
+   space.  Size of data is unlimited.
+   CM_LARGE is model making no assumptions about size of particular sections.
+  
+   CM_SMALL_PIC is model for PIC libraries assuming that code+data+got/plt
+   tables first in 31bits of address space.
+ */
+enum cmodel {
+  CM_32,
+  CM_SMALL,
+  CM_KERNEL,
+  CM_MEDIUM,
+  CM_LARGE,
+  CM_SMALL_PIC
+};
+
+/* Valud of -mcmodel specified by user.  */
+extern const char *ix86_cmodel_string;
+extern enum cmodel ix86_cmodel;
+\f
 /* Variables in i386.c */
 extern const char *ix86_cpu_string;            /* for -mcpu=<xxx> */
 extern const char *ix86_arch_string;           /* for -march=<xxx> */