aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Henderson <rth@gcc.gnu.org>2001-09-11 01:52:39 -0700
committerRichard Henderson <rth@gcc.gnu.org>2001-09-11 01:52:39 -0700
commit30102605e710a95f8cb00ddd14303d7fcc284fae (patch)
tree89de0166f267747621eba79ef570f0cb00c9654a /gcc
parentb1c4394d5db5b1c73458e8927dbcedc101874e04 (diff)
downloadgcc-30102605e710a95f8cb00ddd14303d7fcc284fae.zip
gcc-30102605e710a95f8cb00ddd14303d7fcc284fae.tar.gz
gcc-30102605e710a95f8cb00ddd14303d7fcc284fae.tar.bz2
Cray T3E port.
From-SVN: r45539
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog90
-rw-r--r--gcc/config.gcc8
-rw-r--r--gcc/config/alpha/alpha-protos.h21
-rw-r--r--gcc/config/alpha/alpha.c1727
-rw-r--r--gcc/config/alpha/alpha.h17
-rw-r--r--gcc/config/alpha/alpha.md961
-rw-r--r--gcc/config/alpha/t-unicosmk2
-rw-r--r--gcc/config/alpha/unicosmk.h667
-rw-r--r--gcc/fixinc/fixincl.x51
-rw-r--r--gcc/fixinc/inclhack.def17
-rw-r--r--gcc/ginclude/stddef.h6
11 files changed, 3228 insertions, 339 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f5f5afb..7b9891e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,93 @@
+2001-09-11 Richard Henderson <rth@redhat.com>
+
+ * config/alpha/alpha.c: Tidy formatting.
+ (local_symbolic_operand): Verify mode.
+ (alpha_sa_mask): Ignore unicos for eh_return.
+ (alpha_expand_epilogue): Handle sp_adj2 zero, not NULL.
+ * config/alpha/alpha.md (umk divsi patterns): Remove.
+ (extendsfdf2): Remove unicos check.
+ (tablejump): Merge vms and unicos code; always use direct set
+ plus label_ref use.
+
+2001-09-11 Roman Lechtchinsky <rl@cs.tu-berlin.de>
+
+ * config.gcc (alpha*-*-unicosmk*): New target.
+
+ * config/alpha/alpha-protos.h (symbolic_operand,
+ unicosmk_add_call_info_word, unicosmk_add_extern,
+ unicosmk_defer_case_vector, unicosmk_unique_section,
+ unicosmk_output_align, unicosmk_text_section, unicosmk_data_section,
+ unicosmk_asm_file_start, unicosmk_asm_file_end,
+ unicosmk_output_common): Declare.
+
+ * config/alpha/alpha.c (NUM_ARGS, override_options, call_operand,
+ direct_return, function_arg, alpha_va_start, alpha_va_arg,
+ alpha_does_function_need_gp, alpha_end_function): Support Cray
+ Unicos/Mk.
+ (alpha_init_machine_status, alpha_mark_machine_status,
+ alpha_free_machine_status, unicosmk_output_deferred_case_vectors,
+ unicosmk_gen_dsib, unicosmk_output_ssib, unicosmk_need_dex,
+ unicosmk_asm_named_section, unicosmk_insert_attributes,
+ unicosmk_section_type_flags, symbolic_operand,
+ unicosmk_output_module_name, unicosmk_output_default_externs,
+ unicosmk_output_dex, unicosmk_output_externs,
+ unicosmk_output_addr_vec, unicosmk_ssib_name,
+ unicosmk_initial_elimination_offset, unicosmk_asm_file_start,
+ unicosmk_asm_file_end, unicosmk_output_common,
+ unicosmk_section_type_flags, unicosmk_unique_section,
+ unicosmk_add_call_info_word, unicosmk_text_section,
+ unicosmk_data_section, unicosmk_extern_list, unicosmk_extern_head,
+ unicosmk_add_extern, unicosmk_dex, unicosmk_dex_list,
+ unicosmk_dex_count, unicosmk_special_name): New.
+ (TARGET_INSERT_ATTRIBUTES, TARGET_SECTION_TYPE_FLAGS): Define for
+ TARGET_ABI_UNICOSMK.
+ (get_aligned_mem, alpha_expand_unaligned_load,
+ alpha_expand_unaligned_store, alpha_expand_unaligned_load_words,
+ alpha_expand_unaligned_store_words): Support big-endian mode.
+ (print_operand): Likewise. New format specifier 't'. Use
+ TARGET_AS_SLASH_BEFORE_SUFFIX.
+ (alpha_is_stack_procedure): Rename from vms_is_stack_procedure.
+ (alpha_pv_save_size): Update with above change.
+ (alpha_sa_mask, alpha_sa_size, alpha_expand_prologue,
+ alpha_start_function, alpha_expand_epilogue): Likewise. Support Cray
+ Unicos/Mk.
+
+ * config/alpha/alpha.h (TARGET_ABI_UNICOSMK): New.
+ (TARGET_ABI_OSF): Exclude TARGET_ABI_UNICOSMK.
+ (TARGET_AS_SLASH_BEFORE_SUFFIX): New.
+ (EXTRA_CONSTRAINT): New constraint 'U'.
+ (PREDICATE_CODES): Add symbolic_operand.
+
+ * config/alpha/alpha.md (UNSPEC_UMK_LAUM, UNSPEC_UMK_LALM,
+ UNSPEC_UMK_LAL, UNSPEC_UMK_LOAD_CIW): New constants.
+ (mulsi3, *mulsi_se, mulvsi3): Disable for TARGET_ABI_UNICOSMK.
+ (integer division and modulus patterns): Split in default and
+ Unicos/Mk versions.
+ (*divmodsi_internal, *divmoddi_internal): Disable for
+ TARGET_ABI_UNICOSMK.
+ (unaligned_extend?idi, unaligned_load?i, unaligned_store?i): Split in
+ little-endian and big-endian versions.
+ (ext, ins, msk): Likewise.
+ (extv, extzv, insv): Support big-endian mode.
+ (call, call_value, tablejump): Support TARGET_ABI_UNICOSMK.
+ (call_umk, call_value_umk, *call_umk, tablejump_umk,
+ *tablejump_umk_internal, *call_value_umk): New.
+ (*movdi_nofix): Add pattern for loading an address into a register on
+ TARGET_ABI_UNICOSMK.
+ (umk_laum, umk_lal, umk_lalm, *umk_load_ciw): New.
+ (umk_mismatch_args, arg_home_umk): New.
+ (various insns): Don't use mov, fmov, nop, fnop and unop.
+ (realign): Support TARGET_ABI_UNICOSMK.
+
+ * config/alpha/unicosmk.h: New file.
+ * config/alpha/t-unicosmk: New file.
+
+ * fixinc/inclhack.def (unicosmk_restrict): New.
+ * fixinc/fixincl.x: Regenerate.
+
+ * ginclude/stddef.h (size_t): Check for and define __SIZE_T__.
+ (wchar_t): Check for and define __WCHAR_T__.
+
2001-09-11 Richard Sandiford <rsandifo@redhat.com>
* combine.c (simplify_shift_const): Treat shifts by the mode
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 2af51fa..00ed9b3 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -398,6 +398,14 @@ a29k-wrs-vxworks*)
a29k-*-*) # Default a29k environment.
use_collect2=yes
;;
+alpha*-*-unicosmk*)
+ use_collect2=yes
+ tm_file="${tm_file} alpha/unicosmk.h"
+
+ # Don't include t-ieee for now because we don't support that yet
+ # tmake_file="alpha/t-ieee"
+ tmake_file="alpha/t-unicosmk"
+ ;;
alpha-*-interix)
tm_file="${tm_file} alpha/alpha32.h interix.h alpha/alpha-interix.h"
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index be18c63..c8ff112 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -56,6 +56,7 @@ extern int input_operand PARAMS ((rtx, enum machine_mode));
extern int current_file_function_operand PARAMS ((rtx, enum machine_mode));
extern int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int call_operand PARAMS ((rtx, enum machine_mode));
+extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int alpha_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int alpha_zero_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int alpha_swapped_comparison_operator PARAMS ((rtx, enum machine_mode));
@@ -149,3 +150,23 @@ extern void alpha_start_function PARAMS ((FILE *, const char *, tree));
extern void alpha_end_function PARAMS ((FILE *, const char *, tree));
extern void alpha_encode_section_info PARAMS ((tree));
#endif /* TREE CODE */
+
+#ifdef RTX_CODE
+extern rtx unicosmk_add_call_info_word PARAMS ((rtx));
+#endif
+
+#if TARGET_ABI_UNICOSMK
+#ifdef RTX_CODE
+extern void unicosmk_defer_case_vector PARAMS ((rtx, rtx));
+#endif
+#ifdef TREE_CODE
+extern void unicosmk_unique_section PARAMS ((tree, int));
+#endif
+extern void unicosmk_add_extern PARAMS ((const char *));
+extern void unicosmk_output_align PARAMS ((FILE *, int));
+extern char * unicosmk_text_section PARAMS ((void));
+extern char * unicosmk_data_section PARAMS ((void));
+extern void unicosmk_asm_file_start PARAMS ((FILE *));
+extern void unicosmk_asm_file_end PARAMS ((FILE *));
+extern void unicosmk_output_common PARAMS ((FILE *, const char *, int, int));
+#endif /* TARGET_ABI_UNICOSMK */
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index aba3672..8ee718f 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -153,8 +153,22 @@ static int alpha_issue_rate
static int alpha_variable_issue
PARAMS ((FILE *, int, rtx, int));
+#if TARGET_ABI_UNICOSMK
+static void alpha_init_machine_status
+ PARAMS ((struct function *p));
+static void alpha_mark_machine_status
+ PARAMS ((struct function *p));
+static void alpha_free_machine_status
+ PARAMS ((struct function *p));
+#endif
+
+static void unicosmk_output_deferred_case_vectors PARAMS ((FILE *));
+static void unicosmk_gen_dsib PARAMS ((unsigned long *imaskP));
+static void unicosmk_output_ssib PARAMS ((FILE *, const char *));
+static int unicosmk_need_dex PARAMS ((rtx));
+
/* Get the number of args of a function in one of two ways. */
-#if TARGET_ABI_OPEN_VMS
+#if TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK
#define NUM_ARGS current_function_args_info.num_args
#else
#define NUM_ARGS current_function_args_info
@@ -176,6 +190,17 @@ static void vms_asm_out_destructor PARAMS ((rtx, int));
# define TARGET_SECTION_TYPE_FLAGS vms_section_type_flags
#endif
+#if TARGET_ABI_UNICOSMK
+static void unicosmk_asm_named_section PARAMS ((const char *, unsigned int));
+static void unicosmk_insert_attributes PARAMS ((tree, tree *));
+static unsigned int unicosmk_section_type_flags PARAMS ((tree, const char *,
+ int));
+# undef TARGET_INSERT_ATTRIBUTES
+# define TARGET_INSERT_ATTRIBUTES unicosmk_insert_attributes
+# undef TARGET_SECTION_TYPE_FLAGS
+# define TARGET_SECTION_TYPE_FLAGS unicosmk_section_type_flags
+#endif
+
#undef TARGET_ASM_FUNCTION_END_PROLOGUE
#define TARGET_ASM_FUNCTION_END_PROLOGUE alpha_output_function_end_prologue
@@ -218,20 +243,50 @@ override_options ()
{ 0, 0, 0 }
};
+ /* Unicos/Mk doesn't have shared libraries. */
+ if (TARGET_ABI_UNICOSMK && flag_pic)
+ {
+ warning ("-f%s ignored for Unicos/Mk (not supported)",
+ (flag_pic > 1) ? "PIC" : "pic");
+ flag_pic = 0;
+ }
+
+ /* On Unicos/Mk, the native compiler consistenly generates /d suffices for
+ floating-point instructions. Make that the default for this target. */
+ if (TARGET_ABI_UNICOSMK)
+ alpha_fprm = ALPHA_FPRM_DYN;
+ else
+ alpha_fprm = ALPHA_FPRM_NORM;
+
alpha_tp = ALPHA_TP_PROG;
- alpha_fprm = ALPHA_FPRM_NORM;
alpha_fptm = ALPHA_FPTM_N;
+ /* We cannot use su and sui qualifiers for conversion instructions on
+ Unicos/Mk. I'm not sure if this is due to assembler or hardware
+ limitations. Right now, we issue a warning if -mieee is specified
+ and then ignore it; eventually, we should either get it right or
+ disable the option altogether. */
+
if (TARGET_IEEE)
{
- alpha_tp = ALPHA_TP_INSN;
- alpha_fptm = ALPHA_FPTM_SU;
+ if (TARGET_ABI_UNICOSMK)
+ warning ("-mieee not supported on Unicos/Mk");
+ else
+ {
+ alpha_tp = ALPHA_TP_INSN;
+ alpha_fptm = ALPHA_FPTM_SU;
+ }
}
if (TARGET_IEEE_WITH_INEXACT)
{
- alpha_tp = ALPHA_TP_INSN;
- alpha_fptm = ALPHA_FPTM_SUI;
+ if (TARGET_ABI_UNICOSMK)
+ warning ("-mieee-with-inexact not supported on Unicos/Mk");
+ else
+ {
+ alpha_tp = ALPHA_TP_INSN;
+ alpha_fptm = ALPHA_FPTM_SUI;
+ }
}
if (alpha_tp_string)
@@ -308,6 +363,12 @@ override_options ()
/* Do some sanity checks on the above options. */
+ if (TARGET_ABI_UNICOSMK && alpha_fptm != ALPHA_FPTM_N)
+ {
+ warning ("trap mode not supported on Unicos/Mk");
+ alpha_fptm = ALPHA_FPTM_N;
+ }
+
if ((alpha_fptm == ALPHA_FPTM_SU || alpha_fptm == ALPHA_FPTM_SUI)
&& alpha_tp != ALPHA_TP_INSN && ! TARGET_CPU_EV6)
{
@@ -402,6 +463,15 @@ override_options ()
/* Acquire a unique set number for our register saves and restores. */
alpha_sr_alias_set = new_alias_set ();
+
+ /* Register variables and functions with the garbage collector. */
+
+#if TARGET_ABI_UNICOSMK
+ /* Set up function hooks. */
+ init_machine_status = alpha_init_machine_status;
+ mark_machine_status = alpha_mark_machine_status;
+ free_machine_status = alpha_free_machine_status;
+#endif
}
/* Returns 1 if VALUE is a mask that contains full bytes of zero or ones. */
@@ -774,10 +844,13 @@ current_file_function_operand (op, mode)
int
local_symbolic_operand (op, mode)
rtx op;
- enum machine_mode mode ATTRIBUTE_UNUSED;
+ enum machine_mode mode;
{
const char *str;
+ if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+ return 0;
+
if (GET_CODE (op) == LABEL_REF)
return 1;
@@ -813,6 +886,8 @@ call_operand (op, mode)
if (mode != Pmode)
return 0;
+ if (TARGET_ABI_UNICOSMK)
+ return GET_CODE (op) == REG;
if (GET_CODE (op) == SYMBOL_REF)
return 1;
if (GET_CODE (op) == REG)
@@ -826,6 +901,26 @@ call_operand (op, mode)
return 0;
}
+/* Returns 1 if OP is a symbolic operand, i.e. a symbol_ref or a label_ref,
+ possibly with an offset. */
+
+int
+symbolic_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+ return 0;
+ if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
+ return 1;
+ if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op,0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op,0), 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (XEXP (op,0), 1)) == CONST_INT)
+ return 1;
+ return 0;
+}
+
/* Return 1 if OP is a valid Alpha comparison operator. Here we know which
comparisons are valid in which insn. */
@@ -1140,7 +1235,7 @@ addition_operation (op, mode)
int
direct_return ()
{
- return (! TARGET_ABI_OPEN_VMS
+ return (! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK
&& reload_completed
&& alpha_sa_size () == 0
&& get_frame_size () == 0
@@ -1582,7 +1677,11 @@ get_aligned_mem (ref, paligned_mem, pbitnum)
data in a different alias set. */
set_mem_alias_set (*paligned_mem, 0);
- *pbitnum = GEN_INT ((offset & 3) * 8);
+ if (WORDS_BIG_ENDIAN)
+ *pbitnum = GEN_INT (32 - (GET_MODE_BITSIZE (GET_MODE (ref))
+ + (offset & 3) * 8));
+ else
+ *pbitnum = GEN_INT ((offset & 3) * 8);
}
/* Similar, but just get the address. Handle the two reload cases.
@@ -1912,7 +2011,7 @@ alpha_emit_set_const_1 (target, mode, c, n)
/* Now try high-order 1 bits. We get that with a sign-extension.
But one bit isn't enough here. Be careful to avoid shifting outside
the mode and to avoid shifting outside the host wide int size. */
-
+
if ((bits = (MIN (HOST_BITS_PER_WIDE_INT, GET_MODE_SIZE (mode) * 8)
- floor_log2 (~ c) - 2)) > 0)
for (; bits > 0; bits--)
@@ -3197,12 +3296,23 @@ alpha_expand_unaligned_load (tgt, mem, size, ofs, sign)
set_mem_alias_set (tmp, 0);
emit_move_insn (memh, tmp);
- if (sign && size == 2)
+ if (WORDS_BIG_ENDIAN && sign && (size == 2 || size == 4))
+ {
+ emit_move_insn (addr, plus_constant (mema, -1));
+
+ emit_insn (gen_extqh_be (extl, meml, addr));
+ emit_insn (gen_extxl_be (exth, memh, GEN_INT (64), addr));
+
+ addr = expand_binop (DImode, ior_optab, extl, exth, tgt, 1, OPTAB_WIDEN);
+ addr = expand_binop (DImode, ashr_optab, addr, GEN_INT (64 - size*8),
+ addr, 1, OPTAB_WIDEN);
+ }
+ else if (sign && size == 2)
{
emit_move_insn (addr, plus_constant (mema, ofs+2));
- emit_insn (gen_extxl (extl, meml, GEN_INT (64), addr));
- emit_insn (gen_extqh (exth, memh, addr));
+ emit_insn (gen_extxl_le (extl, meml, GEN_INT (64), addr));
+ emit_insn (gen_extqh_le (exth, memh, addr));
/* We must use tgt here for the target. Alpha-vms port fails if we use
addr for the target, because addr is marked as a pointer and combine
@@ -3213,27 +3323,55 @@ alpha_expand_unaligned_load (tgt, mem, size, ofs, sign)
}
else
{
- emit_move_insn (addr, plus_constant (mema, ofs));
- emit_insn (gen_extxl (extl, meml, GEN_INT (size*8), addr));
- switch ((int) size)
+ if (WORDS_BIG_ENDIAN)
{
- case 2:
- emit_insn (gen_extwh (exth, memh, addr));
- mode = HImode;
- break;
+ emit_move_insn (addr, plus_constant (mema, ofs+size-1));
+ switch ((int) size)
+ {
+ case 2:
+ emit_insn (gen_extwh_be (extl, meml, addr));
+ mode = HImode;
+ break;
- case 4:
- emit_insn (gen_extlh (exth, memh, addr));
- mode = SImode;
- break;
+ case 4:
+ emit_insn (gen_extlh_be (extl, meml, addr));
+ mode = SImode;
+ break;
- case 8:
- emit_insn (gen_extqh (exth, memh, addr));
- mode = DImode;
- break;
+ case 8:
+ emit_insn (gen_extqh_be (extl, meml, addr));
+ mode = DImode;
+ break;
- default:
- abort();
+ default:
+ abort ();
+ }
+ emit_insn (gen_extxl_be (exth, memh, GEN_INT (size*8), addr));
+ }
+ else
+ {
+ emit_move_insn (addr, plus_constant (mema, ofs));
+ emit_insn (gen_extxl_le (extl, meml, GEN_INT (size*8), addr));
+ switch ((int) size)
+ {
+ case 2:
+ emit_insn (gen_extwh_le (exth, memh, addr));
+ mode = HImode;
+ break;
+
+ case 4:
+ emit_insn (gen_extlh_le (exth, memh, addr));
+ mode = SImode;
+ break;
+
+ case 8:
+ emit_insn (gen_extqh_le (exth, memh, addr));
+ mode = DImode;
+ break;
+
+ default:
+ abort();
+ }
}
addr = expand_binop (mode, ior_optab, gen_lowpart (mode, extl),
@@ -3281,47 +3419,94 @@ alpha_expand_unaligned_store (dst, src, size, ofs)
emit_move_insn (dsth, memh);
emit_move_insn (dstl, meml);
- addr = copy_addr_to_reg (plus_constant (dsta, ofs));
-
- if (src != const0_rtx)
+ if (WORDS_BIG_ENDIAN)
{
- emit_insn (gen_insxh (insh, gen_lowpart (DImode, src),
- GEN_INT (size*8), addr));
+ addr = copy_addr_to_reg (plus_constant (dsta, ofs+size-1));
+
+ if (src != const0_rtx)
+ {
+ switch ((int) size)
+ {
+ case 2:
+ emit_insn (gen_inswl_be (insh, gen_lowpart (HImode,src), addr));
+ break;
+ case 4:
+ emit_insn (gen_insll_be (insh, gen_lowpart (SImode,src), addr));
+ break;
+ case 8:
+ emit_insn (gen_insql_be (insh, gen_lowpart (DImode,src), addr));
+ break;
+ }
+ emit_insn (gen_insxh (insl, gen_lowpart (DImode, src),
+ GEN_INT (size*8), addr));
+ }
switch ((int) size)
{
case 2:
- emit_insn (gen_inswl (insl, gen_lowpart (HImode, src), addr));
+ emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffff), addr));
break;
case 4:
- emit_insn (gen_insll (insl, gen_lowpart (SImode, src), addr));
+ emit_insn (gen_mskxl_be (dsth, dsth, GEN_INT (0xffffffff), addr));
break;
case 8:
- emit_insn (gen_insql (insl, src, addr));
+ {
+#if HOST_BITS_PER_WIDE_INT == 32
+ rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
+#else
+ rtx msk = immed_double_const (0xffffffffffffffff, 0, DImode);
+#endif
+ emit_insn (gen_mskxl_be (dsth, dsth, msk, addr));
+ }
break;
}
+
+ emit_insn (gen_mskxh (dstl, dstl, GEN_INT (size*8), addr));
}
+ else
+ {
+ addr = copy_addr_to_reg (plus_constant (dsta, ofs));
- emit_insn (gen_mskxh (dsth, dsth, GEN_INT (size*8), addr));
+ if (src != const0_rtx)
+ {
+ emit_insn (gen_insxh (insh, gen_lowpart (DImode, src),
+ GEN_INT (size*8), addr));
- switch ((int) size)
- {
- case 2:
- emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffff), addr));
- break;
- case 4:
- emit_insn (gen_mskxl (dstl, dstl, GEN_INT (0xffffffff), addr));
- break;
- case 8:
- {
+ switch ((int) size)
+ {
+ case 2:
+ emit_insn (gen_inswl_le (insl, gen_lowpart (HImode, src), addr));
+ break;
+ case 4:
+ emit_insn (gen_insll_le (insl, gen_lowpart (SImode, src), addr));
+ break;
+ case 8:
+ emit_insn (gen_insql_le (insl, src, addr));
+ break;
+ }
+ }
+
+ emit_insn (gen_mskxh (dsth, dsth, GEN_INT (size*8), addr));
+
+ switch ((int) size)
+ {
+ case 2:
+ emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffff), addr));
+ break;
+ case 4:
+ emit_insn (gen_mskxl_le (dstl, dstl, GEN_INT (0xffffffff), addr));
+ break;
+ case 8:
+ {
#if HOST_BITS_PER_WIDE_INT == 32
- rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
+ rtx msk = immed_double_const (0xffffffff, 0xffffffff, DImode);
#else
- rtx msk = immed_double_const (0xffffffffffffffff, 0, DImode);
+ rtx msk = immed_double_const (0xffffffffffffffff, 0, DImode);
#endif
- emit_insn (gen_mskxl (dstl, dstl, msk, addr));
- }
- break;
+ emit_insn (gen_mskxl_le (dstl, dstl, msk, addr));
+ }
+ break;
+ }
}
if (src != const0_rtx)
@@ -3329,10 +3514,18 @@ alpha_expand_unaligned_store (dst, src, size, ofs)
dsth = expand_binop (DImode, ior_optab, insh, dsth, dsth, 0, OPTAB_WIDEN);
dstl = expand_binop (DImode, ior_optab, insl, dstl, dstl, 0, OPTAB_WIDEN);
}
-
- /* Must store high before low for degenerate case of aligned. */
- emit_move_insn (memh, dsth);
- emit_move_insn (meml, dstl);
+
+ if (WORDS_BIG_ENDIAN)
+ {
+ emit_move_insn (meml, dstl);
+ emit_move_insn (memh, dsth);
+ }
+ else
+ {
+ /* Must store high before low for degenerate case of aligned. */
+ emit_move_insn (memh, dsth);
+ emit_move_insn (meml, dstl);
+ }
}
/* The block move code tries to maximize speed by separating loads and
@@ -3397,11 +3590,20 @@ alpha_expand_unaligned_load_words (out_regs, smem, words, ofs)
sreg = copy_addr_to_reg (smema);
areg = expand_binop (DImode, and_optab, sreg, GEN_INT (7), NULL,
1, OPTAB_WIDEN);
+ if (WORDS_BIG_ENDIAN)
+ emit_move_insn (sreg, plus_constant (sreg, 7));
for (i = 0; i < words; ++i)
{
- emit_insn (gen_extxl (data_regs[i], data_regs[i], i64, sreg));
-
- emit_insn (gen_extqh (ext_tmps[i], data_regs[i+1], sreg));
+ if (WORDS_BIG_ENDIAN)
+ {
+ emit_insn (gen_extqh_be (data_regs[i], data_regs[i], sreg));
+ emit_insn (gen_extxl_be (ext_tmps[i], data_regs[i+1], i64, sreg));
+ }
+ else
+ {
+ emit_insn (gen_extxl_le (data_regs[i], data_regs[i], i64, sreg));
+ emit_insn (gen_extqh_le (ext_tmps[i], data_regs[i+1], sreg));
+ }
emit_insn (gen_rtx_SET (VOIDmode, ext_tmps[i],
gen_rtx_IF_THEN_ELSE (DImode,
gen_rtx_EQ (DImode, areg,
@@ -3468,12 +3670,22 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
/* Shift the input data into place. */
dreg = copy_addr_to_reg (dmema);
+ if (WORDS_BIG_ENDIAN)
+ emit_move_insn (dreg, plus_constant (dreg, 7));
if (data_regs != NULL)
{
for (i = words-1; i >= 0; --i)
{
- emit_insn (gen_insxh (ins_tmps[i], data_regs[i], i64, dreg));
- emit_insn (gen_insql (data_regs[i], data_regs[i], dreg));
+ if (WORDS_BIG_ENDIAN)
+ {
+ emit_insn (gen_insql_be (ins_tmps[i], data_regs[i], dreg));
+ emit_insn (gen_insxh (data_regs[i], data_regs[i], i64, dreg));
+ }
+ else
+ {
+ emit_insn (gen_insxh (ins_tmps[i], data_regs[i], i64, dreg));
+ emit_insn (gen_insql_le (data_regs[i], data_regs[i], dreg));
+ }
}
for (i = words-1; i > 0; --i)
{
@@ -3484,8 +3696,16 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
}
/* Split and merge the ends with the destination data. */
- emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg));
- emit_insn (gen_mskxl (st_tmp_1, st_tmp_1, im1, dreg));
+ if (WORDS_BIG_ENDIAN)
+ {
+ emit_insn (gen_mskxl_be (st_tmp_2, st_tmp_2, im1, dreg));
+ emit_insn (gen_mskxh (st_tmp_1, st_tmp_1, i64, dreg));
+ }
+ else
+ {
+ emit_insn (gen_mskxh (st_tmp_2, st_tmp_2, i64, dreg));
+ emit_insn (gen_mskxl_le (st_tmp_1, st_tmp_1, im1, dreg));
+ }
if (data_regs != NULL)
{
@@ -3496,17 +3716,24 @@ alpha_expand_unaligned_store_words (data_regs, dmem, words, ofs)
}
/* Store it all. */
- emit_move_insn (st_addr_2, st_tmp_2);
+ if (WORDS_BIG_ENDIAN)
+ emit_move_insn (st_addr_1, st_tmp_1);
+ else
+ emit_move_insn (st_addr_2, st_tmp_2);
for (i = words-1; i > 0; --i)
{
rtx tmp = change_address (dmem, DImode,
gen_rtx_AND (DImode,
- plus_constant(dmema, i*8),
+ plus_constant(dmema,
+ WORDS_BIG_ENDIAN ? i*8-1 : i*8),
im8));
set_mem_alias_set (tmp, 0);
emit_move_insn (tmp, data_regs ? ins_tmps[i-1] : const0_rtx);
}
- emit_move_insn (st_addr_1, st_tmp_1);
+ if (WORDS_BIG_ENDIAN)
+ emit_move_insn (st_addr_2, st_tmp_2);
+ else
+ emit_move_insn (st_addr_1, st_tmp_1);
}
@@ -4312,6 +4539,45 @@ alpha_variable_issue (dump, verbose, insn, cim)
}
+/* Register global variables and machine-specific functions with the
+ garbage collector. */
+
+#if TARGET_ABI_UNICOSMK
+static void
+alpha_init_machine_status (p)
+ struct function *p;
+{
+ p->machine =
+ (struct machine_function *) xcalloc (1, sizeof (struct machine_function));
+
+ p->machine->first_ciw = NULL_RTX;
+ p->machine->last_ciw = NULL_RTX;
+ p->machine->ciw_count = 0;
+ p->machine->addr_list = NULL_RTX;
+}
+
+static void
+alpha_mark_machine_status (p)
+ struct function *p;
+{
+ struct machine_function *machine = p->machine;
+
+ if (machine)
+ {
+ ggc_mark_rtx (machine->first_ciw);
+ ggc_mark_rtx (machine->addr_list);
+ }
+}
+
+static void
+alpha_free_machine_status (p)
+ struct function *p;
+{
+ free (p->machine);
+ p->machine = NULL;
+}
+#endif /* TARGET_ABI_UNICOSMK */
+
/* Functions to save and restore alpha_return_addr_rtx. */
/* Start the ball rolling with RETURN_ADDR_RTX. */
@@ -4478,8 +4744,8 @@ print_operand (file, x, code)
const char *round = get_round_mode_suffix ();
if (trap || round)
- fprintf (file, "%s%s", (trap ? trap : ""), (round ? round : ""));
-
+ fprintf (file, (TARGET_AS_SLASH_BEFORE_SUFFIX ? "/%s%s" : "%s%s"),
+ (trap ? trap : ""), (round ? round : ""));
break;
}
@@ -4648,13 +4914,20 @@ print_operand (file, x, code)
break;
case 's':
- /* Write the constant value divided by 8. */
+ /* Write the constant value divided by 8 for little-endian mode or
+ (56 - value) / 8 for big-endian mode. */
+
if (GET_CODE (x) != CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (x) >= 64
- && (INTVAL (x) & 7) != 8)
+ || (unsigned HOST_WIDE_INT) INTVAL (x) >= (WORDS_BIG_ENDIAN
+ ? 56
+ : 64)
+ || (INTVAL (x) & 7) != 0)
output_operand_lossage ("invalid %%s value");
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) / 8);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ WORDS_BIG_ENDIAN
+ ? (56 - INTVAL (x)) / 8
+ : INTVAL (x) / 8);
break;
case 'S':
@@ -4668,6 +4941,18 @@ print_operand (file, x, code)
fprintf (file, HOST_WIDE_INT_PRINT_DEC, (64 - INTVAL (x)) / 8);
break;
+ case 't':
+ {
+ /* On Unicos/Mk systems: use a DEX expression if the symbol
+ clashes with a register name. */
+ int dex = unicosmk_need_dex (x);
+ if (dex)
+ fprintf (file, "DEX(%d)", dex);
+ else
+ output_addr_const (file, x);
+ }
+ break;
+
case 'C': case 'D': case 'c': case 'd':
/* Write out comparison name. */
{
@@ -4878,32 +5163,106 @@ function_arg (cum, mode, type, named)
int basereg;
int num_args;
+ /* Set up defaults for FP operands passed in FP registers, and
+ integral operands passed in integer registers. */
+ if (TARGET_FPREGS
+ && (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_FLOAT))
+ basereg = 32 + 16;
+ else
+ basereg = 16;
+
+ /* ??? Irritatingly, the definition of CUMULATIVE_ARGS is different for
+ the three platforms, so we can't avoid conditional compilation. */
#if TARGET_ABI_OPEN_VMS
- if (mode == VOIDmode)
- return alpha_arg_info_reg_val (cum);
+ {
+ if (mode == VOIDmode)
+ return alpha_arg_info_reg_val (cum);
- num_args = cum.num_args;
- if (num_args >= 6 || MUST_PASS_IN_STACK (mode, type))
- return NULL_RTX;
+ num_args = cum.num_args;
+ if (num_args >= 6 || MUST_PASS_IN_STACK (mode, type))
+ return NULL_RTX;
+ }
#else
- if (cum >= 6)
- return NULL_RTX;
- num_args = cum;
+#if TARGET_ABI_UNICOSMK
+ {
+ int size;
- /* VOID is passed as a special flag for "last argument". */
- if (type == void_type_node)
- basereg = 16;
- else if (MUST_PASS_IN_STACK (mode, type))
- return NULL_RTX;
- else if (FUNCTION_ARG_PASS_BY_REFERENCE (cum, mode, type, named))
- basereg = 16;
+ /* If this is the last argument, generate the call info word (CIW). */
+ /* ??? We don't include the caller's line number in the CIW because
+ I don't know how to determine it if debug infos are turned off. */
+ if (mode == VOIDmode)
+ {
+ int i;
+ HOST_WIDE_INT lo;
+ HOST_WIDE_INT hi;
+ rtx ciw;
+
+ lo = 0;
+
+ for (i = 0; i < cum.num_reg_words && i < 5; i++)
+ if (cum.reg_args_type[i])
+ lo |= (1 << (7 - i));
+
+ if (cum.num_reg_words == 6 && cum.reg_args_type[5])
+ lo |= 7;
+ else
+ lo |= cum.num_reg_words;
+
+#if HOST_BITS_PER_WIDE_INT == 32
+ hi = (cum.num_args << 20) | cum.num_arg_words;
+#else
+ lo = lo | (cum.num_args << 52) | (cum.num_arg_words << 32);
+ hi = 0;
+#endif
+ ciw = immed_double_const (lo, hi, DImode);
+
+ return gen_rtx_UNSPEC (DImode, gen_rtvec (1, ciw),
+ UNSPEC_UMK_LOAD_CIW);
+ }
+
+ size = ALPHA_ARG_SIZE (mode, type, named);
+ num_args = cum.num_reg_words;
+ if (MUST_PASS_IN_STACK (mode, type)
+ || cum.num_reg_words + size > 6 || cum.force_stack)
+ return NULL_RTX;
+ else if (type && TYPE_MODE (type) == BLKmode)
+ {
+ rtx reg1, reg2;
+
+ reg1 = gen_rtx_REG (DImode, num_args + 16);
+ reg1 = gen_rtx_EXPR_LIST (DImode, reg1, const0_rtx);
+
+ /* The argument fits in two registers. Note that we still need to
+ reserve a register for empty structures. */
+ if (size == 0)
+ return NULL_RTX;
+ else if (size == 1)
+ return gen_rtx_PARALLEL (mode, gen_rtvec (1, reg1));
+ else
+ {
+ reg2 = gen_rtx_REG (DImode, num_args + 17);
+ reg2 = gen_rtx_EXPR_LIST (DImode, reg2, GEN_INT (8));
+ return gen_rtx_PARALLEL (mode, gen_rtvec (2, reg1, reg2));
+ }
+ }
+ }
+#else
+ {
+ if (cum >= 6)
+ return NULL_RTX;
+ num_args = cum;
+
+ /* VOID is passed as a special flag for "last argument". */
+ if (type == void_type_node)
+ basereg = 16;
+ else if (MUST_PASS_IN_STACK (mode, type))
+ return NULL_RTX;
+ else if (FUNCTION_ARG_PASS_BY_REFERENCE (cum, mode, type, named))
+ basereg = 16;
+ }
+#endif /* TARGET_ABI_UNICOSMK */
#endif /* TARGET_ABI_OPEN_VMS */
- else if (TARGET_FPREGS
- && (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
- || GET_MODE_CLASS (mode) == MODE_FLOAT))
- basereg = 32 + 16;
- else
- basereg = 16;
return gen_rtx_REG (mode, num_args + basereg);
}
@@ -4913,7 +5272,7 @@ alpha_build_va_list ()
{
tree base, ofs, record, type_decl;
- if (TARGET_ABI_OPEN_VMS)
+ if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
return ptr_type_node;
record = make_lang_type (RECORD_TYPE);
@@ -4950,7 +5309,7 @@ alpha_va_start (stdarg_p, valist, nextarg)
if (TREE_CODE (TREE_TYPE (valist)) == ERROR_MARK)
return;
- if (TARGET_ABI_OPEN_VMS)
+ if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
std_expand_builtin_va_start (stdarg_p, valist, nextarg);
/* For Unix, SETUP_INCOMING_VARARGS moves the starting address base
@@ -4998,7 +5357,7 @@ alpha_va_arg (valist, type)
tree wide_type, wide_ofs;
int indirect = 0;
- if (TARGET_ABI_OPEN_VMS)
+ if (TARGET_ABI_OPEN_VMS || TARGET_ABI_UNICOSMK)
return std_expand_builtin_va_arg (valist, type);
tsize = ((TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT + 7) / 8) * 8;
@@ -5067,7 +5426,7 @@ alpha_va_arg (valist, type)
descriptior to generate. */
/* Nonzero if we need a stack procedure. */
-static int vms_is_stack_procedure;
+static int alpha_is_stack_procedure;
/* Register number (either FP or SP) that is used to unwind the frame. */
static int vms_unwind_regno;
@@ -5095,13 +5454,14 @@ alpha_sa_mask (imaskP, fmaskP)
if (!current_function_is_thunk)
#endif
{
- if (TARGET_ABI_OPEN_VMS && vms_is_stack_procedure)
+ if (TARGET_ABI_OPEN_VMS && alpha_is_stack_procedure)
imask |= (1L << HARD_FRAME_POINTER_REGNUM);
/* One for every register we have to save. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (! fixed_regs[i] && ! call_used_regs[i]
- && regs_ever_live[i] && i != REG_RA)
+ && regs_ever_live[i] && i != REG_RA
+ && (!TARGET_ABI_UNICOSMK || i != HARD_FRAME_POINTER_REGNUM))
{
if (i < 32)
imask |= (1L << i);
@@ -5120,9 +5480,15 @@ alpha_sa_mask (imaskP, fmaskP)
imask |= 1L << regno;
}
}
-
- if (imask || fmask || alpha_ra_ever_killed ())
- imask |= (1L << REG_RA);
+
+ if (!TARGET_ABI_UNICOSMK)
+ {
+ /* If any register spilled, then spill the return address also. */
+ /* ??? This is required by the Digital stack unwind specification
+ and isn't needed if we're doing Dwarf2 unwinding. */
+ if (imask || fmask || alpha_ra_ever_killed ())
+ imask |= (1L << REG_RA);
+ }
}
*imaskP = imask;
@@ -5141,19 +5507,55 @@ alpha_sa_size ()
else
#endif
{
- /* One for every register we have to save. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (! fixed_regs[i] && ! call_used_regs[i]
- && regs_ever_live[i] && i != REG_RA)
- sa_size++;
+ if (TARGET_ABI_UNICOSMK)
+ {
+ for (i = 9; i < 15 && sa_size == 0; i++)
+ if (! fixed_regs[i] && ! call_used_regs[i]
+ && regs_ever_live[i])
+ sa_size = 14;
+ for (i = 32 + 2; i < 32 + 10 && sa_size == 0; i++)
+ if (! fixed_regs[i] && ! call_used_regs[i]
+ && regs_ever_live[i])
+ sa_size = 14;
+ }
+ else
+ {
+ /* One for every register we have to save. */
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (! fixed_regs[i] && ! call_used_regs[i]
+ && regs_ever_live[i] && i != REG_RA)
+ sa_size++;
+ }
}
- if (TARGET_ABI_OPEN_VMS)
+ if (TARGET_ABI_UNICOSMK)
+ {
+ /* We might not need to generate a frame if we don't make any calls
+ (including calls to __T3E_MISMATCH if this is a vararg function),
+ don't have any local variables which require stack slots, don't
+ use alloca and have not determined that we need a frame for other
+ reasons. */
+
+ alpha_is_stack_procedure = sa_size != 0
+ || alpha_ra_ever_killed ()
+ || get_frame_size() != 0
+ || current_function_outgoing_args_size
+ || current_function_varargs
+ || current_function_stdarg
+ || current_function_calls_alloca
+ || frame_pointer_needed;
+
+ /* Always reserve space for saving callee-saved registers if we
+ need a frame as required by the calling convention. */
+ if (alpha_is_stack_procedure)
+ sa_size = 14;
+ }
+ else if (TARGET_ABI_OPEN_VMS)
{
/* Start by assuming we can use a register procedure if we don't
make any calls (REG_RA not used) or need to save any
registers and a stack procedure if we do. */
- vms_is_stack_procedure = sa_size != 0 || alpha_ra_ever_killed ();
+ alpha_is_stack_procedure = sa_size != 0 || alpha_ra_ever_killed ();
/* Decide whether to refer to objects off our PV via FP or PV.
If we need FP for something else or if we receive a nonlocal
@@ -5161,7 +5563,7 @@ alpha_sa_size ()
Otherwise, start by assuming we can use FP. */
vms_base_regno = (frame_pointer_needed
|| current_function_has_nonlocal_label
- || vms_is_stack_procedure
+ || alpha_is_stack_procedure
|| current_function_outgoing_args_size
? REG_PV : HARD_FRAME_POINTER_REGNUM);
@@ -5175,21 +5577,21 @@ alpha_sa_size ()
vms_save_fp_regno = i;
if (vms_save_fp_regno == -1)
- vms_base_regno = REG_PV, vms_is_stack_procedure = 1;
+ vms_base_regno = REG_PV, alpha_is_stack_procedure = 1;
/* Stack unwinding should be done via FP unless we use it for PV. */
vms_unwind_regno = (vms_base_regno == REG_PV
? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM);
/* If this is a stack procedure, allow space for saving FP and RA. */
- if (vms_is_stack_procedure)
+ if (alpha_is_stack_procedure)
sa_size += 2;
}
else
{
/* If some registers were saved but not RA, RA must also be saved,
so leave space for it. */
- if (sa_size != 0 || alpha_ra_ever_killed ())
+ if (!TARGET_ABI_UNICOSMK && (sa_size != 0 || alpha_ra_ever_killed ()))
sa_size++;
/* Our size must be even (multiple of 16 bytes). */
@@ -5204,7 +5606,7 @@ int
alpha_pv_save_size ()
{
alpha_sa_size ();
- return vms_is_stack_procedure ? 8 : 0;
+ return alpha_is_stack_procedure ? 8 : 0;
}
int
@@ -5243,8 +5645,8 @@ alpha_does_function_need_gp ()
{
rtx insn;
- /* We never need a GP for Windows/NT or VMS. */
- if (TARGET_ABI_WINDOWS_NT || TARGET_ABI_OPEN_VMS)
+ /* The GP being variable is an OSF abi thing. */
+ if (! TARGET_ABI_OSF)
return 0;
if (TARGET_PROFILING_NEEDS_GP && profile_flag)
@@ -5358,9 +5760,15 @@ alpha_expand_prologue ()
frame_size = get_frame_size ();
if (TARGET_ABI_OPEN_VMS)
frame_size = ALPHA_ROUND (sa_size
- + (vms_is_stack_procedure ? 8 : 0)
+ + (alpha_is_stack_procedure ? 8 : 0)
+ frame_size
+ current_function_pretend_args_size);
+ else if (TARGET_ABI_UNICOSMK)
+ /* We have to allocate space for the DSIB if we generate a frame. */
+ frame_size = ALPHA_ROUND (sa_size
+ + (alpha_is_stack_procedure ? 48 : 0))
+ + ALPHA_ROUND (frame_size
+ + current_function_outgoing_args_size);
else
frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
+ sa_size
@@ -5388,7 +5796,10 @@ alpha_expand_prologue ()
don't represent the call as a call. */
if (TARGET_PROFILING_NEEDS_GP && profile_flag)
emit_insn (gen_prologue_mcount ());
-
+
+ if (TARGET_ABI_UNICOSMK)
+ unicosmk_gen_dsib (&imask);
+
/* Adjust the stack by the frame size. If the frame size is > 4096
bytes, we need to be sure we probe somewhere in the first and last
4096 bytes (we can probably get away without the latter test) and
@@ -5405,7 +5816,9 @@ alpha_expand_prologue ()
int probed = 4096;
do
- emit_insn (gen_probe_stack (GEN_INT (-probed)));
+ 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. */
@@ -5415,7 +5828,9 @@ alpha_expand_prologue ()
if (frame_size != 0)
FRP (emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-frame_size))));
+ GEN_INT (TARGET_ABI_UNICOSMK
+ ? -frame_size + 64
+ : -frame_size))));
}
else
{
@@ -5432,7 +5847,8 @@ alpha_expand_prologue ()
rtx seq;
emit_move_insn (count, GEN_INT (blocks));
- emit_insn (gen_adddi3 (ptr, stack_pointer_rtx, GEN_INT (4096)));
+ emit_insn (gen_adddi3 (ptr, stack_pointer_rtx,
+ GEN_INT (TARGET_ABI_UNICOSMK ? 4096 - 64 : 4096)));
/* Because of the difficulty in emitting a new basic block this
late in the compilation, generate the loop as a single insn. */
@@ -5479,66 +5895,98 @@ alpha_expand_prologue ()
= gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
gen_rtx_SET (VOIDmode, stack_pointer_rtx,
gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- GEN_INT (-frame_size))),
+ GEN_INT (TARGET_ABI_UNICOSMK
+ ? -frame_size + 64
+ : -frame_size))),
REG_NOTES (seq));
}
- /* Cope with very large offsets to the register save area. */
- sa_reg = stack_pointer_rtx;
- if (reg_offset + sa_size > 0x8000)
+ if (!TARGET_ABI_UNICOSMK)
{
- int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
- HOST_WIDE_INT bias;
+ /* Cope with very large offsets to the register save area. */
+ sa_reg = stack_pointer_rtx;
+ if (reg_offset + sa_size > 0x8000)
+ {
+ int low = ((reg_offset & 0xffff) ^ 0x8000) - 0x8000;
+ HOST_WIDE_INT bias;
- if (low + sa_size <= 0x8000)
- bias = reg_offset - low, reg_offset = low;
- else
- bias = reg_offset, reg_offset = 0;
+ if (low + sa_size <= 0x8000)
+ bias = reg_offset - low, reg_offset = low;
+ else
+ bias = reg_offset, reg_offset = 0;
- sa_reg = gen_rtx_REG (DImode, 24);
- FRP (emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx, GEN_INT (bias))));
- }
+ sa_reg = gen_rtx_REG (DImode, 24);
+ FRP (emit_insn (gen_adddi3 (sa_reg, stack_pointer_rtx,
+ GEN_INT (bias))));
+ }
- /* Save regs in stack order. Beginning with VMS PV. */
- if (TARGET_ABI_OPEN_VMS && vms_is_stack_procedure)
- {
- mem = gen_rtx_MEM (DImode, stack_pointer_rtx);
- set_mem_alias_set (mem, alpha_sr_alias_set);
- FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_PV)));
- }
+ /* Save regs in stack order. Beginning with VMS PV. */
+ if (TARGET_ABI_OPEN_VMS && alpha_is_stack_procedure)
+ {
+ mem = gen_rtx_MEM (DImode, stack_pointer_rtx);
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_PV)));
+ }
- /* Save register RA next. */
- if (imask & (1L << REG_RA))
- {
- mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
- set_mem_alias_set (mem, alpha_sr_alias_set);
- FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
- imask &= ~(1L << REG_RA);
- reg_offset += 8;
- }
+ /* Save register RA next. */
+ if (imask & (1L << REG_RA))
+ {
+ mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
+ imask &= ~(1L << REG_RA);
+ reg_offset += 8;
+ }
- /* Now save any other registers required to be saved. */
- for (i = 0; i < 32; i++)
- if (imask & (1L << i))
- {
- mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
- set_mem_alias_set (mem, alpha_sr_alias_set);
- FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i)));
- reg_offset += 8;
- }
+ /* Now save any other registers required to be saved. */
+ for (i = 0; i < 32; i++)
+ if (imask & (1L << i))
+ {
+ mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, reg_offset));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i)));
+ reg_offset += 8;
+ }
- for (i = 0; i < 32; i++)
- if (fmask & (1L << i))
- {
- mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset));
- set_mem_alias_set (mem, alpha_sr_alias_set);
- FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32)));
- reg_offset += 8;
- }
+ for (i = 0; i < 32; i++)
+ if (fmask & (1L << i))
+ {
+ mem = gen_rtx_MEM (DFmode, plus_constant (sa_reg, reg_offset));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32)));
+ reg_offset += 8;
+ }
+ }
+ else if (TARGET_ABI_UNICOSMK && alpha_is_stack_procedure)
+ {
+ /* The standard frame on the T3E includes space for saving registers.
+ We just have to use it. We don't have to save the return address and
+ the old frame pointer here - they are saved in the DSIB. */
+
+ reg_offset = -56;
+ for (i = 9; i < 15; i++)
+ if (imask & (1L << i))
+ {
+ mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
+ reg_offset));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (mem, gen_rtx_REG (DImode, i)));
+ reg_offset -= 8;
+ }
+ for (i = 2; i < 10; i++)
+ if (fmask & (1L << i))
+ {
+ mem = gen_rtx_MEM (DFmode, plus_constant (hard_frame_pointer_rtx,
+ reg_offset));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (mem, gen_rtx_REG (DFmode, i+32)));
+ reg_offset -= 8;
+ }
+ }
if (TARGET_ABI_OPEN_VMS)
{
- if (!vms_is_stack_procedure)
+ if (!alpha_is_stack_procedure)
/* Register frame procedures save the fp. */
/* ??? Ought to have a dwarf2 save for this. */
emit_move_insn (gen_rtx_REG (DImode, vms_save_fp_regno),
@@ -5559,7 +6007,7 @@ alpha_expand_prologue ()
- (ALPHA_ROUND
(current_function_outgoing_args_size)))));
}
- else
+ else if (!TARGET_ABI_UNICOSMK)
{
/* If we need a frame pointer, set it from the stack pointer. */
if (frame_pointer_needed)
@@ -5607,15 +6055,28 @@ alpha_start_function (file, fnname, decl)
char *entry_label = (char *) alloca (strlen (fnname) + 6);
int i;
+ /* Don't emit an extern directive for functions defined in the same file. */
+ if (TARGET_ABI_UNICOSMK)
+ {
+ tree name_tree;
+ name_tree = get_identifier (fnname);
+ TREE_ASM_WRITTEN (name_tree) = 1;
+ }
+
alpha_fnname = fnname;
sa_size = alpha_sa_size ();
frame_size = get_frame_size ();
if (TARGET_ABI_OPEN_VMS)
frame_size = ALPHA_ROUND (sa_size
- + (vms_is_stack_procedure ? 8 : 0)
+ + (alpha_is_stack_procedure ? 8 : 0)
+ frame_size
+ current_function_pretend_args_size);
+ else if (TARGET_ABI_UNICOSMK)
+ frame_size = ALPHA_ROUND (sa_size
+ + (alpha_is_stack_procedure ? 48 : 0))
+ + ALPHA_ROUND (frame_size
+ + current_function_outgoing_args_size);
else
frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
+ sa_size
@@ -5639,15 +6100,20 @@ alpha_start_function (file, fnname, decl)
if (write_symbols == SDB_DEBUG)
{
+#ifdef ASM_OUTPUT_SOURCE_FILENAME
ASM_OUTPUT_SOURCE_FILENAME (file,
DECL_SOURCE_FILE (current_function_decl));
+#endif
+#ifdef ASM_OUTPUT_SOURCE_LINE
if (debug_info_level != DINFO_LEVEL_TERSE)
ASM_OUTPUT_SOURCE_LINE (file,
DECL_SOURCE_LINE (current_function_decl));
+#endif
}
/* Issue function start and label. */
- if (TARGET_ABI_OPEN_VMS || !flag_inhibit_size_directive)
+ if (TARGET_ABI_OPEN_VMS
+ || (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive))
{
fputs ("\t.ent ", file);
assemble_name (file, fnname);
@@ -5666,13 +6132,19 @@ alpha_start_function (file, fnname, decl)
strcpy (entry_label, fnname);
if (TARGET_ABI_OPEN_VMS)
strcat (entry_label, "..en");
+
+ /* For public functions, the label must be globalized by appending an
+ additional colon. */
+ if (TARGET_ABI_UNICOSMK && TREE_PUBLIC (decl))
+ strcat (entry_label, ":");
+
ASM_OUTPUT_LABEL (file, entry_label);
inside_function = TRUE;
if (TARGET_ABI_OPEN_VMS)
fprintf (file, "\t.base $%d\n", vms_base_regno);
- if (!TARGET_ABI_OPEN_VMS && TARGET_IEEE_CONFORMANT
+ if (!TARGET_ABI_OPEN_VMS && !TARGET_ABI_UNICOSMK && TARGET_IEEE_CONFORMANT
&& !flag_inhibit_size_directive)
{
/* Set flags in procedure descriptor to request IEEE-conformant
@@ -5688,7 +6160,9 @@ alpha_start_function (file, fnname, decl)
/* Describe our frame. If the frame size is larger than an integer,
print it as zero to avoid an assembler error. We won't be
properly describing such a frame, but that's the best we can do. */
- if (TARGET_ABI_OPEN_VMS)
+ if (TARGET_ABI_UNICOSMK)
+ ;
+ else if (TARGET_ABI_OPEN_VMS)
{
fprintf (file, "\t.frame $%d,", vms_unwind_regno);
fprintf (file, HOST_WIDE_INT_PRINT_DEC,
@@ -5708,15 +6182,17 @@ alpha_start_function (file, fnname, decl)
}
/* Describe which registers were spilled. */
- if (TARGET_ABI_OPEN_VMS)
+ if (TARGET_ABI_UNICOSMK)
+ ;
+ else if (TARGET_ABI_OPEN_VMS)
{
if (imask)
- /* ??? Does VMS care if mask contains ra? The old code did'nt
+ /* ??? Does VMS care if mask contains ra? The old code didn't
set it, so I don't here. */
fprintf (file, "\t.mask 0x%lx,0\n", imask & ~(1L << REG_RA));
if (fmask)
fprintf (file, "\t.fmask 0x%lx,0\n", fmask);
- if (!vms_is_stack_procedure)
+ if (!alpha_is_stack_procedure)
fprintf (file, "\t.fp_save $%d\n", vms_save_fp_regno);
}
else if (!flag_inhibit_size_directive)
@@ -5760,7 +6236,7 @@ alpha_start_function (file, fnname, decl)
ASM_OUTPUT_LABEL (file, fnname);
fprintf (file, "\t.pdesc ");
assemble_name (file, fnname);
- fprintf (file, "..en,%s\n", vms_is_stack_procedure ? "stack" : "reg");
+ fprintf (file, "..en,%s\n", alpha_is_stack_procedure ? "stack" : "reg");
alpha_need_linkage (fnname, 1);
text_section ();
#endif
@@ -5772,7 +6248,9 @@ static void
alpha_output_function_end_prologue (file)
FILE *file;
{
- if (TARGET_ABI_OPEN_VMS)
+ if (TARGET_ABI_UNICOSMK)
+ ;
+ else if (TARGET_ABI_OPEN_VMS)
fputs ("\t.prologue\n", file);
else if (TARGET_ABI_WINDOWS_NT)
fputs ("\t.prologue 0\n", file);
@@ -5811,9 +6289,14 @@ alpha_expand_epilogue ()
frame_size = get_frame_size ();
if (TARGET_ABI_OPEN_VMS)
frame_size = ALPHA_ROUND (sa_size
- + (vms_is_stack_procedure ? 8 : 0)
+ + (alpha_is_stack_procedure ? 8 : 0)
+ frame_size
+ current_function_pretend_args_size);
+ else if (TARGET_ABI_UNICOSMK)
+ frame_size = ALPHA_ROUND (sa_size
+ + (alpha_is_stack_procedure ? 48 : 0))
+ + ALPHA_ROUND (frame_size
+ + current_function_outgoing_args_size);
else
frame_size = (ALPHA_ROUND (current_function_outgoing_args_size)
+ sa_size
@@ -5827,7 +6310,7 @@ alpha_expand_epilogue ()
alpha_sa_mask (&imask, &fmask);
- fp_is_frame_pointer = ((TARGET_ABI_OPEN_VMS && vms_is_stack_procedure)
+ fp_is_frame_pointer = ((TARGET_ABI_OPEN_VMS && alpha_is_stack_procedure)
|| (!TARGET_ABI_OPEN_VMS && frame_pointer_needed));
fp_offset = 0;
sa_reg = stack_pointer_rtx;
@@ -5837,7 +6320,7 @@ alpha_expand_epilogue ()
else
eh_ofs = NULL_RTX;
- if (sa_size)
+ if (!TARGET_ABI_UNICOSMK && sa_size)
{
/* If we have a frame pointer, restore SP from it. */
if ((TARGET_ABI_OPEN_VMS
@@ -5895,6 +6378,38 @@ alpha_expand_epilogue ()
reg_offset += 8;
}
}
+ else if (TARGET_ABI_UNICOSMK && alpha_is_stack_procedure)
+ {
+ /* Restore callee-saved general-purpose registers. */
+
+ reg_offset = -56;
+
+ for (i = 9; i < 15; i++)
+ if (imask & (1L << i))
+ {
+ mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx,
+ reg_offset));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (gen_rtx_REG (DImode, i), mem));
+ reg_offset -= 8;
+ }
+
+ for (i = 2; i < 10; i++)
+ if (fmask & (1L << i))
+ {
+ mem = gen_rtx_MEM (DFmode, plus_constant(hard_frame_pointer_rtx,
+ reg_offset));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (gen_rtx_REG (DFmode, i+32), mem));
+ reg_offset -= 8;
+ }
+
+ /* Restore the return address from the DSIB. */
+
+ mem = gen_rtx_MEM (DImode, plus_constant(hard_frame_pointer_rtx, -8));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (gen_rtx_REG (DImode, REG_RA), mem));
+ }
if (frame_size || eh_ofs)
{
@@ -5910,8 +6425,15 @@ alpha_expand_epilogue ()
/* If the stack size is large, begin computation into a temporary
register so as not to interfere with a potential fp restore,
which must be consecutive with an SP restore. */
- if (frame_size < 32768)
+ if (frame_size < 32768
+ && ! (TARGET_ABI_UNICOSMK && current_function_calls_alloca))
sp_adj2 = GEN_INT (frame_size);
+ else if (TARGET_ABI_UNICOSMK)
+ {
+ sp_adj1 = gen_rtx_REG (DImode, 23);
+ FRP (emit_move_insn (sp_adj1, hard_frame_pointer_rtx));
+ sp_adj2 = const0_rtx;
+ }
else if (frame_size < 0x40007fffL)
{
int low = ((frame_size & 0xffff) ^ 0x8000) - 0x8000;
@@ -5944,7 +6466,15 @@ alpha_expand_epilogue ()
/* From now on, things must be in order. So emit blockages. */
/* Restore the frame pointer. */
- if (fp_is_frame_pointer)
+ if (TARGET_ABI_UNICOSMK)
+ {
+ emit_insn (gen_blockage ());
+ mem = gen_rtx_MEM (DImode,
+ plus_constant (hard_frame_pointer_rtx, -16));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (hard_frame_pointer_rtx, mem));
+ }
+ else if (fp_is_frame_pointer)
{
emit_insn (gen_blockage ());
mem = gen_rtx_MEM (DImode, plus_constant (sa_reg, fp_offset));
@@ -5960,17 +6490,29 @@ alpha_expand_epilogue ()
/* Restore the stack pointer. */
emit_insn (gen_blockage ());
- FRP (emit_move_insn (stack_pointer_rtx,
- gen_rtx_PLUS (DImode, sp_adj1, sp_adj2)));
+ if (sp_adj2 == const0_rtx)
+ FRP (emit_move_insn (stack_pointer_rtx, sp_adj1));
+ else
+ FRP (emit_move_insn (stack_pointer_rtx,
+ gen_rtx_PLUS (DImode, sp_adj1, sp_adj2)));
}
else
{
- if (TARGET_ABI_OPEN_VMS && !vms_is_stack_procedure)
+ if (TARGET_ABI_OPEN_VMS && !alpha_is_stack_procedure)
{
emit_insn (gen_blockage ());
FRP (emit_move_insn (hard_frame_pointer_rtx,
gen_rtx_REG (DImode, vms_save_fp_regno)));
}
+ else if (TARGET_ABI_UNICOSMK && !alpha_is_stack_procedure)
+ {
+ /* Decrement the frame pointer if the function does not have a
+ frame. */
+
+ emit_insn (gen_blockage ());
+ FRP (emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
+ hard_frame_pointer_rtx, GEN_INT (-1))));
+ }
}
}
@@ -5983,7 +6525,7 @@ alpha_end_function (file, fnname, decl)
tree decl ATTRIBUTE_UNUSED;
{
/* End the function. */
- if (!flag_inhibit_size_directive)
+ if (!TARGET_ABI_UNICOSMK && !flag_inhibit_size_directive)
{
fputs ("\t.end ", file);
assemble_name (file, fnname);
@@ -6000,6 +6542,13 @@ alpha_end_function (file, fnname, decl)
if (!DECL_WEAK (current_function_decl)
&& (!flag_pic || !TREE_PUBLIC (current_function_decl)))
SYMBOL_REF_FLAG (XEXP (DECL_RTL (current_function_decl), 0)) = 1;
+
+ /* Output jump tables and the static subroutine information block. */
+ if (TARGET_ABI_UNICOSMK)
+ {
+ unicosmk_output_ssib (file, fnname);
+ unicosmk_output_deferred_case_vectors (file);
+ }
}
/* Debugging support. */
@@ -7032,7 +7581,7 @@ check_float_value (mode, d, overflow)
return 0;
}
-
+
#if TARGET_ABI_OPEN_VMS
/* Return the VMS argument type corresponding to MODE. */
@@ -7296,3 +7845,801 @@ alpha_need_linkage (name, is_local)
}
#endif /* TARGET_ABI_OPEN_VMS */
+
+#if TARGET_ABI_UNICOSMK
+
+static void unicosmk_output_module_name PARAMS ((FILE *));
+static void unicosmk_output_default_externs PARAMS ((FILE *));
+static void unicosmk_output_dex PARAMS ((FILE *));
+static void unicosmk_output_externs PARAMS ((FILE *));
+static void unicosmk_output_addr_vec PARAMS ((FILE *, rtx));
+static const char *unicosmk_ssib_name PARAMS ((void));
+
+
+/* Define the offset between two registers, one to be eliminated, and the
+ other its replacement, at the start of a routine. */
+
+int
+unicosmk_initial_elimination_offset (from, to)
+ int from;
+ int to;
+{
+ int fixed_size;
+
+ fixed_size = alpha_sa_size();
+ if (fixed_size != 0)
+ fixed_size += 48;
+
+ if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+ return -fixed_size;
+ else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+ return 0;
+ else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
+ return (ALPHA_ROUND (current_function_outgoing_args_size)
+ + ALPHA_ROUND (get_frame_size()));
+ else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
+ return (ALPHA_ROUND (fixed_size)
+ + ALPHA_ROUND (get_frame_size()
+ + current_function_outgoing_args_size));
+ else
+ abort ();
+}
+
+/* Output the module name for .ident and .end directives. We have to strip
+ directories and add make sure that the module name starts with a letter
+ or '$'. */
+
+static void
+unicosmk_output_module_name (file)
+ FILE *file;
+{
+ const char *name;
+
+ /* Strip directories. */
+
+ name = strrchr (main_input_filename, '/');
+ if (name)
+ ++name;
+ else
+ name = main_input_filename;
+
+ /* CAM only accepts module names that start with a letter or '$'. We
+ prefix the module name with a '$' if necessary. */
+
+ if (!ISALPHA (*name))
+ fprintf (file, "$%s", name);
+ else
+ fputs (name, file);
+}
+
+/* Output text that to appear at the beginning of an assembler file. */
+
+void
+unicosmk_asm_file_start (file)
+ FILE *file;
+{
+ int i;
+
+ fputs ("\t.ident\t", file);
+ unicosmk_output_module_name (file);
+ fputs ("\n\n", file);
+
+ /* The Unicos/Mk assembler uses different register names. Instead of trying
+ to support them, we simply use micro definitions. */
+
+ /* CAM has different register names: rN for the integer register N and fN
+ for the floating-point register N. Instead of trying to use these in
+ alpha.md, we define the symbols $N and $fN to refer to the appropriate
+ register. */
+
+ for (i = 0; i < 32; ++i)
+ fprintf (file, "$%d <- r%d\n", i, i);
+
+ for (i = 0; i < 32; ++i)
+ fprintf (file, "$f%d <- f%d\n", i, i);
+
+ putc ('\n', file);
+
+ /* The .align directive fill unused space with zeroes which does not work
+ in code sections. We define the macro 'gcc@code@align' which uses nops
+ instead. Note that it assumes that code sections always have the
+ biggest possible alignment since . refers to the current offset from
+ the beginning of the section. */
+
+ fputs ("\t.macro gcc@code@align n\n", file);
+ fputs ("gcc@n@bytes = 1 << n\n", file);
+ fputs ("gcc@here = . % gcc@n@bytes\n", file);
+ fputs ("\t.if ne, gcc@here, 0\n", file);
+ fputs ("\t.repeat (gcc@n@bytes - gcc@here) / 4\n", file);
+ fputs ("\tbis r31,r31,r31\n", file);
+ fputs ("\t.endr\n", file);
+ fputs ("\t.endif\n", file);
+ fputs ("\t.endm gcc@code@align\n\n", file);
+
+ /* Output extern declarations which should always be visible. */
+ unicosmk_output_default_externs (file);
+
+ /* Open a dummy section. We always need to be inside a section for the
+ section-switching code to work correctly.
+ ??? This should be a module id or something like that. I still have to
+ figure out what the rules for those are. */
+ fputs ("\n\t.psect\t$SG00000,data\n", file);
+}
+
+/* Output text to appear at the end of an assembler file. This includes all
+ pending extern declarations and DEX expressions. */
+
+void
+unicosmk_asm_file_end (file)
+ FILE *file;
+{
+ fputs ("\t.endp\n\n", file);
+
+ /* Output all pending externs. */
+
+ unicosmk_output_externs (file);
+
+ /* Output dex definitions used for functions whose names conflict with
+ register names. */
+
+ unicosmk_output_dex (file);
+
+ fputs ("\t.end\t", file);
+ unicosmk_output_module_name (file);
+ putc ('\n', file);
+}
+
+/* Output the definition of a common variable. */
+
+void
+unicosmk_output_common (file, name, size, align)
+ FILE *file;
+ const char *name;
+ int size;
+ int align;
+{
+ tree name_tree;
+ printf ("T3E__: common %s\n", name);
+
+ common_section ();
+ fputs("\t.endp\n\n\t.psect ", file);
+ assemble_name(file, name);
+ fprintf(file, ",%d,common\n", floor_log2 (align / BITS_PER_UNIT));
+ fprintf(file, "\t.byte\t0:%d\n", size);
+
+ /* Mark the symbol as defined in this module. */
+ name_tree = get_identifier (name);
+ TREE_ASM_WRITTEN (name_tree) = 1;
+}
+
+#define SECTION_PUBLIC SECTION_MACH_DEP
+#define SECTION_MAIN (SECTION_PUBLIC << 1)
+static int current_section_align;
+
+static unsigned int
+unicosmk_section_type_flags (decl, name, reloc)
+ tree decl;
+ const char *name;
+ int reloc ATTRIBUTE_UNUSED;
+{
+ unsigned int flags = default_section_type_flags (decl, name, reloc);
+
+ if (!decl)
+ return flags;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ current_section_align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+ if (align_functions_log > current_section_align)
+ current_section_align = align_functions_log;
+
+ if (! strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), "main"))
+ flags |= SECTION_MAIN;
+ }
+ else
+ current_section_align = floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT);
+
+ if (TREE_PUBLIC (decl))
+ flags |= SECTION_PUBLIC;
+
+ return flags;
+}
+
+/* Generate a section name for decl and associate it with the
+ declaration. */
+
+void
+unicosmk_unique_section (decl, reloc)
+ tree decl;
+ int reloc ATTRIBUTE_UNUSED;
+{
+ const char *name;
+ int len;
+
+ if (!decl)
+ abort ();
+
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ STRIP_NAME_ENCODING (name, name);
+ len = strlen (name);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ char *string;
+
+ /* It is essential that we prefix the section name here because
+ otherwise the section names generated for constructors and
+ destructors confuse collect2. */
+
+ string = alloca (len + 6);
+ sprintf (string, "code@%s", name);
+ DECL_SECTION_NAME (decl) = build_string (len + 5, string);
+ }
+ else if (TREE_PUBLIC (decl))
+ DECL_SECTION_NAME (decl) = build_string (len, name);
+ else
+ {
+ char *string;
+
+ string = alloca (len + 6);
+ sprintf (string, "data@%s", name);
+ DECL_SECTION_NAME (decl) = build_string (len + 5, string);
+ }
+}
+
+/* Switch to an arbitrary section NAME with attributes as specified
+ by FLAGS. ALIGN specifies any known alignment requirements for
+ the section; 0 if the default should be used. */
+
+static void
+unicosmk_asm_named_section (name, flags)
+ const char *name;
+ unsigned int flags;
+{
+ const char *kind;
+
+ /* Close the previous section. */
+
+ fputs ("\t.endp\n\n", asm_out_file);
+
+ /* Find out what kind of section we are opening. */
+
+ if (flags & SECTION_MAIN)
+ fputs ("\t.start\tmain\n", asm_out_file);
+
+ if (flags & SECTION_CODE)
+ kind = "code";
+ else if (flags & SECTION_PUBLIC)
+ kind = "common";
+ else
+ kind = "data";
+
+ if (current_section_align != 0)
+ fprintf (asm_out_file, "\t.psect\t%s,%d,%s\n", name,
+ current_section_align, kind);
+ else
+ fprintf (asm_out_file, "\t.psect\t%s,%s\n", name, kind);
+}
+
+static void
+unicosmk_insert_attributes (decl, attr_ptr)
+ tree decl;
+ tree *attr_ptr ATTRIBUTE_UNUSED;
+{
+ if (DECL_P (decl)
+ && (TREE_PUBLIC (decl) || TREE_CODE (decl) == FUNCTION_DECL))
+ UNIQUE_SECTION (decl, 0);
+}
+
+/* Output an alignment directive. We have to use the macro 'gcc@code@align'
+ in code sections because .align fill unused space with zeroes. */
+
+void
+unicosmk_output_align (file, align)
+ FILE *file;
+ int align;
+{
+ if (inside_function)
+ fprintf (file, "\tgcc@code@align\t%d\n", align);
+ else
+ fprintf (file, "\t.align\t%d\n", align);
+}
+
+/* Add a case vector to the current function's list of deferred case
+ vectors. Case vectors have to be put into a separate section because CAM
+ does not allow data definitions in code sections. */
+
+void
+unicosmk_defer_case_vector (lab, vec)
+ rtx lab;
+ rtx vec;
+{
+ struct machine_function *machine = cfun->machine;
+
+ vec = gen_rtx_EXPR_LIST (VOIDmode, lab, vec);
+ machine->addr_list = gen_rtx_EXPR_LIST (VOIDmode, vec,
+ machine->addr_list);
+}
+
+/* Output a case vector. */
+
+static void
+unicosmk_output_addr_vec (file, vec)
+ FILE *file;
+ rtx vec;
+{
+ rtx lab = XEXP (vec, 0);
+ rtx body = XEXP (vec, 1);
+ int vlen = XVECLEN (body, 0);
+ int idx;
+
+ ASM_OUTPUT_INTERNAL_LABEL (file, "L", CODE_LABEL_NUMBER (lab));
+
+ for (idx = 0; idx < vlen; idx++)
+ {
+ ASM_OUTPUT_ADDR_VEC_ELT
+ (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
+ }
+}
+
+/* Output current function's deferred case vectors. */
+
+static void
+unicosmk_output_deferred_case_vectors (file)
+ FILE *file;
+{
+ struct machine_function *machine = cfun->machine;
+ rtx t;
+
+ if (machine->addr_list == NULL_RTX)
+ return;
+
+ data_section ();
+ for (t = machine->addr_list; t; t = XEXP (t, 1))
+ unicosmk_output_addr_vec (file, XEXP (t, 0));
+}
+
+/* Set up the dynamic subprogram information block (DSIB) and update the
+ frame pointer register ($15) for subroutines which have a frame. If the
+ subroutine doesn't have a frame, simply increment $15. */
+
+static void
+unicosmk_gen_dsib (imaskP)
+ unsigned long * imaskP;
+{
+ if (alpha_is_stack_procedure)
+ {
+ const char *ssib_name;
+ rtx mem;
+
+ /* Allocate 64 bytes for the DSIB. */
+
+ FRP (emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx,
+ GEN_INT (-64))));
+ emit_insn (gen_blockage ());
+
+ /* Save the return address. */
+
+ mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 56));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (mem, gen_rtx_REG (DImode, REG_RA)));
+ (*imaskP) &= ~(1L << REG_RA);
+
+ /* Save the old frame pointer. */
+
+ mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 48));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (mem, hard_frame_pointer_rtx));
+ (*imaskP) &= ~(1L << HARD_FRAME_POINTER_REGNUM);
+
+ emit_insn (gen_blockage ());
+
+ /* Store the SSIB pointer. */
+
+ ssib_name = ggc_strdup (unicosmk_ssib_name ());
+ mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 32));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+
+ FRP (emit_move_insn (gen_rtx_REG (DImode, 5),
+ gen_rtx_SYMBOL_REF (Pmode, ssib_name)));
+ FRP (emit_move_insn (mem, gen_rtx_REG (DImode, 5)));
+
+ /* Save the CIW index. */
+
+ mem = gen_rtx_MEM (DImode, plus_constant (stack_pointer_rtx, 24));
+ set_mem_alias_set (mem, alpha_sr_alias_set);
+ FRP (emit_move_insn (mem, gen_rtx_REG (DImode, 25)));
+
+ emit_insn (gen_blockage ());
+
+ /* Set the new frame pointer. */
+
+ FRP (emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
+ stack_pointer_rtx, GEN_INT (64))));
+
+ }
+ else
+ {
+ /* Increment the frame pointer register to indicate that we do not
+ have a frame. */
+
+ FRP (emit_insn (gen_adddi3 (hard_frame_pointer_rtx,
+ hard_frame_pointer_rtx, GEN_INT (1))));
+ }
+}
+
+#define SSIB_PREFIX "__SSIB_"
+#define SSIB_PREFIX_LEN 7
+
+/* Generate the name of the SSIB section for the current function. */
+
+static const char *
+unicosmk_ssib_name ()
+{
+ /* This is ok since CAM won't be able to deal with names longer than that
+ anyway. */
+
+ static char name[256];
+
+ rtx x;
+ const char *fnname;
+ char *ssib_name;
+ int len;
+
+ x = DECL_RTL (cfun->decl);
+ if (GET_CODE (x) != MEM)
+ abort ();
+ x = XEXP (x, 0);
+ if (GET_CODE (x) != SYMBOL_REF)
+ abort ();
+ fnname = XSTR (x, 0);
+ STRIP_NAME_ENCODING (fnname, fnname);
+
+ len = strlen (fnname);
+ if (len + SSIB_PREFIX_LEN > 255)
+ len = 255 - SSIB_PREFIX_LEN;
+
+ strcpy (name, SSIB_PREFIX);
+ strncpy (name + SSIB_PREFIX_LEN, fnname, len);
+ name[len + SSIB_PREFIX_LEN] = 0;
+
+ return name;
+}
+
+/* Output the static subroutine information block for the current
+ function. */
+
+static void
+unicosmk_output_ssib (file, fnname)
+ FILE *file;
+ const char *fnname;
+{
+ int len;
+ int i;
+ rtx x;
+ rtx ciw;
+ struct machine_function *machine = cfun->machine;
+
+ ssib_section ();
+ fprintf (file, "\t.endp\n\n\t.psect\t%s%s,data\n", user_label_prefix,
+ unicosmk_ssib_name ());
+
+ /* Some required stuff and the function name length. */
+
+ len = strlen (fnname);
+ fprintf (file, "\t.quad\t^X20008%2.2X28\n", len);
+
+ /* Saved registers
+ ??? We don't do that yet. */
+
+ fputs ("\t.quad\t0\n", file);
+
+ /* Function address. */
+
+ fputs ("\t.quad\t", file);
+ assemble_name (file, fnname);
+ putc ('\n', file);
+
+ fputs ("\t.quad\t0\n", file);
+ fputs ("\t.quad\t0\n", file);
+
+ /* Function name.
+ ??? We do it the same way Cray CC does it but this could be
+ simplified. */
+
+ for( i = 0; i < len; i++ )
+ fprintf (file, "\t.byte\t%d\n", (int)(fnname[i]));
+ if( (len % 8) == 0 )
+ fputs ("\t.quad\t0\n", file);
+ else
+ fprintf (file, "\t.bits\t%d : 0\n", (8 - (len % 8))*8);
+
+ /* All call information words used in the function. */
+
+ for (x = machine->first_ciw; x; x = XEXP (x, 1))
+ {
+ ciw = XEXP (x, 0);
+ fprintf (file, "\t.quad\t");
+#if HOST_BITS_PER_WIDE_INT == 32
+ fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+ CONST_DOUBLE_HIGH (ciw), CONST_DOUBLE_LOW (ciw));
+#else
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (ciw));
+#endif
+ fprintf (file, "\n");
+ }
+}
+
+/* Add a call information word (CIW) to the list of the current function's
+ CIWs and return its index.
+
+ X is a CONST_INT or CONST_DOUBLE representing the CIW. */
+
+rtx
+unicosmk_add_call_info_word (x)
+ rtx x;
+{
+ rtx node;
+ struct machine_function *machine = cfun->machine;
+
+ node = gen_rtx_EXPR_LIST (VOIDmode, x, NULL_RTX);
+ if (machine->first_ciw == NULL_RTX)
+ machine->first_ciw = node;
+ else
+ XEXP (machine->last_ciw, 1) = node;
+
+ machine->last_ciw = node;
+ ++machine->ciw_count;
+
+ return GEN_INT (machine->ciw_count
+ + strlen (current_function_name)/8 + 5);
+}
+
+static char unicosmk_section_buf[100];
+
+char *
+unicosmk_text_section ()
+{
+ 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 ()
+{
+ 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
+ extern declarations for those which are referenced but not defined at
+ the end of file. */
+
+/* List of identifiers for which an extern declaration might have to be
+ emitted. */
+
+struct unicosmk_extern_list
+{
+ struct unicosmk_extern_list *next;
+ const char *name;
+};
+
+static struct unicosmk_extern_list *unicosmk_extern_head = 0;
+
+/* Output extern declarations which are required for every asm file. */
+
+static void
+unicosmk_output_default_externs (file)
+ FILE *file;
+{
+ static const char *externs[] =
+ { "__T3E_MISMATCH" };
+
+ int i;
+ int n;
+
+ n = ARRAY_SIZE (externs);
+
+ for (i = 0; i < n; i++)
+ fprintf (file, "\t.extern\t%s\n", externs[i]);
+}
+
+/* Output extern declarations for global symbols which are have been
+ referenced but not defined. */
+
+static void
+unicosmk_output_externs (file)
+ FILE *file;
+{
+ struct unicosmk_extern_list *p;
+ const char *real_name;
+ int len;
+ tree name_tree;
+
+ len = strlen (user_label_prefix);
+ for (p = unicosmk_extern_head; p != 0; p = p->next)
+ {
+ /* We have to strip the encoding and possibly remove user_label_prefix
+ from the identifier in order to handle -fleading-underscore and
+ explicit asm names correctly (cf. gcc.dg/asm-names-1.c). */
+ STRIP_NAME_ENCODING (real_name, p->name);
+ if (len && p->name[0] == '*'
+ && !memcmp (real_name, user_label_prefix, len))
+ real_name += len;
+
+ name_tree = get_identifier (real_name);
+ if (! TREE_ASM_WRITTEN (name_tree))
+ {
+ TREE_ASM_WRITTEN (name_tree) = 1;
+ fputs ("\t.extern\t", file);
+ assemble_name (file, p->name);
+ putc ('\n', file);
+ }
+ }
+}
+
+/* Record an extern. */
+
+void
+unicosmk_add_extern (name)
+ const char *name;
+{
+ struct unicosmk_extern_list *p;
+
+ p = (struct unicosmk_extern_list *)
+ permalloc (sizeof (struct unicosmk_extern_list));
+ p->next = unicosmk_extern_head;
+ p->name = name;
+ unicosmk_extern_head = p;
+}
+
+/* The Cray assembler generates incorrect code if identifiers which
+ conflict with register names are used as instruction operands. We have
+ to replace such identifiers with DEX expressions. */
+
+/* Structure to collect identifiers which have been replaced by DEX
+ expressions. */
+
+struct unicosmk_dex {
+ struct unicosmk_dex *next;
+ const char *name;
+};
+
+/* List of identifiers which have been replaced by DEX expressions. The DEX
+ number is determined by the position in the list. */
+
+static struct unicosmk_dex *unicosmk_dex_list = NULL;
+
+/* The number of elements in the DEX list. */
+
+static int unicosmk_dex_count = 0;
+
+/* Check if NAME must be replaced by a DEX expression. */
+
+static int
+unicosmk_special_name (name)
+ const char *name;
+{
+ if (name[0] == '*')
+ ++name;
+
+ if (name[0] == '$')
+ ++name;
+
+ if (name[0] != 'r' && name[0] != 'f' && name[0] != 'R' && name[0] != 'F')
+ return 0;
+
+ switch (name[1])
+ {
+ case '1': case '2':
+ return (name[2] == '\0' || (ISDIGIT (name[2]) && name[3] == '\0'));
+
+ case '3':
+ return (name[2] == '\0'
+ || ((name[2] == '0' || name[2] == '1') && name[3] == '\0'));
+
+ default:
+ return (ISDIGIT (name[1]) && name[2] == '\0');
+ }
+}
+
+/* Return the DEX number if X must be replaced by a DEX expression and 0
+ otherwise. */
+
+static int
+unicosmk_need_dex (x)
+ rtx x;
+{
+ struct unicosmk_dex *dex;
+ const char *name;
+ int i;
+
+ if (GET_CODE (x) != SYMBOL_REF)
+ return 0;
+
+ name = XSTR (x,0);
+ if (! unicosmk_special_name (name))
+ return 0;
+
+ i = unicosmk_dex_count;
+ for (dex = unicosmk_dex_list; dex; dex = dex->next)
+ {
+ if (! strcmp (name, dex->name))
+ return i;
+ --i;
+ }
+
+ dex = (struct unicosmk_dex *) permalloc (sizeof (struct unicosmk_dex));
+ dex->name = name;
+ dex->next = unicosmk_dex_list;
+ unicosmk_dex_list = dex;
+
+ ++unicosmk_dex_count;
+ return unicosmk_dex_count;
+}
+
+/* Output the DEX definitions for this file. */
+
+static void
+unicosmk_output_dex (file)
+ FILE *file;
+{
+ struct unicosmk_dex *dex;
+ int i;
+
+ if (unicosmk_dex_list == NULL)
+ return;
+
+ fprintf (file, "\t.dexstart\n");
+
+ i = unicosmk_dex_count;
+ for (dex = unicosmk_dex_list; dex; dex = dex->next)
+ {
+ fprintf (file, "\tDEX (%d) = ", i);
+ assemble_name (file, dex->name);
+ putc ('\n', file);
+ --i;
+ }
+
+ fprintf (file, "\t.dexend\n");
+}
+
+#else
+
+static void
+unicosmk_output_deferred_case_vectors (file)
+ FILE *file ATTRIBUTE_UNUSED;
+{}
+
+static void
+unicosmk_gen_dsib (imaskP)
+ unsigned long * imaskP ATTRIBUTE_UNUSED;
+{}
+
+static void
+unicosmk_output_ssib (file, fnname)
+ FILE * file ATTRIBUTE_UNUSED;
+ const char * fnname ATTRIBUTE_UNUSED;
+{}
+
+rtx
+unicosmk_add_call_info_word (x)
+ rtx x ATTRIBUTE_UNUSED;
+{
+ return NULL_RTX;
+}
+
+static int
+unicosmk_need_dex (x)
+ rtx x ATTRIBUTE_UNUSED;
+{
+ return 0;
+}
+
+#endif /* TARGET_ABI_UNICOSMK */
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index 220eb62..3b030b2 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -179,11 +179,17 @@ extern enum alpha_fp_trap_mode alpha_fptm;
/* These are for target os support and cannot be changed at runtime. */
#define TARGET_ABI_WINDOWS_NT 0
#define TARGET_ABI_OPEN_VMS 0
-#define TARGET_ABI_OSF (!TARGET_ABI_WINDOWS_NT && !TARGET_ABI_OPEN_VMS)
+#define TARGET_ABI_UNICOSMK 0
+#define TARGET_ABI_OSF (!TARGET_ABI_WINDOWS_NT \
+ && !TARGET_ABI_OPEN_VMS \
+ && !TARGET_ABI_UNICOSMK)
#ifndef TARGET_AS_CAN_SUBTRACT_LABELS
#define TARGET_AS_CAN_SUBTRACT_LABELS TARGET_GAS
#endif
+#ifndef TARGET_AS_SLASH_BEFORE_SUFFIX
+#define TARGET_AS_SLASH_BEFORE_SUFFIX TARGET_GAS
+#endif
#ifndef TARGET_CAN_FAULT_IN_PROLOGUE
#define TARGET_CAN_FAULT_IN_PROLOGUE 0
#endif
@@ -792,7 +798,9 @@ enum reg_class { NO_REGS, PV_REG, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
`R' is a SYMBOL_REF that has SYMBOL_REF_FLAG set or is the current
function.
- 'S' is a 6-bit constant (valid for a shift insn). */
+ 'S' is a 6-bit constant (valid for a shift insn).
+
+ 'U' is a symbolic operand. */
#define EXTRA_CONSTRAINT(OP, C) \
((C) == 'Q' ? normal_memory_operand (OP, VOIDmode) \
@@ -800,6 +808,8 @@ enum reg_class { NO_REGS, PV_REG, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
: (C) == 'S' ? (GET_CODE (OP) == CONST_INT \
&& (unsigned HOST_WIDE_INT) INTVAL (OP) < 64) \
: (C) == 'T' ? GET_CODE (OP) == HIGH \
+ : (TARGET_ABI_UNICOSMK && (C) == 'U') \
+ ? symbolic_operand (OP, VOIDmode) \
: 0)
/* Given an rtx X being reloaded into a reg required to be
@@ -2174,7 +2184,8 @@ do { \
{"hard_int_register_operand", {SUBREG, REG}}, \
{"reg_not_elim_operand", {SUBREG, REG}}, \
{"reg_no_subreg_operand", {REG}}, \
- {"addition_operation", {PLUS}},
+ {"addition_operation", {PLUS}}, \
+ {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}},
/* Define the `__builtin_va_list' type for the ABI. */
#define BUILD_VA_LIST_TYPE(VALIST) \
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 3cce979..34280f7 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -31,6 +31,10 @@
(UNSPEC_MSKXH 3)
(UNSPEC_CVTQL 4)
(UNSPEC_NT_LDA 5)
+ (UNSPEC_UMK_LAUM 6)
+ (UNSPEC_UMK_LALM 7)
+ (UNSPEC_UMK_LAL 8)
+ (UNSPEC_UMK_LOAD_CIW 9)
])
;; UNSPEC_VOLATILE:
@@ -49,6 +53,12 @@
(UNSPECV_LDGP2 10)
(UNSPECV_FORCE_MOV 11)
])
+
+;; Where necessary, the suffixes _le and _be are used to distinguish between
+;; little-endian and big-endian patterns.
+;;
+;; Note that the Unicos/Mk assembler does not support the following
+;; opcodes: mov, fmov, nop, fnop, unop.
;; Processor type -- this attribute must exactly match the processor_type
;; enumeration in alpha.h.
@@ -904,11 +914,13 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
""
"subqv %r1,%2,%0")
+;; The Unicos/Mk assembler doesn't support mull.
+
(define_insn "mulsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
(match_operand:SI 2 "reg_or_8bit_operand" "rI")))]
- ""
+ "!TARGET_ABI_UNICOSMK"
"mull %r1,%2,%0"
[(set_attr "type" "imul")
(set_attr "opsize" "si")])
@@ -918,7 +930,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(sign_extend:DI
(mult:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
(match_operand:SI 2 "reg_or_8bit_operand" "rI"))))]
- ""
+ "!TARGET_ABI_UNICOSMK"
"mull %r1,%2,%0"
[(set_attr "type" "imul")
(set_attr "opsize" "si")])
@@ -932,7 +944,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(sign_extend:DI (mult:SI (match_dup 1)
(match_dup 2))))
(const_int 0))]
- ""
+ "!TARGET_ABI_UNICOSMK"
"mullv %r1,%2,%0"
[(set_attr "type" "imul")
(set_attr "opsize" "si")])
@@ -984,14 +996,17 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set_attr "type" "imul")
(set_attr "opsize" "udi")])
-;; The divide and remainder operations always take their inputs from
-;; r24 and r25, put their output in r27, and clobber r23 and r28.
-
-;; ??? Force sign-extension here because some versions of OSF/1 don't
-;; do the right thing if the inputs are not properly sign-extended.
-;; But Linux, for instance, does not have this problem. Is it worth
-;; the complication here to eliminate the sign extension?
-;; Interix/NT has the same sign-extension problem.
+;; The divide and remainder operations take their inputs from r24 and
+;; r25, put their output in r27, and clobber r23 and r28 on all
+;; systems except Unicos/Mk. On Unicos, the standard library provides
+;; subroutines which use the standard calling convention and work on
+;; DImode operands.
+
+;; ??? Force sign-extension here because some versions of OSF/1 and
+;; Interix/NT don't do the right thing if the inputs are not properly
+;; sign-extended. But Linux, for instance, does not have this
+;; problem. Is it worth the complication here to eliminate the sign
+;; extension?
(define_expand "divsi3"
[(set (reg:DI 24)
@@ -1004,7 +1019,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(clobber (reg:DI 28))])
(set (match_operand:SI 0 "nonimmediate_operand" "")
(subreg:SI (reg:DI 27) 0))]
- "! TARGET_ABI_OPEN_VMS"
+ "! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK"
"")
(define_expand "udivsi3"
@@ -1018,7 +1033,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(clobber (reg:DI 28))])
(set (match_operand:SI 0 "nonimmediate_operand" "")
(subreg:SI (reg:DI 27) 0))]
- "! TARGET_ABI_OPEN_VMS"
+ "! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK"
"")
(define_expand "modsi3"
@@ -1032,7 +1047,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(clobber (reg:DI 28))])
(set (match_operand:SI 0 "nonimmediate_operand" "")
(subreg:SI (reg:DI 27) 0))]
- "! TARGET_ABI_OPEN_VMS"
+ "! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK"
"")
(define_expand "umodsi3"
@@ -1046,7 +1061,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(clobber (reg:DI 28))])
(set (match_operand:SI 0 "nonimmediate_operand" "")
(subreg:SI (reg:DI 27) 0))]
- "! TARGET_ABI_OPEN_VMS"
+ "! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK"
"")
(define_expand "divdi3"
@@ -1059,7 +1074,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(clobber (reg:DI 28))])
(set (match_operand:DI 0 "nonimmediate_operand" "")
(reg:DI 27))]
- "! TARGET_ABI_OPEN_VMS"
+ "! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK"
"")
(define_expand "udivdi3"
@@ -1072,10 +1087,23 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(clobber (reg:DI 28))])
(set (match_operand:DI 0 "nonimmediate_operand" "")
(reg:DI 27))]
- "! TARGET_ABI_OPEN_VMS"
+ "! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK"
"")
(define_expand "moddi3"
+ [(use (match_operand:DI 0 "nonimmediate_operand" ""))
+ (use (match_operand:DI 1 "input_operand" ""))
+ (use (match_operand:DI 2 "input_operand" ""))]
+ "!TARGET_ABI_OPEN_VMS"
+{
+ if (TARGET_ABI_UNICOSMK)
+ emit_insn (gen_moddi3_umk (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_moddi3_dft (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "moddi3_dft"
[(set (reg:DI 24) (match_operand:DI 1 "input_operand" ""))
(set (reg:DI 25) (match_operand:DI 2 "input_operand" ""))
(parallel [(set (reg:DI 27)
@@ -1085,10 +1113,48 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(clobber (reg:DI 28))])
(set (match_operand:DI 0 "nonimmediate_operand" "")
(reg:DI 27))]
- "! TARGET_ABI_OPEN_VMS"
+ "! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK"
"")
+;; On Unicos/Mk, we do as the system's C compiler does:
+;; compute the quotient, multiply and subtract.
+
+(define_expand "moddi3_umk"
+ [(use (match_operand:DI 0 "nonimmediate_operand" ""))
+ (use (match_operand:DI 1 "input_operand" ""))
+ (use (match_operand:DI 2 "input_operand" ""))]
+ "TARGET_ABI_UNICOSMK"
+{
+ rtx mul, div, tmp;
+
+ mul = gen_reg_rtx (DImode);
+ tmp = gen_reg_rtx (DImode);
+ operands[1] = force_reg (DImode, operands[1]);
+ operands[2] = force_reg (DImode, operands[2]);
+
+ div = expand_binop (DImode, sdiv_optab, operands[1], operands[2],
+ NULL_RTX, 0, OPTAB_LIB);
+ div = force_reg (DImode, div);
+ emit_insn (gen_muldi3 (mul, operands[2], div));
+ emit_insn (gen_subdi3 (tmp, operands[1], mul));
+ emit_move_insn (operands[0], tmp);
+ DONE;
+})
+
(define_expand "umoddi3"
+ [(use (match_operand:DI 0 "nonimmediate_operand" ""))
+ (use (match_operand:DI 1 "input_operand" ""))
+ (use (match_operand:DI 2 "input_operand" ""))]
+ "! TARGET_ABI_OPEN_VMS"
+{
+ if (TARGET_ABI_UNICOSMK)
+ emit_insn (gen_umoddi3_umk (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_umoddi3_dft (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_expand "umoddi3_dft"
[(set (reg:DI 24) (match_operand:DI 1 "input_operand" ""))
(set (reg:DI 25) (match_operand:DI 2 "input_operand" ""))
(parallel [(set (reg:DI 27)
@@ -1098,9 +1164,31 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(clobber (reg:DI 28))])
(set (match_operand:DI 0 "nonimmediate_operand" "")
(reg:DI 27))]
- "! TARGET_ABI_OPEN_VMS"
+ "! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK"
"")
+(define_expand "umoddi3_umk"
+ [(use (match_operand:DI 0 "nonimmediate_operand" ""))
+ (use (match_operand:DI 1 "input_operand" ""))
+ (use (match_operand:DI 2 "input_operand" ""))]
+ "TARGET_ABI_UNICOSMK"
+{
+ rtx mul, div, tmp;
+
+ mul = gen_reg_rtx (DImode);
+ tmp = gen_reg_rtx (DImode);
+ operands[1] = force_reg (DImode, operands[1]);
+ operands[2] = force_reg (DImode, operands[2]);
+
+ div = expand_binop (DImode, udiv_optab, operands[1], operands[2],
+ NULL_RTX, 1, OPTAB_LIB);
+ div = force_reg (DImode, div);
+ emit_insn (gen_muldi3 (mul, operands[2], div));
+ emit_insn (gen_subdi3 (tmp, operands[1], mul));
+ emit_move_insn (operands[0], tmp);
+ DONE;
+})
+
;; Lengths of 8 for ldq $t12,__divq($gp); jsr $t9,($t12),__divq as
;; expanded by the assembler.
@@ -1121,7 +1209,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(reg:DI 24) (reg:DI 25)])))
(clobber (reg:DI 23))
(clobber (reg:DI 28))]
- "! TARGET_ABI_OPEN_VMS"
+ "! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK"
"%E0 $24,$25,$27"
[(set_attr "type" "jsr")
(set_attr "length" "8")])
@@ -1143,7 +1231,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(reg:DI 24) (reg:DI 25)]))
(clobber (reg:DI 23))
(clobber (reg:DI 28))]
- "! TARGET_ABI_OPEN_VMS"
+ "! TARGET_ABI_OPEN_VMS && ! TARGET_ABI_UNICOSMK"
"%E0 $24,$25,$27"
[(set_attr "type" "jsr")
(set_attr "length" "8")])
@@ -1655,6 +1743,18 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
;;
;; Operand 1 is the address + 1 (+2 for HI), operand 0 is the result.
(define_expand "unaligned_extendqidi"
+ [(use (match_operand:QI 0 "register_operand" ""))
+ (use (match_operand:DI 1 "address_operand" ""))]
+ ""
+{
+ if (WORDS_BIG_ENDIAN)
+ emit_insn (gen_unaligned_extendqidi_be (operands[0], operands[1]));
+ else
+ emit_insn (gen_unaligned_extendqidi_le (operands[0], operands[1]));
+ DONE;
+})
+
+(define_expand "unaligned_extendqidi_le"
[(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
(set (match_dup 3)
(mem:DI (and:DI (plus:DI (match_dup 2) (const_int -1))
@@ -1667,14 +1767,51 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(const_int 3)))))
(set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
(ashiftrt:DI (match_dup 4) (const_int 56)))]
- ""
+ "! WORDS_BIG_ENDIAN"
+{
+ operands[2] = gen_reg_rtx (DImode);
+ operands[3] = gen_reg_rtx (DImode);
+ operands[4] = gen_reg_rtx (DImode);
+})
+
+(define_expand "unaligned_extendqidi_be"
+ [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
+ (set (match_dup 3) (plus:DI (match_dup 2) (const_int -1)))
+ (set (match_dup 4)
+ (mem:DI (and:DI (match_dup 3)
+ (const_int -8))))
+ (set (match_dup 5) (plus:DI (match_dup 2) (const_int -2)))
+ (set (match_dup 6)
+ (ashift:DI (match_dup 4)
+ (ashift:DI
+ (and:DI
+ (plus:DI (match_dup 5) (const_int 1))
+ (const_int 7))
+ (const_int 3))))
+ (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
+ (ashiftrt:DI (match_dup 6) (const_int 56)))]
+ "WORDS_BIG_ENDIAN"
{
operands[2] = gen_reg_rtx (DImode);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
+ operands[5] = gen_reg_rtx (DImode);
+ operands[6] = gen_reg_rtx (DImode);
})
(define_expand "unaligned_extendhidi"
+ [(use (match_operand:QI 0 "register_operand" ""))
+ (use (match_operand:DI 1 "address_operand" ""))]
+ ""
+{
+ if (WORDS_BIG_ENDIAN)
+ emit_insn (gen_unaligned_extendhidi_be (operands[0], operands[1]));
+ else
+ emit_insn (gen_unaligned_extendhidi_le (operands[0], operands[1]));
+ DONE;
+})
+
+(define_expand "unaligned_extendhidi_le"
[(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
(set (match_dup 3)
(mem:DI (and:DI (plus:DI (match_dup 2) (const_int -2))
@@ -1687,13 +1824,36 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(const_int 3)))))
(set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
(ashiftrt:DI (match_dup 4) (const_int 48)))]
- ""
+ "! WORDS_BIG_ENDIAN"
{
operands[2] = gen_reg_rtx (DImode);
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
})
+(define_expand "unaligned_extendhidi_be"
+ [(set (match_dup 2) (match_operand:DI 1 "address_operand" ""))
+ (set (match_dup 3) (plus:DI (match_dup 2) (const_int -2)))
+ (set (match_dup 4)
+ (mem:DI (and:DI (match_dup 3)
+ (const_int -8))))
+ (set (match_dup 5) (plus:DI (match_dup 2) (const_int -3)))
+ (set (match_dup 6)
+ (ashift:DI (match_dup 4)
+ (ashift:DI
+ (and:DI (match_dup 5) (const_int 7))
+ (const_int 8))))
+ (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
+ (ashiftrt:DI (match_dup 6) (const_int 48)))]
+ "WORDS_BIG_ENDIAN"
+{
+ operands[2] = gen_reg_rtx (DImode);
+ operands[3] = gen_reg_rtx (DImode);
+ operands[4] = gen_reg_rtx (DImode);
+ operands[5] = gen_reg_rtx (DImode);
+ operands[6] = gen_reg_rtx (DImode);
+})
+
(define_insn "*extxl_const"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
@@ -1703,13 +1863,26 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
"ext%M2l %r1,%s3,%0"
[(set_attr "type" "shift")])
-(define_insn "extxl"
+(define_insn "extxl_le"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
(match_operand:DI 2 "mode_width_operand" "n")
(ashift:DI (match_operand:DI 3 "reg_or_8bit_operand" "rI")
(const_int 3))))]
- ""
+ "! WORDS_BIG_ENDIAN"
+ "ext%M2l %r1,%3,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "extxl_be"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extract:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
+ (match_operand:DI 2 "mode_width_operand" "n")
+ (minus:DI
+ (const_int 56)
+ (ashift:DI
+ (match_operand:DI 3 "reg_or_8bit_operand" "rI")
+ (const_int 3)))))]
+ "WORDS_BIG_ENDIAN"
"ext%M2l %r1,%3,%0"
[(set_attr "type" "shift")])
@@ -1717,26 +1890,50 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
;; in shifts larger than a word size. So capture these patterns that it
;; should have turned into zero_extracts.
-(define_insn "*extxl_1"
+(define_insn "*extxl_1_le"
[(set (match_operand:DI 0 "register_operand" "=r")
(and:DI (lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
(ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
(const_int 3)))
(match_operand:DI 3 "mode_mask_operand" "n")))]
- ""
+ "! WORDS_BIG_ENDIAN"
"ext%U3l %1,%2,%0"
[(set_attr "type" "shift")])
-(define_insn "*extql_2"
+(define_insn "*extxl_1_be"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (lshiftrt:DI
+ (match_operand:DI 1 "reg_or_0_operand" "rJ")
+ (minus:DI (const_int 56)
+ (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+ (const_int 3))))
+ (match_operand:DI 3 "mode_mask_operand" "n")))]
+ "WORDS_BIG_ENDIAN"
+ "ext%U3l %1,%2,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "*extql_2_le"
[(set (match_operand:DI 0 "register_operand" "=r")
(lshiftrt:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
(ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
(const_int 3))))]
- ""
+ "! WORDS_BIG_ENDIAN"
"extql %1,%2,%0"
[(set_attr "type" "shift")])
-(define_insn "extqh"
+(define_insn "*extql_2_be"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (lshiftrt:DI
+ (match_operand:DI 1 "reg_or_0_operand" "rJ")
+ (minus:DI (const_int 56)
+ (ashift:DI
+ (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+ (const_int 3)))))]
+ "WORDS_BIG_ENDIAN"
+ "extql %1,%2,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "extqh_le"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI
(match_operand:DI 1 "reg_or_0_operand" "rJ")
@@ -1746,11 +1943,25 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:DI 2 "reg_or_8bit_operand" "rI")
(const_int 7))
(const_int 3)))))]
- ""
+ "! WORDS_BIG_ENDIAN"
"extqh %r1,%2,%0"
[(set_attr "type" "shift")])
-(define_insn "extlh"
+(define_insn "extqh_be"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ashift:DI
+ (match_operand:DI 1 "reg_or_0_operand" "rJ")
+ (ashift:DI
+ (and:DI
+ (plus:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+ (const_int 1))
+ (const_int 7))
+ (const_int 3))))]
+ "WORDS_BIG_ENDIAN"
+ "extqh %r1,%2,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "extlh_le"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI
(and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
@@ -1761,11 +1972,28 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:DI 2 "reg_or_8bit_operand" "rI")
(const_int 7))
(const_int 3)))))]
- ""
+ "! WORDS_BIG_ENDIAN"
+ "extlh %r1,%2,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "extlh_be"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI
+ (ashift:DI
+ (match_operand:DI 1 "reg_or_0_operand" "rJ")
+ (ashift:DI
+ (and:DI
+ (plus:DI
+ (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+ (const_int 1))
+ (const_int 7))
+ (const_int 3)))
+ (const_int 2147483647)))]
+ "WORDS_BIG_ENDIAN"
"extlh %r1,%2,%0"
[(set_attr "type" "shift")])
-(define_insn "extwh"
+(define_insn "extwh_le"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI
(and:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
@@ -1776,7 +2004,23 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:DI 2 "reg_or_8bit_operand" "rI")
(const_int 7))
(const_int 3)))))]
- ""
+ "! WORDS_BIG_ENDIAN"
+ "extwh %r1,%2,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "extwh_be"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI
+ (ashift:DI (match_operand:DI 1 "reg_or_0_operand" "rJ")
+ (ashift:DI
+ (and:DI
+ (plus:DI
+ (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+ (const_int 1))
+ (const_int 7))
+ (const_int 3)))
+ (const_int 65535)))]
+ "WORDS_BIG_ENDIAN"
"extwh %r1,%2,%0"
[(set_attr "type" "shift")])
@@ -1830,39 +2074,79 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
"insll %1,%s2,%0"
[(set_attr "type" "shift")])
-(define_insn "insbl"
+(define_insn "insbl_le"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
(ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
(const_int 3))))]
- ""
+ "! WORDS_BIG_ENDIAN"
+ "insbl %1,%2,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "insbl_be"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" "r"))
+ (minus:DI (const_int 56)
+ (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+ (const_int 3)))))]
+ "WORDS_BIG_ENDIAN"
"insbl %1,%2,%0"
[(set_attr "type" "shift")])
-(define_insn "inswl"
+(define_insn "inswl_le"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r"))
(ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
(const_int 3))))]
- ""
+ "! WORDS_BIG_ENDIAN"
"inswl %1,%2,%0"
[(set_attr "type" "shift")])
-(define_insn "insll"
+(define_insn "inswl_be"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" "r"))
+ (minus:DI (const_int 56)
+ (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+ (const_int 3)))))]
+ "WORDS_BIG_ENDIAN"
+ "inswl %1,%2,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "insll_le"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
(ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
(const_int 3))))]
- ""
+ "! WORDS_BIG_ENDIAN"
"insll %1,%2,%0"
[(set_attr "type" "shift")])
-(define_insn "insql"
+(define_insn "insll_be"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ashift:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
+ (minus:DI (const_int 56)
+ (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+ (const_int 3)))))]
+ "WORDS_BIG_ENDIAN"
+ "insll %1,%2,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "insql_le"
[(set (match_operand:DI 0 "register_operand" "=r")
(ashift:DI (match_operand:DI 1 "register_operand" "r")
(ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
(const_int 3))))]
- ""
+ "! WORDS_BIG_ENDIAN"
+ "insql %1,%2,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "insql_be"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (ashift:DI (match_operand:DI 1 "register_operand" "r")
+ (minus:DI (const_int 56)
+ (ashift:DI (match_operand:DI 2 "reg_or_8bit_operand" "rI")
+ (const_int 3)))))]
+ "WORDS_BIG_ENDIAN"
"insql %1,%2,%0"
[(set_attr "type" "shift")])
@@ -1913,7 +2197,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
"ins%M2h %1,%3,%0"
[(set_attr "type" "shift")])
-(define_insn "mskxl"
+(define_insn "mskxl_le"
[(set (match_operand:DI 0 "register_operand" "=r")
(and:DI (not:DI (ashift:DI
(match_operand:DI 2 "mode_mask_operand" "n")
@@ -1921,7 +2205,20 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:DI 3 "reg_or_8bit_operand" "rI")
(const_int 3))))
(match_operand:DI 1 "reg_or_0_operand" "rJ")))]
- ""
+ "! WORDS_BIG_ENDIAN"
+ "msk%U2l %r1,%3,%0"
+ [(set_attr "type" "shift")])
+
+(define_insn "mskxl_be"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (and:DI (not:DI (ashift:DI
+ (match_operand:DI 2 "mode_mask_operand" "n")
+ (minus:DI (const_int 56)
+ (ashift:DI
+ (match_operand:DI 3 "reg_or_8bit_operand" "rI")
+ (const_int 3)))))
+ (match_operand:DI 1 "reg_or_0_operand" "rJ")))]
+ "WORDS_BIG_ENDIAN"
"msk%U2l %r1,%3,%0"
[(set_attr "type" "shift")])
@@ -2328,6 +2625,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
operands[1] = force_reg (SFmode, operands[1]);
})
+;; The Unicos/Mk assembler doesn't support cvtst, but we've already
+;; asserted that alpha_fptm == ALPHA_FPTM_N.
+
(define_insn "*extendsfdf2_ieee"
[(set (match_operand:DF 0 "register_operand" "=&f")
(float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
@@ -2341,7 +2641,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,m,f")))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
"@
- fmov %1,%0
+ cpys %1,%1,%0
ld%, %0,%1
st%- %1,%0"
[(set_attr "type" "fcpys,fld,fst")])
@@ -4164,6 +4464,16 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
;; Here are the CALL and unconditional branch insns. Calls on NT and OSF
;; work differently, so we have different patterns for each.
+;; On Unicos/Mk a call information word (CIW) must be generated for each
+;; call. The CIW contains information about arguments passed in registers
+;; and is stored in the caller's SSIB. Its offset relative to the beginning
+;; of the SSIB is passed in $25. Handling this properly is quite complicated
+;; in the presence of inlining since the CIWs for calls performed by the
+;; inlined function must be stored in the SSIB of the function it is inlined
+;; into as well. We encode the CIW in an unspec and append it to the list
+;; of the CIWs for the current function only when the instruction for loading
+;; $25 is generated.
+
(define_expand "call"
[(use (match_operand:DI 0 "" ""))
(use (match_operand 1 "" ""))
@@ -4175,6 +4485,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
emit_call_insn (gen_call_nt (operands[0], operands[1]));
else if (TARGET_ABI_OPEN_VMS)
emit_call_insn (gen_call_vms (operands[0], operands[2]));
+ else if (TARGET_ABI_UNICOSMK)
+ emit_call_insn (gen_call_umk (operands[0], operands[2]));
else
emit_call_insn (gen_call_osf (operands[0], operands[1]));
DONE;
@@ -4225,6 +4537,30 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
operands[0] = force_reg (DImode, operands[0]);
})
+;; Calls on Unicos/Mk are always indirect.
+;; op 0: symbol ref for called function
+;; op 1: CIW for $25 represented by an unspec
+
+(define_expand "call_umk"
+ [(parallel [(call (mem:DI (match_operand 0 "" ""))
+ (match_operand 1 "" ""))
+ (use (reg:DI 25))
+ (clobber (reg:DI 26))])]
+ ""
+{
+ if (GET_CODE (operands[0]) != MEM)
+ abort ();
+
+ /* Always load the address of the called function into a register;
+ load the CIW in $25. */
+
+ operands[0] = XEXP (operands[0], 0);
+ if (GET_CODE (operands[0]) != REG)
+ operands[0] = force_reg (DImode, operands[0]);
+
+ emit_move_insn (gen_rtx_REG (DImode, 25), operands[1]);
+})
+
;;
;; call openvms/alpha
;; op 0: symbol ref for called function
@@ -4279,6 +4615,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
else if (TARGET_ABI_OPEN_VMS)
emit_call_insn (gen_call_value_vms (operands[0], operands[1],
operands[3]));
+ else if (TARGET_ABI_UNICOSMK)
+ emit_call_insn (gen_call_value_umk (operands[0], operands[1],
+ operands[3]));
else
emit_call_insn (gen_call_value_osf (operands[0], operands[1],
operands[2]));
@@ -4369,6 +4708,24 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
}
})
+(define_expand "call_value_umk"
+ [(parallel [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand 1 "" ""))
+ (match_operand 2 "" "")))
+ (use (reg:DI 25))
+ (clobber (reg:DI 26))])]
+ ""
+{
+ if (GET_CODE (operands[1]) != MEM)
+ abort ();
+
+ operands[1] = XEXP (operands[1], 0);
+ if (GET_CODE (operands[1]) != REG)
+ operands[1] = force_reg (DImode, operands[1]);
+
+ emit_move_insn (gen_rtx_REG (DImode, 25), operands[2]);
+})
+
(define_insn "*call_osf_1_er_noreturn"
[(call (mem:DI (match_operand:DI 0 "call_operand" "c,R,i"))
(match_operand 1 "" ""))
@@ -4455,6 +4812,15 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set_attr "type" "jsr")
(set_attr "length" "12,16")])
+(define_insn "*call_umk_1"
+ [(call (mem:DI (match_operand:DI 0 "call_operand" "r"))
+ (match_operand 1 "" ""))
+ (use (reg:DI 25))
+ (clobber (reg:DI 26))]
+ "TARGET_ABI_UNICOSMK"
+ "jsr $26,(%0)"
+ [(set_attr "type" "jsr")])
+
;; Call subroutine returning any type.
(define_expand "untyped_call"
@@ -4517,58 +4883,30 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set_attr "type" "ibr")])
(define_expand "tablejump"
- [(use (match_operand:SI 0 "register_operand" ""))
- (use (match_operand:SI 1 "" ""))]
+ [(parallel [(set (pc)
+ (match_operand 0 "register_operand" ""))
+ (use (label_ref:DI (match_operand 1 "" "")))])]
""
{
if (TARGET_ABI_WINDOWS_NT)
- emit_jump_insn (gen_tablejump_nt (operands[0], operands[1]));
- else if (TARGET_ABI_OPEN_VMS)
- emit_jump_insn (gen_tablejump_vms (operands[0], operands[1]));
- else
- emit_jump_insn (gen_tablejump_osf (operands[0], operands[1]));
-
- DONE;
+ {
+ rtx dest = gen_reg_rtx (DImode);
+ emit_insn (gen_extendsidi2 (dest, operands[0]));
+ operands[0] = dest;
+ }
+ else if (TARGET_ABI_OSF)
+ {
+ rtx dest = gen_reg_rtx (DImode);
+ emit_insn (gen_extendsidi2 (dest, operands[0]));
+ emit_insn (gen_adddi3 (dest, gen_rtx_REG (DImode, 29), dest));
+ operands[0] = dest;
+ }
})
-(define_expand "tablejump_osf"
- [(set (match_dup 3)
- (sign_extend:DI (match_operand:SI 0 "register_operand" "")))
- (set (match_dup 3)
- (plus:DI (reg:DI 29) (match_dup 3)))
- (parallel [(set (pc)
- (match_dup 3))
- (use (label_ref (match_operand 1 "" "")))])]
- ""
- { operands[3] = gen_reg_rtx (DImode); })
-
-(define_expand "tablejump_nt"
- [(set (match_dup 3)
- (sign_extend:DI (match_operand:SI 0 "register_operand" "")))
- (parallel [(set (pc)
- (match_dup 3))
- (use (label_ref (match_operand 1 "" "")))])]
- ""
- { operands[3] = gen_reg_rtx (DImode); })
-
-;;
-;; tablejump, openVMS way
-;; op 0: offset
-;; op 1: label preceding jump-table
-;;
-(define_expand "tablejump_vms"
- [(set (match_dup 2)
- (match_operand:DI 0 "register_operand" ""))
- (set (pc)
- (plus:DI (match_dup 2)
- (label_ref (match_operand 1 "" ""))))]
- ""
- { operands[2] = gen_reg_rtx (DImode); })
-
(define_insn "*tablejump_osf_nt_internal"
[(set (pc)
(match_operand:DI 0 "register_operand" "r"))
- (use (label_ref (match_operand 1 "" "")))]
+ (use (label_ref:DI (match_operand 1 "" "")))]
"(TARGET_ABI_OSF || TARGET_ABI_WINDOWS_NT)
&& alpha_tablejump_addr_vec (insn)"
{
@@ -4577,16 +4915,11 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
}
[(set_attr "type" "ibr")])
-;;
-;; op 0 is table offset
-;; op 1 is table label
-;;
-
-(define_insn "*tablejump_vms_internal"
+(define_insn "*tablejump_internal"
[(set (pc)
- (plus (match_operand:DI 0 "register_operand" "r")
- (label_ref (match_operand 1 "" ""))))]
- "TARGET_ABI_OPEN_VMS"
+ (match_operand:DI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
"jmp $31,(%0),0"
[(set_attr "type" "ibr")])
@@ -4613,9 +4946,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], SFmode)
|| reg_or_fp0_operand (operands[1], SFmode))"
"@
- fmov %R1,%0
+ cpys %R1,%R1,%0
ld%, %0,%1
- mov %r1,%0
+ bis $31,%r1,%0
ldl %0,%1
st%, %R1,%0
stl %r1,%0"
@@ -4628,9 +4961,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], SFmode)
|| reg_or_fp0_operand (operands[1], SFmode))"
"@
- fmov %R1,%0
+ cpys %R1,%R1,%0
ld%, %0,%1
- mov %r1,%0
+ bis $31,%r1,%0
ldl %0,%1
st%, %R1,%0
stl %r1,%0
@@ -4645,7 +4978,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], SFmode)
|| reg_or_fp0_operand (operands[1], SFmode))"
"@
- mov %r1,%0
+ bis $31,%r1,%0
ldl %0,%1
stl %r1,%0"
[(set_attr "type" "ilog,ild,ist")])
@@ -4657,9 +4990,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], DFmode)
|| reg_or_fp0_operand (operands[1], DFmode))"
"@
- fmov %R1,%0
+ cpys %R1,%R1,%0
ld%- %0,%1
- mov %r1,%0
+ bis $31,%r1,%0
ldq %0,%1
st%- %R1,%0
stq %r1,%0"
@@ -4672,9 +5005,9 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], DFmode)
|| reg_or_fp0_operand (operands[1], DFmode))"
"@
- fmov %R1,%0
+ cpys %R1,%R1,%0
ld%- %0,%1
- mov %r1,%0
+ bis $31,%r1,%0
ldq %0,%1
st%- %R1,%0
stq %r1,%0
@@ -4689,7 +5022,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], DFmode)
|| reg_or_fp0_operand (operands[1], DFmode))"
"@
- mov %r1,%0
+ bis $31,%r1,%0
ldq %0,%1
stq %r1,%0"
[(set_attr "type" "ilog,ild,ist")])
@@ -4749,16 +5082,16 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(define_insn "*movsi_nofix"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,r,m,*f,*f,m")
(match_operand:SI 1 "input_operand" "rJ,K,L,m,rJ,*fJ,m,*f"))]
- "TARGET_ABI_OSF && ! TARGET_FIX
+ "(TARGET_ABI_OSF || TARGET_ABI_UNICOSMK) && ! TARGET_FIX
&& (register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
"@
- mov %r1,%0
+ bis $31,%r1,%0
lda %0,%1($31)
ldah %0,%h1($31)
ldl %0,%1
stl %r1,%0
- fmov %R1,%0
+ cpys %R1,%R1,%0
ld%, %0,%1
st%, %R1,%0"
[(set_attr "type" "ilog,iadd,iadd,ild,ist,fcpys,fld,fst")])
@@ -4770,12 +5103,12 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
"@
- mov %r1,%0
+ bis $31,%r1,%0
lda %0,%1($31)
ldah %0,%h1($31)
ldl %0,%1
stl %r1,%0
- fmov %R1,%0
+ cpys %R1,%R1,%0
ld%, %0,%1
st%, %R1,%0
ftois %1,%0
@@ -4789,13 +5122,13 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
"@
- mov %1,%0
+ bis $31,%1,%0
lda %0,%1
ldah %0,%h1
lda %0,%1
ldl %0,%1
stl %r1,%0
- fmov %R1,%0
+ cpys %R1,%R1,%0
ld%, %0,%1
st%, %R1,%0"
[(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")])
@@ -4807,7 +5140,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode))"
"@
- mov %r1,%0
+ bis $31,%r1,%0
lda %0,%L1($31)"
[(set_attr "type" "ilog,iadd")])
@@ -4818,7 +5151,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))"
"@
- mov %r1,%0
+ bis $31,%r1,%0
lda %0,%L1($31)
ldwu %0,%1
stw %r1,%0"
@@ -4831,7 +5164,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode))"
"@
- mov %r1,%0
+ bis $31,%r1,%0
lda %0,%L1($31)"
[(set_attr "type" "ilog,iadd")])
@@ -4842,7 +5175,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode))"
"@
- mov %r1,%0
+ bis $31,%r1,%0
lda %0,%L1($31)
ldbu %0,%1
stb %r1,%0"
@@ -4879,6 +5212,87 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
FAIL;
})
+;; Split the load of an address into a four-insn sequence on Unicos/Mk.
+;; Always generate a REG_EQUAL note for the last instruction to facilitate
+;; optimisations. If the symbolic operand is a label_ref, generate REG_LABEL
+;; notes and update LABEL_NUSES because this is not done automatically.
+;; Labels may be incorrectly deleted if we don't do this.
+;;
+;; Describing what the individual instructions do correctly is too complicated
+;; so use UNSPECs for each of the three parts of an address.
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "symbolic_operand" ""))]
+ "TARGET_ABI_UNICOSMK && reload_completed"
+ [(const_int 0)]
+{
+ rtx insn1, insn2, insn3;
+
+ insn1 = emit_insn (gen_umk_laum (operands[0], operands[1]));
+ emit_insn (gen_ashldi3 (operands[0], operands[0], GEN_INT (32)));
+ insn2 = emit_insn (gen_umk_lalm (operands[0], operands[0], operands[1]));
+ insn3 = emit_insn (gen_umk_lal (operands[0], operands[0], operands[1]));
+ REG_NOTES (insn3) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1],
+ REG_NOTES (insn3));
+ if (GET_CODE (operands[1]) == LABEL_REF)
+ {
+ rtx label;
+
+ label = XEXP (operands[1], 0);
+ REG_NOTES (insn1) = gen_rtx_EXPR_LIST (REG_LABEL, label,
+ REG_NOTES (insn1));
+ REG_NOTES (insn2) = gen_rtx_EXPR_LIST (REG_LABEL, label,
+ REG_NOTES (insn2));
+ REG_NOTES (insn3) = gen_rtx_EXPR_LIST (REG_LABEL, label,
+ REG_NOTES (insn3));
+ LABEL_NUSES (label) += 3;
+ }
+ DONE;
+})
+
+;; Instructions for loading the three parts of an address on Unicos/Mk.
+
+(define_insn "umk_laum"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ UNSPEC_UMK_LAUM))]
+ "TARGET_ABI_UNICOSMK"
+ "laum %r0,%t1($31)"
+ [(set_attr "type" "iadd")])
+
+(define_insn "umk_lalm"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_UMK_LALM)))]
+ "TARGET_ABI_UNICOSMK"
+ "lalm %r0,%t2(%r1)"
+ [(set_attr "type" "iadd")])
+
+(define_insn "umk_lal"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (match_operand:DI 1 "register_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
+ UNSPEC_UMK_LAL)))]
+ "TARGET_ABI_UNICOSMK"
+ "lal %r0,%t2(%r1)"
+ [(set_attr "type" "iadd")])
+
+;; Add a new call information word to the current function's list of CIWs
+;; and load its index into $25. Doing it here ensures that the CIW will be
+;; associated with the correct function even in the presence of inlining.
+
+(define_insn "*umk_load_ciw"
+ [(set (reg:DI 25)
+ (unspec:DI [(match_operand 0 "" "")] UNSPEC_UMK_LOAD_CIW))]
+ "TARGET_ABI_UNICOSMK"
+{
+ operands[0] = unicosmk_add_call_info_word (operands[0]);
+ return "lda $25,%0";
+}
+ [(set_attr "type" "iadd")])
+
(define_insn "*movdi_er_low"
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
@@ -4906,23 +5320,29 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
stt %R1,%0"
[(set_attr "type" "ilog,iadd,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")])
+;; The 'U' constraint matches symbolic operands on Unicos/Mk. Those should
+;; have been split up by the rules above but we shouldn't reject the
+;; possibility of them getting through.
+
(define_insn "*movdi_nofix"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,m,*f,*f,Q")
- (match_operand:DI 1 "input_operand" "rJ,K,L,s,m,rJ,*fJ,Q,*f"))]
- "! TARGET_EXPLICIT_RELOCS && ! TARGET_FIX
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q")
+ (match_operand:DI 1 "input_operand" "rJ,K,L,U,s,m,rJ,*fJ,Q,*f"))]
+ "! TARGET_FIX
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
"@
- mov %r1,%0
+ bis $31,%r1,%0
lda %0,%1($31)
ldah %0,%h1($31)
+ laum %0,%t1($31)\;sll %0,32,%0\;lalm %0,%t1(%0)\;lal %0,%t1(%0)
lda %0,%1
ldq%A1 %0,%1
stq%A0 %r1,%0
- fmov %R1,%0
+ cpys %R1,%R1,%0
ldt %0,%1
stt %R1,%0"
- [(set_attr "type" "ilog,iadd,iadd,ldsym,ild,ist,fcpys,fld,fst")])
+ [(set_attr "type" "ilog,iadd,iadd,ldsym,ldsym,ild,ist,fcpys,fld,fst")
+ (set_attr "length" "*,*,*,16,*,*,*,*,*,*")])
(define_insn "*movdi_er_fix"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q,r,*f")
@@ -4953,13 +5373,13 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
"@
- mov %r1,%0
+ bis $31,%r1,%0
lda %0,%1($31)
ldah %0,%h1($31)
lda %0,%1
ldq%A1 %0,%1
stq%A0 %r1,%0
- fmov %R1,%0
+ cpys %R1,%R1,%0
ldt %0,%1
stt %R1,%0
ftoit %1,%0
@@ -5041,12 +5461,29 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
"")
;; Similar for unaligned loads, where we use the sequence from the
-;; Alpha Architecture manual.
+;; Alpha Architecture manual. We have to distinguish between little-endian
+;; and big-endian systems as the sequences are different.
;;
;; Operand 1 is the address. Operands 2 and 3 are temporaries, where
;; operand 3 can overlap the input and output registers.
(define_expand "unaligned_loadqi"
+ [(use (match_operand:QI 0 "register_operand" ""))
+ (use (match_operand:DI 1 "address_operand" ""))
+ (use (match_operand:DI 2 "register_operand" ""))
+ (use (match_operand:DI 3 "register_operand" ""))]
+ ""
+{
+ if (WORDS_BIG_ENDIAN)
+ emit_insn (gen_unaligned_loadqi_be (operands[0], operands[1],
+ operands[2], operands[3]));
+ else
+ emit_insn (gen_unaligned_loadqi_le (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+})
+
+(define_expand "unaligned_loadqi_le"
[(set (match_operand:DI 2 "register_operand" "")
(mem:DI (and:DI (match_operand:DI 1 "address_operand" "")
(const_int -8))))
@@ -5056,10 +5493,41 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(zero_extract:DI (match_dup 2)
(const_int 8)
(ashift:DI (match_dup 3) (const_int 3))))]
- ""
+ "! WORDS_BIG_ENDIAN"
+ "")
+
+(define_expand "unaligned_loadqi_be"
+ [(set (match_operand:DI 2 "register_operand" "")
+ (mem:DI (and:DI (match_operand:DI 1 "address_operand" "")
+ (const_int -8))))
+ (set (match_operand:DI 3 "register_operand" "")
+ (match_dup 1))
+ (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
+ (zero_extract:DI (match_dup 2)
+ (const_int 8)
+ (minus:DI
+ (const_int 56)
+ (ashift:DI (match_dup 3) (const_int 3)))))]
+ "WORDS_BIG_ENDIAN"
"")
(define_expand "unaligned_loadhi"
+ [(use (match_operand:QI 0 "register_operand" ""))
+ (use (match_operand:DI 1 "address_operand" ""))
+ (use (match_operand:DI 2 "register_operand" ""))
+ (use (match_operand:DI 3 "register_operand" ""))]
+ ""
+{
+ if (WORDS_BIG_ENDIAN)
+ emit_insn (gen_unaligned_loadhi_be (operands[0], operands[1],
+ operands[2], operands[3]));
+ else
+ emit_insn (gen_unaligned_loadhi_le (operands[0], operands[1],
+ operands[2], operands[3]));
+ DONE;
+})
+
+(define_expand "unaligned_loadhi_le"
[(set (match_operand:DI 2 "register_operand" "")
(mem:DI (and:DI (match_operand:DI 1 "address_operand" "")
(const_int -8))))
@@ -5069,7 +5537,22 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(zero_extract:DI (match_dup 2)
(const_int 16)
(ashift:DI (match_dup 3) (const_int 3))))]
- ""
+ "! WORDS_BIG_ENDIAN"
+ "")
+
+(define_expand "unaligned_loadhi_be"
+ [(set (match_operand:DI 2 "register_operand" "")
+ (mem:DI (and:DI (match_operand:DI 1 "address_operand" "")
+ (const_int -8))))
+ (set (match_operand:DI 3 "register_operand" "")
+ (plus:DI (match_dup 1) (const_int 1)))
+ (set (subreg:DI (match_operand:QI 0 "register_operand" "") 0)
+ (zero_extract:DI (match_dup 2)
+ (const_int 16)
+ (minus:DI
+ (const_int 56)
+ (ashift:DI (match_dup 3) (const_int 3)))))]
+ "WORDS_BIG_ENDIAN"
"")
;; Storing an aligned byte or word requires two temporaries. Operand 0 is the
@@ -5102,6 +5585,25 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
;; operand 2 can be that register.
(define_expand "unaligned_storeqi"
+ [(use (match_operand:DI 0 "address_operand" ""))
+ (use (match_operand:QI 1 "register_operand" ""))
+ (use (match_operand:DI 2 "register_operand" ""))
+ (use (match_operand:DI 3 "register_operand" ""))
+ (use (match_operand:DI 4 "register_operand" ""))]
+ ""
+{
+ if (WORDS_BIG_ENDIAN)
+ emit_insn (gen_unaligned_storeqi_be (operands[0], operands[1],
+ operands[2], operands[3],
+ operands[4]));
+ else
+ emit_insn (gen_unaligned_storeqi_le (operands[0], operands[1],
+ operands[2], operands[3],
+ operands[4]));
+ DONE;
+})
+
+(define_expand "unaligned_storeqi_le"
[(set (match_operand:DI 3 "register_operand" "")
(mem:DI (and:DI (match_operand:DI 0 "address_operand" "")
(const_int -8))))
@@ -5117,10 +5619,50 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(set (match_dup 4) (ior:DI (match_dup 4) (match_dup 3)))
(set (mem:DI (and:DI (match_dup 0) (const_int -8)))
(match_dup 4))]
- ""
+ "! WORDS_BIG_ENDIAN"
+ "")
+
+(define_expand "unaligned_storeqi_be"
+ [(set (match_operand:DI 3 "register_operand" "")
+ (mem:DI (and:DI (match_operand:DI 0 "address_operand" "")
+ (const_int -8))))
+ (set (match_operand:DI 2 "register_operand" "")
+ (match_dup 0))
+ (set (match_dup 3)
+ (and:DI (not:DI (ashift:DI (const_int 255)
+ (minus:DI (const_int 56)
+ (ashift:DI (match_dup 2) (const_int 3)))))
+ (match_dup 3)))
+ (set (match_operand:DI 4 "register_operand" "")
+ (ashift:DI (zero_extend:DI (match_operand:QI 1 "register_operand" ""))
+ (minus:DI (const_int 56)
+ (ashift:DI (match_dup 2) (const_int 3)))))
+ (set (match_dup 4) (ior:DI (match_dup 4) (match_dup 3)))
+ (set (mem:DI (and:DI (match_dup 0) (const_int -8)))
+ (match_dup 4))]
+ "WORDS_BIG_ENDIAN"
"")
(define_expand "unaligned_storehi"
+ [(use (match_operand:DI 0 "address_operand" ""))
+ (use (match_operand:HI 1 "register_operand" ""))
+ (use (match_operand:DI 2 "register_operand" ""))
+ (use (match_operand:DI 3 "register_operand" ""))
+ (use (match_operand:DI 4 "register_operand" ""))]
+ ""
+{
+ if (WORDS_BIG_ENDIAN)
+ emit_insn (gen_unaligned_storehi_be (operands[0], operands[1],
+ operands[2], operands[3],
+ operands[4]));
+ else
+ emit_insn (gen_unaligned_storehi_le (operands[0], operands[1],
+ operands[2], operands[3],
+ operands[4]));
+ DONE;
+})
+
+(define_expand "unaligned_storehi_le"
[(set (match_operand:DI 3 "register_operand" "")
(mem:DI (and:DI (match_operand:DI 0 "address_operand" "")
(const_int -8))))
@@ -5136,7 +5678,29 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(set (match_dup 4) (ior:DI (match_dup 4) (match_dup 3)))
(set (mem:DI (and:DI (match_dup 0) (const_int -8)))
(match_dup 4))]
- ""
+ "! WORDS_BIG_ENDIAN"
+ "")
+
+(define_expand "unaligned_storehi_be"
+ [(set (match_operand:DI 3 "register_operand" "")
+ (mem:DI (and:DI (match_operand:DI 0 "address_operand" "")
+ (const_int -8))))
+ (set (match_operand:DI 2 "register_operand" "")
+ (plus:DI (match_dup 0) (const_int 1)))
+ (set (match_dup 3)
+ (and:DI (not:DI (ashift:DI
+ (const_int 65535)
+ (minus:DI (const_int 56)
+ (ashift:DI (match_dup 2) (const_int 3)))))
+ (match_dup 3)))
+ (set (match_operand:DI 4 "register_operand" "")
+ (ashift:DI (zero_extend:DI (match_operand:HI 1 "register_operand" ""))
+ (minus:DI (const_int 56)
+ (ashift:DI (match_dup 2) (const_int 3)))))
+ (set (match_dup 4) (ior:DI (match_dup 4) (match_dup 3)))
+ (set (mem:DI (and:DI (match_dup 0) (const_int -8)))
+ (match_dup 4))]
+ "WORDS_BIG_ENDIAN"
"")
;; Here are the define_expand's for QI and HI moves that use the above
@@ -5356,6 +5920,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
{
rtx aligned_mem, bitnum;
get_aligned_mem (operands[1], &aligned_mem, &bitnum);
+
emit_insn (gen_aligned_loadqi (operands[0], aligned_mem, bitnum,
operands[2]));
DONE;
@@ -5370,6 +5935,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
{
rtx aligned_mem, bitnum;
get_aligned_mem (operands[1], &aligned_mem, &bitnum);
+
emit_insn (gen_aligned_loadhi (operands[0], aligned_mem, bitnum,
operands[2]));
DONE;
@@ -5414,6 +5980,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:DI 3 "immediate_operand" "")))]
""
{
+ int ofs;
+
/* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries. */
if (INTVAL (operands[3]) % 8 != 0
|| (INTVAL (operands[2]) != 16
@@ -5426,9 +5994,21 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
if (GET_CODE (operands[1]) != MEM)
FAIL;
+ /* The bit number is relative to the mode of operand 1 which is
+ usually QImode (this might actually be a bug in expmed.c). Note
+ that the bit number is negative in big-endian mode in this case.
+ We have to convert that to the offset. */
+ if (WORDS_BIG_ENDIAN)
+ ofs = GET_MODE_BITSIZE (GET_MODE (operands[1]))
+ - INTVAL (operands[2]) - INTVAL (operands[3]);
+ else
+ ofs = INTVAL (operands[3]);
+
+ ofs = ofs / 8;
+
alpha_expand_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]) / 8,
- INTVAL (operands[3]) / 8, 1);
+ ofs, 1);
DONE;
})
@@ -5449,13 +6029,27 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
if (GET_CODE (operands[1]) == MEM)
{
+ int ofs;
+
/* Fail 8 bit fields, falling back on a simple byte load. */
if (INTVAL (operands[2]) == 8)
FAIL;
+ /* The bit number is relative to the mode of operand 1 which is
+ usually QImode (this might actually be a bug in expmed.c). Note
+ that the bit number is negative in big-endian mode in this case.
+ We have to convert that to the offset. */
+ if (WORDS_BIG_ENDIAN)
+ ofs = GET_MODE_BITSIZE (GET_MODE (operands[1]))
+ - INTVAL (operands[2]) - INTVAL (operands[3]);
+ else
+ ofs = INTVAL (operands[3]);
+
+ ofs = ofs / 8;
+
alpha_expand_unaligned_load (operands[0], operands[1],
INTVAL (operands[2]) / 8,
- INTVAL (operands[3]) / 8, 0);
+ ofs, 0);
DONE;
}
})
@@ -5467,6 +6061,8 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:DI 3 "register_operand" ""))]
""
{
+ int ofs;
+
/* We can do 16, 32 and 64 bit fields, if aligned on byte boundaries. */
if (INTVAL (operands[2]) % 8 != 0
|| (INTVAL (operands[1]) != 16
@@ -5479,9 +6075,20 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
if (GET_CODE (operands[0]) != MEM)
FAIL;
+ /* The bit number is relative to the mode of operand 1 which is
+ usually QImode (this might actually be a bug in expmed.c). Note
+ that the bit number is negative in big-endian mode in this case.
+ We have to convert that to the offset. */
+ if (WORDS_BIG_ENDIAN)
+ ofs = GET_MODE_BITSIZE (GET_MODE (operands[0]))
+ - INTVAL (operands[1]) - INTVAL (operands[2]);
+ else
+ ofs = INTVAL (operands[2]);
+
+ ofs = ofs / 8;
+
alpha_expand_unaligned_store (operands[0], operands[3],
- INTVAL (operands[1]) / 8,
- INTVAL (operands[2]) / 8);
+ INTVAL (operands[1]) / 8, ofs);
DONE;
})
@@ -5675,7 +6282,7 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(match_operand:DI 1 "register_operand" "r"))
(clobber (mem:BLK (match_operand:DI 2 "register_operand" "=r")))]
""
- "mov %1,%0")
+ "bis $31,%1,%0")
(define_expand "epilogue"
[(return)]
@@ -5836,6 +6443,58 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
[(set_attr "length" "16")
(set_attr "type" "multi")])
+;; Load the CIW into r2 for calling __T3E_MISMATCH
+
+(define_expand "umk_mismatch_args"
+ [(set:DI (match_dup 1) (mem:DI (plus:DI (reg:DI 15) (const_int -16))))
+ (set:DI (match_dup 2) (mem:DI (plus:DI (match_dup 1) (const_int -32))))
+ (set:DI (reg:DI 1) (match_operand:DI 0 "const_int_operand" ""))
+ (set:DI (match_dup 3) (plus:DI (mult:DI (reg:DI 25)
+ (const_int 8))
+ (match_dup 2)))
+ (set:DI (reg:DI 2) (mem:DI (match_dup 3)))]
+ "TARGET_ABI_UNICOSMK"
+{
+ operands[1] = gen_reg_rtx (DImode);
+ operands[2] = gen_reg_rtx (DImode);
+ operands[3] = gen_reg_rtx (DImode);
+})
+
+(define_insn "arg_home_umk"
+ [(unspec [(const_int 0)] UNSPEC_ARG_HOME)
+ (use (reg:DI 1))
+ (use (reg:DI 2))
+ (use (reg:DI 16))
+ (use (reg:DI 17))
+ (use (reg:DI 18))
+ (use (reg:DI 19))
+ (use (reg:DI 20))
+ (use (reg:DI 21))
+ (use (reg:DI 48))
+ (use (reg:DI 49))
+ (use (reg:DI 50))
+ (use (reg:DI 51))
+ (use (reg:DI 52))
+ (use (reg:DI 53))
+ (clobber (mem:BLK (const_int 0)))
+ (parallel [
+ (clobber (reg:DI 22))
+ (clobber (reg:DI 23))
+ (clobber (reg:DI 24))
+ (clobber (reg:DI 0))
+ (clobber (reg:DI 1))
+ (clobber (reg:DI 2))
+ (clobber (reg:DI 3))
+ (clobber (reg:DI 4))
+ (clobber (reg:DI 5))
+ (clobber (reg:DI 6))
+ (clobber (reg:DI 7))
+ (clobber (reg:DI 8))])]
+ "TARGET_ABI_UNICOSMK"
+ "laum $4,__T3E_MISMATCH($31)\;sll $4,32,$4\;lalm $4,__T3E_MISMATCH($4)\;lal $4,__T3E_MISMATCH($4)\;jsr $3,($4)"
+ [(set_attr "length" "16")
+ (set_attr "type" "multi")])
+
;; Close the trap shadow of preceeding instructions. This is generated
;; by alpha_reorg.
@@ -5847,33 +6506,51 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
;; No-op instructions used by machine-dependant reorg to preserve
;; alignment for instruction issue.
+;; The Unicos/Mk assembler does not support these opcodes.
(define_insn "nop"
[(const_int 0)]
""
- "nop"
+ "bis $31,$31,$31"
[(set_attr "type" "ilog")])
(define_insn "fnop"
[(const_int 1)]
"TARGET_FP"
- "fnop"
+ "cpys $f31,$f31,$f31"
[(set_attr "type" "fcpys")])
(define_insn "unop"
[(const_int 2)]
""
- "unop")
+ "ldq_u $31,($31)")
+
+;; On Unicos/Mk we use a macro for aligning code.
(define_insn "realign"
[(unspec_volatile [(match_operand 0 "immediate_operand" "i")]
UNSPECV_REALIGN)]
""
- ".align %0 #realign")
+{
+ if (TARGET_ABI_UNICOSMK)
+ return "gcc@code@align %0";
+ else
+ return ".align %0 #realign";
+})
;; The call patterns are at the end of the file because their
;; wildcard operand0 interferes with nice recognition.
+(define_insn "*call_value_umk"
+ [(set (match_operand 0 "" "")
+ (call (mem:DI (match_operand:DI 1 "call_operand" "r"))
+ (match_operand 2 "" "")))
+ (use (reg:DI 25))
+ (clobber (reg:DI 26))]
+ "TARGET_ABI_UNICOSMK"
+ "jsr $26,(%1)"
+ [(set_attr "type" "jsr")])
+
(define_insn "*call_value_osf_1_er"
[(set (match_operand 0 "" "")
(call (mem:DI (match_operand:DI 1 "call_operand" "c,R,i"))
diff --git a/gcc/config/alpha/t-unicosmk b/gcc/config/alpha/t-unicosmk
new file mode 100644
index 0000000..9c52b98
--- /dev/null
+++ b/gcc/config/alpha/t-unicosmk
@@ -0,0 +1,2 @@
+# This file is empty for now.
+
diff --git a/gcc/config/alpha/unicosmk.h b/gcc/config/alpha/unicosmk.h
new file mode 100644
index 0000000..6ecc3d2
--- /dev/null
+++ b/gcc/config/alpha/unicosmk.h
@@ -0,0 +1,667 @@
+/* Definitions of target machine for GNU compiler, for DEC Alpha on Cray
+ T3E running Unicos/Mk.
+ Copyright (C) 2001
+ Free Software Foundation, Inc.
+ Contributed by Roman Lechtchinsky (rl@cs.tu-berlin.de)
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+#undef TARGET_ABI_UNICOSMK
+#define TARGET_ABI_UNICOSMK 1
+
+/* CAM requires a slash before floating-pointing instruction suffixes. */
+
+#undef TARGET_AS_SLASH_BEFORE_SUFFIX
+#define TARGET_AS_SLASH_BEFORE_SUFFIX 1
+
+/* The following defines are necessary for the standard headers to work
+ correctly. */
+
+#undef CPP_PREDEFINES
+#define CPP_PREDEFINES "-D__unix=1 -D_UNICOS=205 -D_CRAY=1 -D_CRAYT3E=1 -D_CRAYMPP=1 -D_CRAYIEEE=1 -D_ADDR64=1 -D_LD64=1 -D__UNICOSMK__ -D__INT_MAX__=9223372036854775807 -D__SHRT_MAX__=2147483647"
+
+/* Disable software floating point emulation because it requires a 16-bit
+ type which we do not have. */
+
+#ifndef __GNUC__
+#undef REAL_ARITHMETIC
+#endif
+
+#define SHORT_TYPE_SIZE 32
+
+#undef INT_TYPE_SIZE
+#define INT_TYPE_SIZE 64
+
+/* This is consistent with the definition Cray CC uses. */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 64
+
+/*
+#define SIZE_TYPE "unsigned int"
+#define PTRDIFF_TYPE "int"
+*/
+
+/* Alphas are operated in big endian mode on the Cray T3E. */
+
+#undef BITS_BIG_ENDIAN
+#undef BYTES_BIG_ENDIAN
+#undef WORDS_BIG_ENDIAN
+#define BITS_BIG_ENDIAN 0
+#define BYTES_BIG_ENDIAN 1
+#define WORDS_BIG_ENDIAN 1
+
+
+/* Every structure's size must be a multiple of this. */
+
+#undef STRUCTURE_SIZE_BOUNDARY
+#define STRUCTURE_SIZE_BOUNDARY 64
+
+/* Allocation boundary (in *bits*) for the code of a function. Functions
+ should be cache-aligned on the T3E. */
+
+#undef FUNCTION_BOUNDARY
+#define FUNCTION_BOUNDARY 256
+
+/* No data type wants to be aligned rounder than this. */
+
+#undef BIGGEST_ALIGNMENT
+#define BIGGEST_ALIGNMENT 256
+
+/* Include the frame pointer in fixed_regs and call_used_regs as it can't be
+ used as a general-purpose register even in frameless functions.
+ ??? The global_regs hack is needed for now because -O2 sometimes tries to
+ eliminate $15 increments/decrements in frameless functions. */
+
+#undef CONDITIONAL_REGISTER_USAGE
+#define CONDITIONAL_REGISTER_USAGE \
+ do { \
+ fixed_regs[15] = 1; \
+ call_used_regs[15] = 1; \
+ global_regs[15] = 1; \
+ } while(0)
+
+/* The stack frame grows downward. */
+
+#define FRAME_GROWS_DOWNWARD
+
+/* Define the offset between two registers, one to be eliminated, and the
+ other its replacement, at the start of a routine. This is somewhat
+ complicated on the T3E which is why we use a function. */
+
+extern int unicosmk_initial_elimination_offset PARAMS ((int, int));
+
+#undef INITIAL_ELIMINATION_OFFSET
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ do { \
+ (OFFSET) = unicosmk_initial_elimination_offset ((FROM), (TO)); \
+ } while (0)
+
+
+/* Define this if stack space is still allocated for a parameter passed
+ in a register. On the T3E, stack space is preallocated for all outgoing
+ arguments, including those passed in registers. To avoid problems, we
+ assume that at least 48 bytes (i.e. enough space for all arguments passed
+ in registers) are allocated. */
+
+#define REG_PARM_STACK_SPACE(DECL) 48
+#define OUTGOING_REG_PARM_STACK_SPACE
+
+/* If an argument can't be passed in registers even though not all argument
+ registers have been used yet, it is passed on the stack in the space
+ preallocated for these registers. */
+
+#define STACK_PARMS_IN_REG_PARM_AREA
+
+/* This evaluates to nonzero if we do not know how to pass TYPE solely in
+ registers. This is the case for all arguments that do not fit in two
+ registers. */
+
+#define MUST_PASS_IN_STACK(MODE,TYPE) \
+ ((TYPE) != 0 \
+ && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
+ || (TREE_ADDRESSABLE (TYPE) || ALPHA_ARG_SIZE (MODE, TYPE, 0) > 2)))
+
+/* Define a data type for recording info about an argument list
+ during the scan of that argument list. This data type should
+ hold all necessary information about the function itself
+ and about the args processed so far, enough to enable macros
+ such as FUNCTION_ARG to determine where the next arg should go.
+
+ On Unicos/Mk, this is a structure that contains various information for
+ the static subroutine information block (SSIB) and the call information
+ word (CIW). */
+
+typedef struct {
+
+ /* The overall number of arguments. */
+ int num_args;
+
+ /* The overall size of the arguments in words. */
+ int num_arg_words;
+
+ /* The number of words passed in registers. */
+ int num_reg_words;
+
+ /* If an argument must be passed in the stack, all subsequent arguments
+ must be passed there, too. This flag indicates whether this is the
+ case. */
+ int force_stack;
+
+ /* This array indicates whether a word is passed in an integer register or
+ a floating point one. */
+
+ /* For each of the 6 register arguments, the corresponding flag in this
+ array indicates whether the argument is passed in an integer or a
+ floating point register. */
+ int reg_args_type[6];
+
+} unicosmk_arg_info;
+
+#undef CUMULATIVE_ARGS
+#define CUMULATIVE_ARGS unicosmk_arg_info
+
+/* Initialize a variable CUM of type CUMULATIVE_ARGS for a call to a
+ function whose data type is FNTYPE. For a library call, FNTYPE is 0. */
+
+#undef INIT_CUMULATIVE_ARGS
+#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT) \
+ do { (CUM).num_args = 0; \
+ (CUM).num_arg_words = 0; \
+ (CUM).num_reg_words = 0; \
+ (CUM).force_stack = 0; \
+ } while(0)
+
+/* Update the data in CUM to advance over an argument of mode MODE and data
+ type TYPE. (TYPE is null for libcalls where that information may not be
+ available.)
+
+ On Unicos/Mk, at most 6 words can be passed in registers. Structures
+ which fit in two words are passed in registers, larger structures are
+ passed on stack. */
+
+#undef FUNCTION_ARG_ADVANCE
+#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
+do { \
+ int size; \
+ \
+ size = ALPHA_ARG_SIZE (MODE, TYPE, NAMED); \
+ \
+ if (size > 2 || MUST_PASS_IN_STACK (MODE, TYPE) \
+ || (CUM).num_reg_words + size > 6) \
+ (CUM).force_stack = 1; \
+ \
+ if (! (CUM).force_stack) \
+ { \
+ int i; \
+ int isfloat; \
+ isfloat = (GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \
+ || GET_MODE_CLASS (MODE) == MODE_FLOAT); \
+ for (i = 0; i < size; i++) \
+ { \
+ (CUM).reg_args_type[(CUM).num_reg_words] = isfloat; \
+ ++(CUM).num_reg_words; \
+ } \
+ } \
+ (CUM).num_arg_words += size; \
+ ++(CUM).num_args; \
+} while(0)
+
+/* We want the default definition for this.
+ ??? In fact, we should delete the definition from alpha.h as it
+ corresponds to the default definition for little-endian machines. */
+
+#undef FUNCTION_ARG_PADDING
+
+/* An argument is passed either entirely in registers or entirely on stack. */
+
+#undef FUNCTION_ARG_PARTIAL_NREGS
+/* #define FUNCTION_ARG_PARTIAL_NREGS(CUM,MODE,TYPE,NAMED) 0 */
+
+/* Perform any needed actions needed for a function that is receiving a
+ variable number of arguments.
+
+ On Unicos/Mk, the standard subroutine __T3E_MISMATCH stores all register
+ arguments on the stack. Unfortunately, it doesn't always store the first
+ one (i.e. the one that arrives in $16 or $f16). This is not a problem
+ with stdargs as we always have at least one named argument there. This is
+ not always the case when varargs.h is used, however. In such cases, we
+ have to store the first argument ourselves. We use the information from
+ the CIW to determine whether the first argument arrives in $16 or $f16. */
+
+#undef SETUP_INCOMING_VARARGS
+#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
+{ if ((CUM).num_reg_words < 6) \
+ { \
+ if (! (NO_RTL)) \
+ { \
+ int start; \
+ \
+ start = (CUM).num_reg_words; \
+ if (!current_function_varargs || start == 0) \
+ ++start; \
+ \
+ emit_insn (gen_umk_mismatch_args (GEN_INT (start))); \
+ if (current_function_varargs && (CUM).num_reg_words == 0) \
+ { \
+ rtx tmp; \
+ rtx int_label, end_label; \
+ \
+ tmp = gen_reg_rtx (DImode); \
+ emit_move_insn (tmp, \
+ gen_rtx_ZERO_EXTRACT (DImode, \
+ gen_rtx_REG (DImode, 2),\
+ (GEN_INT (1)), \
+ (GEN_INT (7)))); \
+ int_label = gen_label_rtx (); \
+ end_label = gen_label_rtx (); \
+ emit_insn (gen_cmpdi (tmp, GEN_INT (0))); \
+ emit_jump_insn (gen_beq (int_label)); \
+ emit_move_insn (gen_rtx_MEM (DFmode, virtual_incoming_args_rtx),\
+ gen_rtx_REG (DFmode, 48)); \
+ emit_jump (end_label); \
+ emit_label (int_label); \
+ emit_move_insn (gen_rtx_MEM (DImode, virtual_incoming_args_rtx),\
+ gen_rtx_REG (DImode, 16)); \
+ emit_label (end_label); \
+ } \
+ emit_insn (gen_arg_home_umk ()); \
+ } \
+ \
+ PRETEND_SIZE = 0; \
+ } \
+}
+
+/* This ensures that $15 increments/decrements in leaf functions won't get
+ eliminated. */
+
+#undef EPILOGUE_USES
+#define EPILOGUE_USES(REGNO) ((REGNO) == 26 || (REGNO) == 15)
+
+/* Machine-specific function data. */
+
+struct machine_function
+{
+ /* List of call information words for calls from this function. */
+ struct rtx_def *first_ciw;
+ struct rtx_def *last_ciw;
+ int ciw_count;
+
+ /* List of deferred case vectors. */
+ struct rtx_def *addr_list;
+};
+
+/* Would have worked, only the stack doesn't seem to be executable
+#undef TRAMPOLINE_TEMPLATE
+#define TRAMPOLINE_TEMPLATE(FILE) \
+do { fprintf (FILE, "\tbr $1,0\n"); \
+ fprintf (FILE, "\tldq $0,12($1)\n"); \
+ fprintf (FILE, "\tldq $1,20($1)\n"); \
+ fprintf (FILE, "\tjmp $31,(r0)\n"); \
+ fprintf (FILE, "\tbis $31,$31,$31\n"); \
+ fprintf (FILE, "\tbis $31,$31,$31\n"); \
+} while (0) */
+
+/* We don't support nested functions (yet). */
+
+#undef TRAMPOLINE_TEMPLATE
+#define TRAMPOLINE_TEMPLATE(FILE) abort ()
+
+/* Specify the machine mode that this machine uses for the index in the
+ tablejump instruction. On Unicos/Mk, we don't support relative case
+ vectors yet, thus the entries should be absolute addresses. */
+
+#undef CASE_VECTOR_MODE
+#define CASE_VECTOR_MODE DImode
+
+#undef CASE_VECTOR_PC_RELATIVE
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+/* #define DEFAULT_SIGNED_CHAR 1 */
+
+/* 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. The following is a rather bad hack
+ as TEXT_SECTION_ASM_OP and DATA_SECTION_ASM_OP are supposed to be
+ constants. */
+
+#undef TEXT_SECTION_ASM_OP
+#define TEXT_SECTION_ASM_OP unicosmk_text_section ()
+
+#undef DATA_SECTION_ASM_OP
+#define DATA_SECTION_ASM_OP unicosmk_data_section ()
+
+/* There are ni read-only sections on Unicos/Mk. */
+
+#undef READONLY_DATA_SECTION
+#define READONLY_DATA_SECTION data_section
+
+/* Define extra sections for common data and SSIBs (static subroutine
+ information blocks). The actual section header is output by the callers
+ of these functions. */
+
+#undef EXTRA_SECTIONS
+#undef EXTRA_SECTION_FUNCTIONS
+
+#define EXTRA_SECTIONS in_common, in_ssib
+#define EXTRA_SECTION_FUNCTIONS \
+COMMON_SECTION \
+SSIB_SECTION
+
+#define COMMON_SECTION \
+void \
+common_section () \
+{ \
+ in_section = in_common; \
+}
+
+#define SSIB_SECTION \
+void \
+ssib_section () \
+{ \
+ in_section = in_ssib; \
+}
+
+/* A C expression which evaluates to true if declshould be placed into a
+ unique section for some target-specific reason. On Unicos/Mk, functions
+ and public variables are always placed in unique sections. */
+
+/*
+#define UNIQUE_SECTION_P(DECL) (TREE_PUBLIC (DECL) \
+ || TREE_CODE (DECL) == FUNCTION_DECL)
+*/
+#define UNIQUE_SECTION(DECL, RELOC) unicosmk_unique_section (DECL, RELOC)
+
+/* This outputs text to go at the start of an assembler file. */
+
+#undef ASM_FILE_START
+#define ASM_FILE_START(FILE) unicosmk_asm_file_start (FILE)
+
+/* This outputs text to go at the end of an assembler file. */
+
+#undef ASM_FILE_END
+#define ASM_FILE_END(FILE) unicosmk_asm_file_end (FILE)
+
+/* We take care of that in ASM_FILE_START. */
+
+#undef ASM_OUTPUT_SOURCE_FILENAME
+
+/* There is no directive for declaring a label as global. Instead, an
+ additional colon must be appended when the label is defined. */
+
+#undef ASM_GLOBALIZE_LABEL
+#define ASM_GLOBALIZE_LABEL(FILE,NAME)
+
+/* This is how to output a label for a jump table. Arguments are the same as
+ for ASM_OUTPUT_INTERNAL_LABEL, except the insn for the jump table is
+ passed. */
+
+#undef ASM_OUTPUT_CASE_LABEL
+#define ASM_OUTPUT_CASE_LABEL(FILE,PREFIX,NUM,TABLEINSN) \
+ ASM_OUTPUT_INTERNAL_LABEL (FILE, PREFIX, NUM)
+
+/* This is how to output an assembler line defining a `double' constant. */
+
+#undef ASM_OUTPUT_DOUBLE
+#ifdef REAL_ARITHMETIC
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ do { long t[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \
+ fprintf (FILE, "\t.quad ^X%lx%08lx\n", \
+ t[0] & 0xffffffff, t[1] & 0xffffffff); \
+ } while (0)
+#else
+#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
+ do { long t[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE ((VALUE), t); \
+ fprintf (FILE, "\t.quad ^X%x\n", t[0]); \
+ } while(0)
+#endif
+
+
+/* This is how to output an assembler line defining a `long double'
+ constant. `long double' and `double' are the same on the Cray T3E. */
+
+#undef ASM_OUTPUT_LONG_DOUBLE
+#define ASM_OUTPUT_LONG_DOUBLE(FILE,VALUE) \
+ ASM_OUTPUT_DOUBLE (FILE,VALUE)
+
+/* This is how to output an assembler line defining a `float' constant.
+ ??? Somehow, REAL_VALUE_TO_TARGET_SINGLE gets confused and returns the
+ value in the upper bits of the int. */
+
+#undef ASM_OUTPUT_FLOAT
+#ifdef REAL_ARITHMETIC
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ do { long t; \
+ REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \
+ fprintf (FILE, "\t.long ^X%x\n", t & 0xffffffff);\
+ } while (0)
+#else
+#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
+ do { long t; \
+ REAL_VALUE_TO_TARGET_SINGLE ((VALUE), t); \
+ fprintf (FILE, "\t.long ^X%x\n", (t >> 32) & 0xffffffff);\
+ } while(0)
+#endif
+
+/* CAM has some restrictions with respect to string literals. It won't
+ accept lines with more that 256 characters which means that we have
+ to split long strings. Moreover, it only accepts escape sequences of
+ the form \nnn in the range 0 to 127. We generate .byte directives for
+ escapes characters greater than 127. And finally, ` must be escaped. */
+
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(MYFILE, MYSTRING, MYLENGTH) \
+ do { \
+ FILE *_hide_asm_out_file = (MYFILE); \
+ const unsigned char *_hide_p = (const unsigned char *) (MYSTRING); \
+ int _hide_thissize = (MYLENGTH); \
+ int _size_so_far = 0; \
+ { \
+ FILE *asm_out_file = _hide_asm_out_file; \
+ const unsigned char *p = _hide_p; \
+ int thissize = _hide_thissize; \
+ int in_ascii = 0; \
+ int i; \
+ \
+ for (i = 0; i < thissize; i++) \
+ { \
+ register int c = p[i]; \
+ \
+ if (c > 127) \
+ { \
+ if (in_ascii) \
+ { \
+ fprintf (asm_out_file, "\"\n"); \
+ in_ascii = 0; \
+ } \
+ \
+ fprintf (asm_out_file, "\t.byte\t%d\n", c); \
+ } \
+ else \
+ { \
+ if (! in_ascii) \
+ { \
+ fprintf (asm_out_file, "\t.ascii\t\""); \
+ in_ascii = 1; \
+ _size_so_far = 0; \
+ } \
+ else if (_size_so_far >= 64) \
+ { \
+ fprintf (asm_out_file, "\"\n\t.ascii\t\""); \
+ _size_so_far = 0; \
+ } \
+ \
+ if (c == '\"' || c == '\\' || c == '`') \
+ putc ('\\', asm_out_file); \
+ if (c >= ' ') \
+ putc (c, asm_out_file); \
+ else \
+ fprintf (asm_out_file, "\\%.3o", c); \
+ ++ _size_so_far; \
+ } \
+ } \
+ if (in_ascii) \
+ fprintf (asm_out_file, "\"\n"); \
+ } \
+ } while(0)
+
+/* This is how to output an element of a case-vector that is absolute. */
+
+#undef ASM_OUTPUT_ADDR_VEC_ELT
+#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
+ fprintf (FILE, "\t.quad $L%d\n", (VALUE))
+
+/* This is how to output an element of a case-vector that is relative.
+ (Unicos/Mk does not use such vectors yet). */
+
+#undef ASM_OUTPUT_ADDR_DIFF_ELT
+#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) abort ()
+
+/* We can't output case vectors in the same section as the function code
+ because CAM doesn't allow data definitions in code sections. Thus, we
+ simply record the case vectors and put them in a separate section after
+ the function. */
+
+#define ASM_OUTPUT_ADDR_VEC(LAB,VEC) \
+ unicosmk_defer_case_vector ((LAB),(VEC))
+
+#define ASM_OUTPUT_ADDR_DIFF_VEC(LAB,VEC) abort ()
+
+/* This is how to output an assembler line that says to advance the location
+ counter to a multiple of 2**LOG bytes. Annoyingly, CAM always uses zeroes
+ to fill the unused space which does not work in code sections. We have to
+ be careful not to use the .align directive in code sections. */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(STREAM,LOG) unicosmk_output_align (STREAM, LOG)
+
+/* This is how to advance the location counter by SIZE bytes. */
+
+#undef ASM_OUTPUT_SKIP
+#define ASM_OUTPUT_SKIP(STREAM,SIZE) \
+ fprintf ((STREAM), "\t.byte\t0:%d\n", (SIZE));
+
+/* This says how to output an assembler line to define a global common
+ symbol. We need the alignment information because it has to be supplied
+ in the section header. */
+
+#undef ASM_OUTPUT_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+ unicosmk_output_common ((FILE), (NAME), (SIZE), (ALIGN))
+
+/* This says how to output an assembler line to define a local symbol. */
+
+#undef ASM_OUTPUT_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
+ do { data_section (); \
+ fprintf (FILE, "\t.align\t%d\n", floor_log2 ((ALIGN) / BITS_PER_UNIT));\
+ ASM_OUTPUT_LABEL ((FILE), (NAME)); \
+ fprintf (FILE, "\t.byte 0:%d\n", SIZE); \
+ } while (0)
+
+/* CAM does not allow us to declare a symbol as external first and then
+ define it in the same file later. Thus, we keep a list of all external
+ references, remove all symbols defined locally from it and output it at
+ the end of the asm file. */
+
+#define ASM_OUTPUT_EXTERNAL(FILE,DECL,NAME) \
+ unicosmk_add_extern ((NAME))
+
+#define ASM_OUTPUT_EXTERNAL_LIBCALL(STREAM,SYMREF) \
+ unicosmk_add_extern (XSTR ((SYMREF), 0))
+
+/* This is how to declare an object. We don't have to output anything if
+ it is a global variable because those go into unique `common' sections
+ and the section name is globally visible. For local variables, we simply
+ output the label. In any case, we have to record that no extern
+ declaration should be generated for the symbol. */
+
+#define ASM_DECLARE_OBJECT_NAME(STREAM,NAME,DECL) \
+ do { tree name_tree; \
+ name_tree = get_identifier ((NAME)); \
+ TREE_ASM_WRITTEN (name_tree) = 1; \
+ if (!TREE_PUBLIC (DECL)) \
+ { \
+ assemble_name (STREAM, NAME); \
+ fputs (":\n", STREAM); \
+ } \
+ } while(0)
+
+/*
+#define ASM_OUTPUT_SECTION_NAME(STREAM, DECL, NAME, RELOC) \
+ unicosmk_output_section_name ((STREAM), (DECL), (NAME), (RELOC))
+*/
+
+/* Switch into a generic section. */
+#define TARGET_ASM_NAMED_SECTION unicosmk_asm_named_section
+
+#undef ASM_OUTPUT_MAX_SKIP_ALIGN
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(STREAM,POWER,MAXSKIP)
+
+/* We have to define these because we do not use the floating-point
+ emulation. Unfortunately, atof does not accept hex literals. */
+
+#ifndef REAL_ARITHMETIC
+#define REAL_VALUE_ATOF(x,s) atof(x)
+#define REAL_VALUE_HTOF(x,s) atof(x)
+#endif
+
+#undef NM_FLAGS
+
+#undef OBJECT_FORMAT_COFF
+
+/* We cannot generate debugging information on Unicos/Mk. */
+
+#undef SDB_DEBUGGING_INFO
+#undef MIPS_DEBUGGING_INFO
+#undef DBX_DEBUGGING_INFO
+#undef DWARF_DEBUGGING_INFO
+#undef DWARF2_DEBUGGING_INFO
+#undef DWARF2_UNWIND_INFO
+#undef INCOMING_RETURN_ADDR_RTX
+
+
+/* We use the functions provided by the system library for integer
+ division. */
+
+#undef UDIVDI3_LIBCALL
+#undef DIVDI3_LIBCALL
+#define UDIVDI3_LIBCALL "$uldiv"
+#define DIVDI3_LIBCALL "$sldiv"
+
+#undef ASM_OUTPUT_SOURCE_LINE
+
+/* We don't need a start file. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC ""
+
+/* These are the libraries we have to link with.
+ ??? The Craylibs directory should be autoconfed. */
+#undef LIB_SPEC
+#define LIB_SPEC "-L/opt/ctl/craylibs/craylibs -lu -lm -lc -lsma"
+
+#undef BUILD_VA_LIST_TYPE
+#undef EXPAND_BUILTIN_VA_START
+#undef EXPAND_BUILTIN_VA_ARG
+
+#define EH_FRAME_IN_DATA_SECTION 1
diff --git a/gcc/fixinc/fixincl.x b/gcc/fixinc/fixincl.x
index 873e481..79b3e7e 100644
--- a/gcc/fixinc/fixincl.x
+++ b/gcc/fixinc/fixincl.x
@@ -5,7 +5,7 @@
* files which are fixed to work correctly with ANSI C and placed in a
* directory that GNU C will search.
*
- * This file contains 143 fixup descriptions.
+ * This file contains 144 fixup descriptions.
*
* See README for more information.
*
@@ -1954,7 +1954,7 @@ tSCC zHpux10_Cpp_Pow_InlineName[] =
* File name selection pattern
*/
tSCC zHpux10_Cpp_Pow_InlineList[] =
- "|math.h|";
+ "|fixinc-test-limits.h|math.h|";
/*
* Machine/OS name selection pattern
*/
@@ -5107,6 +5107,43 @@ static const char* apzUndefine_NullPatch[] = {
/* * * * * * * * * * * * * * * * * * * * * * * * * *
*
+ * Description of Unicosmk_Restrict fix
+ */
+tSCC zUnicosmk_RestrictName[] =
+ "unicosmk_restrict";
+
+/*
+ * File name selection pattern
+ */
+tSCC zUnicosmk_RestrictList[] =
+ "|stdio.h|stdlib.h|wchar.h|";
+/*
+ * Machine/OS name selection pattern
+ */
+tSCC* apzUnicosmk_RestrictMachs[] = {
+ "*-*-unicosmk*",
+ (const char*)NULL };
+
+/*
+ * content selection pattern - do fix if pattern found
+ */
+tSCC zUnicosmk_RestrictSelect0[] =
+ "(\\*[ \t]*)restrict([ \t]+)";
+
+#define UNICOSMK_RESTRICT_TEST_CT 1
+static tTestDesc aUnicosmk_RestrictTests[] = {
+ { TT_EGREP, zUnicosmk_RestrictSelect0, (regex_t*)NULL }, };
+
+/*
+ * Fix Command Arguments for Unicosmk_Restrict
+ */
+static const char* apzUnicosmk_RestrictPatch[] = {
+ "format",
+ "%1__restrict__%2",
+ (char*)NULL };
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
* Description of Uw7_Byteorder_Fix fix
*/
tSCC zUw7_Byteorder_FixName[] =
@@ -5577,9 +5614,9 @@ static const char* apzX11_SprintfPatch[] = {
*
* List of all fixes
*/
-#define REGEX_COUNT 150
+#define REGEX_COUNT 151
#define MACH_LIST_SIZE_LIMIT 279
-#define FIX_COUNT 143
+#define FIX_COUNT 144
/*
* Enumerate the fixes
@@ -5717,6 +5754,7 @@ typedef enum {
ULTRIX_STATIC_FIXIDX,
ULTRIX_STRINGS_FIXIDX,
UNDEFINE_NULL_FIXIDX,
+ UNICOSMK_RESTRICT_FIXIDX,
UW7_BYTEORDER_FIX_FIXIDX,
VA_I960_MACRO_FIXIDX,
VOID_NULL_FIXIDX,
@@ -6391,6 +6429,11 @@ tFixDesc fixDescList[ FIX_COUNT ] = {
UNDEFINE_NULL_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
aUndefine_NullTests, apzUndefine_NullPatch, 0 },
+ { zUnicosmk_RestrictName, zUnicosmk_RestrictList,
+ apzUnicosmk_RestrictMachs,
+ UNICOSMK_RESTRICT_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+ aUnicosmk_RestrictTests, apzUnicosmk_RestrictPatch, 0 },
+
{ zUw7_Byteorder_FixName, zUw7_Byteorder_FixList,
apzUw7_Byteorder_FixMachs,
UW7_BYTEORDER_FIX_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
diff --git a/gcc/fixinc/inclhack.def b/gcc/fixinc/inclhack.def
index aedf097..40194e2 100644
--- a/gcc/fixinc/inclhack.def
+++ b/gcc/fixinc/inclhack.def
@@ -3102,6 +3102,23 @@ fix = {
test_text = "#define NULL 0UL\r\n#define NULL\t((void*)0)\n";
};
+/*
+ * On Cray Unicos/Mk some standard headers use the C99 keyword "restrict"
+ * which must be replaced by __restrict__ for GCC.
+ */
+fix = {
+ hackname = unicosmk_restrict;
+ files = stdio.h;
+ files = stdlib.h;
+ files = wchar.h;
+ mach = "*-*-unicosmk*";
+ select = "(\\*[ \t]*)restrict([ \t]+)";
+
+ c_fix = format;
+ c_fix_arg = "%1__restrict__%2";
+
+ test_text = "void f (char * restrict x);";
+};
/*
* If arpa/inet.h prototypes are incompatible with the ones we just
diff --git a/gcc/ginclude/stddef.h b/gcc/ginclude/stddef.h
index 7e5075a..cce87e5 100644
--- a/gcc/ginclude/stddef.h
+++ b/gcc/ginclude/stddef.h
@@ -165,6 +165,7 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t;
or if we want this type in particular. */
#if defined (_STDDEF_H) || defined (__need_size_t)
#ifndef __size_t__ /* BeOS */
+#ifndef __SIZE_T__ /* Cray Unicos/Mk */
#ifndef _SIZE_T /* in case <sys/types.h> has defined it. */
#ifndef _SYS_SIZE_T_H
#ifndef _T_SIZE_
@@ -179,6 +180,7 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t;
#ifndef _SIZET_
#ifndef __size_t
#define __size_t__ /* BeOS */
+#define __SIZE_T__ /* Cray Unicos/Mk */
#define _SIZE_T
#define _SYS_SIZE_T_H
#define _T_SIZE_
@@ -214,6 +216,7 @@ typedef long ssize_t;
#endif /* _T_SIZE_ */
#endif /* _SYS_SIZE_T_H */
#endif /* _SIZE_T */
+#endif /* __SIZE_T__ */
#endif /* __size_t__ */
#undef __need_size_t
#endif /* _STDDEF_H or __need_size_t. */
@@ -228,6 +231,7 @@ typedef long ssize_t;
or if we want this type in particular. */
#if defined (_STDDEF_H) || defined (__need_wchar_t)
#ifndef __wchar_t__ /* BeOS */
+#ifndef __WCHAR_T__ /* Cray Unicos/Mk */
#ifndef _WCHAR_T
#ifndef _T_WCHAR_
#ifndef _T_WCHAR
@@ -242,6 +246,7 @@ typedef long ssize_t;
#ifndef __INT_WCHAR_T_H
#ifndef _GCC_WCHAR_T
#define __wchar_t__ /* BeOS */
+#define __WCHAR_T__ /* Cray Unicos/Mk */
#define _WCHAR_T
#define _T_WCHAR_
#define _T_WCHAR
@@ -300,6 +305,7 @@ typedef __WCHAR_TYPE__ wchar_t;
#endif
#endif
#endif
+#endif /* __WCHAR_T__ */
#endif /* __wchar_t__ */
#undef __need_wchar_t
#endif /* _STDDEF_H or __need_wchar_t. */