SUBTARGET_OVERRIDE_OPTIONS;
#endif
+ /* Default to full IEEE compliance mode for Go language. */
+ if (strcmp (lang_hooks.name, "GNU Go") == 0
+ && !(target_flags_explicit & MASK_IEEE))
+ target_flags |= MASK_IEEE;
+
alpha_fprm = ALPHA_FPRM_NORM;
alpha_tp = ALPHA_TP_PROG;
alpha_fptm = ALPHA_FPTM_N;
return 0;
MEM_VOLATILE_P (x) = MEM_VOLATILE_P (orig);
- MEM_IN_STRUCT_P (x) = MEM_IN_STRUCT_P (orig);
- MEM_SCALAR_P (x) = MEM_SCALAR_P (orig);
MEM_NOTRAP_P (x) = MEM_NOTRAP_P (orig);
MEM_READONLY_P (x) = MEM_READONLY_P (orig);
generated from one of the insn patterns. So if everything is
zero, the pattern is already up-to-date. */
if (!MEM_VOLATILE_P (ref)
- && !MEM_IN_STRUCT_P (ref)
- && !MEM_SCALAR_P (ref)
&& !MEM_NOTRAP_P (ref)
&& !MEM_READONLY_P (ref))
return;
emit_insn (fn (res, mem, val));
}
+/* Subroutines of the atomic operation splitters. Emit barriers
+ as needed for the memory MODEL. */
+
+static void
+alpha_pre_atomic_barrier (enum memmodel model)
+{
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_CONSUME:
+ case MEMMODEL_ACQUIRE:
+ break;
+ case MEMMODEL_RELEASE:
+ case MEMMODEL_ACQ_REL:
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_memory_barrier ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
+static void
+alpha_post_atomic_barrier (enum memmodel model)
+{
+ switch (model)
+ {
+ case MEMMODEL_RELAXED:
+ case MEMMODEL_CONSUME:
+ case MEMMODEL_RELEASE:
+ break;
+ case MEMMODEL_ACQUIRE:
+ case MEMMODEL_ACQ_REL:
+ case MEMMODEL_SEQ_CST:
+ emit_insn (gen_memory_barrier ());
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* A subroutine of the atomic operation splitters. Emit an insxl
instruction in MODE. */
a scratch register. */
void
-alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
- rtx before, rtx after, rtx scratch)
+alpha_split_atomic_op (enum rtx_code code, rtx mem, rtx val, rtx before,
+ rtx after, rtx scratch, enum memmodel model)
{
enum machine_mode mode = GET_MODE (mem);
rtx label, x, cond = gen_rtx_REG (DImode, REGNO (scratch));
- emit_insn (gen_memory_barrier ());
+ alpha_pre_atomic_barrier (model);
label = gen_label_rtx ();
emit_label (label);
x = gen_rtx_EQ (DImode, cond, const0_rtx);
emit_unlikely_jump (x, label);
- emit_insn (gen_memory_barrier ());
+ alpha_post_atomic_barrier (model);
}
/* Expand a compare and swap operation. */
void
-alpha_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
- rtx scratch)
+alpha_split_compare_and_swap (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
- rtx label1, label2, x, cond = gen_lowpart (DImode, scratch);
+ rtx cond, retval, mem, oldval, newval;
+ bool is_weak;
+ enum memmodel mod_s, mod_f;
+ enum machine_mode mode;
+ rtx label1, label2, x;
- emit_insn (gen_memory_barrier ());
+ cond = operands[0];
+ retval = operands[1];
+ mem = operands[2];
+ oldval = operands[3];
+ newval = operands[4];
+ is_weak = (operands[5] != const0_rtx);
+ mod_s = (enum memmodel) INTVAL (operands[6]);
+ mod_f = (enum memmodel) INTVAL (operands[7]);
+ mode = GET_MODE (mem);
- label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+ alpha_pre_atomic_barrier (mod_s);
+
+ label1 = NULL_RTX;
+ if (!is_weak)
+ {
+ label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+ emit_label (XEXP (label1, 0));
+ }
label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
- emit_label (XEXP (label1, 0));
emit_load_locked (mode, retval, mem);
x = gen_lowpart (DImode, retval);
if (oldval == const0_rtx)
- x = gen_rtx_NE (DImode, x, const0_rtx);
+ {
+ emit_move_insn (cond, const0_rtx);
+ x = gen_rtx_NE (DImode, x, const0_rtx);
+ }
else
{
x = gen_rtx_EQ (DImode, x, oldval);
}
emit_unlikely_jump (x, label2);
- emit_move_insn (scratch, newval);
- emit_store_conditional (mode, cond, mem, scratch);
+ emit_move_insn (cond, newval);
+ emit_store_conditional (mode, cond, mem, gen_lowpart (mode, cond));
- x = gen_rtx_EQ (DImode, cond, const0_rtx);
- emit_unlikely_jump (x, label1);
+ if (!is_weak)
+ {
+ x = gen_rtx_EQ (DImode, cond, const0_rtx);
+ emit_unlikely_jump (x, label1);
+ }
- emit_insn (gen_memory_barrier ());
- emit_label (XEXP (label2, 0));
+ if (mod_f != MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
+
+ alpha_post_atomic_barrier (mod_s);
+
+ if (mod_f == MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
}
void
-alpha_expand_compare_and_swap_12 (rtx dst, rtx mem, rtx oldval, rtx newval)
+alpha_expand_compare_and_swap_12 (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
+ rtx cond, dst, mem, oldval, newval, is_weak, mod_s, mod_f;
+ enum machine_mode mode;
rtx addr, align, wdst;
- rtx (*fn5) (rtx, rtx, rtx, rtx, rtx);
+ rtx (*gen) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
+
+ cond = operands[0];
+ dst = operands[1];
+ mem = operands[2];
+ oldval = operands[3];
+ newval = operands[4];
+ is_weak = operands[5];
+ mod_s = operands[6];
+ mod_f = operands[7];
+ mode = GET_MODE (mem);
+
+ /* We forced the address into a register via mem_noofs_operand. */
+ addr = XEXP (mem, 0);
+ gcc_assert (register_operand (addr, DImode));
- addr = force_reg (DImode, XEXP (mem, 0));
align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
NULL_RTX, 1, OPTAB_DIRECT);
oldval = convert_modes (DImode, mode, oldval, 1);
- newval = emit_insxl (mode, newval, addr);
+
+ if (newval != const0_rtx)
+ newval = emit_insxl (mode, newval, addr);
wdst = gen_reg_rtx (DImode);
if (mode == QImode)
- fn5 = gen_sync_compare_and_swapqi_1;
+ gen = gen_atomic_compare_and_swapqi_1;
else
- fn5 = gen_sync_compare_and_swaphi_1;
- emit_insn (fn5 (wdst, addr, oldval, newval, align));
+ gen = gen_atomic_compare_and_swaphi_1;
+ emit_insn (gen (cond, wdst, mem, oldval, newval, align,
+ is_weak, mod_s, mod_f));
emit_move_insn (dst, gen_lowpart (mode, wdst));
}
void
-alpha_split_compare_and_swap_12 (enum machine_mode mode, rtx dest, rtx addr,
- rtx oldval, rtx newval, rtx align,
- rtx scratch, rtx cond)
+alpha_split_compare_and_swap_12 (rtx operands[])
{
- rtx label1, label2, mem, width, mask, x;
+ rtx cond, dest, orig_mem, oldval, newval, align, scratch;
+ enum machine_mode mode;
+ bool is_weak;
+ enum memmodel mod_s, mod_f;
+ rtx label1, label2, mem, addr, width, mask, x;
+
+ cond = operands[0];
+ dest = operands[1];
+ orig_mem = operands[2];
+ oldval = operands[3];
+ newval = operands[4];
+ align = operands[5];
+ is_weak = (operands[6] != const0_rtx);
+ mod_s = (enum memmodel) INTVAL (operands[7]);
+ mod_f = (enum memmodel) INTVAL (operands[8]);
+ scratch = operands[9];
+ mode = GET_MODE (orig_mem);
+ addr = XEXP (orig_mem, 0);
mem = gen_rtx_MEM (DImode, align);
- MEM_VOLATILE_P (mem) = 1;
+ MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (orig_mem);
+ if (MEM_ALIAS_SET (orig_mem) == ALIAS_SET_MEMORY_BARRIER)
+ set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
+
+ alpha_pre_atomic_barrier (mod_s);
- emit_insn (gen_memory_barrier ());
- label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+ label1 = NULL_RTX;
+ if (!is_weak)
+ {
+ label1 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
+ emit_label (XEXP (label1, 0));
+ }
label2 = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
- emit_label (XEXP (label1, 0));
emit_load_locked (DImode, scratch, mem);
emit_insn (gen_extxl (dest, scratch, width, addr));
if (oldval == const0_rtx)
- x = gen_rtx_NE (DImode, dest, const0_rtx);
+ {
+ emit_move_insn (cond, const0_rtx);
+ x = gen_rtx_NE (DImode, dest, const0_rtx);
+ }
else
{
x = gen_rtx_EQ (DImode, dest, oldval);
}
emit_unlikely_jump (x, label2);
- emit_insn (gen_mskxl (scratch, scratch, mask, addr));
- emit_insn (gen_iordi3 (scratch, scratch, newval));
+ emit_insn (gen_mskxl (cond, scratch, mask, addr));
- emit_store_conditional (DImode, scratch, mem, scratch);
+ if (newval != const0_rtx)
+ emit_insn (gen_iordi3 (cond, cond, newval));
- x = gen_rtx_EQ (DImode, scratch, const0_rtx);
- emit_unlikely_jump (x, label1);
+ emit_store_conditional (DImode, cond, mem, cond);
+
+ if (!is_weak)
+ {
+ x = gen_rtx_EQ (DImode, cond, const0_rtx);
+ emit_unlikely_jump (x, label1);
+ }
+
+ if (mod_f != MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
+
+ alpha_post_atomic_barrier (mod_s);
- emit_insn (gen_memory_barrier ());
- emit_label (XEXP (label2, 0));
+ if (mod_f == MEMMODEL_RELAXED)
+ emit_label (XEXP (label2, 0));
}
/* Expand an atomic exchange operation. */
void
-alpha_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
+alpha_split_atomic_exchange (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
- rtx label, x, cond = gen_lowpart (DImode, scratch);
+ rtx retval, mem, val, scratch;
+ enum memmodel model;
+ enum machine_mode mode;
+ rtx label, x, cond;
+
+ retval = operands[0];
+ mem = operands[1];
+ val = operands[2];
+ model = (enum memmodel) INTVAL (operands[3]);
+ scratch = operands[4];
+ mode = GET_MODE (mem);
+ cond = gen_lowpart (DImode, scratch);
+
+ alpha_pre_atomic_barrier (model);
label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
emit_label (XEXP (label, 0));
x = gen_rtx_EQ (DImode, cond, const0_rtx);
emit_unlikely_jump (x, label);
- emit_insn (gen_memory_barrier ());
+ alpha_post_atomic_barrier (model);
}
void
-alpha_expand_lock_test_and_set_12 (rtx dst, rtx mem, rtx val)
+alpha_expand_atomic_exchange_12 (rtx operands[])
{
- enum machine_mode mode = GET_MODE (mem);
+ rtx dst, mem, val, model;
+ enum machine_mode mode;
rtx addr, align, wdst;
- rtx (*fn4) (rtx, rtx, rtx, rtx);
+ rtx (*gen) (rtx, rtx, rtx, rtx, rtx);
- /* Force the address into a register. */
- addr = force_reg (DImode, XEXP (mem, 0));
+ dst = operands[0];
+ mem = operands[1];
+ val = operands[2];
+ model = operands[3];
+ mode = GET_MODE (mem);
+
+ /* We forced the address into a register via mem_noofs_operand. */
+ addr = XEXP (mem, 0);
+ gcc_assert (register_operand (addr, DImode));
- /* Align it to a multiple of 8. */
align = expand_simple_binop (Pmode, AND, addr, GEN_INT (-8),
NULL_RTX, 1, OPTAB_DIRECT);
/* Insert val into the correct byte location within the word. */
- val = emit_insxl (mode, val, addr);
+ if (val != const0_rtx)
+ val = emit_insxl (mode, val, addr);
wdst = gen_reg_rtx (DImode);
if (mode == QImode)
- fn4 = gen_sync_lock_test_and_setqi_1;
+ gen = gen_atomic_exchangeqi_1;
else
- fn4 = gen_sync_lock_test_and_sethi_1;
- emit_insn (fn4 (wdst, addr, val, align));
+ gen = gen_atomic_exchangehi_1;
+ emit_insn (gen (wdst, mem, val, align, model));
emit_move_insn (dst, gen_lowpart (mode, wdst));
}
void
-alpha_split_lock_test_and_set_12 (enum machine_mode mode, rtx dest, rtx addr,
- rtx val, rtx align, rtx scratch)
+alpha_split_atomic_exchange_12 (rtx operands[])
{
+ rtx dest, orig_mem, addr, val, align, scratch;
rtx label, mem, width, mask, x;
+ enum machine_mode mode;
+ enum memmodel model;
+
+ dest = operands[0];
+ orig_mem = operands[1];
+ val = operands[2];
+ align = operands[3];
+ model = (enum memmodel) INTVAL (operands[4]);
+ scratch = operands[5];
+ mode = GET_MODE (orig_mem);
+ addr = XEXP (orig_mem, 0);
mem = gen_rtx_MEM (DImode, align);
- MEM_VOLATILE_P (mem) = 1;
+ MEM_VOLATILE_P (mem) = MEM_VOLATILE_P (orig_mem);
+ if (MEM_ALIAS_SET (orig_mem) == ALIAS_SET_MEMORY_BARRIER)
+ set_mem_alias_set (mem, ALIAS_SET_MEMORY_BARRIER);
+
+ alpha_pre_atomic_barrier (model);
label = gen_rtx_LABEL_REF (DImode, gen_label_rtx ());
emit_label (XEXP (label, 0));
mask = GEN_INT (mode == QImode ? 0xff : 0xffff);
emit_insn (gen_extxl (dest, scratch, width, addr));
emit_insn (gen_mskxl (scratch, scratch, mask, addr));
- emit_insn (gen_iordi3 (scratch, scratch, val));
+ if (val != const0_rtx)
+ emit_insn (gen_iordi3 (scratch, scratch, val));
emit_store_conditional (DImode, scratch, mem, scratch);
x = gen_rtx_EQ (DImode, scratch, const0_rtx);
emit_unlikely_jump (x, label);
- emit_insn (gen_memory_barrier ());
+ alpha_post_atomic_barrier (model);
}
\f
/* Adjust the cost of a scheduling dependency. Return the new cost of
if (TARGET_ABI_OPEN_VMS
&& !TREE_PUBLIC (decl)
&& DECL_CONTEXT (decl)
- && !TYPE_P (DECL_CONTEXT (decl)))
+ && !TYPE_P (DECL_CONTEXT (decl))
+ && TREE_CODE (DECL_CONTEXT (decl)) != TRANSLATION_UNIT_DECL)
{
strcpy (tramp_label, fnname);
strcat (tramp_label, "..tr");
{
size_t buf_len;
char *linksym;
+ tree id;
if (name[0] == '*')
name++;
+ /* Follow transparent alias, as this is used for CRTL translations. */
+ id = maybe_get_identifier (name);
+ if (id)
+ {
+ while (IDENTIFIER_TRANSPARENT_ALIAS (id))
+ id = TREE_CHAIN (id);
+ name = IDENTIFIER_POINTER (id);
+ }
+
buf_len = strlen (name) + 8 + 9;
linksym = (char *) alloca (buf_len);
snprintf (linksym, buf_len, "$%d..%s..lk", cfun->funcdef_no, name);
if (link->rkind == KIND_CODEADDR)
{
/* External and used, request code address. */
- fprintf (stream, "\t.code_address %s\n", name);
+ fprintf (stream, "\t.code_address ");
}
else
{
{
/* Locally defined, build linkage pair. */
fprintf (stream, "\t.quad %s..en\n", name);
- fprintf (stream, "\t.quad %s\n", name);
+ fprintf (stream, "\t.quad ");
}
else
{
/* External, request linkage pair. */
- fprintf (stream, "\t.linkage %s\n", name);
+ fprintf (stream, "\t.linkage ");
}
}
+ assemble_name (stream, name);
+ fputs ("\n", stream);
return 0;
}
#define TARGET_STDARG_OPTIMIZE_HOOK alpha_stdarg_optimize_hook
#endif
+/* Use 16-bits anchor. */
+#undef TARGET_MIN_ANCHOR_OFFSET
+#define TARGET_MIN_ANCHOR_OFFSET -0x7fff - 1
+#undef TARGET_MAX_ANCHOR_OFFSET
+#define TARGET_MAX_ANCHOR_OFFSET 0x7fff
+#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
+#define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_true
+
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS alpha_rtx_costs
#undef TARGET_ADDRESS_COST