return true;
}
+#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
+/* Implement TARGET_MANGLE_FUNDAMENTAL_TYPE. */
+
+static const char *
+alpha_mangle_fundamental_type (tree type)
+{
+ if (TYPE_MAIN_VARIANT (type) == long_double_type_node
+ && TARGET_LONG_DOUBLE_128)
+ return "g";
+
+ /* For all other types, use normal C++ mangling. */
+ return NULL;
+}
+#endif
+
/* Parse target option strings. */
void
REAL_MODE_FORMAT (DFmode) = &vax_g_format;
REAL_MODE_FORMAT (TFmode) = NULL;
}
+
+#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
+ if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
+ target_flags |= MASK_LONG_DOUBLE_128;
+#endif
}
\f
/* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */
if (GET_CODE (op) != SYMBOL_REF)
return 0;
- if (SYMBOL_REF_LOCAL_P (op))
- {
- if (alpha_tls_size > size)
- return 0;
- }
- else
- {
- if (size != 64)
- return 0;
- }
-
switch (SYMBOL_REF_TLS_MODEL (op))
{
case TLS_MODEL_LOCAL_DYNAMIC:
- return unspec == UNSPEC_DTPREL;
+ return unspec == UNSPEC_DTPREL && size == alpha_tls_size;
case TLS_MODEL_INITIAL_EXEC:
return unspec == UNSPEC_TPREL && size == 64;
case TLS_MODEL_LOCAL_EXEC:
- return unspec == UNSPEC_TPREL;
+ return unspec == UNSPEC_TPREL && size == alpha_tls_size;
default:
gcc_unreachable ();
}
case UNSIGNED_FLOAT:
case FIX:
case UNSIGNED_FIX:
- case FLOAT_EXTEND:
case FLOAT_TRUNCATE:
*total = cost_data->fp_add;
return false;
+ case FLOAT_EXTEND:
+ if (GET_CODE (XEXP (x, 0)) == MEM)
+ *total = 0;
+ else
+ *total = cost_data->fp_add;
+ return false;
+
default:
return false;
}
get_aligned_mem (rtx ref, rtx *paligned_mem, rtx *pbitnum)
{
rtx base;
- HOST_WIDE_INT offset = 0;
+ HOST_WIDE_INT disp, offset;
gcc_assert (GET_CODE (ref) == MEM);
&& ! memory_address_p (GET_MODE (ref), XEXP (ref, 0)))
{
base = find_replacement (&XEXP (ref, 0));
-
gcc_assert (memory_address_p (GET_MODE (ref), base));
}
else
base = XEXP (ref, 0);
if (GET_CODE (base) == PLUS)
- offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
+ disp = INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
+ else
+ disp = 0;
+
+ /* Find the byte offset within an aligned word. If the memory itself is
+ claimed to be aligned, believe it. Otherwise, aligned_memory_operand
+ will have examined the base register and determined it is aligned, and
+ thus displacements from it are naturally alignable. */
+ if (MEM_ALIGN (ref) >= 32)
+ offset = 0;
+ else
+ offset = disp & 3;
- *paligned_mem
- = widen_memory_access (ref, SImode, (offset & ~3) - offset);
+ /* Access the entire aligned word. */
+ *paligned_mem = widen_memory_access (ref, SImode, -offset);
+ /* Convert the byte offset within the word to a bit offset. */
if (WORDS_BIG_ENDIAN)
- *pbitnum = GEN_INT (32 - (GET_MODE_BITSIZE (GET_MODE (ref))
- + (offset & 3) * 8));
+ offset = 32 - (GET_MODE_BITSIZE (GET_MODE (ref)) + offset * 8);
else
- *pbitnum = GEN_INT ((offset & 3) * 8);
+ offset *= 8;
+ *pbitnum = GEN_INT (offset);
}
/* Similar, but just get the address. Handle the two reload cases.
from register elimination into a DImode fp register. */
enum reg_class
-secondary_reload_class (enum reg_class class, enum machine_mode mode,
+alpha_secondary_reload_class (enum reg_class class, enum machine_mode mode,
rtx x, int in)
{
if ((mode == QImode || mode == HImode) && ! TARGET_BWX)
operands[1]));
}
-/* Split a TFmode OP[1] into DImode OP[2,3] and likewise for
- OP[0] into OP[0,1]. Naturally, output operand ordering is
- little-endian. */
-
+/* Split a TImode or TFmode move from OP[1] to OP[0] into a pair of
+ DImode moves from OP[2,3] to OP[0,1]. If FIXUP_OVERLAP is true,
+ guarantee that the sequence
+ set (OP[0] OP[2])
+ set (OP[1] OP[3])
+ is valid. Naturally, output operand ordering is little-endian.
+ This is used by *movtf_internal and *movti_internal. */
+
void
-alpha_split_tfmode_pair (rtx operands[4])
+alpha_split_tmode_pair (rtx operands[4], enum machine_mode mode,
+ bool fixup_overlap)
{
switch (GET_CODE (operands[1]))
{
operands[2] = adjust_address (operands[1], DImode, 0);
break;
+ case CONST_INT:
case CONST_DOUBLE:
- gcc_assert (operands[1] == CONST0_RTX (TFmode));
+ gcc_assert (operands[1] == CONST0_RTX (mode));
operands[2] = operands[3] = const0_rtx;
break;
default:
gcc_unreachable ();
}
+
+ if (fixup_overlap && reg_overlap_mentioned_p (operands[0], operands[3]))
+ {
+ rtx tmp;
+ tmp = operands[0], operands[0] = operands[1], operands[1] = tmp;
+ tmp = operands[2], operands[2] = operands[3], operands[3] = tmp;
+ }
}
/* Implement negtf2 or abstf2. Op0 is destination, op1 is source,
rtx scratch;
int move;
- alpha_split_tfmode_pair (operands);
+ alpha_split_tmode_pair (operands, TFmode, false);
/* Detect three flavors of operand overlap. */
move = 1;
#if TARGET_ABI_OPEN_VMS
if (cum->num_args < 6
&& 6 < cum->num_args + ALPHA_ARG_SIZE (mode, type, named))
- words = 6 - (CUM).num_args;
+ words = 6 - cum->num_args;
#elif TARGET_ABI_UNICOSMK
/* Never any split arguments. */
#elif TARGET_ABI_OSF
tmp = gen_rtx_MEM (BLKmode,
plus_constant (virtual_incoming_args_rtx,
(cum + 6) * UNITS_PER_WORD));
+ MEM_NOTRAP_P (tmp) = 1;
set_mem_alias_set (tmp, set);
move_block_from_reg (16 + cum, tmp, count);
}
tmp = gen_rtx_MEM (BLKmode,
plus_constant (virtual_incoming_args_rtx,
cum * UNITS_PER_WORD));
+ MEM_NOTRAP_P (tmp) = 1;
set_mem_alias_set (tmp, set);
move_block_from_reg (16 + cum + TARGET_FPREGS*32, tmp, count);
}
{
nextarg = plus_constant (nextarg, offset);
nextarg = plus_constant (nextarg, NUM_ARGS * UNITS_PER_WORD);
- t = build (MODIFY_EXPR, TREE_TYPE (valist), valist,
- make_tree (ptr_type_node, nextarg));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist,
+ make_tree (ptr_type_node, nextarg));
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
base_field = TYPE_FIELDS (TREE_TYPE (valist));
offset_field = TREE_CHAIN (base_field);
- base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
- valist, base_field, NULL_TREE);
- offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
- valist, offset_field, NULL_TREE);
+ base_field = build3 (COMPONENT_REF, TREE_TYPE (base_field),
+ valist, base_field, NULL_TREE);
+ offset_field = build3 (COMPONENT_REF, TREE_TYPE (offset_field),
+ valist, offset_field, NULL_TREE);
t = make_tree (ptr_type_node, virtual_incoming_args_rtx);
- t = build (PLUS_EXPR, ptr_type_node, t,
- build_int_cst (NULL_TREE, offset));
- t = build (MODIFY_EXPR, TREE_TYPE (base_field), base_field, t);
+ t = build2 (PLUS_EXPR, ptr_type_node, t,
+ build_int_cst (NULL_TREE, offset));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (base_field), base_field, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
t = build_int_cst (NULL_TREE, NUM_ARGS * UNITS_PER_WORD);
- t = build (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field, t);
+ t = build2 (MODIFY_EXPR, TREE_TYPE (offset_field), offset_field, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
if (targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))
{
t = build_int_cst (TREE_TYPE (offset), 6*8);
- t = build (MODIFY_EXPR, TREE_TYPE (offset), offset,
- build (MAX_EXPR, TREE_TYPE (offset), offset, t));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (offset), offset,
+ build2 (MAX_EXPR, TREE_TYPE (offset), offset, t));
gimplify_and_add (t, pre_p);
}
imag_part = alpha_gimplify_va_arg_1 (TREE_TYPE (type), base,
offset, pre_p);
- return build (COMPLEX_EXPR, type, real_temp, imag_part);
+ return build2 (COMPLEX_EXPR, type, real_temp, imag_part);
}
else if (TREE_CODE (type) == REAL_TYPE)
{
tree fpaddend, cond, fourtyeight;
fourtyeight = build_int_cst (TREE_TYPE (addend), 6*8);
- fpaddend = fold (build (MINUS_EXPR, TREE_TYPE (addend),
- addend, fourtyeight));
- cond = fold (build (LT_EXPR, boolean_type_node, addend, fourtyeight));
- addend = fold (build (COND_EXPR, TREE_TYPE (addend), cond,
- fpaddend, addend));
+ fpaddend = fold_build2 (MINUS_EXPR, TREE_TYPE (addend),
+ addend, fourtyeight);
+ cond = fold_build2 (LT_EXPR, boolean_type_node, addend, fourtyeight);
+ addend = fold_build3 (COND_EXPR, TREE_TYPE (addend), cond,
+ fpaddend, addend);
}
/* Build the final address and force that value into a temporary. */
- addr = build (PLUS_EXPR, ptr_type, fold_convert (ptr_type, base),
- fold_convert (ptr_type, addend));
+ addr = build2 (PLUS_EXPR, ptr_type, fold_convert (ptr_type, base),
+ fold_convert (ptr_type, addend));
internal_post = NULL;
gimplify_expr (&addr, pre_p, &internal_post, is_gimple_val, fb_rvalue);
append_to_statement_list (internal_post, pre_p);
t = size_binop (MULT_EXPR, t, size_int (8));
}
t = fold_convert (TREE_TYPE (offset), t);
- t = build (MODIFY_EXPR, void_type_node, offset,
- build (PLUS_EXPR, TREE_TYPE (offset), offset, t));
+ t = build2 (MODIFY_EXPR, void_type_node, offset,
+ build2 (PLUS_EXPR, TREE_TYPE (offset), offset, t));
gimplify_and_add (t, pre_p);
- return build_fold_indirect_ref (addr);
+ return build_va_arg_indirect_ref (addr);
}
static tree
base_field = TYPE_FIELDS (va_list_type_node);
offset_field = TREE_CHAIN (base_field);
- base_field = build (COMPONENT_REF, TREE_TYPE (base_field),
- valist, base_field, NULL_TREE);
- offset_field = build (COMPONENT_REF, TREE_TYPE (offset_field),
- valist, offset_field, NULL_TREE);
+ base_field = build3 (COMPONENT_REF, TREE_TYPE (base_field),
+ valist, base_field, NULL_TREE);
+ offset_field = build3 (COMPONENT_REF, TREE_TYPE (offset_field),
+ valist, offset_field, NULL_TREE);
/* Pull the fields of the structure out into temporaries. Since we never
modify the base field, we can use a formal temporary. Sign-extend the
r = alpha_gimplify_va_arg_1 (type, base, offset, pre_p);
/* Stuff the offset temporary back into its field. */
- t = build (MODIFY_EXPR, void_type_node, offset_field,
- fold_convert (TREE_TYPE (offset_field), offset));
+ t = build2 (MODIFY_EXPR, void_type_node, offset_field,
+ fold_convert (TREE_TYPE (offset_field), offset));
gimplify_and_add (t, pre_p);
if (indirect)
- r = build_fold_indirect_ref (r);
+ r = build_va_arg_indirect_ref (r);
return r;
}
alpha_init_builtins (void)
{
const struct alpha_builtin_def *p;
+ tree dimode_integer_type_node;
tree ftype, attrs[2];
size_t i;
+ dimode_integer_type_node = lang_hooks.types.type_for_mode (DImode, 0);
+
attrs[0] = tree_cons (get_identifier ("nothrow"), NULL, NULL);
attrs[1] = tree_cons (get_identifier ("const"), NULL, attrs[0]);
- ftype = build_function_type (long_integer_type_node, void_list_node);
+ ftype = build_function_type (dimode_integer_type_node, void_list_node);
p = zero_arg_builtins;
for (i = 0; i < ARRAY_SIZE (zero_arg_builtins); ++i, ++p)
lang_hooks.builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
NULL, attrs[p->is_const]);
- ftype = build_function_type_list (long_integer_type_node,
- long_integer_type_node, NULL_TREE);
+ ftype = build_function_type_list (dimode_integer_type_node,
+ dimode_integer_type_node, NULL_TREE);
p = one_arg_builtins;
for (i = 0; i < ARRAY_SIZE (one_arg_builtins); ++i, ++p)
lang_hooks.builtin_function (p->name, ftype, p->code, BUILT_IN_MD,
NULL, attrs[p->is_const]);
- ftype = build_function_type_list (long_integer_type_node,
- long_integer_type_node,
- long_integer_type_node, NULL_TREE);
+ ftype = build_function_type_list (dimode_integer_type_node,
+ dimode_integer_type_node,
+ dimode_integer_type_node, NULL_TREE);
p = two_arg_builtins;
for (i = 0; i < ARRAY_SIZE (two_arg_builtins); ++i, ++p)
{
if (frame_size > 4096)
{
- int probed = 4096;
+ int probed;
- do
+ for (probed = 4096; probed < frame_size; probed += 8192)
emit_insn (gen_probe_stack (GEN_INT (TARGET_ABI_UNICOSMK
? -probed + 64
: -probed)));
- while ((probed += 8192) < frame_size);
/* We only have to do this probe if we aren't saving registers. */
- if (sa_size == 0 && probed + 4096 < frame_size)
+ if (sa_size == 0 && frame_size > probed - 4096)
emit_insn (gen_probe_stack (GEN_INT (-frame_size)));
}
#if TARGET_ABI_OPEN_VMS
/* Ifdef'ed cause link_section are only available then. */
- readonly_data_section ();
+ switch_to_section (readonly_data_section);
fprintf (file, "\t.align 3\n");
assemble_name (file, fnname); fputs ("..na:\n", file);
fputs ("\t.ascii \"", file);
assemble_name (file, fnname);
fputs ("\\0\"\n", file);
alpha_need_linkage (fnname, 1);
- text_section ();
+ switch_to_section (text_section);
#endif
}
\f
/* Alpha can only issue instruction groups simultaneously if they are
suitably aligned. This is very processor-specific. */
+/* There are a number of entries in alphaev4_insn_pipe and alphaev5_insn_pipe
+ that are marked "fake". These instructions do not exist on that target,
+ but it is possible to see these insns with deranged combinations of
+ command-line options, such as "-mtune=ev4 -mmax". Instead of aborting,
+ choose a result at random. */
enum alphaev4_pipe {
EV4_STOP = 0,
case TYPE_SHIFT:
case TYPE_IMUL:
case TYPE_FBR:
+ case TYPE_MVI: /* fake */
return EV4_IB0;
case TYPE_IST:
case TYPE_FMUL:
case TYPE_ST_C:
case TYPE_MB:
+ case TYPE_FSQRT: /* fake */
+ case TYPE_FTOI: /* fake */
+ case TYPE_ITOF: /* fake */
return EV4_IB1;
default:
case TYPE_LD_L:
case TYPE_ST_C:
case TYPE_MB:
+ case TYPE_FTOI: /* fake */
+ case TYPE_ITOF: /* fake */
return EV5_E0;
case TYPE_IBR:
case TYPE_FCMOV:
case TYPE_FADD:
case TYPE_FDIV:
+ case TYPE_FSQRT: /* fake */
return EV5_FA;
case TYPE_FMUL:
#ifdef OBJECT_FORMAT_ELF
-/* Switch to the section to which we should output X. The only thing
- special we do here is to honor small data. */
+/* Return a section for X. The only special thing we do here is to
+ honor small data. */
-static void
+static section *
alpha_elf_select_rtx_section (enum machine_mode mode, rtx x,
unsigned HOST_WIDE_INT align)
{
if (TARGET_SMALL_DATA && GET_MODE_SIZE (mode) <= g_switch_value)
/* ??? Consider using mergeable sdata sections. */
- sdata_section ();
+ return sdata_section;
else
- default_elf_select_rtx_section (mode, x, align);
+ return default_elf_select_rtx_section (mode, x, align);
}
#endif /* OBJECT_FORMAT_ELF */
splay_tree_node node;
struct alpha_funcs *func;
- link_section ();
+ fprintf (stream, "\t.link\n");
fprintf (stream, "\t.align 3\n");
+ in_section = NULL;
+
node = splay_tree_lookup (alpha_funcs_tree, (splay_tree_key) fundecl);
func = (struct alpha_funcs *) node->value;
static void
vms_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
{
- ctors_section ();
+ switch_to_section (ctors_section);
assemble_align (BITS_PER_WORD);
assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
}
static void
vms_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
{
- dtors_section ();
+ switch_to_section (dtors_section);
assemble_align (BITS_PER_WORD);
assemble_integer (symbol, UNITS_PER_WORD, BITS_PER_WORD, 1);
}
tree name_tree;
printf ("T3E__: common %s\n", name);
- common_section ();
+ in_section = NULL;
fputs("\t.endp\n\n\t.psect ", file);
assemble_name(file, name);
fprintf(file, ",%d,common\n", floor_log2 (align / BITS_PER_UNIT));
#define SECTION_MAIN (SECTION_PUBLIC << 1)
static int current_section_align;
+/* A get_unnamed_section callback for switching to the text section. */
+
+static void
+unicosmk_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
+{
+ static int count = 0;
+ fprintf (asm_out_file, "\t.endp\n\n\t.psect\tgcc@text___%d,code\n", count++);
+}
+
+/* A get_unnamed_section callback for switching to the data section. */
+
+static void
+unicosmk_output_data_section_asm_op (const void *data ATTRIBUTE_UNUSED)
+{
+ static int count = 1;
+ fprintf (asm_out_file, "\t.endp\n\n\t.psect\tgcc@data___%d,data\n", count++);
+}
+
+/* Implement TARGET_ASM_INIT_SECTIONS.
+
+ The Cray assembler is really weird with respect to sections. It has only
+ named sections and you can't reopen a section once it has been closed.
+ This means that we have to generate unique names whenever we want to
+ reenter the text or the data section. */
+
+static void
+unicosmk_init_sections (void)
+{
+ text_section = get_unnamed_section (SECTION_CODE,
+ unicosmk_output_text_section_asm_op,
+ NULL);
+ data_section = get_unnamed_section (SECTION_WRITE,
+ unicosmk_output_data_section_asm_op,
+ NULL);
+ readonly_data_section = data_section;
+}
+
static unsigned int
unicosmk_section_type_flags (tree decl, const char *name,
int reloc ATTRIBUTE_UNUSED)
if (machine->addr_list == NULL_RTX)
return;
- data_section ();
+ switch_to_section (data_section);
for (t = machine->addr_list; t; t = XEXP (t, 1))
unicosmk_output_addr_vec (file, XEXP (t, 0));
}
rtx ciw;
struct machine_function *machine = cfun->machine;
- ssib_section ();
+ in_section = NULL;
fprintf (file, "\t.endp\n\n\t.psect\t%s%s,data\n", user_label_prefix,
unicosmk_ssib_name ());
+ strlen (current_function_name ())/8 + 5);
}
-static char unicosmk_section_buf[100];
-
-char *
-unicosmk_text_section (void)
-{
- static int count = 0;
- sprintf (unicosmk_section_buf, "\t.endp\n\n\t.psect\tgcc@text___%d,code",
- count++);
- return unicosmk_section_buf;
-}
-
-char *
-unicosmk_data_section (void)
-{
- static int count = 1;
- sprintf (unicosmk_section_buf, "\t.endp\n\n\t.psect\tgcc@data___%d,data",
- count++);
- return unicosmk_section_buf;
-}
-
/* The Cray assembler doesn't accept extern declarations for symbols which
are defined in the same file. We have to keep track of all global
symbols which are referenced and/or defined in a source file and output
#undef TARGET_HANDLE_OPTION
#define TARGET_HANDLE_OPTION alpha_handle_option
+#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
+#undef TARGET_MANGLE_FUNDAMENTAL_TYPE
+#define TARGET_MANGLE_FUNDAMENTAL_TYPE alpha_mangle_fundamental_type
+#endif
+
struct gcc_target targetm = TARGET_INITIALIZER;
\f