OSDN Git Service

(vax_rtx_cost): Remove LSHIFT case.
[pf3gnuchains/gcc-fork.git] / gcc / config / vax / vax.h
index 459fda9..36cf4a7 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions of target machine for GNU compiler.  Vax version.
-   Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991, 1993, 1994 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -20,7 +20,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* Names to predefine in the preprocessor for this target machine.  */
 
-#define CPP_PREDEFINES "-Dvax -Dunix"
+#define CPP_PREDEFINES "-Dvax -Dunix -Asystem(unix) -Asystem(bsd) -Acpu(vax) -Amachine(vax)"
 
 /* If using g-format floating point, alter math.h.  */
 
@@ -79,6 +79,10 @@ extern int target_flags;
 \f
 /* Target machine storage layout */
 
+/* Define for software floating point emulation of VAX format
+   when cross compiling from a non-VAX host. */
+/* #define REAL_ARITHMETIC */
+
 /* Define this if most significant bit is lowest numbered
    in instructions that operate on numbered bit-fields.
    This is not true on the vax.  */
@@ -93,7 +97,7 @@ extern int target_flags;
 /* This is not true on the vax.  */
 #define WORDS_BIG_ENDIAN 0
 
-/* Number of bits in an addressible storage unit */
+/* Number of bits in an addressable storage unit */
 #define BITS_PER_UNIT 8
 
 /* Width in bits of a "word", which is the contents of a machine register.
@@ -130,9 +134,12 @@ extern int target_flags;
 /* No structure field wants to be aligned rounder than this.  */
 #define BIGGEST_FIELD_ALIGNMENT (TARGET_VAXC_ALIGNMENT ? 8 : 32)
 
-/* Define this if move instructions will actually fail to work
+/* Set this nonzero if move instructions will actually fail to work
    when given unaligned data.  */
-/* #define STRICT_ALIGNMENT */
+#define STRICT_ALIGNMENT 0
+
+/* Let's keep the stack somewhat aligned.  */
+#define STACK_BOUNDARY 32
 \f
 /* Standard register usage.  */
 
@@ -283,6 +290,16 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
                 || (VALUE) == CONST0_RTX (SFmode))     \
    : 0)
 
+/* Optional extra constraints for this machine.
+
+   For the VAX, `Q' means that OP is a MEM that does not have a mode-dependent
+   address.  */
+
+#define EXTRA_CONSTRAINT(OP, C) \
+  ((C) == 'Q'                                                          \
+   ? GET_CODE (OP) == MEM && ! mode_dependent_address_p (XEXP (OP, 0)) \
+   : 0)
+
 /* Given an rtx X being reloaded into a reg required to be
    in class CLASS, return the class of reg to actually use.
    In general this is just CLASS; but on some machines
@@ -319,6 +336,12 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
    of the first local allocated.  */
 #define STARTING_FRAME_OFFSET 0
 
+/* Given an rtx for the address of a frame,
+   return an rtx for the address of the word in the frame
+   that holds the dynamic chain--the previous frame's address.  */
+#define DYNAMIC_CHAIN_ADDRESS(frame) \
+gen_rtx (PLUS, Pmode, frame, gen_rtx (CONST_INT, VOIDmode, 12))
+
 /* If we generate an insn to push BYTES bytes,
    this says how many the stack pointer really advances by.
    On the vax, -(sp) pushes only the bytes of the operands.  */
@@ -518,6 +541,8 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
    to the start of the trampoline.  */
 #define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT)                      \
 {                                                                      \
+  emit_insn (gen_rtx (ASM_INPUT, VOIDmode,                             \
+                     "movpsl -(sp)\n\tpushal 1(pc)\n\trei"));          \
   emit_move_insn (gen_rtx (MEM, HImode, TRAMP),                                \
                  gen_rtx (MEM, HImode, FNADDR));                       \
   emit_move_insn (gen_rtx (MEM, SImode, plus_constant (TRAMP, 4)), CXT);\
@@ -552,7 +577,10 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 
 /* 1 if X is an rtx for a constant that is a valid address.  */
 
-#define CONSTANT_ADDRESS_P(X) CONSTANT_P (X)
+#define CONSTANT_ADDRESS_P(X)   \
+  (GET_CODE (X) == LABEL_REF || GET_CODE (X) == SYMBOL_REF             \
+   || GET_CODE (X) == CONST_INT || GET_CODE (X) == CONST               \
+   || GET_CODE (X) == HIGH)
 
 /* Nonzero if the constant value X is a legitimate general operand.
    It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.  */
@@ -649,7 +677,14 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
    (This much is the easy part.)  */
 #define GO_IF_NONINDEXED_ADDRESS(X, ADDR)  \
 { register rtx xfoob = (X);                                            \
-  if (GET_CODE (xfoob) == REG) goto ADDR;                              \
+  if (GET_CODE (xfoob) == REG)                                         \
+    {                                                                  \
+      extern rtx *reg_equiv_mem;                                       \
+      if (! reload_in_progress                                         \
+         || reg_equiv_mem[REGNO (xfoob)] == 0                          \
+         || INDIRECTABLE_ADDRESS_P (reg_equiv_mem[REGNO (xfoob)]))     \
+       goto ADDR;                                                      \
+    }                                                                  \
   if (CONSTANT_ADDRESS_P (xfoob)) goto ADDR;                           \
   if (INDIRECTABLE_ADDRESS_P (xfoob)) goto ADDR;                       \
   xfoob = XEXP (X, 0);                                                 \
@@ -816,32 +851,45 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
    of a switch statement.  If the code is computed here,
    return it with a return statement.  Otherwise, break from the switch.  */
 
-#define CONST_COSTS(RTX,CODE) \
+/* On a VAX, constants from 0..63 are cheap because they can use the
+   1 byte literal constant format.  compare to -1 should be made cheap
+   so that decrement-and-branch insns can be formed more easily (if
+   the value -1 is copied to a register some decrement-and-branch patterns
+   will not match).  */
+
+#define CONST_COSTS(RTX,CODE,OUTER_CODE) \
   case CONST_INT:                                              \
-    /* Constant zero is super cheap due to clr instruction.  */        \
-    if ((RTX) == const0_rtx) return 0;                         \
-    /* Constants of +/- 1 should also be super cheap since     \
-       may be used in decl/incl/aob/sob insns.  */             \
-    if ((RTX) == const1_rtx || (RTX) == constm1_rtx) return 0; \
-    if ((unsigned) INTVAL (RTX) < 077) return 1;               \
+    if (INTVAL (RTX) == 0) return 0;                           \
+    if ((OUTER_CODE) == AND)                                   \
+      return ((unsigned) ~INTVAL (RTX) <= 077) ? 1 : 2;                \
+    if ((unsigned) INTVAL (RTX) <= 077) return 1;              \
+    if ((OUTER_CODE) == COMPARE && INTVAL (RTX) == -1)         \
+      return 1;                                                        \
+    if ((OUTER_CODE) == PLUS && (unsigned) -INTVAL (RTX) <= 077)\
+      return 1;                                                        \
   case CONST:                                                  \
   case LABEL_REF:                                              \
   case SYMBOL_REF:                                             \
     return 3;                                                  \
   case CONST_DOUBLE:                                           \
-    return 5;
-
-/* On most VAX models, shift are almost as expensive as multiplies, so
-   we'd rather use multiply unless it can be done in an extremely small
-   sequence.  */
-#define RTX_COSTS(RTX,CODE) \
- case LSHIFT:  \
- case ASHIFT:  \
- case ASHIFTRT:        \
- case LSHIFTRT:        \
- case ROTATE:  \
- case ROTATERT:        \
-  return COSTS_N_INSNS (4);
+    if (GET_MODE_CLASS (GET_MODE (RTX)) == MODE_FLOAT)         \
+      return vax_float_literal (RTX) ? 5 : 8;                  \
+    else                                                       \
+      return (((CONST_DOUBLE_HIGH (RTX) == 0                   \
+               && (unsigned) CONST_DOUBLE_LOW (RTX) < 64)      \
+              || ((OUTER_CODE) == PLUS                         \
+                  && CONST_DOUBLE_HIGH (RTX) == -1             \
+                  && (unsigned)-CONST_DOUBLE_LOW (RTX) < 64))  \
+             ? 2 : 5);
+
+#define RTX_COSTS(RTX,CODE,OUTER_CODE) case FIX: case FLOAT:   \
+ case MULT: case DIV: case UDIV: case MOD: case UMOD:          \
+ case ASHIFT: case LSHIFTRT: case ASHIFTRT:                    \
+ case ROTATE: case ROTATERT: case PLUS: case MINUS: case IOR:  \
+ case XOR: case AND: case NEG: case NOT: case ZERO_EXTRACT:    \
+ case SIGN_EXTRACT: case MEM: return vax_rtx_cost(RTX)
+
+#define        ADDRESS_COST(RTX) (1 + (GET_CODE (RTX) == REG ? 0 : vax_address_cost(RTX)))
 
 /* Specify the cost of a branch insn; roughly the number of extra insns that
    should be added to avoid a branch.
@@ -861,24 +909,11 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 
 /* Check a `double' value for validity for a particular machine mode.  */
 
-/* note that it is very hard to accidently create a number that fits in a
+/* note that it is very hard to accidentally create a number that fits in a
    double but not in a float, since their ranges are almost the same */
-#define CHECK_FLOAT_VALUE(mode, d) \
-  if ((mode) == SFmode) \
-    { \
-      if ((d) > 1.7014117331926444e+38) \
-       { error ("magnitude of constant too large for `float'"); \
-         (d) = 1.7014117331926444e+38; } \
-      else if ((d) < -1.7014117331926444e+38) \
-       { error ("magnitude of constant too large for `float'"); \
-         (d) = -1.7014117331926444e+38; } \
-      else if (((d) > 0) && ((d) < 2.9387358770557188e-39)) \
-       { warning ("`float' constant truncated to zero"); \
-         (d) = 0.0; } \
-      else if (((d) < 0) && ((d) > -2.9387358770557188e-39)) \
-       { warning ("`float' constant truncated to zero"); \
-         (d) = 0.0; } \
-    }
+
+#define CHECK_FLOAT_VALUE(MODE, D, OVERFLOW) \
+  ((OVERFLOW) = check_float_value (MODE, &D, OVERFLOW))
 
 /* For future reference:
    D Float: 9 bit, sign magnitude, excess 128 binary exponent
@@ -1040,13 +1075,18 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
    It is .dfloat or .gfloat, depending.  */
 
 #define ASM_OUTPUT_DOUBLE(FILE,VALUE)  \
-  fprintf (FILE, "\t.%cfloat 0%c%.20e\n", ASM_DOUBLE_CHAR, \
-                                         ASM_DOUBLE_CHAR, (VALUE))
+do { char dstr[30];                                                    \
+     REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", dstr);                     \
+     fprintf (FILE, "\t.%cfloat 0%c%s\n", ASM_DOUBLE_CHAR,             \
+                                         ASM_DOUBLE_CHAR, dstr);       \
+   } while (0);
 
 /* This is how to output an assembler line defining a `float' constant.  */
 
 #define ASM_OUTPUT_FLOAT(FILE,VALUE)  \
-  fprintf (FILE, "\t.float 0f%.20e\n", (VALUE))
+  do { char dstr[30];                                          \
+       REAL_VALUE_TO_DECIMAL (VALUE, "%.20e", dstr);           \
+       fprintf (FILE, "\t.float 0f%s\n", dstr); } while (0);
 
 /* This is how to output an assembler line defining an `int' constant.  */
 
@@ -1151,15 +1191,25 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
 /* Print an instruction operand X on file FILE.
    CODE is the code from the %-spec that requested printing this operand;
    if `%z3' was used to print operand 3, then CODE is 'z'.
-   On the Vax, the codes used are:
-   `#', indicating that either `d' or `g' should be printed,
-   depending on whether we're using dfloat or gfloat.
-   `C', indicating the reverse of the condition name specified by the
-   operand.
-   `P', indicating one plus a constant operand
-   `N', indicating the one's complement of a constant operand
-   `H', indicating the low-order 16 bits of the one's complement of a constant
-   `B', similarly for the low-order 8 bits.  */
+
+VAX operand formatting codes:
+
+ letter           print
+   C   reverse branch condition
+   D   64-bit immediate operand
+   B   the low 8 bits of the complement of a constant operand
+   H   the low 16 bits of the complement of a constant operand
+   M   a mask for the N highest bits of a word
+   N   the complement of a constant integer operand
+   P   constant operand plus 1
+   R   32 - constant operand
+   b   the low 8 bits of a negated constant operand
+   h   the low 16 bits of a negated constant operand
+   #   'd' or 'g' depending on whether dfloat or gfloat is used  */
+
+/* The purpose of D is to get around a quirk or bug in vax assembler
+   whereby -1 in a 64-bit immediate operand means 0x00000000ffffffff,
+   which is not a 64-bit minus one.  */
 
 #define PRINT_OPERAND_PUNCT_VALID_P(CODE)                              \
   ((CODE) == '#')
@@ -1169,6 +1219,8 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
   if (CODE == '#') fputc (ASM_DOUBLE_CHAR, FILE);                      \
   else if (CODE == 'C')                                                        \
     fputs (rev_cond_name (X), FILE);                                   \
+  else if (CODE == 'D' && GET_CODE (X) == CONST_INT && INTVAL (X) < 0) \
+    fprintf (FILE, "$0xffffffff%08x", INTVAL (X));                     \
   else if (CODE == 'P' && GET_CODE (X) == CONST_INT)                   \
     fprintf (FILE, "$%d", INTVAL (X) + 1);                             \
   else if (CODE == 'N' && GET_CODE (X) == CONST_INT)                   \
@@ -1178,16 +1230,28 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
     fprintf (FILE, "$%d", 32 - INTVAL (X));                            \
   else if (CODE == 'H' && GET_CODE (X) == CONST_INT)                   \
     fprintf (FILE, "$%d", 0xffff & ~ INTVAL (X));                      \
+  else if (CODE == 'h' && GET_CODE (X) == CONST_INT)                   \
+    fprintf (FILE, "$%d", (short) - INTVAL (x));                       \
   else if (CODE == 'B' && GET_CODE (X) == CONST_INT)                   \
     fprintf (FILE, "$%d", 0xff & ~ INTVAL (X));                                \
+  else if (CODE == 'b' && GET_CODE (X) == CONST_INT)                   \
+    fprintf (FILE, "$%d", 0xff & - INTVAL (X));                                \
+  else if (CODE == 'M' && GET_CODE (X) == CONST_INT)                   \
+    fprintf (FILE, "$%d", ~((1 << INTVAL (x)) - 1));                   \
   else if (GET_CODE (X) == REG)                                                \
     fprintf (FILE, "%s", reg_names[REGNO (X)]);                                \
   else if (GET_CODE (X) == MEM)                                                \
     output_address (XEXP (X, 0));                                      \
-  else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) != DImode)     \
-    { union { double d; int i[2]; } u;                                 \
-      u.i[0] = CONST_DOUBLE_LOW (X); u.i[1] = CONST_DOUBLE_HIGH (X);   \
-      fprintf (FILE, "$0%c%.20e", ASM_DOUBLE_CHAR, u.d); }             \
+  else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == SFmode)     \
+    { REAL_VALUE_TYPE r; char dstr[30];                                        \
+      REAL_VALUE_FROM_CONST_DOUBLE (r, X);                             \
+      REAL_VALUE_TO_DECIMAL (r, "%.20e", dstr);                                \
+      fprintf (FILE, "$0f%s", dstr); }                                 \
+  else if (GET_CODE (X) == CONST_DOUBLE && GET_MODE (X) == DFmode)     \
+    { REAL_VALUE_TYPE r; char dstr[30];                                        \
+      REAL_VALUE_FROM_CONST_DOUBLE (r, X);                             \
+      REAL_VALUE_TO_DECIMAL (r, "%.20e", dstr);                                \
+      fprintf (FILE, "$0%c%s", ASM_DOUBLE_CHAR, dstr); }               \
   else { putc ('$', FILE); output_addr_const (FILE, X); }}
 
 /* Print a memory operand whose address is X, on file FILE.