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]

Re: PATCH: mips16 function attributes, version N+1


Richard Sandiford wrote:

Unfortunately, I think removing the code _will_ need a retest.  OK with
that change on top of the other ones.

OK, fixed up as suggested, retested, and committed now. For the record, I'm attaching the final version of the patch as committed.


-Sandra



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

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

gcc/

* 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_SET_CURRENT_FUNCTION): Define.
	(mips_mips16_type_p, mips_nomips16_type_p): New.
	(mips_comp_type_attributes): Check mips16/nomips16 attributes.
	(mips_function_ok_for_sibcall): Make it deal with functions with
	mips16 attributes.
	(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_set_current_function): New.
	(override_options):  Add sorry for unsupported mips16/pic
	combination.  Remove error for mips16/dsp combination.	Save
	base option settings.
	(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.

	gcc/testsuite/
	* gcc.target/mips/mips16-attributes.c: New.

Index: gcc/config/mips/mips.opt
===================================================================
*** gcc/config/mips/mips.opt	(revision 128000)
--- 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 128000)
--- gcc/config/mips/mips.h	(working copy)
*************** typedef struct mips_args {
*** 2294,2299 ****
--- 2294,2304 ----
  #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 128000)
--- gcc/config/mips/mips.c	(working copy)
*************** static rtx mips_expand_builtin_bposge (e
*** 424,429 ****
--- 424,431 ----
  static void mips_encode_section_info (tree, rtx, int);
  static void mips_extra_live_on_entry (bitmap);
  static int mips_comp_type_attributes (const_tree, const_tree);
+ static void mips_set_mips16_mode (int);
+ static void mips_set_current_function (tree);
  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;
*** 617,622 ****
--- 619,636 ----
  /* Cost information to use.  */
  const struct mips_rtx_cost_data *mips_cost;
  
+ /* Remember the ambient target flags, excluding mips16.  */
+ static int mips_base_target_flags;
+ /* The mips16 command-line target flags only.  */
+ static bool 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
*** 715,720 ****
--- 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_
*** 1251,1256 ****
--- 1268,1276 ----
  #undef TARGET_FUNCTION_OK_FOR_SIBCALL
  #define TARGET_FUNCTION_OK_FOR_SIBCALL mips_function_ok_for_sibcall
  
+ #undef TARGET_SET_CURRENT_FUNCTION
+ #define TARGET_SET_CURRENT_FUNCTION mips_set_current_function
+ 
  #undef TARGET_VALID_POINTER_MODE
  #define TARGET_VALID_POINTER_MODE mips_valid_pointer_mode
  #undef TARGET_RTX_COSTS
*************** mips_far_type_p (const_tree type)
*** 1369,1374 ****
--- 1389,1407 ----
  	  || lookup_attribute ("far", TYPE_ATTRIBUTES (type)) != NULL);
  }
  
+ /* Similar predicates for "mips16"/"nomips16" attributes.  */
+ 
+ static bool
+ mips_mips16_type_p (const_tree type)
+ {
+   return lookup_attribute ("mips16", TYPE_ATTRIBUTES (type)) != NULL;
+ }
+ 
+ static bool
+ mips_nomips16_type_p (const_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 (const_tree ty
*** 1387,1392 ****
--- 1420,1430 ----
    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_expand_call (rtx result, rtx addr, 
*** 3782,3794 ****
  }
  
  
! /* 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
--- 3833,3854 ----
  }
  
  
! /* Implement TARGET_FUNCTION_OK_FOR_SIBCALL.  */
  
  static bool
! mips_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
  {
!   if (!TARGET_SIBCALLS)
!     return false;
! 
!   /* 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 false;
! 
!   /* Otherwise OK.  */
!   return true;
  }
  
  /* Emit code to move general operand SRC into condition-code
*************** mips_set_tune (const struct mips_cpu_inf
*** 5031,5036 ****
--- 5091,5321 ----
      }
  }
  
+ /* Initialize mips_split_addresses from the associated command-line
+    settings.
+ 
+    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.  */
+       target_flags &= ~MASK_DSP;
+       target_flags &= ~MASK_DSPR2;
+     }
+   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;
+ 
+       /* Provide default values for align_* for 64-bit targets.  */
+       if (TARGET_64BIT)
+ 	{
+ 	  if (align_loops == 0)
+ 	    align_loops = 8;
+ 	  if (align_jumps == 0)
+ 	    align_jumps = 8;
+ 	  if (align_functions == 0)
+ 	    align_functions = 8;
+ 	}
+     }
+ 
+   /* (Re)initialize 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_SET_CURRENT_FUNCTION.  Decide whether the current 
+    function should use the MIPS16 ISA and switch modes accordingly.  */
+ 
+ static void
+ mips_set_current_function (tree fndecl)
+ {
+   int mips16p;
+   if (fndecl)
+     mips16p = SYMBOL_REF_MIPS16_FUNC_P (XEXP (DECL_RTL (fndecl), 0));
+   else
+     mips16p = mips_base_mips16;
+   mips_set_mips16_mode (mips16p);
+ }
+ 
  /* Implement TARGET_HANDLE_OPTION.  */
  
  static bool
*************** override_options (void)
*** 5258,5263 ****
--- 5543,5556 ----
        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)
*** 5275,5328 ****
    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
       above.  */
    if (optimize > 2 && (target_flags_explicit & MASK_VR4130_ALIGN) == 0)
      target_flags |= MASK_VR4130_ALIGN;
  
-   if (TARGET_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;
-     }
- 
-   /* 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;
-     }
- 
    /* Prefer a call to memcpy over inline code when optimizing for size,
       though see MOVE_RATIO in mips.h.  */
    if (optimize_size && (target_flags_explicit & MASK_MEMCPY) == 0)
--- 5568,5579 ----
*************** override_options (void)
*** 5356,5364 ****
    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;
--- 5607,5612 ----
*************** override_options (void)
*** 5486,5605 ****
       initialized yet, so we can't use that here.  */
    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;
-       if (align_jumps == 0)
- 	align_jumps = 8;
-       if (align_functions == 0)
- 	align_functions = 8;
-     }
- 
    /* 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(";
- 
    /* Default to working around R4000 errata only if the processor
       was selected explicitly.  */
    if ((target_flags_explicit & MASK_FIX_R4000) == 0
--- 5734,5742 ----
*************** override_options (void)
*** 5616,5621 ****
--- 5748,5766 ----
    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_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);
  }
  
  /* Swap the register information for registers I and I + 1, which
*************** mips_file_start (void)
*** 6371,6379 ****
    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,
--- 6516,6521 ----
*************** mips_output_function_prologue (FILE *fil
*** 7228,7233 ****
--- 7370,7381 ----
        && 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
*** 8184,8190 ****
  	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
--- 8332,8337 ----
*************** mips_output_mi_thunk (FILE *file, tree t
*** 8235,8241 ****
    /* 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.
--- 8382,8389 ----
    /* 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)
*** 9071,9078 ****
        fputs ("\n", file);
      }
  
-   fprintf (file, "\t.set\tmips16\n");
- 
    switch_to_section (function_section (current_function_decl));
  }
  
--- 9219,9224 ----
*************** build_mips16_call_stub (rtx retval, rtx 
*** 9404,9411 ****
  	  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);
--- 9550,9555 ----
*************** mips_expand_builtin (tree exp, rtx targe
*** 11646,11651 ****
--- 11790,11802 ----
    fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
    fcode = DECL_FUNCTION_CODE (fndecl);
  
+   if (TARGET_MIPS16)
+     {
+       error ("built-in function %qs 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
*** 12152,12157 ****
--- 12303,12345 ----
  				       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 bool
+ mips_use_mips16_mode_p (rtx symbol, tree decl, int first, tree type)
+ {
+   tree parent;
+ 
+   /* Explicit function attributes take precedence.  */
+   if (mips_mips16_type_p (type))
+     return true;
+   if (mips_nomips16_type_p (type))
+     return false;
+ 
+   /* A nested function should inherit the MIPS16 setting from its parent.  */
+   parent = decl_function_context (decl);
+   if (parent)
+     return SYMBOL_REF_MIPS16_FUNC_P (XEXP (DECL_RTL (parent), 0));
+ 
+   /* Handle -mflip-mips16.  */
+   if (TARGET_FLIP_MIPS16
+       && !DECL_BUILT_IN (decl)
+       && !DECL_ARTIFICIAL (decl))
+     {
+       if (!first)
+ 	/* Use the setting we picked first time around.  */
+ 	return SYMBOL_REF_MIPS16_FUNC_P (symbol);
+ 
+       mips16_flipper = !mips16_flipper;
+       if (mips16_flipper)
+ 	return !mips_base_mips16;
+     }
+ 
+   return mips_base_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
*** 12163,12172 ****
    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;
      }
  }
  
--- 12351,12369 ----
    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 128000)
--- gcc/doc/extend.texi	(working copy)
*************** long as the old pointer is never referre
*** 2202,2207 ****
--- 2202,2225 ----
  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, 
+ while MIPS16 code generation is disabled for functions with the 
+ @code{nomips16} attribute.  These attributes override the 
+ @option{-mips16} and @option{-mno-mips16} options on the command line
+ (@pxref{MIPS 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 128000)
--- gcc/doc/invoke.texi	(working copy)
*************** Objective-C and Objective-C++ Dialects}.
*** 620,626 ****
  @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
--- 620,627 ----
  @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}.
*** 11587,11592 ****
--- 11588,11603 ----
  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 { target mipsisa*-*-elf* } } */
+ 
+ #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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]