diff options
Diffstat (limited to 'gcc/config/mips/mips.c')
-rw-r--r-- | gcc/config/mips/mips.c | 74 |
1 files changed, 50 insertions, 24 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index ccdfbbc3fd1..c2162973393 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -58,6 +58,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "bitmap.h" #include "diagnostic.h" +#include "target-globals.h" /* True if X is an UNSPEC wrapper around a SYMBOL_REF or LABEL_REF. */ #define UNSPEC_ADDRESS_P(X) \ @@ -568,6 +569,9 @@ static const char *mips_lo_relocs[NUM_SYMBOL_TYPES]; /* Likewise for HIGHs. */ static const char *mips_hi_relocs[NUM_SYMBOL_TYPES]; +/* Target state for MIPS16. */ +struct target_globals *mips16_globals; + /* Index R is the smallest register class that contains register R. */ const enum reg_class mips_regno_to_class[FIRST_PSEUDO_REGISTER] = { LEA_REGS, LEA_REGS, M16_REGS, V1_REG, @@ -4853,7 +4857,7 @@ mips_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, tree field; /* First check to see if there is any such field. */ - for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) + for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL && SCALAR_FLOAT_TYPE_P (TREE_TYPE (field)) && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD @@ -4880,7 +4884,7 @@ mips_function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, { rtx reg; - for (; field; field = TREE_CHAIN (field)) + for (; field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL && int_bit_position (field) >= bitpos) break; @@ -5118,7 +5122,7 @@ mips_fpr_return_fields (const_tree valtype, tree *fields) return 0; i = 0; - for (field = TYPE_FIELDS (valtype); field != 0; field = TREE_CHAIN (field)) + for (field = TYPE_FIELDS (valtype); field != 0; field = DECL_CHAIN (field)) { if (TREE_CODE (field) != FIELD_DECL) continue; @@ -5440,11 +5444,11 @@ mips_build_builtin_va_list (void) DECL_FIELD_CONTEXT (f_res) = record; TYPE_FIELDS (record) = f_ovfl; - TREE_CHAIN (f_ovfl) = f_gtop; - TREE_CHAIN (f_gtop) = f_ftop; - TREE_CHAIN (f_ftop) = f_goff; - TREE_CHAIN (f_goff) = f_foff; - TREE_CHAIN (f_foff) = f_res; + DECL_CHAIN (f_ovfl) = f_gtop; + DECL_CHAIN (f_gtop) = f_ftop; + DECL_CHAIN (f_ftop) = f_goff; + DECL_CHAIN (f_goff) = f_foff; + DECL_CHAIN (f_foff) = f_res; layout_type (record); return record; @@ -5479,10 +5483,10 @@ mips_va_start (tree valist, rtx nextarg) = (MAX_ARGS_IN_REGISTERS - cum->num_fprs) * UNITS_PER_FPREG; f_ovfl = TYPE_FIELDS (va_list_type_node); - f_gtop = TREE_CHAIN (f_ovfl); - f_ftop = TREE_CHAIN (f_gtop); - f_goff = TREE_CHAIN (f_ftop); - f_foff = TREE_CHAIN (f_goff); + f_gtop = DECL_CHAIN (f_ovfl); + f_ftop = DECL_CHAIN (f_gtop); + f_goff = DECL_CHAIN (f_ftop); + f_foff = DECL_CHAIN (f_goff); ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, NULL_TREE); @@ -5564,10 +5568,10 @@ mips_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, tree t, u; f_ovfl = TYPE_FIELDS (va_list_type_node); - f_gtop = TREE_CHAIN (f_ovfl); - f_ftop = TREE_CHAIN (f_gtop); - f_goff = TREE_CHAIN (f_ftop); - f_foff = TREE_CHAIN (f_goff); + f_gtop = DECL_CHAIN (f_ovfl); + f_ftop = DECL_CHAIN (f_gtop); + f_goff = DECL_CHAIN (f_ftop); + f_foff = DECL_CHAIN (f_goff); /* Let: @@ -6314,19 +6318,28 @@ mips16_build_call_stub (rtx retval, rtx *fn_ptr, rtx args_size, int fp_code) switch (GET_MODE (retval)) { case SCmode: - mips_output_32bit_xfer ('f', GP_RETURN + 1, - FP_REG_FIRST + MAX_FPRS_PER_FMT); - /* Fall though. */ - case SFmode: - mips_output_32bit_xfer ('f', GP_RETURN, FP_REG_FIRST); + mips_output_32bit_xfer ('f', GP_RETURN + TARGET_BIG_ENDIAN, + TARGET_BIG_ENDIAN + ? FP_REG_FIRST + MAX_FPRS_PER_FMT + : FP_REG_FIRST); + mips_output_32bit_xfer ('f', GP_RETURN + TARGET_LITTLE_ENDIAN, + TARGET_LITTLE_ENDIAN + ? FP_REG_FIRST + MAX_FPRS_PER_FMT + : FP_REG_FIRST); if (GET_MODE (retval) == SCmode && TARGET_64BIT) { /* On 64-bit targets, complex floats are returned in a single GPR, such that "sd" on a suitably-aligned target would store the value correctly. */ fprintf (asm_out_file, "\tdsll\t%s,%s,32\n", + reg_names[GP_RETURN + TARGET_BIG_ENDIAN], + reg_names[GP_RETURN + TARGET_BIG_ENDIAN]); + fprintf (asm_out_file, "\tdsll\t%s,%s,32\n", reg_names[GP_RETURN + TARGET_LITTLE_ENDIAN], reg_names[GP_RETURN + TARGET_LITTLE_ENDIAN]); + fprintf (asm_out_file, "\tdsrl\t%s,%s,32\n", + reg_names[GP_RETURN + TARGET_BIG_ENDIAN], + reg_names[GP_RETURN + TARGET_BIG_ENDIAN]); fprintf (asm_out_file, "\tor\t%s,%s,%s\n", reg_names[GP_RETURN], reg_names[GP_RETURN], @@ -6334,6 +6347,10 @@ mips16_build_call_stub (rtx retval, rtx *fn_ptr, rtx args_size, int fp_code) } break; + case SFmode: + mips_output_32bit_xfer ('f', GP_RETURN, FP_REG_FIRST); + break; + case DCmode: mips_output_64bit_xfer ('f', GP_RETURN + (8 / UNITS_PER_WORD), FP_REG_FIRST + MAX_FPRS_PER_FMT); @@ -15200,9 +15217,15 @@ mips_set_mips16_mode (int mips16_p) /* (Re)initialize MIPS target internals for new ISA. */ mips_init_relocs (); - if (was_mips16_p >= 0 || was_mips16_pch_p >= 0) - /* Reinitialize target-dependent state. */ - target_reinit (); + if (mips16_p) + { + if (!mips16_globals) + mips16_globals = save_target_globals (); + else + restore_target_globals (mips16_globals); + } + else + restore_target_globals (&default_target_globals); was_mips16_p = mips16_p; was_mips16_pch_p = mips16_p; @@ -15436,6 +15459,9 @@ mips_override_options (void) target_flags_explicit |= MASK_SOFT_FLOAT_ABI; } + if (TARGET_FLIP_MIPS16) + TARGET_INTERLINK_MIPS16 = 1; + /* Set the small data limit. */ mips_small_data_threshold = (g_switch_set ? g_switch_value |