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]

PATCH: support for mips16/nomips16 function attributes


This is part 3 of the 3-part patch set that allows selecting mips16/nomips16 mode on a per-function basis. This version incorporates most of the review comments from last time (thanks Richard!) -- see http://gcc.gnu.org/ml/gcc-patches/2007-08/msg00231.html

I've split out the bits to get rid of mips16_hard_float; that's already been committed by itself, since it was really just a cleanup from some previous patches. I also removed the bit to create MIPS16 function stubs for library functions, since that didn't seem to be necessary for the testing I did; we can revisit that later if we find some test case where it seems to be necessary after all. And, I merged in some changes to keep it current with other recent MIPS patches.

As with the previous patch in this series (that this one depends on), I'm not really expecting this to be approved in its current form, and am just posting it for informational purposes while we work out where the initialization hook should really be invoked.

-Sandra
2007-08-10  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.

	* config/mips/mips.h (SYMBOL_FLAG_MIPS16_FUNC): Define.
	(SYMBOL_FLAG_MIPS16_FUNC_P): Define.

	* config/mips/mips.c (mips_base_target_flags): New.
	(mips_base_mips16): New.
	(mips_base_schedule_insns): New.
	(mips_base_reorder_blocks_and_partition): New.
	(mips_base_align_loops): New.
	(mips_base_align_jumps): New.
	(mips_base_align_functions): New.
	(mips16_flipper): 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.
	(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_split_addresses): New, split out from override_options.
	(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.  Call
	mips_set_mips16_mode instead of doing initialization inline.
	(mips_file_start): Move mips16 mode setting output from here....
	(mips_output_function_prologue): ....to here.
	(mips_output_mi_thunk): Check for mips16 function.
	(build_mips16_function_stub): Don't set .mips16 here.
	(build_mips16_call_stub): Likewise.
	(mips_expand_builtin): Error in mips16 mode.
	(mips_use_mips16_mode_p): New.
	(mips_encode_section_info): Check for mips16 function, and 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.
	* testsuite/gcc.target/mips/madd-3.c: Add nomips16 attributes.
	* testsuite/gcc.target/mips/maddu-3.c: Likewise.
	* testsuite/gcc.target/mips/msub-3.c: Likewise.
	* testsuite/gcc.target/mips/msubu-3.c: Likewise.
	* testsuite/gcc.target/mips/dspr2-MULT.c: Likewise.
	* testsuite/gcc.target/mips/dspr2-MULTU.c: Likewise.
	


Index: gcc/config/mips/mips.opt
===================================================================
*** gcc/config/mips/mips.opt	(revision 127325)
--- gcc/config/mips/mips.opt	(working copy)
*************** mbranch-likely
*** 42,47 ****
--- 42,51 ----
  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
Index: gcc/config/mips/mips.h
===================================================================
*** gcc/config/mips/mips.h	(revision 127325)
--- gcc/config/mips/mips.h	(working copy)
*************** typedef struct mips_args {
*** 2289,2294 ****
--- 2289,2299 ----
  #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)
+ 
  /* True if we're generating a form of MIPS16 code in which jump tables
     are stored in the text section and encoded as 16-bit PC-relative
     offsets.  This is only possible when general text loads are allowed,
Index: gcc/config/mips/mips.c
===================================================================
*** gcc/config/mips/mips.c	(revision 127325)
--- gcc/config/mips/mips.c	(working copy)
*************** static rtx mips_expand_builtin_bposge (e
*** 423,428 ****
--- 423,431 ----
  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;
*** 616,621 ****
--- 619,636 ----
  /* 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_reorder_blocks_and_partition; /* flag_reorder... */
+ 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 -mtext-loads setting.  */
  enum mips_code_readable_setting mips_code_readable = CODE_READABLE_YES;
  
*************** const struct attribute_spec mips_attribu
*** 714,719 ****
--- 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_
*** 1246,1251 ****
--- 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)
*** 1364,1369 ****
--- 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
*** 1382,1387 ****
--- 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)
*** 1773,1779 ****
  	return true;
      }
  
!   if (TARGET_HAVE_TLS && for_each_rtx (&x, &mips_tls_symbol_ref_1, 0))
      return true;
  
    return false;
--- 1815,1821 ----
  	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, 
*** 3758,3770 ****
  }
  
  
! /* 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
--- 3800,3823 ----
  }
  
  
! /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL.  */
  
  static bool
! mips_function_ok_for_sibcall (tree decl,
  			      tree exp ATTRIBUTE_UNUSED)
  {
!   /* Not if TARGET_SIBCALLS isn't set.  */
!   if (!TARGET_SIBCALLS)
!     return 0;
! 
!   /* We can't do a sibcall if the called function is a MIPS16 function
!      because there is no direct "jx" instruction equivalent to "jalx" to
!      switch the ISA mode.  */
!   if (decl && SYMBOL_REF_MIPS16_FUNC_P (XEXP (DECL_RTL (decl), 0)))
!     return 0;
! 
!   /* Otherwise OK.  */
!   return 1;
  }
  
  /* Emit code to move general operand SRC into condition-code
*************** function_arg (const CUMULATIVE_ARGS *cum
*** 4201,4207 ****
       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
--- 4254,4261 ----
       stored as the mode.  */
    if (mode == VOIDmode)
      {
!       if ((TARGET_MIPS16 || mips_base_mips16)
! 	  && cum->fp_code != 0)
  	return gen_rtx_REG ((enum machine_mode) cum->fp_code, 0);
  
        else
*************** mips_set_tune (const struct mips_cpu_inf
*** 5007,5012 ****
--- 5061,5296 ----
      }
  }
  
+ /* mips_split_addresses is a half-way house between explicit
+    relocations and the traditional assembler macros.  It can
+    split absolute 32-bit symbolic constants into a high/lo_sum
+    pair but uses macros for other sorts of access.
+    
+    Like explicit relocation support for REL targets, it relies
+    on GNU extensions in the assembler and the linker.
+ 
+    Although this code should work for -O0, it has traditionally
+    been treated as an optimization.  */
+ 
+ static void
+ mips_init_split_addresses (void)
+ {
+   if (!TARGET_MIPS16 && TARGET_SPLIT_ADDRESSES
+       && optimize && !flag_pic
+       && !ABI_HAS_64BIT_SYMBOLS)
+     mips_split_addresses = 1;
+   else
+     mips_split_addresses = 0;
+ }
+ 
+ /* (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_ABSOLUTE] = true;
+ 	  mips_lo_relocs[SYMBOL_ABSOLUTE] = "%lo(";
+ 	}
+     }
+   else
+     {
+       if (TARGET_EXPLICIT_RELOCS || mips_split_addresses || TARGET_MIPS16)
+ 	{
+ 	  mips_split_p[SYMBOL_ABSOLUTE] = true;
+ 	  mips_hi_relocs[SYMBOL_ABSOLUTE] = "%hi(";
+ 	  mips_lo_relocs[SYMBOL_ABSOLUTE] = "%lo(";
+ 
+ 	  mips_lo_relocs[SYMBOL_32_HIGH] = "%hi(";
+ 	}
+     }
+ 
+   if (TARGET_MIPS16)
+     {
+       /* The high part is provided by a pseudo copy of $gp.  */
+       mips_split_p[SYMBOL_GP_RELATIVE] = true;
+       mips_lo_relocs[SYMBOL_GP_RELATIVE] = "%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_GP_RELATIVE] = "%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;
+ 
+ /* Set up the target-dependent global state so that it matches the
+    current function's ISA mode.  */
+ static void
+ mips_set_mips16_mode (int mips16_p)
+ {
+   if (mips16_p == was_mips16_p)
+     return;
+ 
+   /* Restore base settings of various flags.  */
+   target_flags = mips_base_target_flags;
+   align_loops = mips_base_align_loops;
+   align_jumps = mips_base_align_jumps;
+   align_functions = mips_base_align_functions;
+   flag_schedule_insns = mips_base_schedule_insns;
+   flag_reorder_blocks_and_partition = mips_base_reorder_blocks_and_partition;
+   flag_delayed_branch = mips_flag_delayed_branch;
+   
+   if (mips16_p) 
+     {
+       /* Select mips16 instruction set.  */
+       target_flags |= MASK_MIPS16;
+ 
+       /* 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;
+ 
+       /* Silently disable DSP extensions.  We already complained in
+ 	 override_options if both -mdsp and -mips16 were specified on the
+ 	 command line, so here we're assuming local mips16 function
+ 	 attribute takes precedence over command-line -mdsp.  */
+       target_flags &= ~MASK_DSP;
+       target_flags &= ~MASK_DSPR2;
+ 
+       /* 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;
+ 
+       /* 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_split_addresses ();
+   mips_init_relocs ();
+ 
+   if (was_mips16_p >= 0)
+     /* Reinitialize target-dependent state.  */
+     target_reinit ();
+ 
+   was_mips16_p = TARGET_MIPS16;
+ }
+ 
+ /* Implement TARGET_PREPARE_FUNCTION_START.  Decide whether the current 
+    function should use the MIPS16 ISA and switch modes accordingly.  */
+ 
+ static void
+ mips_prepare_function_start (tree fndecl)
+ {
+   mips_set_mips16_mode (SYMBOL_REF_MIPS16_FUNC_P (XEXP (DECL_RTL (fndecl), 0)));
+ }
+ 
+ /* Implement TARGET_END_OF_FILE_CLEANUP.  Restore the MIPS16 setting specified
+    on the command line.  */
+ 
+ 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)
*** 5234,5239 ****
--- 5518,5531 ----
        target_flags &= ~MASK_ABICALLS;
      }
  
+   /* MIPS16 cannot generate PIC yet.  */
+   if (TARGET_MIPS16 && (flag_pic || TARGET_ABICALLS))
+     {
+       sorry ("MIPS16 PIC");
+       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)
*** 5251,5272 ****
    if (TARGET_VXWORKS_RTP && mips_section_threshold > 0)
      warning (0, "-G and -mrtp are incompatible");
  
-   /* mips_split_addresses is a half-way house between explicit
-      relocations and the traditional assembler macros.  It can
-      split absolute 32-bit symbolic constants into a high/lo_sum
-      pair but uses macros for other sorts of access.
- 
-      Like explicit relocation support for REL targets, it relies
-      on GNU extensions in the assembler and the linker.
- 
-      Although this code should work for -O0, it has traditionally
-      been treated as an optimization.  */
-   if (!TARGET_MIPS16 && TARGET_SPLIT_ADDRESSES
-       && optimize && !flag_pic
-       && !ABI_HAS_64BIT_SYMBOLS)
-     mips_split_addresses = 1;
-   else
-     mips_split_addresses = 0;
  
    /* -mvr4130-align is a "speed over size" optimization: it usually produces
       faster code, but at the expense of more nops.  Enable it at -O3 and
--- 5543,5548 ----
*************** override_options (void)
*** 5458,5464 ****
    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;
--- 5734,5740 ----
    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)
*** 5471,5581 ****
    /* 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_ABSOLUTE] = true;
- 	  mips_lo_relocs[SYMBOL_ABSOLUTE] = "%lo(";
- 	}
-     }
-   else
-     {
-       if (TARGET_EXPLICIT_RELOCS || mips_split_addresses || TARGET_MIPS16)
- 	{
- 	  mips_split_p[SYMBOL_ABSOLUTE] = true;
- 	  mips_hi_relocs[SYMBOL_ABSOLUTE] = "%hi(";
- 	  mips_lo_relocs[SYMBOL_ABSOLUTE] = "%lo(";
- 
- 	  mips_lo_relocs[SYMBOL_32_HIGH] = "%hi(";
- 	}
-     }
- 
-   if (TARGET_MIPS16)
-     {
-       /* The high part is provided by a pseudo copy of $gp.  */
-       mips_split_p[SYMBOL_GP_RELATIVE] = true;
-       mips_lo_relocs[SYMBOL_GP_RELATIVE] = "%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_GP_RELATIVE] = "%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
--- 5747,5752 ----
*************** override_options (void)
*** 5587,5592 ****
--- 5758,5776 ----
    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.  */
+   mips_base_mips16 = target_flags & MASK_MIPS16;
+   mips_base_target_flags = target_flags;
+   mips_base_schedule_insns = flag_schedule_insns;
+   mips_base_reorder_blocks_and_partition = flag_reorder_blocks_and_partition;
+   mips_base_align_loops = align_loops;
+   mips_base_align_jumps = align_jumps;
+   mips_base_align_functions = align_functions;
+   mips_flag_delayed_branch = flag_delayed_branch;
+ 
+   /* 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)
*** 6342,6350 ****
    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,
--- 6526,6531 ----
*************** mips_output_function_prologue (FILE *fil
*** 7199,7204 ****
--- 7380,7391 ----
        && current_function_args_info.fp_code != 0)
      build_mips16_function_stub (file);
  
+   /* 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)
      {
        /* Get the function name the same way that toplev.c does before calling
*************** mips_output_mi_thunk (FILE *file, tree t
*** 8155,8161 ****
  	TARGET_CALL_SAVED_GP ? 15 : GLOBAL_POINTER_REGNUM;
  
        SET_REGNO (pic_offset_table_rtx, cfun->machine->global_pointer);
- 
      }
  
    /* Set up the global pointer for n32 or n64 abicalls.  If
--- 8342,8347 ----
*************** mips_output_mi_thunk (FILE *file, tree t
*** 8206,8212 ****
    /* 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.
--- 8392,8399 ----
    /* 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.
*************** build_mips16_function_stub (FILE *file)
*** 9042,9049 ****
        fputs ("\n", file);
      }
  
-   fprintf (file, "\t.set\tmips16\n");
- 
    switch_to_section (function_section (current_function_decl));
  }
  
--- 9229,9234 ----
*************** build_mips16_call_stub (rtx retval, rtx 
*** 9375,9382 ****
  	  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);
--- 9560,9565 ----
*************** mips_expand_builtin (tree exp, rtx targe
*** 11515,11520 ****
--- 11698,11710 ----
    fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
    fcode = DECL_FUNCTION_CODE (fndecl);
  
+   if (TARGET_MIPS16)
+     {
+       error ("built-in function `%s' not supported for MIPS16",
+ 	     IDENTIFIER_POINTER (DECL_NAME (fndecl)));
+       return const0_rtx;
+     }
+ 
    bdesc = NULL;
    for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++)
      {
*************** mips_expand_builtin_bposge (enum mips_bu
*** 12021,12026 ****
--- 12211,12258 ----
  				       const1_rtx, const0_rtx);
  }
  
+ /* Return true if we should force MIPS16 mode for the function named by
+    the SYMBOL_REF SYMBOL, which belongs to DECL and has type TYPE.
+    FIRST is true if this is the first time handling this decl.  */
+ static int
+ mips_use_mips16_mode_p (rtx symbol, tree decl, int first, tree type)
+ {
+   int is_mips16 = mips_base_mips16;
+   tree parent;
+ 
+   if (mips_mips16_type_p (type))
+     is_mips16 = 1;
+   else if (mips_nomips16_type_p (type))
+     is_mips16 = 0;
+   else if (parent = decl_function_context (decl))
+     /* Nested function should inherit MIPS16 setting from its parent.  */
+     is_mips16 = SYMBOL_REF_MIPS16_FUNC_P (XEXP (DECL_RTL (parent), 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;
+ 
+   return is_mips16;
+ }
+ 
+ 
  /* Set SYMBOL_REF_FLAGS for the SYMBOL_REF inside RTL, which belongs to DECL.
     FIRST is true if this is the first time handling this decl.  */
  
*************** mips_encode_section_info (tree decl, rtx
*** 12032,12041 ****
    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;
      }
  }
  
--- 12264,12282 ----
    if (TREE_CODE (decl) == FUNCTION_DECL)
      {
        rtx symbol = XEXP (rtl, 0);
+       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;
+ 
+       if (mips_use_mips16_mode_p (symbol, decl, first, type))
+ 	{
+ 	  if (flag_pic || TARGET_ABICALLS)
+ 	    sorry ("MIPS16 PIC");
+ 	  else
+ 	    SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_MIPS16_FUNC;
+ 	}
      }
  }
  
Index: gcc/doc/extend.texi
===================================================================
*** gcc/doc/extend.texi	(revision 127325)
--- 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 127325)
--- 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}.
*** 11549,11554 ****
--- 11550,11565 ----
  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 127325)
--- 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 127325)
--- 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 127325)
--- 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 127325)
--- 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 127325)
--- 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 127325)
--- 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 127325)
--- 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: gcc/testsuite/gcc.target/mips/madd-3.c
===================================================================
*** gcc/testsuite/gcc.target/mips/madd-3.c	(revision 127325)
--- gcc/testsuite/gcc.target/mips/madd-3.c	(working copy)
***************
*** 2,20 ****
  /* { dg-mips-options "-O2 -mips32 -mgp32" } */
  /* { dg-final { scan-assembler-times "\tmadd\t" 3 } } */
  
! long long
  f1 (int x, int y, long long z)
  {
    return (long long) x * y + z;
  }
  
! long long
  f2 (int x, int y, long long z)
  {
    return z + (long long) y * x;
  }
  
! long long
  f3 (int x, int y, long long z)
  {
    long long t = (long long) x * y;
--- 2,20 ----
  /* { dg-mips-options "-O2 -mips32 -mgp32" } */
  /* { dg-final { scan-assembler-times "\tmadd\t" 3 } } */
  
! long long __attribute__ ((nomips16))
  f1 (int x, int y, long long z)
  {
    return (long long) x * y + z;
  }
  
! long long __attribute__ ((nomips16))
  f2 (int x, int y, long long z)
  {
    return z + (long long) y * x;
  }
  
! long long __attribute__ ((nomips16))
  f3 (int x, int y, long long z)
  {
    long long t = (long long) x * y;
Index: gcc/testsuite/gcc.target/mips/maddu-3.c
===================================================================
*** gcc/testsuite/gcc.target/mips/maddu-3.c	(revision 127325)
--- gcc/testsuite/gcc.target/mips/maddu-3.c	(working copy)
***************
*** 5,23 ****
  typedef unsigned int ui;
  typedef unsigned long long ull;
  
! ull
  f1 (ui x, ui y, ull z)
  {
    return (ull) x * y + z;
  }
  
! ull
  f2 (ui x, ui y, ull z)
  {
    return z + (ull) y * x;
  }
  
! ull
  f3 (ui x, ui y, ull z)
  {
    ull t = (ull) x * y;
--- 5,23 ----
  typedef unsigned int ui;
  typedef unsigned long long ull;
  
! ull __attribute__ ((nomips16))
  f1 (ui x, ui y, ull z)
  {
    return (ull) x * y + z;
  }
  
! ull __attribute__ ((nomips16))
  f2 (ui x, ui y, ull z)
  {
    return z + (ull) y * x;
  }
  
! ull __attribute__ ((nomips16))
  f3 (ui x, ui y, ull z)
  {
    ull t = (ull) x * y;
Index: gcc/testsuite/gcc.target/mips/msub-3.c
===================================================================
*** gcc/testsuite/gcc.target/mips/msub-3.c	(revision 127325)
--- gcc/testsuite/gcc.target/mips/msub-3.c	(working copy)
***************
*** 2,14 ****
  /* { dg-mips-options "-O2 -mips32 -mgp32" } */
  /* { dg-final { scan-assembler-times "\tmsub\t" 2 } } */
  
! long long
  f1 (int x, int y, long long z)
  {
    return z - (long long) y * x;
  }
  
! long long
  f2 (int x, int y, long long z)
  {
    long long t = (long long) x * y;
--- 2,14 ----
  /* { dg-mips-options "-O2 -mips32 -mgp32" } */
  /* { dg-final { scan-assembler-times "\tmsub\t" 2 } } */
  
! long long __attribute__ ((nomips16))
  f1 (int x, int y, long long z)
  {
    return z - (long long) y * x;
  }
  
! long long __attribute__ ((nomips16))
  f2 (int x, int y, long long z)
  {
    long long t = (long long) x * y;
Index: gcc/testsuite/gcc.target/mips/msubu-3.c
===================================================================
*** gcc/testsuite/gcc.target/mips/msubu-3.c	(revision 127325)
--- gcc/testsuite/gcc.target/mips/msubu-3.c	(working copy)
***************
*** 5,17 ****
  typedef unsigned int ui;
  typedef unsigned long long ull;
  
! ull
  f1 (ui x, ui y, ull z)
  {
    return z - (ull) y * x;
  }
  
! ull
  f2 (ui x, ui y, ull z)
  {
    ull t = (ull) x * y;
--- 5,17 ----
  typedef unsigned int ui;
  typedef unsigned long long ull;
  
! ull __attribute__ ((nomips16))
  f1 (ui x, ui y, ull z)
  {
    return z - (ull) y * x;
  }
  
! ull __attribute__ ((nomips16))
  f2 (ui x, ui y, ull z)
  {
    ull t = (ull) x * y;
Index: gcc/testsuite/gcc.target/mips/dspr2-MULT.c
===================================================================
*** gcc/testsuite/gcc.target/mips/dspr2-MULT.c	(revision 127325)
--- gcc/testsuite/gcc.target/mips/dspr2-MULT.c	(working copy)
*************** typedef long long a64;
*** 11,17 ****
  a64 a[4];
  int b[4], c[4];
  
! void test ()
  {
    a[0] = (a64) b[0] * c[0];
    a[1] = (a64) b[1] * c[1];
--- 11,17 ----
  a64 a[4];
  int b[4], c[4];
  
! void __attribute__ ((nomips16)) test ()
  {
    a[0] = (a64) b[0] * c[0];
    a[1] = (a64) b[1] * c[1];
Index: gcc/testsuite/gcc.target/mips/dspr2-MULTU.c
===================================================================
*** gcc/testsuite/gcc.target/mips/dspr2-MULTU.c	(revision 127325)
--- gcc/testsuite/gcc.target/mips/dspr2-MULTU.c	(working copy)
*************** typedef long long a64;
*** 11,17 ****
  a64 a[4];
  unsigned int b[4], c[4];
  
! void test ()
  {
    a[0] = (a64) b[0] * c[0];
    a[1] = (a64) b[1] * c[1];
--- 11,17 ----
  a64 a[4];
  unsigned int b[4], c[4];
  
! void __attribute__ ((nomips16)) test ()
  {
    a[0] = (a64) b[0] * c[0];
    a[1] = (a64) b[1] * c[1];

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