This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

revised PATCH: per-function back end reinitialization, part 2/2


This is the MIPS-specific part of the patch that implements support for mixed MIPS16 and non-MIPS16 code in the same file. The only bit that's changed since the previous version I posted is a bit of cleanup at the point where it invokes the non-MIPS-specific backend reinitialization (provided by part 1 of the patch).

Is this OK to commit now if the other part passes muster?

-Sandra

2007-07-30  Sandra Loosemore  <sandra@codesourcery.com>
	    David Ung  <davidu@mips.com>
            Nigel Stephens <nigel@mips.com>

	gcc/
	Add mips16/nomips16 function attributes and -mflip-mips16 option
	for testing mixed-mode compilation.

	* config/mips/mips.opt (mflip-mips16): New.
	(mhard-float, msoft-float):  Make these control TARGET_HARD_FLOAT_ABI
	and TARGET_SOFT_FLOAT_ABI, rather than TARGET_HARD_FLOAT and
	TARGET_SOFT_FLOAT.  

	* config/mips/mips.h (mips16_hard_float): Delete.
	(TARGET_HARD_FLOAT_ABI, TARGET_SOFT_FLOAT_ABI):  Delete these
	definitions, and replace with....
	(TARGET_HARD_FLOAT, TARGET_SOFT_FLOAT): Define.
	(SYMBOL_FLAG_MIPS16_FUNC): Define.
	(SYMBOL_FLAG_MIPS16_FUNC_P): Define.

	* config/mips/mips.c (mips16_hard_float): Delete.  Replace
	all references with (TARGET_MIPS16 && TARGET_HARD_FLOAT_ABI).
	(mips_base_target_flags): New.
	(mips_base_mips16): New.
	(mips_base_schedule_insns): New.
	(mips_base_align_loops): New.
	(mips_base_align_functions): New.
	(mips16_flipper): New.
	(mips_base_split_addresses): New.
	(mips_attribute_table): Add "mips16" and "nomips16" entries.
	(TARGET_PREPARE_FUNCTION_START): Define.
	(TARGET_END_OF_FILE_CLEANUP): Define.
	(mips_mips16_type_p, mips_nomips16_type_p): New.
	(mips_comp_type_attributes): Check mips16/nomips16 attributes.
	(mips_cannot_force_const_mem): Check current have_tls setting, not
	base setting for file.
	(mips16_expand_call):  Add check for built-in functions that
	need function stubs.
	(mips_function_ok_for_sibcall): Make it deal with functions with
	mips16 attributes.
	(function_arg): Must check base mips16 mode for file, not just
	current setting.
	(mips_init_relocs): New, split out from override_options.
	(was_mips16_p): New.
	(mips_set_mips16_mode): New, split out from override_options.
	(mips_prepare_function_start): New.
	(mips_end_of_file_cleanup): New.
	(override_options):  Save base option settings.  Make it reflect new
	interpretation of -mhard-float and -msoft-float as affecting ABI
	settings.  Warn about lack of PIC support.  Call mips_set_mips16_mode
	instead of doing initialization inline.
	(mips_start_file): Move mips16 mode setting output from here....
	(mips_output_function_prologue): ....to here.
	(mips_output_mi_thunk): Check for mips16 function.
	(mips_select_rtx_section): Don't try to put constant data in the same
	section as the function if it's invoked without a function.
	(mips16_fn_stubs): New.
	(mips16_call_stubs): Renamed from mips16_stubs.
	(build_mips16_function_stub): Make fn_decl and fp_code arguments.
	Use assembler name for stub, if there is one.  Cache stubs and
	check if we've already emitted one before.
	(mips_expand_builtin): Error in mips16 mode.
	(mips_encode_section_info): Check for mips16/nomips16 attributes,
	and/or flip mode if -mflip-mips16 was given.  Set SYMBOL_REF_FLAGS
	accordingly.

	* doc/extend.texi (Function Attributes): Document new
	mips16/nomips16 attributes.
	* doc/invoke.texi (Option Summary): Add -mflip-mips16.
	(MIPS Options): Document -mflip-mips16.

	* testsuite/gcc.target/mips/mips16-attributes.c: New.
	* testsuite/gcc.c-torture/compile/mipscop-1.c: Use nomips16
	attribute instead of using #ifndef to disable test for mips16.
	* testsuite/gcc.c-torture/compile/mipscop-2.c: Likewise.
	* testsuite/gcc.c-torture/compile/mipscop-3.c: Likewise.
	* testsuite/gcc.c-torture/compile/mipscop-4.c: Likewise.
	* testsuite/gcc.dg/torture/mips-hilo-1.c: Likewise.
	* testsuite/gcc.dg/torture/mips-hilo-2.c: Likewise.
	* testsuite/gcc.dg/torture/pr19683-1.c: Likewise.
	


Index: gcc/config/mips/mips.opt
===================================================================
*** gcc/config/mips/mips.opt	(revision 127016)
--- gcc/config/mips/mips.opt	(working copy)
*************** mbranch-likely
*** 43,48 ****
--- 43,52 ----
  Target Report Mask(BRANCHLIKELY)
  Use Branch Likely instructions, overriding the architecture default
  
+ mflip-mips16
+ Target Report Var(TARGET_FLIP_MIPS16)
+ Switch on/off mips16 ASE on alternating functions for compiler testing
+ 
  mcheck-zero-division
  Target Report Mask(CHECK_ZERO_DIV)
  Trap on integer divide by zero
*************** Target Report RejectNegative Mask(64BIT)
*** 146,153 ****
  Use 64-bit general registers
  
  mhard-float
! Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
! Allow the use of hardware floating-point instructions
  
  mips
  Target RejectNegative Joined
--- 150,157 ----
  Use 64-bit general registers
  
  mhard-float
! Target Report RejectNegative InverseMask(SOFT_FLOAT_ABI, HARD_FLOAT_ABI)
! Allow the use of hardware floating-point ABI and instructions
  
  mips
  Target RejectNegative Joined
*************** Target Report RejectNegative Mask(SMARTM
*** 218,224 ****
  Use SmartMIPS instructions
  
  msoft-float
! Target Report RejectNegative Mask(SOFT_FLOAT)
  Prevent the use of all hardware floating-point instructions
  
  msplit-addresses
--- 222,228 ----
  Use SmartMIPS instructions
  
  msoft-float
! Target Report RejectNegative Mask(SOFT_FLOAT_ABI)
  Prevent the use of all hardware floating-point instructions
  
  msplit-addresses
Index: gcc/config/mips/mips.h
===================================================================
*** gcc/config/mips/mips.h	(revision 127016)
--- gcc/config/mips/mips.h	(working copy)
*************** extern enum processor_type mips_arch;   
*** 134,140 ****
  extern enum processor_type mips_tune;   /* which cpu to schedule for */
  extern int mips_isa;			/* architectural level */
  extern int mips_abi;			/* which ABI to use */
- extern int mips16_hard_float;		/* mips16 without -msoft-float */
  extern const struct mips_cpu_info mips_cpu_info_table[];
  extern const struct mips_cpu_info *mips_arch_info;
  extern const struct mips_cpu_info *mips_tune_info;
--- 134,139 ----
*************** extern const struct mips_rtx_cost_data *
*** 299,308 ****
  #define TARGET_OLDABI		    (mips_abi == ABI_32 || mips_abi == ABI_O64)
  #define TARGET_NEWABI		    (mips_abi == ABI_N32 || mips_abi == ABI_64)
  
! /* Similar to TARGET_HARD_FLOAT and TARGET_SOFT_FLOAT, but reflect the ABI
!    in use rather than whether the FPU is directly accessible.  */
! #define TARGET_HARD_FLOAT_ABI (TARGET_HARD_FLOAT || mips16_hard_float)
! #define TARGET_SOFT_FLOAT_ABI (!TARGET_HARD_FLOAT_ABI)
  
  /* IRIX specific stuff.  */
  #define TARGET_IRIX	   0
--- 298,309 ----
  #define TARGET_OLDABI		    (mips_abi == ABI_32 || mips_abi == ABI_O64)
  #define TARGET_NEWABI		    (mips_abi == ABI_N32 || mips_abi == ABI_64)
  
! /* TARGET_HARD_FLOAT and TARGET_SOFT_FLOAT reflect whether the FPU is
!    directly accessible, while the command-line options select
!    TARGET_HARD_FLOAT_ABI and TARGET_SOFT_FLOAT_ABI to reflect the ABI
!    in use.  */
! #define TARGET_HARD_FLOAT (TARGET_HARD_FLOAT_ABI && !TARGET_MIPS16)
! #define TARGET_SOFT_FLOAT (TARGET_SOFT_FLOAT_ABI || TARGET_MIPS16)
  
  /* IRIX specific stuff.  */
  #define TARGET_IRIX	   0
*************** typedef struct mips_args {
*** 2234,2239 ****
--- 2235,2245 ----
  #define SYMBOL_REF_LONG_CALL_P(X)					\
    ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_LONG_CALL) != 0)
  
+ /* Flag to mark a function decl symbol a "mips16" function.  */
+ #define SYMBOL_FLAG_MIPS16_FUNC	(SYMBOL_FLAG_MACH_DEP << 1)
+ #define SYMBOL_REF_MIPS16_FUNC_P(RTX) \
+   ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_MIPS16_FUNC) != 0)
+ 
  /* Specify the machine mode that this machine uses
     for the index in the tablejump instruction.
     ??? Using HImode in mips16 mode can cause overflow.  */
Index: gcc/config/mips/mips.c
===================================================================
*** gcc/config/mips/mips.c	(revision 127016)
--- gcc/config/mips/mips.c	(working copy)
*************** static rtx mips_return_fpr_pair (enum ma
*** 356,362 ****
  				 enum machine_mode mode2, HOST_WIDE_INT);
  static rtx mips16_gp_pseudo_reg (void);
  static void mips16_fp_args (FILE *, int, int);
! static void build_mips16_function_stub (FILE *);
  static rtx dump_constants_1 (enum machine_mode, rtx, rtx);
  static void dump_constants (struct mips16_constant *, rtx);
  static int mips16_insn_length (rtx);
--- 356,362 ----
  				 enum machine_mode mode2, HOST_WIDE_INT);
  static rtx mips16_gp_pseudo_reg (void);
  static void mips16_fp_args (FILE *, int, int);
! static void build_mips16_function_stub (FILE *, tree, int);
  static rtx dump_constants_1 (enum machine_mode, rtx, rtx);
  static void dump_constants (struct mips16_constant *, rtx);
  static int mips16_insn_length (rtx);
*************** static rtx mips_expand_builtin_bposge (e
*** 426,431 ****
--- 426,434 ----
  static void mips_encode_section_info (tree, rtx, int);
  static void mips_extra_live_on_entry (bitmap);
  static int mips_comp_type_attributes (tree, tree);
+ static void mips_set_mips16_mode (int);
+ static void mips_prepare_function_start (tree);
+ static void mips_end_of_file_cleanup (void);
  static int mips_mode_rep_extended (enum machine_mode, enum machine_mode);
  static bool mips_offset_within_alignment_p (rtx, HOST_WIDE_INT);
  static void mips_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
*************** int mips_abi = MIPS_ABI_DEFAULT;
*** 619,635 ****
  /* Cost information to use.  */
  const struct mips_rtx_cost_data *mips_cost;
  
! /* Whether we are generating mips16 hard float code.  In mips16 mode
!    we always set TARGET_SOFT_FLOAT; this variable is nonzero if
!    -msoft-float was not specified by the user, which means that we
!    should arrange to call mips32 hard floating point code.  */
! int mips16_hard_float;
  
  /* The architecture selected by -mipsN.  */
  static const struct mips_cpu_info *mips_isa_info;
  
  /* If TRUE, we split addresses into their high and low parts in the RTL.  */
  int mips_split_addresses;
  
  /* Mode used for saving/restoring general purpose registers.  */
  static enum machine_mode gpr_mode;
--- 622,644 ----
  /* Cost information to use.  */
  const struct mips_rtx_cost_data *mips_cost;
  
! /* Remember the ambient target flags, excluding mips16.  */
! static GTY(()) int mips_base_target_flags;
! /* The mips16 command-line target flags only.  */
! static GTY(()) int mips_base_mips16;
! /* Similar copies of option settings.  */
! static int mips_base_schedule_insns; /* flag_schedule_insns */
! static int mips_base_align_loops; /* align_loops */
! static int mips_base_align_jumps; /* align_jumps */
! static int mips_base_align_functions; /* align_functions */
! static GTY(()) int mips16_flipper;
  
  /* The architecture selected by -mipsN.  */
  static const struct mips_cpu_info *mips_isa_info;
  
  /* If TRUE, we split addresses into their high and low parts in the RTL.  */
  int mips_split_addresses;
+ int mips_base_split_addresses;
  
  /* Mode used for saving/restoring general purpose registers.  */
  static enum machine_mode gpr_mode;
*************** const struct attribute_spec mips_attribu
*** 720,725 ****
--- 729,737 ----
    { "long_call",   0, 0, false, true,  true,  NULL },
    { "far",     	   0, 0, false, true,  true,  NULL },
    { "near",        0, 0, false, true,  true,  NULL },
+   /* Switch MIPS16 ASE on and off per-function.  */
+   { "mips16", 	   0, 0, false, true,  true,  NULL },
+   { "nomips16",    0, 0, false, true,  true,  NULL },
    { NULL,	   0, 0, false, false, false, NULL }
  };
  
*************** static const unsigned char mips16e_save_
*** 1203,1209 ****
    31, 30, 23, 22, 21, 20, 19, 18, 17, 16, 7, 6, 5, 4
  };
  
! /* Nonzero if -march should decide the default value of MASK_SOFT_FLOAT.  */
  #ifndef MIPS_MARCH_CONTROLS_SOFT_FLOAT
  #define MIPS_MARCH_CONTROLS_SOFT_FLOAT 0
  #endif
--- 1215,1222 ----
    31, 30, 23, 22, 21, 20, 19, 18, 17, 16, 7, 6, 5, 4
  };
  
! /* Nonzero if -march should decide the default value of
!    MASK_SOFT_FLOAT_ABI.  */
  #ifndef MIPS_MARCH_CONTROLS_SOFT_FLOAT
  #define MIPS_MARCH_CONTROLS_SOFT_FLOAT 0
  #endif
*************** static const unsigned char mips16e_save_
*** 1251,1256 ****
--- 1264,1275 ----
  #undef TARGET_FUNCTION_OK_FOR_SIBCALL
  #define TARGET_FUNCTION_OK_FOR_SIBCALL mips_function_ok_for_sibcall
  
+ #undef TARGET_PREPARE_FUNCTION_START
+ #define TARGET_PREPARE_FUNCTION_START mips_prepare_function_start
+ 
+ #undef TARGET_END_OF_FILE_CLEANUP
+ #define TARGET_END_OF_FILE_CLEANUP mips_end_of_file_cleanup
+ 
  #undef TARGET_VALID_POINTER_MODE
  #define TARGET_VALID_POINTER_MODE mips_valid_pointer_mode
  #undef TARGET_RTX_COSTS
*************** mips_far_type_p (tree type)
*** 1369,1374 ****
--- 1388,1406 ----
  	  || lookup_attribute ("far", TYPE_ATTRIBUTES (type)) != NULL);
  }
  
+ /* Similar predicates for "mips16"/"nomips16" attributes.  */
+ 
+ static bool
+ mips_mips16_type_p (tree type)
+ {
+   return lookup_attribute ("mips16", TYPE_ATTRIBUTES (type)) != NULL;
+ }
+ 
+ static bool
+ mips_nomips16_type_p (tree type)
+ {
+   return lookup_attribute ("nomips16", TYPE_ATTRIBUTES (type)) != NULL;
+ }
  
  /* Return 0 if the attributes for two types are incompatible, 1 if they
     are compatible, and 2 if they are nearly compatible (which causes a
*************** mips_comp_type_attributes (tree type1, t
*** 1387,1392 ****
--- 1419,1429 ----
    if (mips_near_type_p (type1) && mips_far_type_p (type2))
      return 0;
  
+   /* Mips16/nomips16 attributes must match exactly.  */
+   if (mips_nomips16_type_p (type1) != mips_nomips16_type_p (type2)
+       || mips_mips16_type_p (type1) != mips_mips16_type_p (type2))
+     return 0;
+ 
    return 1;
  }
  
*************** mips_cannot_force_const_mem (rtx x)
*** 1813,1819 ****
  	return true;
      }
  
!   if (TARGET_HAVE_TLS && for_each_rtx (&x, &mips_tls_symbol_ref_1, 0))
      return true;
  
    return false;
--- 1850,1856 ----
  	return true;
      }
  
!   if (targetm.have_tls && for_each_rtx (&x, &mips_tls_symbol_ref_1, 0))
      return true;
  
    return false;
*************** mips_expand_call (rtx result, rtx addr, 
*** 3671,3681 ****
        mips_load_call_address (addr, orig_addr, sibcall_p);
      }
  
!   if (mips16_hard_float
        && build_mips16_call_stub (result, addr, args_size,
  				 aux == 0 ? 0 : (int) GET_MODE (aux)))
      return;
  
    if (result == 0)
      pattern = (sibcall_p
  	       ? gen_sibcall_internal (addr, args_size)
--- 3708,3733 ----
        mips_load_call_address (addr, orig_addr, sibcall_p);
      }
  
!   if (TARGET_MIPS16
!       && TARGET_HARD_FLOAT_ABI
        && build_mips16_call_stub (result, addr, args_size,
  				 aux == 0 ? 0 : (int) GET_MODE (aux)))
      return;
  
+   /* If we are generating non-mips16 code for this function and we pass
+      -mips16 on the command line, we need to generate a fn_stub for any 
+      built-in functions that we call.  */
+   if (!TARGET_MIPS16
+       && mips_base_mips16
+       && TARGET_HARD_FLOAT_ABI
+       && GET_CODE (addr) == SYMBOL_REF
+       && SYMBOL_REF_DECL (addr)
+       && TREE_TYPE (SYMBOL_REF_DECL (addr))
+       && TREE_TYPE (SYMBOL_REF_DECL (addr)) != error_mark_node
+       && DECL_BUILT_IN (SYMBOL_REF_DECL (addr)))
+     build_mips16_function_stub (asm_out_file, SYMBOL_REF_DECL (addr),
+ 				aux == 0 ? 0 : (int) GET_MODE (aux));
+ 
    if (result == 0)
      pattern = (sibcall_p
  	       ? gen_sibcall_internal (addr, args_size)
*************** mips_expand_call (rtx result, rtx addr, 
*** 3704,3716 ****
  }
  
  
! /* We can handle any sibcall when TARGET_SIBCALLS is true.  */
  
  static bool
! mips_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
  			      tree exp ATTRIBUTE_UNUSED)
  {
!   return TARGET_SIBCALLS;
  }
  
  /* Emit code to move general operand SRC into condition-code
--- 3756,3774 ----
  }
  
  
! /* We can handle any sibcall when TARGET_SIBCALLS is true except when
!    the called function is a MIPS16 function, since there is no direct
!    "jx" instruction equivalent to "jalx" to switch the ISA  mode.  */
  
  static bool
! mips_function_ok_for_sibcall (tree decl,
  			      tree exp ATTRIBUTE_UNUSED)
  {
!   if (!TARGET_SIBCALLS)
!     return 0;
!   if (decl && SYMBOL_REF_MIPS16_FUNC_P (XEXP (DECL_RTL (decl), 0)))
!     return 0;
!   return 1;
  }
  
  /* Emit code to move general operand SRC into condition-code
*************** function_arg (const CUMULATIVE_ARGS *cum
*** 4147,4153 ****
       stored as the mode.  */
    if (mode == VOIDmode)
      {
!       if (TARGET_MIPS16 && cum->fp_code != 0)
  	return gen_rtx_REG ((enum machine_mode) cum->fp_code, 0);
  
        else
--- 4205,4213 ----
       stored as the mode.  */
    if (mode == VOIDmode)
      {
!       if ((TARGET_MIPS16 
! 	   || (!TARGET_MIPS16 && mips_base_mips16 && TARGET_HARD_FLOAT_ABI))
! 	  && cum->fp_code != 0)
  	return gen_rtx_REG ((enum machine_mode) cum->fp_code, 0);
  
        else
*************** mips_set_tune (const struct mips_cpu_inf
*** 4953,4958 ****
--- 5013,5239 ----
      }
  }
  
+ /* (Re-)Initialize information about relocs.  */
+ 
+ static void
+ mips_init_relocs (void)
+ {
+   memset (mips_split_p, '\0', sizeof (mips_split_p));
+   memset (mips_hi_relocs, '\0', sizeof (mips_hi_relocs));
+   memset (mips_lo_relocs, '\0', sizeof (mips_lo_relocs));
+ 
+   if (ABI_HAS_64BIT_SYMBOLS)
+     {
+       if (TARGET_EXPLICIT_RELOCS)
+ 	{
+ 	  mips_split_p[SYMBOL_64_HIGH] = true;
+ 	  mips_hi_relocs[SYMBOL_64_HIGH] = "%highest(";
+ 	  mips_lo_relocs[SYMBOL_64_HIGH] = "%higher(";
+ 
+ 	  mips_split_p[SYMBOL_64_MID] = true;
+ 	  mips_hi_relocs[SYMBOL_64_MID] = "%higher(";
+ 	  mips_lo_relocs[SYMBOL_64_MID] = "%hi(";
+ 
+ 	  mips_split_p[SYMBOL_64_LOW] = true;
+ 	  mips_hi_relocs[SYMBOL_64_LOW] = "%hi(";
+ 	  mips_lo_relocs[SYMBOL_64_LOW] = "%lo(";
+ 
+ 	  mips_split_p[SYMBOL_GENERAL] = true;
+ 	  mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
+ 	}
+     }
+   else
+     {
+       if (TARGET_EXPLICIT_RELOCS || mips_split_addresses)
+ 	{
+ 	  mips_split_p[SYMBOL_GENERAL] = true;
+ 	  mips_hi_relocs[SYMBOL_GENERAL] = "%hi(";
+ 	  mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
+ 	}
+     }
+ 
+   if (TARGET_MIPS16)
+     {
+       /* The high part is provided by a pseudo copy of $gp.  */
+       mips_split_p[SYMBOL_SMALL_DATA] = true;
+       mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gprel(";
+     }
+ 
+   if (TARGET_EXPLICIT_RELOCS)
+     {
+       /* Small data constants are kept whole until after reload,
+ 	 then lowered by mips_rewrite_small_data.  */
+       mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gp_rel(";
+ 
+       mips_split_p[SYMBOL_GOT_PAGE_OFST] = true;
+       if (TARGET_NEWABI)
+ 	{
+ 	  mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got_page(";
+ 	  mips_lo_relocs[SYMBOL_GOT_PAGE_OFST] = "%got_ofst(";
+ 	}
+       else
+ 	{
+ 	  mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got(";
+ 	  mips_lo_relocs[SYMBOL_GOT_PAGE_OFST] = "%lo(";
+ 	}
+ 
+       if (TARGET_XGOT)
+ 	{
+ 	  /* The HIGH and LO_SUM are matched by special .md patterns.  */
+ 	  mips_split_p[SYMBOL_GOT_DISP] = true;
+ 
+ 	  mips_split_p[SYMBOL_GOTOFF_DISP] = true;
+ 	  mips_hi_relocs[SYMBOL_GOTOFF_DISP] = "%got_hi(";
+ 	  mips_lo_relocs[SYMBOL_GOTOFF_DISP] = "%got_lo(";
+ 
+ 	  mips_split_p[SYMBOL_GOTOFF_CALL] = true;
+ 	  mips_hi_relocs[SYMBOL_GOTOFF_CALL] = "%call_hi(";
+ 	  mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call_lo(";
+ 	}
+       else
+ 	{
+ 	  if (TARGET_NEWABI)
+ 	    mips_lo_relocs[SYMBOL_GOTOFF_DISP] = "%got_disp(";
+ 	  else
+ 	    mips_lo_relocs[SYMBOL_GOTOFF_DISP] = "%got(";
+ 	  mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call16(";
+ 	}
+     }
+ 
+   if (TARGET_NEWABI)
+     {
+       mips_split_p[SYMBOL_GOTOFF_LOADGP] = true;
+       mips_hi_relocs[SYMBOL_GOTOFF_LOADGP] = "%hi(%neg(%gp_rel(";
+       mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel(";
+     }
+ 
+   /* Thread-local relocation operators.  */
+   mips_lo_relocs[SYMBOL_TLSGD] = "%tlsgd(";
+   mips_lo_relocs[SYMBOL_TLSLDM] = "%tlsldm(";
+   mips_split_p[SYMBOL_DTPREL] = 1;
+   mips_hi_relocs[SYMBOL_DTPREL] = "%dtprel_hi(";
+   mips_lo_relocs[SYMBOL_DTPREL] = "%dtprel_lo(";
+   mips_lo_relocs[SYMBOL_GOTTPREL] = "%gottprel(";
+   mips_split_p[SYMBOL_TPREL] = 1;
+   mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi(";
+   mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo(";
+ 
+   mips_lo_relocs[SYMBOL_HALF] = "%half(";
+ }
+ 
+ static GTY(()) int was_mips16_p = -1;
+ 
+ /* Resets compiler middle end to match the instruction set mode selected for
+    the current function.  */
+ static void
+ mips_set_mips16_mode (int mips16_p)
+ {
+   static int first = 1;
+ 
+   if (mips16_p == was_mips16_p)
+     return;
+ 
+   target_flags = mips_base_target_flags;
+   if (mips16_p) 
+     {
+ 
+       /* MIPS16 mode is incompatible with TARGET_DSP.  */
+       if (TARGET_DSP)
+ 	error ("MIPS16 mode cannot be used with -mdsp");
+ 
+       /* Select mips16 instruction set.  */
+       target_flags |= MASK_MIPS16 | mips_base_mips16;
+ 
+       /* Don't run the scheduler before reload, since it tends to
+          increase register pressure.  */
+       flag_schedule_insns = 0;
+ 
+       /* Silently disable -mexplicit-relocs since it doesn't apply
+ 	 to mips16 code.  Even so, it would overly pedantic to warn
+ 	 about "-mips16 -mexplicit-relocs", especially given that
+ 	 we use a %gprel() operator.  */
+       target_flags &= ~MASK_EXPLICIT_RELOCS;
+       mips_split_addresses = 0;
+ 
+       /* Use default default delayed_branch option.  */
+       flag_delayed_branch = mips_flag_delayed_branch;
+ 
+       /* Force no alignment of mips16 code.  */
+       /* XXX would 32-bit alignment be an acceptable compromise?  */
+       align_loops = align_jumps = align_functions = 1;
+ 
+       /* We don't have a thread pointer access instruction on MIPS16, or
+ 	 appropriate TLS relocations.  */
+       targetm.have_tls = false;
+ 
+     }
+   else 
+     {
+       /* Reset to select base non-mips16 ISA.  */
+       target_flags &= ~(MASK_MIPS16);
+ 
+       /* When using explicit relocs, we call dbr_schedule from within
+ 	 mips_reorg.  */
+       if (TARGET_EXPLICIT_RELOCS)
+ 	flag_delayed_branch = 0;
+       else 
+ 	flag_delayed_branch = mips_flag_delayed_branch;
+ 
+       /* Reset other flags overridden in mips16 mode.  */
+       mips_split_addresses = mips_base_split_addresses;
+       flag_schedule_insns = mips_base_schedule_insns;
+       if (mips_base_align_loops > 0)
+ 	align_loops = mips_base_align_loops;
+       if (mips_base_align_jumps > 0)
+ 	align_jumps = mips_base_align_jumps;
+       if (mips_base_align_functions > 0)
+ 	align_functions = mips_base_align_functions;
+ 
+       /* TLS is only supported for per-file nomips16 processing, not
+ 	 per-function, so we can correctly generate the initialization
+ 	 code for TLS variables. */
+       targetm.have_tls = TARGET_HAVE_TLS && !mips_base_mips16;
+     }
+ 
+   /* (Re)initialise mips target internals for new ISA.  */
+   mips_init_relocs ();
+ 
+   if (!first)
+     /* Reinitialize target-dependent state.  */
+     target_reinit ();
+ 
+   first = 0;
+   was_mips16_p = !!TARGET_MIPS16;
+ }
+ 
+ /* Called just before starting to generate RTL for a function, and picks the
+    appropriate 16 or 32-bit mode, as selected by the "mips16" or "nomips16"
+    function attributes.  */
+ static void
+ mips_prepare_function_start (tree fndecl)
+ {
+   tree x;
+ 
+   if (!fndecl)
+     return;
+ 
+   /* Get the DECL of the top-most enclosing function.  */
+   /* XXX do we still need to do this? */
+   while ((x = decl_function_context (fndecl)))
+     fndecl = x;
+ 
+   mips_set_mips16_mode (SYMBOL_REF_MIPS16_FUNC_P (XEXP (DECL_RTL (fndecl), 0)));
+ }
+ 
+ /* Called after finishing generating RTL for all functions in the file, and
+    before emitting deferred declarations and data; reset MIPS16 mode.
+ */
+ static void
+ mips_end_of_file_cleanup (void)
+ {
+   mips_set_mips16_mode (mips_base_mips16 != 0);
+ }
+ 
  /* Implement TARGET_HANDLE_OPTION.  */
  
  static bool
*************** override_options (void)
*** 5001,5006 ****
--- 5282,5292 ----
    int i, start, regno;
    enum machine_mode mode;
  
+   /* Save the command-line MIPS16 setting, then disable.  It will be
+      set again on a per-function basis by mips_set_mips16_mode().  */
+   mips_base_mips16 = target_flags & MASK_MIPS16;
+   target_flags ^= mips_base_mips16;
+ 
  #ifdef SUBTARGET_OVERRIDE_OPTIONS
    SUBTARGET_OVERRIDE_OPTIONS;
  #endif
*************** override_options (void)
*** 5112,5132 ****
      }
  
    if (MIPS_MARCH_CONTROLS_SOFT_FLOAT
!       && (target_flags_explicit & MASK_SOFT_FLOAT) == 0)
      {
        /* For some configurations, it is useful to have -march control
! 	 the default setting of MASK_SOFT_FLOAT.  */
        switch ((int) mips_arch)
  	{
  	case PROCESSOR_R4100:
  	case PROCESSOR_R4111:
  	case PROCESSOR_R4120:
  	case PROCESSOR_R4130:
! 	  target_flags |= MASK_SOFT_FLOAT;
  	  break;
  
  	default:
! 	  target_flags &= ~MASK_SOFT_FLOAT;
  	  break;
  	}
      }
--- 5398,5418 ----
      }
  
    if (MIPS_MARCH_CONTROLS_SOFT_FLOAT
!       && (target_flags_explicit & MASK_SOFT_FLOAT_ABI) == 0)
      {
        /* For some configurations, it is useful to have -march control
! 	 the default setting of MASK_SOFT_FLOAT_ABI.  */
        switch ((int) mips_arch)
  	{
  	case PROCESSOR_R4100:
  	case PROCESSOR_R4111:
  	case PROCESSOR_R4120:
  	case PROCESSOR_R4130:
! 	  target_flags |= MASK_SOFT_FLOAT_ABI;
  	  break;
  
  	default:
! 	  target_flags &= ~MASK_SOFT_FLOAT_ABI;
  	  break;
  	}
      }
*************** override_options (void)
*** 5169,5174 ****
--- 5455,5471 ----
        target_flags &= ~MASK_ABICALLS;
      }
  
+   /* MIPS16 cannot generate PIC yet.  */
+   if (mips_base_mips16 && (flag_pic || TARGET_ABICALLS))
+     {
+       warning (0, "%s is not supported with -mips16, ignored",
+  	       (flag_pic > 1 ? "-fPIC" : 
+  		flag_pic ? "-fpic" :
+  		"-mabicalls"));
+       target_flags &= ~MASK_ABICALLS;
+       flag_pic = flag_pie = flag_shlib = 0;
+     }
+ 
    if (TARGET_ABICALLS)
      {
        /* We need to set flag_pic for executables as well as DSOs
*************** override_options (void)
*** 5209,5246 ****
    if (optimize > 2 && (target_flags_explicit & MASK_VR4130_ALIGN) == 0)
      target_flags |= MASK_VR4130_ALIGN;
  
-   /* When compiling for the mips16, we cannot use floating point.  We
-      record the original hard float value in mips16_hard_float.  */
-   if (TARGET_MIPS16)
-     {
-       if (TARGET_SOFT_FLOAT)
- 	mips16_hard_float = 0;
-       else
- 	mips16_hard_float = 1;
-       target_flags |= MASK_SOFT_FLOAT;
- 
-       /* Don't run the scheduler before reload, since it tends to
-          increase register pressure.  */
-       flag_schedule_insns = 0;
- 
-       /* Don't do hot/cold partitioning.  The constant layout code expects
- 	 the whole function to be in a single section.  */
-       flag_reorder_blocks_and_partition = 0;
- 
-       /* Silently disable -mexplicit-relocs since it doesn't apply
- 	 to mips16 code.  Even so, it would overly pedantic to warn
- 	 about "-mips16 -mexplicit-relocs", especially given that
- 	 we use a %gprel() operator.  */
-       target_flags &= ~MASK_EXPLICIT_RELOCS;
-     }
- 
    /* When using explicit relocs, we call dbr_schedule from within
       mips_reorg.  */
    if (TARGET_EXPLICIT_RELOCS)
!     {
!       mips_flag_delayed_branch = flag_delayed_branch;
!       flag_delayed_branch = 0;
!     }
  
  #ifdef MIPS_TFMODE_FORMAT
    REAL_MODE_FORMAT (TFmode) = &MIPS_TFMODE_FORMAT;
--- 5506,5516 ----
    if (optimize > 2 && (target_flags_explicit & MASK_VR4130_ALIGN) == 0)
      target_flags |= MASK_VR4130_ALIGN;
  
    /* When using explicit relocs, we call dbr_schedule from within
       mips_reorg.  */
+   mips_flag_delayed_branch = flag_delayed_branch;
    if (TARGET_EXPLICIT_RELOCS)
!     flag_delayed_branch = 0;
  
  #ifdef MIPS_TFMODE_FORMAT
    REAL_MODE_FORMAT (TFmode) = &MIPS_TFMODE_FORMAT;
*************** override_options (void)
*** 5270,5278 ****
    if (TARGET_DSPR2)
      target_flags |= MASK_DSP;
  
-   if (TARGET_MIPS16 && TARGET_DSP)
-     error ("-mips16 and -mdsp cannot be used together");
- 
    mips_print_operand_punct['?'] = 1;
    mips_print_operand_punct['#'] = 1;
    mips_print_operand_punct['/'] = 1;
--- 5540,5545 ----
*************** override_options (void)
*** 5366,5383 ****
  			 && size <= UNITS_PER_FPREG))
  		    && (((class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT
  			  || class == MODE_VECTOR_FLOAT)
! 			 && size <= UNITS_PER_FPVALUE)
! 			/* Allow integer modes that fit into a single
! 			   register.  We need to put integers into FPRs
! 			   when using instructions like cvt and trunc.
! 			   We can't allow sizes smaller than a word,
! 			   the FPU has no appropriate load/store
! 			   instructions for those.  */
! 			|| (class == MODE_INT
! 			    && size >= MIN_UNITS_PER_WORD
! 			    && size <= UNITS_PER_FPREG)
! 			/* Allow TFmode for CCmode reloads.  */
! 			|| (ISA_HAS_8CC && mode == TFmode)));
  
            else if (ACC_REG_P (regno))
  	    temp = (INTEGRAL_MODE_P (mode)
--- 5633,5650 ----
  			 && size <= UNITS_PER_FPREG))
  		    && (((class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT
  			  || class == MODE_VECTOR_FLOAT)
! 			 && size <= UNITS_PER_FPVALUE))
! 		  /* Allow integer modes that fit into a single
! 		     register.  We need to put integers into FPRs
! 		     when using instructions like cvt and trunc.
! 		     We can't allow sizes smaller than a word,
! 		     the FPU has no appropriate load/store
! 		     instructions for those.  */
! 		  || (class == MODE_INT
! 		      && size >= MIN_UNITS_PER_WORD
! 		      && size <= UNITS_PER_FPREG)
! 		  /* Allow TFmode for CCmode reloads.  */
! 		    || (ISA_HAS_8CC && mode == TFmode));
  
            else if (ACC_REG_P (regno))
  	    temp = (INTEGRAL_MODE_P (mode)
*************** override_options (void)
*** 5401,5407 ****
    gpr_mode = TARGET_64BIT ? DImode : SImode;
  
    /* Provide default values for align_* for 64-bit targets.  */
!   if (TARGET_64BIT && !TARGET_MIPS16)
      {
        if (align_loops == 0)
  	align_loops = 8;
--- 5668,5674 ----
    gpr_mode = TARGET_64BIT ? DImode : SImode;
  
    /* Provide default values for align_* for 64-bit targets.  */
!   if (TARGET_64BIT)
      {
        if (align_loops == 0)
  	align_loops = 8;
*************** override_options (void)
*** 5414,5522 ****
    /* Function to allocate machine-dependent function status.  */
    init_machine_status = &mips_init_machine_status;
  
-   if (ABI_HAS_64BIT_SYMBOLS)
-     {
-       if (TARGET_EXPLICIT_RELOCS)
- 	{
- 	  mips_split_p[SYMBOL_64_HIGH] = true;
- 	  mips_hi_relocs[SYMBOL_64_HIGH] = "%highest(";
- 	  mips_lo_relocs[SYMBOL_64_HIGH] = "%higher(";
- 
- 	  mips_split_p[SYMBOL_64_MID] = true;
- 	  mips_hi_relocs[SYMBOL_64_MID] = "%higher(";
- 	  mips_lo_relocs[SYMBOL_64_MID] = "%hi(";
- 
- 	  mips_split_p[SYMBOL_64_LOW] = true;
- 	  mips_hi_relocs[SYMBOL_64_LOW] = "%hi(";
- 	  mips_lo_relocs[SYMBOL_64_LOW] = "%lo(";
- 
- 	  mips_split_p[SYMBOL_GENERAL] = true;
- 	  mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
- 	}
-     }
-   else
-     {
-       if (TARGET_EXPLICIT_RELOCS || mips_split_addresses)
- 	{
- 	  mips_split_p[SYMBOL_GENERAL] = true;
- 	  mips_hi_relocs[SYMBOL_GENERAL] = "%hi(";
- 	  mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
- 	}
-     }
- 
-   if (TARGET_MIPS16)
-     {
-       /* The high part is provided by a pseudo copy of $gp.  */
-       mips_split_p[SYMBOL_SMALL_DATA] = true;
-       mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gprel(";
-     }
- 
-   if (TARGET_EXPLICIT_RELOCS)
-     {
-       /* Small data constants are kept whole until after reload,
- 	 then lowered by mips_rewrite_small_data.  */
-       mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gp_rel(";
- 
-       mips_split_p[SYMBOL_GOT_PAGE_OFST] = true;
-       if (TARGET_NEWABI)
- 	{
- 	  mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got_page(";
- 	  mips_lo_relocs[SYMBOL_GOT_PAGE_OFST] = "%got_ofst(";
- 	}
-       else
- 	{
- 	  mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got(";
- 	  mips_lo_relocs[SYMBOL_GOT_PAGE_OFST] = "%lo(";
- 	}
- 
-       if (TARGET_XGOT)
- 	{
- 	  /* The HIGH and LO_SUM are matched by special .md patterns.  */
- 	  mips_split_p[SYMBOL_GOT_DISP] = true;
- 
- 	  mips_split_p[SYMBOL_GOTOFF_DISP] = true;
- 	  mips_hi_relocs[SYMBOL_GOTOFF_DISP] = "%got_hi(";
- 	  mips_lo_relocs[SYMBOL_GOTOFF_DISP] = "%got_lo(";
- 
- 	  mips_split_p[SYMBOL_GOTOFF_CALL] = true;
- 	  mips_hi_relocs[SYMBOL_GOTOFF_CALL] = "%call_hi(";
- 	  mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call_lo(";
- 	}
-       else
- 	{
- 	  if (TARGET_NEWABI)
- 	    mips_lo_relocs[SYMBOL_GOTOFF_DISP] = "%got_disp(";
- 	  else
- 	    mips_lo_relocs[SYMBOL_GOTOFF_DISP] = "%got(";
- 	  mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call16(";
- 	}
-     }
- 
-   if (TARGET_NEWABI)
-     {
-       mips_split_p[SYMBOL_GOTOFF_LOADGP] = true;
-       mips_hi_relocs[SYMBOL_GOTOFF_LOADGP] = "%hi(%neg(%gp_rel(";
-       mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel(";
-     }
- 
-   /* Thread-local relocation operators.  */
-   mips_lo_relocs[SYMBOL_TLSGD] = "%tlsgd(";
-   mips_lo_relocs[SYMBOL_TLSLDM] = "%tlsldm(";
-   mips_split_p[SYMBOL_DTPREL] = 1;
-   mips_hi_relocs[SYMBOL_DTPREL] = "%dtprel_hi(";
-   mips_lo_relocs[SYMBOL_DTPREL] = "%dtprel_lo(";
-   mips_lo_relocs[SYMBOL_GOTTPREL] = "%gottprel(";
-   mips_split_p[SYMBOL_TPREL] = 1;
-   mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi(";
-   mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo(";
- 
-   mips_lo_relocs[SYMBOL_HALF] = "%half(";
- 
-   /* We don't have a thread pointer access instruction on MIPS16, or
-      appropriate TLS relocations.  */
-   if (TARGET_MIPS16)
-     targetm.have_tls = false;
- 
    /* Default to working around R4000 errata only if the processor
       was selected explicitly.  */
    if ((target_flags_explicit & MASK_FIX_R4000) == 0
--- 5681,5686 ----
*************** override_options (void)
*** 5528,5533 ****
--- 5692,5708 ----
    if ((target_flags_explicit & MASK_FIX_R4400) == 0
        && mips_matching_cpu_name_p (mips_arch_info->name, "r4400"))
      target_flags |= MASK_FIX_R4400;
+ 
+   /* Save base state of options for 32-bit ISA.  */
+   mips_base_target_flags = target_flags;
+   mips_base_split_addresses = mips_split_addresses;
+   mips_base_schedule_insns = flag_schedule_insns;
+   mips_base_align_loops = align_loops;
+   mips_base_align_jumps = align_jumps;
+   mips_base_align_functions = align_functions;
+ 
+   /* Now select the mips16 or 32-bit instruction set, as requested.  */
+   mips_set_mips16_mode (mips_base_mips16 != 0);
  }
  
  /* Swap the register information for registers I and I + 1, which
*************** mips_file_start (void)
*** 6272,6280 ****
    if (TARGET_ABICALLS)
      fprintf (asm_out_file, "\t.abicalls\n");
  
-   if (TARGET_MIPS16)
-     fprintf (asm_out_file, "\t.set\tmips16\n");
- 
    if (flag_verbose_asm)
      fprintf (asm_out_file, "\n%s -G value = %d, Arch = %s, ISA = %d\n",
  	     ASM_COMMENT_START,
--- 6447,6452 ----
*************** static bool
*** 6614,6620 ****
  mips16_cfun_returns_in_fpr_p (void)
  {
    tree return_type = DECL_RESULT (current_function_decl);
!   return (mips16_hard_float
  	  && !aggregate_value_p (return_type, current_function_decl)
   	  && mips_return_mode_in_fpr_p (DECL_MODE (return_type)));
  }
--- 6786,6793 ----
  mips16_cfun_returns_in_fpr_p (void)
  {
    tree return_type = DECL_RESULT (current_function_decl);
!   return (TARGET_MIPS16
! 	  && TARGET_HARD_FLOAT_ABI
  	  && !aggregate_value_p (return_type, current_function_decl)
   	  && mips_return_mode_in_fpr_p (DECL_MODE (return_type)));
  }
*************** mips_output_function_prologue (FILE *fil
*** 7102,7110 ****
       floating point arguments.  The linker will arrange for any 32-bit
       functions to call this stub, which will then jump to the 16-bit
       function proper.  */
!   if (mips16_hard_float
        && current_function_args_info.fp_code != 0)
!     build_mips16_function_stub (file);
  
    if (!FUNCTION_NAME_ALREADY_DECLARED)
      {
--- 7275,7291 ----
       floating point arguments.  The linker will arrange for any 32-bit
       functions to call this stub, which will then jump to the 16-bit
       function proper.  */
!   if (TARGET_MIPS16
!       && TARGET_HARD_FLOAT_ABI
        && current_function_args_info.fp_code != 0)
!     build_mips16_function_stub (file, current_function_decl,
! 				current_function_args_info.fp_code);
! 
!   /* Select the mips16 mode for this function.  */
!   if (TARGET_MIPS16)
!     fprintf (file, "\t.set\tmips16\n");
!   else 
!     fprintf (file, "\t.set\tnomips16\n");
  
    if (!FUNCTION_NAME_ALREADY_DECLARED)
      {
*************** mips_output_mi_thunk (FILE *file, tree t
*** 8113,8119 ****
    /* Jump to the target function.  Use a sibcall if direct jumps are
       allowed, otherwise load the address into a register first.  */
    fnaddr = XEXP (DECL_RTL (function), 0);
!   if (TARGET_MIPS16 || TARGET_USE_GOT || SYMBOL_REF_LONG_CALL_P (fnaddr))
      {
        /* This is messy.  gas treats "la $25,foo" as part of a call
  	 sequence and may allow a global "foo" to be lazily bound.
--- 8294,8301 ----
    /* Jump to the target function.  Use a sibcall if direct jumps are
       allowed, otherwise load the address into a register first.  */
    fnaddr = XEXP (DECL_RTL (function), 0);
!   if (TARGET_MIPS16 || TARGET_USE_GOT || SYMBOL_REF_LONG_CALL_P (fnaddr)
!       || SYMBOL_REF_MIPS16_FUNC_P (fnaddr))
      {
        /* This is messy.  gas treats "la $25,foo" as part of a call
  	 sequence and may allow a global "foo" to be lazily bound.
*************** static section *
*** 8188,8194 ****
  mips_select_rtx_section (enum machine_mode mode, rtx x,
  			 unsigned HOST_WIDE_INT align)
  {
!   if (TARGET_MIPS16)
      {
        /* In mips16 mode, the constant table always goes in the same section
           as the function, so that constants can be loaded using PC relative
--- 8370,8376 ----
  mips_select_rtx_section (enum machine_mode mode, rtx x,
  			 unsigned HOST_WIDE_INT align)
  {
!   if (TARGET_MIPS16 && current_function_decl)
      {
        /* In mips16 mode, the constant table always goes in the same section
           as the function, so that constants can be loaded using PC relative
*************** mips16_fp_args (FILE *file, int fp_code,
*** 8877,8910 ****
      }
  }
  
  /* Build a mips16 function stub.  This is used for functions which
     take arguments in the floating point registers.  It is 32-bit code
     that moves the floating point args into the general registers, and
     then jumps to the 16-bit code.  */
  
  static void
! build_mips16_function_stub (FILE *file)
  {
    const char *fnname;
    char *secname, *stubname;
    tree stubid, stubdecl;
    int need_comma;
    unsigned int f;
  
!   fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
    secname = (char *) alloca (strlen (fnname) + 20);
    sprintf (secname, ".mips16.fn.%s", fnname);
    stubname = (char *) alloca (strlen (fnname) + 20);
    sprintf (stubname, "__fn_stub_%s", fnname);
    stubid = get_identifier (stubname);
    stubdecl = build_decl (FUNCTION_DECL, stubid,
  			 build_function_type (void_type_node, NULL_TREE));
    DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
    DECL_RESULT (stubdecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
  
!   fprintf (file, "\t# Stub function for %s (", current_function_name ());
    need_comma = 0;
!   for (f = (unsigned int) current_function_args_info.fp_code; f != 0; f >>= 2)
      {
        fprintf (file, "%s%s",
  	       need_comma ? ", " : "",
--- 9059,9128 ----
      }
  }
  
+ 
+ /* We keep 2 list of functions for which we have already built fn_stubs
+    and call_stubs.  */
+ 
+ struct mips16_stub
+ {
+   struct mips16_stub *next;
+   char *name;
+   int fpret;
+ };
+ 
+ static struct mips16_stub *mips16_fn_stubs;
+ static struct mips16_stub *mips16_call_stubs;
+ 
  /* Build a mips16 function stub.  This is used for functions which
     take arguments in the floating point registers.  It is 32-bit code
     that moves the floating point args into the general registers, and
     then jumps to the 16-bit code.  */
  
  static void
! build_mips16_function_stub (FILE *file, tree fn_decl, int fp_code)
  {
    const char *fnname;
    char *secname, *stubname;
    tree stubid, stubdecl;
    int need_comma;
    unsigned int f;
+   struct mips16_stub *l;
  
!   if (DECL_ASSEMBLER_NAME_SET_P (fn_decl))
!     {
!       fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn_decl));
!       /* Check for user assembler names.  */
!       if (fnname[0] == '*')
! 	{
! 	  fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fn_decl)) + 1;
! 	  /* Do we care about prefix such as -fleading-underscore?
! 	     If so, handle user_label_prefix.  */
! 	}
!     }
!   else
!     fnname = XSTR (XEXP (DECL_RTL (fn_decl), 0), 0);
    secname = (char *) alloca (strlen (fnname) + 20);
    sprintf (secname, ".mips16.fn.%s", fnname);
    stubname = (char *) alloca (strlen (fnname) + 20);
    sprintf (stubname, "__fn_stub_%s", fnname);
    stubid = get_identifier (stubname);
+ 
+   for (l = mips16_fn_stubs; l != NULL; l = l->next)
+     if (strcmp (l->name, fnname) == 0)
+       break;
+ 
+   if (l != NULL)
+     return;
+ 
    stubdecl = build_decl (FUNCTION_DECL, stubid,
  			 build_function_type (void_type_node, NULL_TREE));
    DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
    DECL_RESULT (stubdecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
  
!   fprintf (file, "\t# Stub function for %s (", 
! 	   lang_hooks.decl_printable_name (fn_decl, 2));
    need_comma = 0;
!   for (f = (unsigned int) fp_code; f != 0; f >>= 2)
      {
        fprintf (file, "%s%s",
  	       need_comma ? ", " : "",
*************** build_mips16_function_stub (FILE *file)
*** 8932,8938 ****
    /* We don't want the assembler to insert any nops here.  */
    fprintf (file, "\t.set\tnoreorder\n");
  
!   mips16_fp_args (file, current_function_args_info.fp_code, 1);
  
    fprintf (asm_out_file, "\t.set\tnoat\n");
    fprintf (asm_out_file, "\tla\t%s,", reg_names[GP_REG_FIRST + 1]);
--- 9150,9156 ----
    /* We don't want the assembler to insert any nops here.  */
    fprintf (file, "\t.set\tnoreorder\n");
  
!   mips16_fp_args (file, fp_code, 1);
  
    fprintf (asm_out_file, "\t.set\tnoat\n");
    fprintf (asm_out_file, "\tla\t%s,", reg_names[GP_REG_FIRST + 1]);
*************** build_mips16_function_stub (FILE *file)
*** 8957,8978 ****
        fputs ("\n", file);
      }
  
-   fprintf (file, "\t.set\tmips16\n");
- 
    switch_to_section (function_section (current_function_decl));
- }
- 
- /* We keep a list of functions for which we have already built stubs
-    in build_mips16_call_stub.  */
  
! struct mips16_stub
! {
!   struct mips16_stub *next;
!   char *name;
!   int fpret;
! };
  
- static struct mips16_stub *mips16_stubs;
  
  /* Emit code to return a double value from a mips16 stub.  GPREG is the
     first GP reg to use, FPREG is the first FP reg to use.  */
--- 9175,9190 ----
        fputs ("\n", file);
      }
  
    switch_to_section (function_section (current_function_decl));
  
!   /* Record function stub.  */
!   l = (struct mips16_stub *) xmalloc (sizeof *l);
!   l->name = xstrdup (fnname);
!   l->fpret = -1;
!   l->next = mips16_fn_stubs;
!   mips16_fn_stubs = l;
! }
  
  
  /* Emit code to return a double value from a mips16 stub.  GPREG is the
     first GP reg to use, FPREG is the first FP reg to use.  */
*************** build_mips16_call_stub (rtx retval, rtx 
*** 9046,9052 ****
  
    /* We don't need to do anything if we aren't in mips16 mode, or if
       we were invoked with the -msoft-float option.  */
!   if (!mips16_hard_float)
      return 0;
  
    /* Figure out whether the value might come back in a floating point
--- 9258,9264 ----
  
    /* We don't need to do anything if we aren't in mips16 mode, or if
       we were invoked with the -msoft-float option.  */
!   if (!TARGET_MIPS16 || TARGET_SOFT_FLOAT_ABI)
      return 0;
  
    /* Figure out whether the value might come back in a floating point
*************** build_mips16_call_stub (rtx retval, rtx 
*** 9130,9136 ****
       built a stub, we don't need to do anything further.  */
  
    fnname = XSTR (fn, 0);
!   for (l = mips16_stubs; l != NULL; l = l->next)
      if (strcmp (l->name, fnname) == 0)
        break;
  
--- 9342,9349 ----
       built a stub, we don't need to do anything further.  */
  
    fnname = XSTR (fn, 0);
! 
!   for (l = mips16_call_stubs; l != NULL; l = l->next)
      if (strcmp (l->name, fnname) == 0)
        break;
  
*************** build_mips16_call_stub (rtx retval, rtx 
*** 9290,9303 ****
  	  fputs ("\n", asm_out_file);
  	}
  
-       fprintf (asm_out_file, "\t.set\tmips16\n");
- 
        /* Record this stub.  */
        l = (struct mips16_stub *) xmalloc (sizeof *l);
        l->name = xstrdup (fnname);
        l->fpret = fpret;
!       l->next = mips16_stubs;
!       mips16_stubs = l;
      }
  
    /* If we expect a floating point return value, but we've built a
--- 9503,9514 ----
  	  fputs ("\n", asm_out_file);
  	}
  
        /* Record this stub.  */
        l = (struct mips16_stub *) xmalloc (sizeof *l);
        l->name = xstrdup (fnname);
        l->fpret = fpret;
!       l->next = mips16_call_stubs;
!       mips16_call_stubs = l;
      }
  
    /* If we expect a floating point return value, but we've built a
*************** mips_init_libfuncs (void)
*** 10102,10108 ****
        set_optab_libfunc (smod_optab, SImode, "__vr4120_modsi3");
      }
  
!   if (mips16_hard_float)
      {
        set_optab_libfunc (add_optab, SFmode, "__mips16_addsf3");
        set_optab_libfunc (sub_optab, SFmode, "__mips16_subsf3");
--- 10313,10319 ----
        set_optab_libfunc (smod_optab, SImode, "__vr4120_modsi3");
      }
  
!   if (TARGET_MIPS16 && TARGET_HARD_FLOAT_ABI)
      {
        set_optab_libfunc (add_optab, SFmode, "__mips16_addsf3");
        set_optab_libfunc (sub_optab, SFmode, "__mips16_subsf3");
*************** mips_expand_builtin (tree exp, rtx targe
*** 11409,11414 ****
--- 11620,11632 ----
    const struct builtin_description *bdesc;
    const struct bdesc_map *m;
  
+   if (TARGET_MIPS16)
+     {
+       error ("built-in function `%s' not supported for MIPS16",
+ 	     IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+       return const0_rtx;
+     }
+ 
    fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
    fcode = DECL_FUNCTION_CODE (fndecl);
  
*************** mips_encode_section_info (tree decl, rtx
*** 11929,11938 ****
    if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        rtx symbol = XEXP (rtl, 0);
  
!       if ((TARGET_LONG_CALLS && !mips_near_type_p (TREE_TYPE (decl)))
! 	  || mips_far_type_p (TREE_TYPE (decl)))
  	SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LONG_CALL;
      }
  }
  
--- 12147,12200 ----
    if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        rtx symbol = XEXP (rtl, 0);
+       int is_mips16 = mips_base_mips16;
+       tree type = TREE_TYPE (decl);
  
!       if ((TARGET_LONG_CALLS && !mips_near_type_p (type))
! 	  || mips_far_type_p (type))
  	SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LONG_CALL;
+ 
+       /* MIPS16 function attribute handling.  */
+       if (mips_mips16_type_p (type))
+ 	is_mips16 = 1;
+       else if (mips_nomips16_type_p (type))
+ 	is_mips16 = 0;
+       else if (TARGET_FLIP_MIPS16
+ 	       && !DECL_BUILT_IN (decl)
+ 	       && !DECL_ARTIFICIAL (decl))
+ 	{
+ 	  if (first)
+ 	    {
+ 	      /* Debug: flip MIPS16 on each function. */
+ 	      mips16_flipper = !mips16_flipper;
+ 	      if (mips16_flipper)
+ 		is_mips16 = !is_mips16;
+ 	    }
+ 	  else
+ 	    /* Don't flip after first again. */
+ 	    is_mips16 = SYMBOL_REF_MIPS16_FUNC_P (symbol);
+ 	}
+ 
+       /* If there was an explicit -mno-mips16, then prevent MIPS16
+ 	 selection, even when an explicit attribute is given.  */
+       if ((target_flags_explicit & MASK_MIPS16)
+ 	  && mips_base_mips16 == 0)
+ 	is_mips16 = 0;
+ 
+       if (is_mips16 && (flag_pic || TARGET_ABICALLS))
+ 	{
+ 	  warning (0, "%J%s is not supported with mips16 attribute on '%F'; attribute ignored",
+ 		   decl, 
+ 		   (flag_pic > 1 ? "-fPIC"
+ 		    : flag_pic ? "-fpic" 
+ 		    : "-mabicalls"),
+ 		   decl);
+ 	  is_mips16 = 0;
+ 	}
+ 
+       if (is_mips16)
+ 	SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_MIPS16_FUNC;
+ 
      }
  }
  
Index: gcc/doc/extend.texi
===================================================================
*** gcc/doc/extend.texi	(revision 127016)
--- gcc/doc/extend.texi	(working copy)
*************** long as the old pointer is never referre
*** 2191,2196 ****
--- 2191,2214 ----
  to the new pointer) after the function returns a non-@code{NULL}
  value.
  
+ @item mips16/nomips16
+ @cindex @code{mips16} attribute
+ @cindex @code{nomips16} attribute
+ 
+ On MIPS targets, you can use the @code{mips16} and @code{nomips16}
+ function attributes to locally select or turn off MIPS16 code generation.
+ A function with the @code{mips16} attribute is emitted as MIPS16 code
+ unless an explicit @option{-mno-mips16} option was specified on the command
+ line.  MIPS16 code generation is disabled for functions with the 
+ @code{nomips16} attribute, even if @option{-mips16} was specified on the
+ command line.  @xref{MIPS Options}, for more details about these options.
+ 
+ When compiling files containing mixed MIPS16 and non-MIPS16 code, the 
+ preprocessor symbol @code{__mips16} reflects the setting on the command line,
+ not that within individual functions.  Mixed MIPS16 and non-MIPS16 code
+ may interact badly with some GCC extensions such as @code{__builtin_apply}
+ (@pxref{Constructing Calls}).  
+ 
  @item model (@var{model-name})
  @cindex function addressability on the M32R/D
  @cindex variable addressability on the IA-64
Index: gcc/doc/invoke.texi
===================================================================
*** gcc/doc/invoke.texi	(revision 127016)
--- gcc/doc/invoke.texi	(working copy)
*************** Objective-C and Objective-C++ Dialects}.
*** 618,624 ****
  @emph{MIPS Options}
  @gccoptlist{-EL  -EB  -march=@var{arch}  -mtune=@var{arch} @gol
  -mips1  -mips2  -mips3  -mips4  -mips32  -mips32r2  -mips64 @gol
! -mips16  -mno-mips16  -mabi=@var{abi}  -mabicalls  -mno-abicalls @gol
  -mshared  -mno-shared  -mxgot  -mno-xgot  -mgp32  -mgp64 @gol
  -mfp32  -mfp64  -mhard-float  -msoft-float @gol
  -msingle-float  -mdouble-float  -mdsp  -mno-dsp  -mdspr2  -mno-dspr2 @gol
--- 618,625 ----
  @emph{MIPS Options}
  @gccoptlist{-EL  -EB  -march=@var{arch}  -mtune=@var{arch} @gol
  -mips1  -mips2  -mips3  -mips4  -mips32  -mips32r2  -mips64 @gol
! -mips16  -mno-mips16  -mflip-mips16 @gol
! -mabi=@var{abi}  -mabicalls  -mno-abicalls @gol
  -mshared  -mno-shared  -mxgot  -mno-xgot  -mgp32  -mgp64 @gol
  -mfp32  -mfp64  -mhard-float  -msoft-float @gol
  -msingle-float  -mdouble-float  -mdsp  -mno-dsp  -mdspr2  -mno-dspr2 @gol
*************** Equivalent to @samp{-march=mips64}.
*** 11529,11534 ****
--- 11530,11545 ----
  Generate (do not generate) MIPS16 code.  If GCC is targetting a
  MIPS32 or MIPS64 architecture, it will make use of the MIPS16e ASE@.
  
+ MIPS16 code generation can also be controlled on a per-function basis
+ by means of @code{mips16} and @code{nomips16} attributes.  
+ @xref{Function Attributes}, for more information.
+ 
+ @item -mflip-mips16
+ @opindex mflip-mips16
+ Generate MIPS16 code on alternating functions.  This option is provided
+ for regression testing of mixed MIPS16/non-MIPS16 code generation, and is
+ not intended for ordinary use in compiling user code.
+ 
  @item -mabi=32
  @itemx -mabi=o64
  @itemx -mabi=n32
Index: gcc/testsuite/gcc.target/mips/mips16-attributes.c
===================================================================
*** gcc/testsuite/gcc.target/mips/mips16-attributes.c	(revision 0)
--- gcc/testsuite/gcc.target/mips/mips16-attributes.c	(revision 0)
***************
*** 0 ****
--- 1,82 ----
+ /* Verify that mips16 and nomips16 attributes work, checking all combinations
+    of calling a nomips16/mips16/default function from a nomips16/mips16/default
+    function.  */
+ /* { dg-do run } */
+ 
+ #include <stdlib.h>
+ 
+ #define ATTR1 __attribute__ ((nomips16))
+ #define ATTR2 __attribute__ ((mips16))
+ #define ATTR3
+ 
+ double ATTR1
+ f1 (int i, float f, double d)
+ {
+   return i + f + d;
+ }
+ 
+ double ATTR2
+ f2 (int i, float f, double d)
+ {
+   return i + f + d;
+ }
+ 
+ double ATTR3
+ f3 (int i, float f, double d)
+ {
+   return i + f + d;
+ }
+ 
+ void ATTR1
+ g1 (int i, float f, double d)
+ {
+   double r = i + f + d;
+ 
+   if (f1 (i, f, d) != r)
+     abort ();
+   if (f2 (i+1, f+1, d+1) != r + 3)
+     abort ();
+   if (f3 (i+2, f+2, d+2) != r + 6)
+     abort ();
+ }
+ 
+ void ATTR2
+ g2 (int i, float f, double d)
+ {
+   double r = i + f + d;
+ 
+   if (f1 (i, f, d) != r)
+     abort ();
+   if (f2 (i+1, f+1, d+1) != r + 3)
+     abort ();
+   if (f3 (i+2, f+2, d+2) != r + 6)
+     abort ();
+ }
+ 
+ void ATTR3
+ g3 (int i, float f, double d)
+ {
+   double r = i + f + d;
+ 
+   if (f1 (i, f, d) != r)
+     abort ();
+   if (f2 (i+1, f+1, d+1) != r + 3)
+     abort ();
+   if (f3 (i+2, f+2, d+2) != r + 6)
+     abort ();
+ }
+ 
+ int ATTR3
+ main (void)
+ {
+   int i = 1;
+   float f = -2.0;
+   double d = 3.0;
+ 
+   g1 (i, f, d);
+   g2 (i, f, d);
+   g3 (i, f, d);
+ 
+   exit (0);
+ }
+ 
Index: gcc/testsuite/gcc.c-torture/compile/mipscop-1.c
===================================================================
*** gcc/testsuite/gcc.c-torture/compile/mipscop-1.c	(revision 126515)
--- gcc/testsuite/gcc.c-torture/compile/mipscop-1.c	(working copy)
***************
*** 1,9 ****
  /* { dg-do compile { target mips*-*-* } } */
  
- #ifndef __mips16
  register unsigned int cp0count asm ("$c0r1");
  
! int
  main (int argc, char *argv[])
  {
    unsigned int d;
--- 1,8 ----
  /* { dg-do compile { target mips*-*-* } } */
  
  register unsigned int cp0count asm ("$c0r1");
  
! int __attribute__ ((nomips16))
  main (int argc, char *argv[])
  {
    unsigned int d;
*************** main (int argc, char *argv[])
*** 11,14 ****
    d = cp0count + 3;
    printf ("%d\n", d);
  }
- #endif
--- 10,12 ----
Index: gcc/testsuite/gcc.c-torture/compile/mipscop-2.c
===================================================================
*** gcc/testsuite/gcc.c-torture/compile/mipscop-2.c	(revision 126515)
--- gcc/testsuite/gcc.c-torture/compile/mipscop-2.c	(working copy)
***************
*** 1,11 ****
  /* { dg-do compile { target mips*-*-* } } */
  
- #ifndef __mips16
  register unsigned int c3r1 asm ("$c3r1");
  
  extern unsigned int b, c;
  
! void
  foo ()
  {
    unsigned int a, d;
--- 1,10 ----
  /* { dg-do compile { target mips*-*-* } } */
  
  register unsigned int c3r1 asm ("$c3r1");
  
  extern unsigned int b, c;
  
! void __attribute__ ((nomips16))
  foo ()
  {
    unsigned int a, d;
*************** foo ()
*** 17,20 ****
    d = c3r1;
    printf ("%d\n", d);
  }
- #endif
--- 16,18 ----
Index: gcc/testsuite/gcc.c-torture/compile/mipscop-3.c
===================================================================
*** gcc/testsuite/gcc.c-torture/compile/mipscop-3.c	(revision 126515)
--- gcc/testsuite/gcc.c-torture/compile/mipscop-3.c	(working copy)
***************
*** 1,11 ****
  /* { dg-do compile { target mips*-*-* } } */
  
- #ifndef __mips16
  register unsigned int c3r1 asm ("$c3r1"), c3r2 asm ("$c3r2");
  
  extern unsigned int b, c;
  
! void
  foo ()
  {
    unsigned int a, d;
--- 1,10 ----
  /* { dg-do compile { target mips*-*-* } } */
  
  register unsigned int c3r1 asm ("$c3r1"), c3r2 asm ("$c3r2");
  
  extern unsigned int b, c;
  
! void __attribute__ ((nomips16))
  foo ()
  {
    unsigned int a, d;
*************** foo ()
*** 17,20 ****
    d = c3r1;
    printf ("%d\n", d);
  }
- #endif
--- 16,18 ----
Index: gcc/testsuite/gcc.c-torture/compile/mipscop-4.c
===================================================================
*** gcc/testsuite/gcc.c-torture/compile/mipscop-4.c	(revision 126515)
--- gcc/testsuite/gcc.c-torture/compile/mipscop-4.c	(working copy)
***************
*** 1,11 ****
  /* { dg-do compile { target mips*-*-* } } */
  
- #ifndef __mips16
  register unsigned long c3r1 asm ("$c3r1"), c3r2 asm ("$c3r2");
  
  extern unsigned long b, c;
  
! void
  foo ()
  {
    unsigned long a, d;
--- 1,10 ----
  /* { dg-do compile { target mips*-*-* } } */
  
  register unsigned long c3r1 asm ("$c3r1"), c3r2 asm ("$c3r2");
  
  extern unsigned long b, c;
  
! void __attribute__ ((nomips16))
  foo ()
  {
    unsigned long a, d;
*************** foo ()
*** 17,20 ****
    d = c3r1;
    printf ("%d\n", d);
  }
! #endif
--- 16,19 ----
    d = c3r1;
    printf ("%d\n", d);
  }
! 
Index: gcc/testsuite/gcc.dg/torture/mips-hilo-1.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/mips-hilo-1.c	(revision 126515)
--- gcc/testsuite/gcc.dg/torture/mips-hilo-1.c	(working copy)
***************
*** 6,15 ****
  extern void abort (void);
  extern void exit (int);
  
- #if !defined(__mips16)
- 
  #define DECLARE(TYPE)							\
!   TYPE __attribute__ ((noinline))					\
    f1##TYPE (TYPE x1, TYPE x2, TYPE x3)					\
    {									\
      TYPE t1, t2;							\
--- 6,13 ----
  extern void abort (void);
  extern void exit (int);
  
  #define DECLARE(TYPE)							\
!   TYPE __attribute__ ((noinline)) __attribute__ ((nomips16))		\
    f1##TYPE (TYPE x1, TYPE x2, TYPE x3)					\
    {									\
      TYPE t1, t2;							\
*************** extern void exit (int);
*** 19,25 ****
      return t1 + t2;							\
    }									\
  									\
!   TYPE __attribute__ ((noinline))					\
    f2##TYPE (TYPE x1, TYPE x2, TYPE x3)					\
    {									\
      TYPE t1, t2;							\
--- 17,23 ----
      return t1 + t2;							\
    }									\
  									\
!   TYPE __attribute__ ((noinline)) __attribute__ ((nomips16))		\
    f2##TYPE (TYPE x1, TYPE x2, TYPE x3)					\
    {									\
      TYPE t1, t2;							\
*************** main ()
*** 73,78 ****
  #endif
    exit (0);
  }
- #else
- int main () { exit (0); }
- #endif
--- 71,73 ----
Index: gcc/testsuite/gcc.dg/torture/mips-hilo-2.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/mips-hilo-2.c	(revision 126515)
--- gcc/testsuite/gcc.dg/torture/mips-hilo-2.c	(working copy)
***************
*** 5,14 ****
  extern void abort (void);
  extern void exit (int);
  
- #if !defined(__mips16)
  unsigned int g;
  
! unsigned long long f (unsigned int x)
  {
    union { unsigned long long ll; unsigned int parts[2]; } u;
  
--- 5,13 ----
  extern void abort (void);
  extern void exit (int);
  
  unsigned int g;
  
! unsigned __attribute__ ((nomips16)) long long f (unsigned int x)
  {
    union { unsigned long long ll; unsigned int parts[2]; } u;
  
*************** unsigned long long f (unsigned int x)
*** 17,23 ****
    return u.ll;
  }
  
! int main ()
  {
    union { unsigned long long ll; unsigned int parts[2]; } u;
  
--- 16,22 ----
    return u.ll;
  }
  
! int __attribute__ ((nomips16)) main ()
  {
    union { unsigned long long ll; unsigned int parts[2]; } u;
  
*************** int main ()
*** 26,31 ****
      abort ();
    exit (0);
  }
- #else
- int main () { exit (0); }
- #endif
--- 25,27 ----
Index: gcc/testsuite/gcc.dg/torture/pr19683-1.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr19683-1.c	(revision 126515)
--- gcc/testsuite/gcc.dg/torture/pr19683-1.c	(working copy)
***************
*** 6,12 ****
  extern void abort (void);
  extern void exit (int);
  
- #ifndef __mips16
  #define REPEAT10(X, Y)					\
    X(Y##0); X(Y##1); X(Y##2); X(Y##3); X(Y##4);		\
    X(Y##5); X(Y##6); X(Y##7); X(Y##8); X(Y##9)
--- 6,11 ----
*************** extern void exit (int);
*** 17,23 ****
  
  union u { unsigned long long ll; unsigned int i[2]; };
  
! unsigned int
  foo (volatile unsigned int *ptr)
  {
    union u u;
--- 16,22 ----
  
  union u { unsigned long long ll; unsigned int i[2]; };
  
! unsigned int __attribute__ ((nomips16))
  foo (volatile unsigned int *ptr)
  {
    union u u;
*************** foo (volatile unsigned int *ptr)
*** 30,36 ****
    return result;
  }
  
! int
  main (void)
  {
    unsigned int array[] = { 1000 * 1000 * 1000 };
--- 29,35 ----
    return result;
  }
  
! int __attribute__ ((nomips16))
  main (void)
  {
    unsigned int array[] = { 1000 * 1000 * 1000 };
*************** main (void)
*** 41,50 ****
      abort ();
    exit (0);
  }
- #else
- int
- main (void)
- {
-   exit (0);
- }
- #endif
--- 40,42 ----

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]