/* 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)
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. */
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);
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
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. */
}
\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.
+ M_TRAMP. FNDECL is target function's decl. CHAIN_VALUE is an rtx
+ for the static chain value for the function. */
- 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. */
-
-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;
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.
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));
}
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)
{
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. */
/* 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);
}
}
#if TARGET_ABI_OPEN_VMS
-int
-alpha_vms_can_eliminate (unsigned int from ATTRIBUTE_UNUSED, unsigned int to)
+/* Worker function for TARGET_CAN_ELIMINATE. */
+
+static bool
+alpha_vms_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
{
/* We need the alpha_procedure_type to decide. Evaluate it now. */
alpha_sa_size ();
pop_topmost_sequence ();
for (; insn; insn = NEXT_INSN (insn))
- if (INSN_P (insn)
+ if (NONDEBUG_INSN_P (insn)
&& ! JUMP_TABLE_DATA_P (insn)
&& GET_CODE (PATTERN (insn)) != USE
&& GET_CODE (PATTERN (insn)) != CLOBBER
if (insn && CALL_P (insn))
output_asm_insn (get_insn_template (CODE_FOR_nop, NULL), NULL);
-#if TARGET_ABI_OSF
- if (cfun->is_thunk)
- free_after_compilation (cfun);
-#endif
-
#if TARGET_ABI_OPEN_VMS
alpha_write_linkage (file, fnname, decl);
#endif
HOST_WIDE_INT hi, lo;
rtx this_rtx, insn, funexp;
- gcc_assert (cfun->is_thunk);
-
/* We always require a valid GP. */
emit_insn (gen_prologue_ldgp ());
emit_note (NOTE_INSN_PROLOGUE_END);
#if TARGET_ABI_OPEN_VMS
# undef TARGET_ATTRIBUTE_TABLE
# define TARGET_ATTRIBUTE_TABLE vms_attribute_table
+# undef TARGET_CAN_ELIMINATE
+# define TARGET_CAN_ELIMINATE alpha_vms_can_eliminate
#endif
#undef TARGET_IN_SMALL_DATA_P
#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