OSDN Git Service

* hooks.h (hook_tree_tree_tree_bool_null): Rename to...
[pf3gnuchains/gcc-fork.git] / gcc / config / alpha / alpha.c
index 46ad8f4..2cc173f 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines used for code generation on the DEC Alpha.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
@@ -388,7 +388,7 @@ override_options (void)
            break;
          }
       if (i == ct_size)
-       error ("bad value %qs for -mcpu switch", alpha_tune_string);
+       error ("bad value %qs for -mtune switch", alpha_tune_string);
     }
 
   /* Do some sanity checks on the above options.  */
@@ -1475,6 +1475,10 @@ get_aligned_mem (rtx ref, rtx *paligned_mem, rtx *pbitnum)
   else
     offset = disp & 3;
 
+  /* The location should not cross aligned word boundary.  */
+  gcc_assert (offset + GET_MODE_SIZE (GET_MODE (ref))
+             <= GET_MODE_SIZE (SImode));
+
   /* Access the entire aligned word.  */
   *paligned_mem = widen_memory_access (ref, SImode, -offset);
 
@@ -4728,7 +4732,7 @@ alpha_split_lock_test_and_set_12 (enum machine_mode mode, rtx dest, rtx addr,
 static int
 alpha_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
 {
-  enum attr_type insn_type, dep_insn_type;
+  enum attr_type dep_insn_type;
 
   /* If the dependence is an anti-dependence, there is no cost.  For an
      output dependence, there is sometimes a cost, but it doesn't seem
@@ -4740,7 +4744,6 @@ alpha_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
   if (recog_memoized (insn) < 0 || recog_memoized (dep_insn) < 0)
     return cost;
 
-  insn_type = get_attr_type (insn);
   dep_insn_type = get_attr_type (dep_insn);
 
   /* Bring in the user-defined memory latency.  */
@@ -5541,34 +5544,23 @@ print_operand_address (FILE *file, rtx addr)
 }
 \f
 /* Emit RTL insns to initialize the variable parts of a trampoline at
-   TRAMP. FNADDR is an RTX for the address of the function's pure
-   code.  CXT is an RTX for the static chain value for the function.
-
-   The three offset parameters are for the individual template's
-   layout.  A JMPOFS < 0 indicates that the trampoline does not
-   contain instructions at all.
-
-   We assume here that a function will be called many more times than
-   its address is taken (e.g., it might be passed to qsort), so we
-   take the trouble to initialize the "hint" field in the JMP insn.
-   Note that the hint field is PC (new) + 4 * bits 13:0.  */
+   M_TRAMP.  FNDECL is target function's decl.  CHAIN_VALUE is an rtx
+   for the static chain value for the function.  */
 
-void
-alpha_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt,
-                            int fnofs, int cxtofs, int jmpofs)
+static void
+alpha_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
 {
-  rtx addr;
-  /* VMS really uses DImode pointers in memory at this point.  */
-  enum machine_mode mode = TARGET_ABI_OPEN_VMS ? Pmode : ptr_mode;
+  rtx fnaddr, mem, word1, word2;
+
+  fnaddr = XEXP (DECL_RTL (fndecl), 0);
 
 #ifdef POINTERS_EXTEND_UNSIGNED
-  fnaddr = convert_memory_address (mode, fnaddr);
-  cxt = convert_memory_address (mode, cxt);
+  fnaddr = convert_memory_address (Pmode, fnaddr);
+  chain_value = convert_memory_address (Pmode, chain_value);
 #endif
 
   if (TARGET_ABI_OPEN_VMS)
     {
-      rtx temp1, traddr;
       const char *fnname;
       char *trname;
 
@@ -5577,37 +5569,48 @@ alpha_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt,
       trname = (char *) alloca (strlen (fnname) + 5);
       strcpy (trname, fnname);
       strcat (trname, "..tr");
-      traddr = gen_rtx_SYMBOL_REF
-       (mode, ggc_alloc_string (trname, strlen (trname) + 1));
+      fnname = ggc_alloc_string (trname, strlen (trname) + 1);
+      word2 = gen_rtx_SYMBOL_REF (Pmode, fnname);
 
       /* Trampoline (or "bounded") procedure descriptor is constructed from
         the function's procedure descriptor with certain fields zeroed IAW
         the VMS calling standard. This is stored in the first quadword.  */
-      temp1 = force_reg (DImode, gen_rtx_MEM (DImode, fnaddr));
-      temp1 = expand_and (DImode, temp1,
-                         GEN_INT (0xffff0fff0000fff0), NULL_RTX);
-      addr = memory_address (mode, plus_constant (tramp, 0));
-      emit_move_insn (gen_rtx_MEM (DImode, addr), temp1);
-
-      /* Trampoline transfer address is stored in the second quadword
-        of the trampoline.  */
-      addr = memory_address (mode, plus_constant (tramp, 8));
-      emit_move_insn (gen_rtx_MEM (mode, addr), traddr);
+      word1 = force_reg (DImode, gen_const_mem (DImode, fnaddr));
+      word1 = expand_and (DImode, word1, GEN_INT (0xffff0fff0000fff0), NULL);
     }
+  else
+    {
+      /* These 4 instructions are:
+           ldq $1,24($27)
+           ldq $27,16($27)
+           jmp $31,($27),0
+           nop
+        We don't bother setting the HINT field of the jump; the nop
+        is merely there for padding.  */
+      word1 = GEN_INT (0xa77b0010a43b0018);
+      word2 = GEN_INT (0x47ff041f6bfb0000);
+    }
+
+  /* Store the first two words, as computed above.  */
+  mem = adjust_address (m_tramp, DImode, 0);
+  emit_move_insn (mem, word1);
+  mem = adjust_address (m_tramp, DImode, 8);
+  emit_move_insn (mem, word2);
+
+  /* Store function address and static chain value.  */
+  mem = adjust_address (m_tramp, Pmode, 16);
+  emit_move_insn (mem, fnaddr);
+  mem = adjust_address (m_tramp, Pmode, 24);
+  emit_move_insn (mem, chain_value);
 
-  /* Store function address and CXT.  */
-  addr = memory_address (mode, plus_constant (tramp, fnofs));
-  emit_move_insn (gen_rtx_MEM (mode, addr), fnaddr);
-  addr = memory_address (mode, plus_constant (tramp, cxtofs));
-  emit_move_insn (gen_rtx_MEM (mode, addr), cxt);
-
+  if (!TARGET_ABI_OPEN_VMS)
+    {
+      emit_insn (gen_imb ());
 #ifdef ENABLE_EXECUTE_STACK
-  emit_library_call (init_one_libfunc ("__enable_execute_stack"),
-                    LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
+      emit_library_call (init_one_libfunc ("__enable_execute_stack"),
+                        LCT_NORMAL, VOIDmode, 1, XEXP (m_tramp, 0), Pmode);
 #endif
-
-  if (jmpofs >= 0)
-    emit_insn (gen_imb ());
+    }
 }
 \f
 /* Determine where to put an argument to a function.
@@ -5851,7 +5854,7 @@ rtx
 function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED,
                enum machine_mode mode)
 {
-  unsigned int regnum, dummy;
+  unsigned int regnum, dummy ATTRIBUTE_UNUSED;
   enum mode_class mclass;
 
   gcc_assert (!valtype || !alpha_return_in_memory (valtype, func));
@@ -6339,7 +6342,7 @@ alpha_gimplify_va_arg_1 (tree type, tree base, tree offset,
     }
 
   addend = offset;
-  ptr_type = build_pointer_type (type);
+  ptr_type = build_pointer_type_for_mode (type, ptr_mode, true);
 
   if (TREE_CODE (type) == COMPLEX_TYPE)
     {
@@ -6420,7 +6423,7 @@ alpha_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
 
   indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
   if (indirect)
-    type = build_pointer_type (type);
+    type = build_pointer_type_for_mode (type, ptr_mode, true);
 
   /* Find the value.  Note that this will be a stable indirection, or
      a composite of stable indirections in the case of complex.  */
@@ -7135,26 +7138,27 @@ alpha_fold_builtin_ctpop (unsigned HOST_WIDE_INT opint[], long op_const)
 /* Fold one of our builtin functions.  */
 
 static tree
-alpha_fold_builtin (tree fndecl, tree arglist, bool ignore ATTRIBUTE_UNUSED)
+alpha_fold_builtin (tree fndecl, int n_args, tree *op,
+                   bool ignore ATTRIBUTE_UNUSED)
 {
-  tree op[MAX_ARGS], t;
   unsigned HOST_WIDE_INT opint[MAX_ARGS];
-  long op_const = 0, arity = 0;
+  long op_const = 0;
+  int i;
+
+  if (n_args >= MAX_ARGS)
+    return NULL;
 
-  for (t = arglist; t ; t = TREE_CHAIN (t), ++arity)
+  for (i = 0; i < n_args; i++)
     {
-      tree arg = TREE_VALUE (t);
+      tree arg = op[i];
       if (arg == error_mark_node)
        return NULL;
-      if (arity >= MAX_ARGS)
-       return NULL;
 
-      op[arity] = arg;
-      opint[arity] = 0;
+      opint[i] = 0;
       if (TREE_CODE (arg) == INTEGER_CST)
        {
-          op_const |= 1L << arity;
-         opint[arity] = int_cst_value (arg);
+          op_const |= 1L << i;
+         opint[i] = int_cst_value (arg);
        }
     }
 
@@ -11114,6 +11118,8 @@ alpha_init_libfuncs (void)
 #define TARGET_GIMPLIFY_VA_ARG_EXPR alpha_gimplify_va_arg
 #undef TARGET_ARG_PARTIAL_BYTES
 #define TARGET_ARG_PARTIAL_BYTES alpha_arg_partial_bytes
+#undef TARGET_TRAMPOLINE_INIT
+#define TARGET_TRAMPOLINE_INIT alpha_trampoline_init
 
 #undef TARGET_SECONDARY_RELOAD
 #define TARGET_SECONDARY_RELOAD alpha_secondary_reload