mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			MIPS compact branch support
gcc/ * config/mips/mips-opts.h (mips_cb_setting): New enum. * config/mips/mips-protos.h: Add definitions for mips_output_jump and mips_output_equal_conditional_branch * gcc/config/mips/mips.c (MIPS_JR): Change to support the JIC instruction. (mips_emit_compare): Add support for the MIPS R6 conditional compact branches. (mips_process_sync_loop): Likewise. (mips_output_order_conditional_branch): Likewise. (mips16_build_call_stub): Change MIPS_CALL to mips_output_jump. (mips_print_operand_punctuation): Update 's' case to only apply to micromips r2. (mips_adjust_insn_length): Add support for forbidden slot hazards. (mips_avoid_hazard): Likewise. (mips_reorg_process_insns): Likewise. (mips_output_jump): New function. (mips_output_equal_conditional_branch): Likewise. (mips_output_conditional_branch): Use jrc/bc if compact branch support is enabled. Ensure the forbidden slots between the two branch instructions is filled with a nop. (mips_option_override): Add support to process the compact branch option and set the correct defaults. Prevent non-explict relocs being using for MIPS R6. (mips_trampoline_init): Add compact branch support. (mips_mult_zero_zero_cost): Allow zero initialisation of accumulators with TARGET_DSP. * gcc/config/mips/mips.h (TARGET_CB_NEVER): New define. (TARGET_CB_MAYBE): New define. (TARGET_CB_ALWAYS): New define. (ISA_HAS_DELAY_SLOTS): New define. (ISA_HAS_COMPACT_BRANCHES): New define. (ISA_HAS_JRC): New define. (MIPS_BRANCH_C): New define. (MIPS_CALL): Removed. (MICROMIPS_J): Removed. * config/mips/mips.md (compact_form): New attr. (hazard): Add support for forbidden slots. (define_delay): Add support for compact branches. (*branch_order<mode>): Likewise. (*branch_order<mode>_inverted): Likewise. (*branch_equality<mode>): Likewise. (*branch_equality<mode>_inverted): Likewise. (*jump_absolute): Likewise. (*jump_pic): Likewise. (indirect_jump): Use mips_output_jump to produce assembly output. (tablejump_<mode>"): Likewise. (*<optab>"): Likewise. (<optab>_internal): Likewise. (sibcall_internal): Likewise. (sibcall_value_internal): Likewise. (sibcall_value_multiple_internal): Likewise. (call_internal): Likewise. (call_split): Likewise. (call_internal_direct): Likewise. (call_direct_split): Likewise. (call_value_internal): Likewise. (call_value_split): Likewise. (call_value_internal_direct): Likewise. (call_value_direct_split): Likewise. (call_value_multiple_internal): Likewise. (call_value_multiple_split): Likewise. (mips_get_fcsr_mips16_<mode>): Likewise. (mips_set_fcsr_mips16_<mode>): Likewise. (tls_get_tp_mips16_<mode>): Likewise. * config/mips/mips.opt: Add -mcompact-branches option. * config/mips/predicates.md (order_operator): Ensure the conditional compact branches are only used if the ISA them. * doc/invoke.texi: Document -mcompact-branches option. gcc/testsuite/ * gcc.target/mips/mips.exp (mips-dg-options): Handle the dependencies between ISA level and compact-branches. * gcc.target/mips/branch-10.c: Update expected output to allow compact forms of b/bal. * gcc.target/mips/branch-11.c: Likewise. * gcc.target/mips/branch-12.c: Likewise. * gcc.target/mips/branch-13.c: Likewise. * gcc.target/mips/branch-3.c: Likewise. * gcc.target/mips/branch-4.c: Likewise. * gcc.target/mips/branch-5.c: Likewise. * gcc.target/mips/branch-6.c: Likewise. * gcc.target/mips/branch-7.c: Likewise. * gcc.target/mips/branch-8.c: Likewise. * gcc.target/mips/branch-9.c: Likewise. * gcc.target/mips/branch-cost-1.c: Likewise. * gcc.target/mips/call-1.c: Likewise. * gcc.target/mips/call-2.c: Likewise. * gcc.target/mips/call-3.c: Likewise. * gcc.target/mips/call-4.c: Likewise. * gcc.target/mips/call-5.c: Likewise. * gcc.target/mips/call-6.c: Likewise. * gcc.target/mips/lazy-binding-1.c: Likewise. * gcc.target/mips/near-far-1.c: Likewise. * gcc.target/mips/near-far-2.c: Likewise. * gcc.target/mips/near-far-3.c: Likewise. * gcc.target/mips/near-far-4.c: Likewise. * gcc.target/mips/umips-branch-3.c: Ensure the test is run with compact branches allowed. * gcc.target/mips/compact-branches-1.c: New file. * gcc.target/mips/compact-branches-2.c: Likewise. * gcc.target/mips/compact-branches-3.c: Likewise. * gcc.target/mips/compact-branches-4.c: Likewise. * gcc.target/mips/compact-branches-5.c: Likewise. * gcc.target/mips/compact-branches-6.c: Likewise. * gcc.target/mips/compact-branches-7.c: Likewise. Co-Authored-By: Andrew Bennett <andrew.bennett@imgtec.com> From-SVN: r227385
This commit is contained in:
		
							parent
							
								
									2503fd9e07
								
							
						
					
					
						commit
						22219d9b1a
					
				|  | @ -1,3 +1,77 @@ | ||||||
|  | 2015-09-01  Matthew Fortune  <matthew.fortune@imgtec.com> | ||||||
|  | 	    Andrew Bennett  <andrew.bennett@imgtec.com> | ||||||
|  | 
 | ||||||
|  | 	* config/mips/mips-opts.h (mips_cb_setting): New enum. | ||||||
|  | 	* config/mips/mips-protos.h: Add definitions for | ||||||
|  | 	mips_output_jump and mips_output_equal_conditional_branch | ||||||
|  | 	* gcc/config/mips/mips.c (MIPS_JR): Change to support the | ||||||
|  | 	JIC instruction. | ||||||
|  | 	(mips_emit_compare): Add support for the MIPS R6 conditional | ||||||
|  | 	compact branches. | ||||||
|  | 	(mips_process_sync_loop): Likewise. | ||||||
|  | 	(mips_output_order_conditional_branch): Likewise. | ||||||
|  | 	(mips16_build_call_stub): Change MIPS_CALL to | ||||||
|  | 	mips_output_jump. | ||||||
|  | 	(mips_print_operand_punctuation): Update 's' case to only | ||||||
|  | 	apply to micromips r2. | ||||||
|  | 	(mips_adjust_insn_length): Add support for forbidden slot | ||||||
|  | 	hazards. | ||||||
|  | 	(mips_avoid_hazard): Likewise. | ||||||
|  | 	(mips_reorg_process_insns): Likewise. | ||||||
|  | 	(mips_output_jump): New function. | ||||||
|  | 	(mips_output_equal_conditional_branch): Likewise. | ||||||
|  | 	(mips_output_conditional_branch): Use jrc/bc if compact | ||||||
|  | 	branch support is enabled.  Ensure the forbidden slots | ||||||
|  | 	between the two branch instructions is filled with a nop. | ||||||
|  | 	(mips_option_override): Add support to process the compact | ||||||
|  | 	branch option and set the correct defaults.  Prevent | ||||||
|  | 	non-explict relocs being using for MIPS R6. | ||||||
|  | 	(mips_trampoline_init): Add compact branch support. | ||||||
|  | 	(mips_mult_zero_zero_cost): Allow zero initialisation of | ||||||
|  | 	accumulators with TARGET_DSP. | ||||||
|  | 	* gcc/config/mips/mips.h (TARGET_CB_NEVER): New define. | ||||||
|  | 	(TARGET_CB_MAYBE): New define. | ||||||
|  | 	(TARGET_CB_ALWAYS): New define. | ||||||
|  | 	(ISA_HAS_DELAY_SLOTS): New define. | ||||||
|  | 	(ISA_HAS_COMPACT_BRANCHES): New define. | ||||||
|  | 	(ISA_HAS_JRC): New define. | ||||||
|  | 	(MIPS_BRANCH_C): New define. | ||||||
|  | 	(MIPS_CALL): Removed. | ||||||
|  | 	(MICROMIPS_J): Removed. | ||||||
|  | 	* config/mips/mips.md (compact_form): New attr. | ||||||
|  | 	(hazard): Add support for forbidden slots. | ||||||
|  | 	(define_delay): Add support for compact branches. | ||||||
|  | 	(*branch_order<mode>): Likewise. | ||||||
|  | 	(*branch_order<mode>_inverted): Likewise. | ||||||
|  | 	(*branch_equality<mode>): Likewise. | ||||||
|  | 	(*branch_equality<mode>_inverted): Likewise. | ||||||
|  | 	(*jump_absolute): Likewise. | ||||||
|  | 	(*jump_pic): Likewise. | ||||||
|  | 	(indirect_jump): Use mips_output_jump to produce assembly output. | ||||||
|  | 	(tablejump_<mode>"): Likewise. | ||||||
|  | 	(*<optab>"): Likewise. | ||||||
|  | 	(<optab>_internal): Likewise. | ||||||
|  | 	(sibcall_internal): Likewise. | ||||||
|  | 	(sibcall_value_internal): Likewise. | ||||||
|  | 	(sibcall_value_multiple_internal): Likewise. | ||||||
|  | 	(call_internal): Likewise. | ||||||
|  | 	(call_split): Likewise. | ||||||
|  | 	(call_internal_direct): Likewise. | ||||||
|  | 	(call_direct_split): Likewise. | ||||||
|  | 	(call_value_internal): Likewise. | ||||||
|  | 	(call_value_split): Likewise. | ||||||
|  | 	(call_value_internal_direct): Likewise. | ||||||
|  | 	(call_value_direct_split): Likewise. | ||||||
|  | 	(call_value_multiple_internal): Likewise. | ||||||
|  | 	(call_value_multiple_split): Likewise. | ||||||
|  | 	(mips_get_fcsr_mips16_<mode>): Likewise. | ||||||
|  | 	(mips_set_fcsr_mips16_<mode>): Likewise. | ||||||
|  | 	(tls_get_tp_mips16_<mode>): Likewise. | ||||||
|  | 	* config/mips/mips.opt: Add -mcompact-branches option. | ||||||
|  | 	* config/mips/predicates.md (order_operator): Ensure the | ||||||
|  | 	conditional compact branches are only used if the ISA them. | ||||||
|  | 	* doc/invoke.texi: Document -mcompact-branches option. | ||||||
|  | 
 | ||||||
| 2015-09-01  Vladimir Makarov  <vmakarov@redhat.com> | 2015-09-01  Vladimir Makarov  <vmakarov@redhat.com> | ||||||
| 
 | 
 | ||||||
| 	PR target/61578 | 	PR target/61578 | ||||||
|  |  | ||||||
|  | @ -47,4 +47,10 @@ enum mips_r10k_cache_barrier_setting { | ||||||
| #define MIPS_ARCH_OPTION_FROM_ABI -1 | #define MIPS_ARCH_OPTION_FROM_ABI -1 | ||||||
| #define MIPS_ARCH_OPTION_NATIVE -2 | #define MIPS_ARCH_OPTION_NATIVE -2 | ||||||
| 
 | 
 | ||||||
|  | /* Enumerates the setting of the -mcompact-branches= option.  */ | ||||||
|  | enum mips_cb_setting { | ||||||
|  |   MIPS_CB_NEVER, | ||||||
|  |   MIPS_CB_OPTIMAL, | ||||||
|  |   MIPS_CB_ALWAYS | ||||||
|  | }; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -298,6 +298,9 @@ extern const char *mips_output_conditional_branch (rtx_insn *, rtx *, | ||||||
| 						   const char *, const char *); | 						   const char *, const char *); | ||||||
| extern const char *mips_output_order_conditional_branch (rtx_insn *, rtx *, | extern const char *mips_output_order_conditional_branch (rtx_insn *, rtx *, | ||||||
| 							 bool); | 							 bool); | ||||||
|  | extern const char *mips_output_equal_conditional_branch (rtx_insn *, rtx *, | ||||||
|  | 							 bool); | ||||||
|  | extern const char *mips_output_jump (rtx *, int, int, bool); | ||||||
| extern const char *mips_output_sync (void); | extern const char *mips_output_sync (void); | ||||||
| extern const char *mips_output_sync_loop (rtx_insn *, rtx *); | extern const char *mips_output_sync_loop (rtx_insn *, rtx *); | ||||||
| extern unsigned int mips_sync_loop_insns (rtx_insn *, rtx *); | extern unsigned int mips_sync_loop_insns (rtx_insn *, rtx *); | ||||||
|  |  | ||||||
|  | @ -176,7 +176,8 @@ along with GCC; see the file COPYING3.  If not see | ||||||
| /* Return the opcode to jump to register DEST.  When the JR opcode is not
 | /* Return the opcode to jump to register DEST.  When the JR opcode is not
 | ||||||
|    available use JALR $0, DEST.  */ |    available use JALR $0, DEST.  */ | ||||||
| #define MIPS_JR(DEST) \ | #define MIPS_JR(DEST) \ | ||||||
|   (((DEST) << 21) | (ISA_HAS_JR ? 0x8 : 0x9)) |   (TARGET_CB_ALWAYS ? ((0x1b << 27) | ((DEST) << 16)) \ | ||||||
|  | 		    : (((DEST) << 21) | (ISA_HAS_JR ? 0x8 : 0x9))) | ||||||
| 
 | 
 | ||||||
| /* Return the opcode for:
 | /* Return the opcode for:
 | ||||||
| 
 | 
 | ||||||
|  | @ -5181,7 +5182,8 @@ mips_allocate_fcc (machine_mode mode) | ||||||
|    conditions are: |    conditions are: | ||||||
| 
 | 
 | ||||||
|       - EQ or NE between two registers. |       - EQ or NE between two registers. | ||||||
|       - any comparison between a register and zero.  */ |       - any comparison between a register and zero. | ||||||
|  |       - if compact branches are available then any condition is valid.  */ | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) | mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) | ||||||
|  | @ -5203,6 +5205,44 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) | ||||||
| 	  else | 	  else | ||||||
| 	    *op1 = force_reg (GET_MODE (cmp_op0), cmp_op1); | 	    *op1 = force_reg (GET_MODE (cmp_op0), cmp_op1); | ||||||
| 	} | 	} | ||||||
|  |       else if (!need_eq_ne_p && TARGET_CB_MAYBE) | ||||||
|  | 	{ | ||||||
|  | 	  bool swap = false; | ||||||
|  | 	  switch (*code) | ||||||
|  | 	    { | ||||||
|  | 	    case LE: | ||||||
|  | 	      swap = true; | ||||||
|  | 	      *code = GE; | ||||||
|  | 	      break; | ||||||
|  | 	    case GT: | ||||||
|  | 	      swap = true; | ||||||
|  | 	      *code = LT; | ||||||
|  | 	      break; | ||||||
|  | 	    case LEU: | ||||||
|  | 	      swap = true; | ||||||
|  | 	      *code = GEU; | ||||||
|  | 	      break; | ||||||
|  | 	    case GTU: | ||||||
|  | 	      swap = true; | ||||||
|  | 	      *code = LTU; | ||||||
|  | 	      break; | ||||||
|  | 	    case GE: | ||||||
|  | 	    case LT: | ||||||
|  | 	    case GEU: | ||||||
|  | 	    case LTU: | ||||||
|  | 	      /* Do nothing.  */ | ||||||
|  | 	      break; | ||||||
|  | 	    default: | ||||||
|  | 	      gcc_unreachable (); | ||||||
|  | 	    } | ||||||
|  | 	  *op1 = force_reg (GET_MODE (cmp_op0), cmp_op1); | ||||||
|  | 	  if (swap) | ||||||
|  | 	    { | ||||||
|  | 	      rtx tmp = *op1; | ||||||
|  | 	      *op1 = *op0; | ||||||
|  | 	      *op0 = tmp; | ||||||
|  | 	    } | ||||||
|  | 	} | ||||||
|       else |       else | ||||||
| 	{ | 	{ | ||||||
| 	  /* The comparison needs a separate scc instruction.  Store the
 | 	  /* The comparison needs a separate scc instruction.  Store the
 | ||||||
|  | @ -7260,7 +7300,7 @@ mips16_build_call_stub (rtx retval, rtx *fn_ptr, rtx args_size, int fp_code) | ||||||
|       if (fp_ret_p) |       if (fp_ret_p) | ||||||
| 	{ | 	{ | ||||||
| 	  /* Now call the non-MIPS16 function.  */ | 	  /* Now call the non-MIPS16 function.  */ | ||||||
| 	  output_asm_insn (MIPS_CALL ("jal", &fn, 0, -1), &fn); | 	  output_asm_insn (mips_output_jump (&fn, 0, -1, true), &fn); | ||||||
| 	  fprintf (asm_out_file, "\t.cfi_register 31,18\n"); | 	  fprintf (asm_out_file, "\t.cfi_register 31,18\n"); | ||||||
| 
 | 
 | ||||||
| 	  /* Move the result from floating-point registers to
 | 	  /* Move the result from floating-point registers to
 | ||||||
|  | @ -8378,7 +8418,7 @@ mips_pop_asm_switch (struct mips_asm_switch *asm_switch) | ||||||
|    '!'  Print "s" to use the short version if the delay slot contains a |    '!'  Print "s" to use the short version if the delay slot contains a | ||||||
| 	16-bit instruction. | 	16-bit instruction. | ||||||
| 
 | 
 | ||||||
|    See also mips_init_print_operand_pucnt.  */ |    See also mips_init_print_operand_punct.  */ | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mips_print_operand_punctuation (FILE *file, int ch) | mips_print_operand_punctuation (FILE *file, int ch) | ||||||
|  | @ -8462,7 +8502,8 @@ mips_print_operand_punctuation (FILE *file, int ch) | ||||||
| 
 | 
 | ||||||
|     case ':': |     case ':': | ||||||
|       /* When final_sequence is 0, the delay slot will be a nop.  We can
 |       /* When final_sequence is 0, the delay slot will be a nop.  We can
 | ||||||
| 	 use the compact version for microMIPS.  */ | 	 use the compact version where available.  The %: formatter will | ||||||
|  | 	 only be present if a compact form of the branch is available.  */ | ||||||
|       if (final_sequence == 0) |       if (final_sequence == 0) | ||||||
| 	putc ('c', file); | 	putc ('c', file); | ||||||
|       break; |       break; | ||||||
|  | @ -8470,8 +8511,9 @@ mips_print_operand_punctuation (FILE *file, int ch) | ||||||
|     case '!': |     case '!': | ||||||
|       /* If the delay slot instruction is short, then use the
 |       /* If the delay slot instruction is short, then use the
 | ||||||
| 	 compact version.  */ | 	 compact version.  */ | ||||||
|       if (final_sequence == 0 |       if (TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED && mips_isa_rev <= 5 | ||||||
| 	  || get_attr_length (final_sequence->insn (1)) == 2) | 	  && (final_sequence == 0 | ||||||
|  | 	      || get_attr_length (final_sequence->insn (1)) == 2)) | ||||||
| 	putc ('s', file); | 	putc ('s', file); | ||||||
|       break; |       break; | ||||||
| 
 | 
 | ||||||
|  | @ -12969,6 +13011,7 @@ mips_adjust_insn_length (rtx_insn *insn, int length) | ||||||
| 	break; | 	break; | ||||||
| 
 | 
 | ||||||
|       case HAZARD_DELAY: |       case HAZARD_DELAY: | ||||||
|  |       case HAZARD_FORBIDDEN_SLOT: | ||||||
| 	length += NOP_INSN_LENGTH; | 	length += NOP_INSN_LENGTH; | ||||||
| 	break; | 	break; | ||||||
| 
 | 
 | ||||||
|  | @ -12980,6 +13023,78 @@ mips_adjust_insn_length (rtx_insn *insn, int length) | ||||||
|   return length; |   return length; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Return the asm template for a call.  OPERANDS are the operands, TARGET_OPNO
 | ||||||
|  |    is the operand number of the target.  SIZE_OPNO is the operand number of | ||||||
|  |    the argument size operand that can optionally hold the call attributes.  If | ||||||
|  |    SIZE_OPNO is not -1 and the call is indirect, use the function symbol from | ||||||
|  |    the call attributes to attach a R_MIPS_JALR relocation to the call.  LINK_P | ||||||
|  |    indicates whether the jump is a call and needs to set the link register. | ||||||
|  | 
 | ||||||
|  |    When generating GOT code without explicit relocation operators, all calls | ||||||
|  |    should use assembly macros.  Otherwise, all indirect calls should use "jr" | ||||||
|  |    or "jalr"; we will arrange to restore $gp afterwards if necessary.  Finally, | ||||||
|  |    we can only generate direct calls for -mabicalls by temporarily switching | ||||||
|  |    to non-PIC mode. | ||||||
|  | 
 | ||||||
|  |    For microMIPS jal(r), we try to generate jal(r)s when a 16-bit | ||||||
|  |    instruction is in the delay slot of jal(r). | ||||||
|  | 
 | ||||||
|  |    Where compact branches are available, we try to use them if the delay slot | ||||||
|  |    has a NOP (or equivalently delay slots were not enabled for the instruction | ||||||
|  |    anyway).  */ | ||||||
|  | 
 | ||||||
|  | const char * | ||||||
|  | mips_output_jump (rtx *operands, int target_opno, int size_opno, bool link_p) | ||||||
|  | { | ||||||
|  |   static char buffer[300]; | ||||||
|  |   char *s = buffer; | ||||||
|  |   bool reg_p = REG_P (operands[target_opno]); | ||||||
|  | 
 | ||||||
|  |   const char *and_link = link_p ? "al" : ""; | ||||||
|  |   const char *reg = reg_p ? "r" : ""; | ||||||
|  |   const char *compact = ""; | ||||||
|  |   const char *nop = "%/"; | ||||||
|  |   const char *short_delay = link_p ? "%!" : ""; | ||||||
|  |   const char *insn_name = TARGET_CB_NEVER || reg_p ? "j" : "b"; | ||||||
|  | 
 | ||||||
|  |   /* Compact branches can only be described when the ISA has support for them
 | ||||||
|  |      as both the compact formatter '%:' and the delay slot NOP formatter '%/' | ||||||
|  |      work as a mutually exclusive pair.  I.e. a NOP is never required if a | ||||||
|  |      compact form is available.  */ | ||||||
|  |   if (!final_sequence | ||||||
|  |       && (TARGET_CB_MAYBE | ||||||
|  | 	  || (ISA_HAS_JRC && !link_p && reg_p))) | ||||||
|  |     { | ||||||
|  |       compact = "c"; | ||||||
|  |       nop = ""; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   if (TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS) | ||||||
|  |     sprintf (s, "%%*%s%s\t%%%d%%/", insn_name, and_link, target_opno); | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       if (!reg_p && TARGET_ABICALLS_PIC2) | ||||||
|  | 	s += sprintf (s, ".option\tpic0\n\t"); | ||||||
|  | 
 | ||||||
|  |       if (reg_p && mips_get_pic_call_symbol (operands, size_opno)) | ||||||
|  | 	{ | ||||||
|  | 	  s += sprintf (s, "%%*.reloc\t1f,R_MIPS_JALR,%%%d\n1:\t", size_opno); | ||||||
|  | 	  /* Not sure why this shouldn't permit a short delay but it did not
 | ||||||
|  | 	     allow it before so we still don't allow it.  */ | ||||||
|  | 	  short_delay = ""; | ||||||
|  | 	} | ||||||
|  |       else | ||||||
|  | 	s += sprintf (s, "%%*"); | ||||||
|  | 
 | ||||||
|  |       s += sprintf (s, "%s%s%s%s%s\t%%%d%s", insn_name, and_link, reg, compact, short_delay, | ||||||
|  | 					    target_opno, nop); | ||||||
|  | 
 | ||||||
|  |       if (!reg_p && TARGET_ABICALLS_PIC2) | ||||||
|  | 	s += sprintf (s, "\n\t.option\tpic2"); | ||||||
|  |     } | ||||||
|  |   return buffer; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* Return the assembly code for INSN, which has the operands given by
 | /* Return the assembly code for INSN, which has the operands given by
 | ||||||
|    OPERANDS, and which branches to OPERANDS[0] if some condition is true. |    OPERANDS, and which branches to OPERANDS[0] if some condition is true. | ||||||
|    BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[0] |    BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[0] | ||||||
|  | @ -13033,12 +13148,25 @@ mips_output_conditional_branch (rtx_insn *insn, rtx *operands, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   /* Output the unconditional branch to TAKEN.  */ |   /* Output the unconditional branch to TAKEN.  */ | ||||||
|   if (TARGET_ABSOLUTE_JUMPS) |   if (TARGET_ABSOLUTE_JUMPS && TARGET_CB_MAYBE) | ||||||
|  |     { | ||||||
|  |       /* Add a hazard nop.  */ | ||||||
|  |       if (!final_sequence) | ||||||
|  | 	{ | ||||||
|  | 	  output_asm_insn ("nop\t\t# hazard nop", 0); | ||||||
|  | 	  fprintf (asm_out_file, "\n"); | ||||||
|  | 	} | ||||||
|  |       output_asm_insn (MIPS_ABSOLUTE_JUMP ("bc\t%0"), &taken); | ||||||
|  |     } | ||||||
|  |   else if (TARGET_ABSOLUTE_JUMPS) | ||||||
|     output_asm_insn (MIPS_ABSOLUTE_JUMP ("j\t%0%/"), &taken); |     output_asm_insn (MIPS_ABSOLUTE_JUMP ("j\t%0%/"), &taken); | ||||||
|   else |   else | ||||||
|     { |     { | ||||||
|       mips_output_load_label (taken); |       mips_output_load_label (taken); | ||||||
|       output_asm_insn ("jr\t%@%]%/", 0); |       if (TARGET_CB_MAYBE) | ||||||
|  | 	output_asm_insn ("jrc\t%@%]", 0); | ||||||
|  |       else | ||||||
|  | 	output_asm_insn ("jr\t%@%]%/", 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   /* Now deal with its delay slot; see above.  */ |   /* Now deal with its delay slot; see above.  */ | ||||||
|  | @ -13052,7 +13180,7 @@ mips_output_conditional_branch (rtx_insn *insn, rtx *operands, | ||||||
| 			   asm_out_file, optimize, 1, NULL); | 			   asm_out_file, optimize, 1, NULL); | ||||||
| 	  final_sequence->insn (1)->set_deleted (); | 	  final_sequence->insn (1)->set_deleted (); | ||||||
| 	} | 	} | ||||||
|       else |       else if (TARGET_CB_NEVER) | ||||||
| 	output_asm_insn ("nop", 0); | 	output_asm_insn ("nop", 0); | ||||||
|       fprintf (asm_out_file, "\n"); |       fprintf (asm_out_file, "\n"); | ||||||
|     } |     } | ||||||
|  | @ -13063,43 +13191,156 @@ mips_output_conditional_branch (rtx_insn *insn, rtx *operands, | ||||||
|   return ""; |   return ""; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Return the assembly code for INSN, which branches to OPERANDS[0]
 | ||||||
|  |    if some equality condition is true.  The condition is given by | ||||||
|  |    OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of | ||||||
|  |    OPERANDS[1].  OPERANDS[2] is the comparison's first operand; | ||||||
|  |    OPERANDS[3] is the second operand and may be zero or a register.  */ | ||||||
|  | 
 | ||||||
|  | const char * | ||||||
|  | mips_output_equal_conditional_branch (rtx_insn* insn, rtx *operands, | ||||||
|  | 				      bool inverted_p) | ||||||
|  | { | ||||||
|  |   const char *branch[2]; | ||||||
|  |   /* For a simple BNEZ or BEQZ microMIPSr3 branch.  */ | ||||||
|  |   if (TARGET_MICROMIPS | ||||||
|  |       && mips_isa_rev <= 5 | ||||||
|  |       && operands[3] == const0_rtx | ||||||
|  |       && get_attr_length (insn) <= 8) | ||||||
|  |     { | ||||||
|  |       if (mips_cb == MIPS_CB_OPTIMAL) | ||||||
|  | 	{ | ||||||
|  | 	  branch[!inverted_p] = "%*b%C1z%:\t%2,%0"; | ||||||
|  | 	  branch[inverted_p] = "%*b%N1z%:\t%2,%0"; | ||||||
|  | 	} | ||||||
|  |       else | ||||||
|  | 	{ | ||||||
|  | 	  branch[!inverted_p] = "%*b%C1z\t%2,%0%/"; | ||||||
|  | 	  branch[inverted_p] = "%*b%N1z\t%2,%0%/"; | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  |   else if (TARGET_CB_MAYBE) | ||||||
|  |     { | ||||||
|  |       if (operands[3] == const0_rtx) | ||||||
|  | 	{ | ||||||
|  | 	  branch[!inverted_p] = MIPS_BRANCH_C ("b%C1z", "%2,%0"); | ||||||
|  | 	  branch[inverted_p] = MIPS_BRANCH_C ("b%N1z", "%2,%0"); | ||||||
|  | 	} | ||||||
|  |       else if (REGNO (operands[2]) != REGNO (operands[3])) | ||||||
|  | 	{ | ||||||
|  | 	  branch[!inverted_p] = MIPS_BRANCH_C ("b%C1", "%2,%3,%0"); | ||||||
|  | 	  branch[inverted_p] = MIPS_BRANCH_C ("b%N1", "%2,%3,%0"); | ||||||
|  | 	} | ||||||
|  |       else | ||||||
|  | 	{ | ||||||
|  | 	  /* This case is degenerate.  It should not happen, but does.  */ | ||||||
|  | 	  if (GET_CODE (operands[1]) == NE) | ||||||
|  | 	    inverted_p = !inverted_p; | ||||||
|  | 
 | ||||||
|  | 	  branch[!inverted_p] = MIPS_BRANCH_C ("b", "%0"); | ||||||
|  | 	  branch[inverted_p] = "%*\t\t# branch never"; | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       branch[!inverted_p] = MIPS_BRANCH ("b%C1", "%2,%z3,%0"); | ||||||
|  |       branch[inverted_p] = MIPS_BRANCH ("b%N1", "%2,%z3,%0"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   return mips_output_conditional_branch (insn, operands, branch[1], branch[0]); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* Return the assembly code for INSN, which branches to OPERANDS[0]
 | /* Return the assembly code for INSN, which branches to OPERANDS[0]
 | ||||||
|    if some ordering condition is true.  The condition is given by |    if some ordering condition is true.  The condition is given by | ||||||
|    OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of |    OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of | ||||||
|    OPERANDS[1].  OPERANDS[2] is the comparison's first operand; |    OPERANDS[1].  OPERANDS[2] is the comparison's first operand; | ||||||
|    its second is always zero.  */ |    OPERANDS[3] is the second operand and may be zero or a register.  */ | ||||||
| 
 | 
 | ||||||
| const char * | const char * | ||||||
| mips_output_order_conditional_branch (rtx_insn *insn, rtx *operands, bool inverted_p) | mips_output_order_conditional_branch (rtx_insn *insn, rtx *operands, | ||||||
|  | 				      bool inverted_p) | ||||||
| { | { | ||||||
|   const char *branch[2]; |   const char *branch[2]; | ||||||
| 
 | 
 | ||||||
|   /* Make BRANCH[1] branch to OPERANDS[0] when the condition is true.
 |   /* Make BRANCH[1] branch to OPERANDS[0] when the condition is true.
 | ||||||
|      Make BRANCH[0] branch on the inverse condition.  */ |      Make BRANCH[0] branch on the inverse condition.  */ | ||||||
|   switch (GET_CODE (operands[1])) |   if (operands[3] != const0_rtx) | ||||||
|     { |     { | ||||||
|       /* These cases are equivalent to comparisons against zero.  */ |       /* Handle degenerate cases that should not, but do, occur.  */ | ||||||
|     case LEU: |       if (REGNO (operands[2]) == REGNO (operands[3])) | ||||||
|       inverted_p = !inverted_p; | 	{ | ||||||
|       /* Fall through.  */ | 	  switch (GET_CODE (operands[1])) | ||||||
|     case GTU: | 	    { | ||||||
|       branch[!inverted_p] = MIPS_BRANCH ("bne", "%2,%.,%0"); | 	    case LT: | ||||||
|       branch[inverted_p] = MIPS_BRANCH ("beq", "%2,%.,%0"); | 	    case LTU: | ||||||
|       break; | 	      inverted_p = !inverted_p; | ||||||
|  | 	      /* Fall through.  */ | ||||||
|  | 	    case GE: | ||||||
|  | 	    case GEU: | ||||||
|  | 	      branch[!inverted_p] = MIPS_BRANCH_C ("b", "%0"); | ||||||
|  | 	      branch[inverted_p] = "%*\t\t# branch never"; | ||||||
|  | 	      break; | ||||||
|  | 	   default: | ||||||
|  | 	      gcc_unreachable (); | ||||||
|  | 	    } | ||||||
|  | 	} | ||||||
|  |       else | ||||||
|  | 	{ | ||||||
|  | 	  branch[!inverted_p] = MIPS_BRANCH_C ("b%C1", "%2,%3,%0"); | ||||||
|  | 	  branch[inverted_p] = MIPS_BRANCH_C ("b%N1", "%2,%3,%0"); | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       switch (GET_CODE (operands[1])) | ||||||
|  | 	{ | ||||||
|  | 	  /* These cases are equivalent to comparisons against zero.  */ | ||||||
|  | 	case LEU: | ||||||
|  | 	  inverted_p = !inverted_p; | ||||||
|  | 	  /* Fall through.  */ | ||||||
|  | 	case GTU: | ||||||
|  | 	  if (TARGET_CB_MAYBE) | ||||||
|  | 	    { | ||||||
|  | 	      branch[!inverted_p] = MIPS_BRANCH_C ("bnez", "%2,%0"); | ||||||
|  | 	      branch[inverted_p] = MIPS_BRANCH_C ("beqz", "%2,%0"); | ||||||
|  | 	    } | ||||||
|  | 	  else | ||||||
|  | 	    { | ||||||
|  | 	      branch[!inverted_p] = MIPS_BRANCH ("bne", "%2,%.,%0"); | ||||||
|  | 	      branch[inverted_p] = MIPS_BRANCH ("beq", "%2,%.,%0"); | ||||||
|  | 	    } | ||||||
|  | 	  break; | ||||||
| 
 | 
 | ||||||
|       /* These cases are always true or always false.  */ | 	  /* These cases are always true or always false.  */ | ||||||
|     case LTU: | 	case LTU: | ||||||
|       inverted_p = !inverted_p; | 	  inverted_p = !inverted_p; | ||||||
|       /* Fall through.  */ | 	  /* Fall through.  */ | ||||||
|     case GEU: | 	case GEU: | ||||||
|       branch[!inverted_p] = MIPS_BRANCH ("beq", "%.,%.,%0"); | 	  if (TARGET_CB_MAYBE) | ||||||
|       branch[inverted_p] = MIPS_BRANCH ("bne", "%.,%.,%0"); | 	    { | ||||||
|       break; | 	      branch[!inverted_p] = MIPS_BRANCH_C ("b", "%0"); | ||||||
|  | 	      branch[inverted_p] = "%*\t\t# branch never"; | ||||||
|  | 	    } | ||||||
|  | 	  else | ||||||
|  | 	    { | ||||||
|  | 	      branch[!inverted_p] = MIPS_BRANCH ("beq", "%.,%.,%0"); | ||||||
|  | 	      branch[inverted_p] = MIPS_BRANCH ("bne", "%.,%.,%0"); | ||||||
|  | 	    } | ||||||
|  | 	  break; | ||||||
| 
 | 
 | ||||||
|     default: | 	default: | ||||||
|       branch[!inverted_p] = MIPS_BRANCH ("b%C1z", "%2,%0"); | 	  if (TARGET_CB_MAYBE) | ||||||
|       branch[inverted_p] = MIPS_BRANCH ("b%N1z", "%2,%0"); | 	    { | ||||||
|       break; | 	      branch[!inverted_p] = MIPS_BRANCH_C ("b%C1z", "%2,%0"); | ||||||
|  | 	      branch[inverted_p] = MIPS_BRANCH_C ("b%N1z", "%2,%0"); | ||||||
|  | 	    } | ||||||
|  | 	  else | ||||||
|  | 	    { | ||||||
|  | 	      branch[!inverted_p] = MIPS_BRANCH ("b%C1z", "%2,%0"); | ||||||
|  | 	      branch[inverted_p] = MIPS_BRANCH ("b%N1z", "%2,%0"); | ||||||
|  | 	    } | ||||||
|  | 	  break; | ||||||
|  | 	} | ||||||
|     } |     } | ||||||
|   return mips_output_conditional_branch (insn, operands, branch[1], branch[0]); |   return mips_output_conditional_branch (insn, operands, branch[1], branch[0]); | ||||||
| } | } | ||||||
|  | @ -13302,11 +13543,18 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands) | ||||||
| 			       at, oldval, inclusive_mask, NULL); | 			       at, oldval, inclusive_mask, NULL); | ||||||
| 	  tmp1 = at; | 	  tmp1 = at; | ||||||
| 	} | 	} | ||||||
|       mips_multi_add_insn ("bne\t%0,%z1,2f", tmp1, required_oldval, NULL); |       if (TARGET_CB_NEVER) | ||||||
|  | 	mips_multi_add_insn ("bne\t%0,%z1,2f", tmp1, required_oldval, NULL); | ||||||
| 
 | 
 | ||||||
|       /* CMP = 0 [delay slot].  */ |       /* CMP = 0 [delay slot].  */ | ||||||
|       if (cmp) |       if (cmp) | ||||||
|         mips_multi_add_insn ("li\t%0,0", cmp, NULL); |         mips_multi_add_insn ("li\t%0,0", cmp, NULL); | ||||||
|  | 
 | ||||||
|  |       if (TARGET_CB_MAYBE && required_oldval == const0_rtx) | ||||||
|  | 	mips_multi_add_insn ("bnezc\t%0,2f", tmp1, NULL); | ||||||
|  |       else if (TARGET_CB_MAYBE) | ||||||
|  | 	mips_multi_add_insn ("bnec\t%0,%1,2f", tmp1, required_oldval, NULL); | ||||||
|  | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|   /* $TMP1 = OLDVAL & EXCLUSIVE_MASK.  */ |   /* $TMP1 = OLDVAL & EXCLUSIVE_MASK.  */ | ||||||
|  | @ -13369,7 +13617,10 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands) | ||||||
|      be annulled.  To ensure this behaviour unconditionally use a NOP |      be annulled.  To ensure this behaviour unconditionally use a NOP | ||||||
|      in the delay slot for the branch likely case.  */ |      in the delay slot for the branch likely case.  */ | ||||||
| 
 | 
 | ||||||
|   mips_multi_add_insn ("beq%?\t%0,%.,1b%~", at, NULL); |   if (TARGET_CB_MAYBE) | ||||||
|  |     mips_multi_add_insn ("beqzc\t%0,1b", at, NULL); | ||||||
|  |   else | ||||||
|  |     mips_multi_add_insn ("beq%?\t%0,%.,1b%~", at, NULL); | ||||||
| 
 | 
 | ||||||
|   /* if (INSN1 != MOVE && INSN1 != LI) NEWVAL = $TMP3 [delay slot].  */ |   /* if (INSN1 != MOVE && INSN1 != LI) NEWVAL = $TMP3 [delay slot].  */ | ||||||
|   if (insn1 != SYNC_INSN1_MOVE && insn1 != SYNC_INSN1_LI && tmp3 != newval) |   if (insn1 != SYNC_INSN1_MOVE && insn1 != SYNC_INSN1_LI && tmp3 != newval) | ||||||
|  | @ -16651,7 +16902,7 @@ mips_orphaned_high_part_p (mips_offset_table *htab, rtx_insn *insn) | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay, | mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay, | ||||||
| 		   rtx *delayed_reg, rtx lo_reg) | 		   rtx *delayed_reg, rtx lo_reg, bool *fs_delay) | ||||||
| { | { | ||||||
|   rtx pattern, set; |   rtx pattern, set; | ||||||
|   int nops, ninsns; |   int nops, ninsns; | ||||||
|  | @ -16677,6 +16928,15 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay, | ||||||
|     nops = 2 - *hilo_delay; |     nops = 2 - *hilo_delay; | ||||||
|   else if (*delayed_reg != 0 && reg_referenced_p (*delayed_reg, pattern)) |   else if (*delayed_reg != 0 && reg_referenced_p (*delayed_reg, pattern)) | ||||||
|     nops = 1; |     nops = 1; | ||||||
|  |   /* If processing a forbidden slot hazard then a NOP is required if the
 | ||||||
|  |      branch instruction was not in a sequence (as the sequence would | ||||||
|  |      imply it is not actually a compact branch anyway) and the current | ||||||
|  |      insn is not an inline asm, and can't go in a delay slot.  */ | ||||||
|  |   else if (*fs_delay && get_attr_can_delay (insn) == CAN_DELAY_NO | ||||||
|  | 	   && GET_CODE (PATTERN (after)) != SEQUENCE | ||||||
|  | 	   && GET_CODE (pattern) != ASM_INPUT | ||||||
|  | 	   && asm_noperands (pattern) < 0) | ||||||
|  |     nops = 1; | ||||||
|   else |   else | ||||||
|     nops = 0; |     nops = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -16689,12 +16949,18 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay, | ||||||
|   /* Set up the state for the next instruction.  */ |   /* Set up the state for the next instruction.  */ | ||||||
|   *hilo_delay += ninsns; |   *hilo_delay += ninsns; | ||||||
|   *delayed_reg = 0; |   *delayed_reg = 0; | ||||||
|  |   *fs_delay = false; | ||||||
|   if (INSN_CODE (insn) >= 0) |   if (INSN_CODE (insn) >= 0) | ||||||
|     switch (get_attr_hazard (insn)) |     switch (get_attr_hazard (insn)) | ||||||
|       { |       { | ||||||
|       case HAZARD_NONE: |       case HAZARD_NONE: | ||||||
| 	break; | 	break; | ||||||
| 
 | 
 | ||||||
|  |       case HAZARD_FORBIDDEN_SLOT: | ||||||
|  | 	if (TARGET_CB_MAYBE) | ||||||
|  | 	  *fs_delay = true; | ||||||
|  | 	break; | ||||||
|  | 
 | ||||||
|       case HAZARD_HILO: |       case HAZARD_HILO: | ||||||
| 	*hilo_delay = 0; | 	*hilo_delay = 0; | ||||||
| 	break; | 	break; | ||||||
|  | @ -16718,6 +16984,7 @@ mips_reorg_process_insns (void) | ||||||
|   rtx_insn *insn, *last_insn, *subinsn, *next_insn; |   rtx_insn *insn, *last_insn, *subinsn, *next_insn; | ||||||
|   rtx lo_reg, delayed_reg; |   rtx lo_reg, delayed_reg; | ||||||
|   int hilo_delay; |   int hilo_delay; | ||||||
|  |   bool fs_delay; | ||||||
| 
 | 
 | ||||||
|   /* Force all instructions to be split into their final form.  */ |   /* Force all instructions to be split into their final form.  */ | ||||||
|   split_all_insns_noflow (); |   split_all_insns_noflow (); | ||||||
|  | @ -16786,6 +17053,7 @@ mips_reorg_process_insns (void) | ||||||
|   hilo_delay = 2; |   hilo_delay = 2; | ||||||
|   delayed_reg = 0; |   delayed_reg = 0; | ||||||
|   lo_reg = gen_rtx_REG (SImode, LO_REGNUM); |   lo_reg = gen_rtx_REG (SImode, LO_REGNUM); | ||||||
|  |   fs_delay = false; | ||||||
| 
 | 
 | ||||||
|   /* Make a second pass over the instructions.  Delete orphaned
 |   /* Make a second pass over the instructions.  Delete orphaned
 | ||||||
|      high-part relocations or turn them into NOPs.  Avoid hazards |      high-part relocations or turn them into NOPs.  Avoid hazards | ||||||
|  | @ -16809,7 +17077,7 @@ mips_reorg_process_insns (void) | ||||||
| 			INSN_CODE (subinsn) = CODE_FOR_nop; | 			INSN_CODE (subinsn) = CODE_FOR_nop; | ||||||
| 		      } | 		      } | ||||||
| 		    mips_avoid_hazard (last_insn, subinsn, &hilo_delay, | 		    mips_avoid_hazard (last_insn, subinsn, &hilo_delay, | ||||||
| 				       &delayed_reg, lo_reg); | 				       &delayed_reg, lo_reg, &fs_delay); | ||||||
| 		  } | 		  } | ||||||
| 	      last_insn = insn; | 	      last_insn = insn; | ||||||
| 	    } | 	    } | ||||||
|  | @ -16830,7 +17098,7 @@ mips_reorg_process_insns (void) | ||||||
| 	      else | 	      else | ||||||
| 		{ | 		{ | ||||||
| 		  mips_avoid_hazard (last_insn, insn, &hilo_delay, | 		  mips_avoid_hazard (last_insn, insn, &hilo_delay, | ||||||
| 				     &delayed_reg, lo_reg); | 				     &delayed_reg, lo_reg, &fs_delay); | ||||||
| 		  last_insn = insn; | 		  last_insn = insn; | ||||||
| 		} | 		} | ||||||
| 	    } | 	    } | ||||||
|  | @ -17695,6 +17963,27 @@ mips_option_override (void) | ||||||
|       target_flags |= MASK_ODD_SPREG; |       target_flags |= MASK_ODD_SPREG; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |   if (!ISA_HAS_COMPACT_BRANCHES && mips_cb == MIPS_CB_ALWAYS) | ||||||
|  |     { | ||||||
|  |       error ("unsupported combination: %qs%s %s", | ||||||
|  | 	      mips_arch_info->name, TARGET_MICROMIPS ? " -mmicromips" : "", | ||||||
|  | 	      "-mcompact-branches=always"); | ||||||
|  |     } | ||||||
|  |   else if (!ISA_HAS_DELAY_SLOTS && mips_cb == MIPS_CB_NEVER) | ||||||
|  |     { | ||||||
|  |       error ("unsupported combination: %qs%s %s", | ||||||
|  | 	      mips_arch_info->name, TARGET_MICROMIPS ? " -mmicromips" : "", | ||||||
|  | 	      "-mcompact-branches=never"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |   /* Require explicit relocs for MIPS R6 onwards.  This enables simplification
 | ||||||
|  |      of the compact branch and jump support through the backend.  */ | ||||||
|  |   if (!TARGET_EXPLICIT_RELOCS && mips_isa_rev >= 6) | ||||||
|  |     { | ||||||
|  |       error ("unsupported combination: %qs %s", | ||||||
|  | 	     mips_arch_info->name, "-mno-explicit-relocs"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|   /* The effect of -mabicalls isn't defined for the EABI.  */ |   /* The effect of -mabicalls isn't defined for the EABI.  */ | ||||||
|   if (mips_abi == ABI_EABI && TARGET_ABICALLS) |   if (mips_abi == ABI_EABI && TARGET_ABICALLS) | ||||||
|     { |     { | ||||||
|  | @ -18714,6 +19003,18 @@ mips_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) | ||||||
| 
 | 
 | ||||||
| #undef OP | #undef OP | ||||||
| 
 | 
 | ||||||
|  |   /* If we are using compact branches we don't have delay slots so
 | ||||||
|  |      place the instruction that was in the delay slot before the JRC | ||||||
|  |      instruction.  */ | ||||||
|  | 
 | ||||||
|  |   if (TARGET_CB_ALWAYS) | ||||||
|  |     { | ||||||
|  |       rtx temp; | ||||||
|  |       temp = trampoline[i-2]; | ||||||
|  |       trampoline[i-2] = trampoline[i-1]; | ||||||
|  |       trampoline[i-1] = temp; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|   /* Copy the trampoline code.  Leave any padding uninitialized.  */ |   /* Copy the trampoline code.  Leave any padding uninitialized.  */ | ||||||
|   for (j = 0; j < i; j++) |   for (j = 0; j < i; j++) | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -92,6 +92,33 @@ struct mips_cpu_info { | ||||||
| /* True if we are generating position-independent VxWorks RTP code.  */ | /* True if we are generating position-independent VxWorks RTP code.  */ | ||||||
| #define TARGET_RTP_PIC (TARGET_VXWORKS_RTP && flag_pic) | #define TARGET_RTP_PIC (TARGET_VXWORKS_RTP && flag_pic) | ||||||
| 
 | 
 | ||||||
|  | /* Compact branches must not be used if the user either selects the
 | ||||||
|  |    'never' policy or the 'optimal' policy on a core that lacks | ||||||
|  |    compact branch instructions.  */ | ||||||
|  | #define TARGET_CB_NEVER (mips_cb == MIPS_CB_NEVER	\ | ||||||
|  | 			 || (mips_cb == MIPS_CB_OPTIMAL \ | ||||||
|  | 			     && !ISA_HAS_COMPACT_BRANCHES)) | ||||||
|  | 
 | ||||||
|  | /* Compact branches may be used if the user either selects the
 | ||||||
|  |    'always' policy or the 'optimal' policy on a core that supports | ||||||
|  |    compact branch instructions.  */ | ||||||
|  | #define TARGET_CB_MAYBE (TARGET_CB_ALWAYS		\ | ||||||
|  | 			 || (mips_cb == MIPS_CB_OPTIMAL \ | ||||||
|  | 			     && ISA_HAS_COMPACT_BRANCHES)) | ||||||
|  | 
 | ||||||
|  | /* Compact branches must always be generated if the user selects
 | ||||||
|  |    the 'always' policy or the 'optimal' policy om a core that | ||||||
|  |    lacks delay slot branch instructions.  */ | ||||||
|  | #define TARGET_CB_ALWAYS (mips_cb == MIPS_CB_ALWAYS	\ | ||||||
|  | 			 || (mips_cb == MIPS_CB_OPTIMAL \ | ||||||
|  | 			     && !ISA_HAS_DELAY_SLOTS)) | ||||||
|  | 
 | ||||||
|  | /* Special handling for JRC that exists in microMIPSR3 as well as R6
 | ||||||
|  |    ISAs with full compact branch support.  */ | ||||||
|  | #define ISA_HAS_JRC ((ISA_HAS_COMPACT_BRANCHES		\ | ||||||
|  | 		      || TARGET_MICROMIPS)		\ | ||||||
|  | 		     && mips_cb != MIPS_CB_NEVER) | ||||||
|  | 
 | ||||||
| /* True if the output file is marked as ".abicalls; .option pic0"
 | /* True if the output file is marked as ".abicalls; .option pic0"
 | ||||||
|    (-call_nonpic).  */ |    (-call_nonpic).  */ | ||||||
| #define TARGET_ABICALLS_PIC0 \ | #define TARGET_ABICALLS_PIC0 \ | ||||||
|  | @ -872,6 +899,10 @@ struct mips_cpu_info { | ||||||
| 
 | 
 | ||||||
| #define ISA_HAS_JR		(mips_isa_rev <= 5) | #define ISA_HAS_JR		(mips_isa_rev <= 5) | ||||||
| 
 | 
 | ||||||
|  | #define ISA_HAS_DELAY_SLOTS	1 | ||||||
|  | 
 | ||||||
|  | #define ISA_HAS_COMPACT_BRANCHES (mips_isa_rev >= 6) | ||||||
|  | 
 | ||||||
| /* ISA has branch likely instructions (e.g. mips2).  */ | /* ISA has branch likely instructions (e.g. mips2).  */ | ||||||
| /* Disable branchlikely for tx39 until compare rewrite.  They haven't
 | /* Disable branchlikely for tx39 until compare rewrite.  They haven't
 | ||||||
|    been generated up to this point.  */ |    been generated up to this point.  */ | ||||||
|  | @ -2645,6 +2676,9 @@ typedef struct mips_args { | ||||||
| #define MIPS_BRANCH(OPCODE, OPERANDS) \ | #define MIPS_BRANCH(OPCODE, OPERANDS) \ | ||||||
|   "%*" OPCODE "%?\t" OPERANDS "%/" |   "%*" OPCODE "%?\t" OPERANDS "%/" | ||||||
| 
 | 
 | ||||||
|  | #define MIPS_BRANCH_C(OPCODE, OPERANDS) \ | ||||||
|  |   "%*" OPCODE "%:\t" OPERANDS | ||||||
|  | 
 | ||||||
| /* Return an asm string that forces INSN to be treated as an absolute
 | /* Return an asm string that forces INSN to be treated as an absolute
 | ||||||
|    J or JAL instruction instead of an assembler macro.  */ |    J or JAL instruction instead of an assembler macro.  */ | ||||||
| #define MIPS_ABSOLUTE_JUMP(INSN) \ | #define MIPS_ABSOLUTE_JUMP(INSN) \ | ||||||
|  | @ -2652,45 +2686,6 @@ typedef struct mips_args { | ||||||
|    ? ".option\tpic0\n\t" INSN "\n\t.option\tpic2"		\ |    ? ".option\tpic0\n\t" INSN "\n\t.option\tpic2"		\ | ||||||
|    : INSN) |    : INSN) | ||||||
| 
 | 
 | ||||||
| /* Return the asm template for a call.  INSN is the instruction's mnemonic
 |  | ||||||
|    ("j" or "jal"), OPERANDS are its operands, TARGET_OPNO is the operand |  | ||||||
|    number of the target.  SIZE_OPNO is the operand number of the argument size |  | ||||||
|    operand that can optionally hold the call attributes.  If SIZE_OPNO is not |  | ||||||
|    -1 and the call is indirect, use the function symbol from the call |  | ||||||
|    attributes to attach a R_MIPS_JALR relocation to the call. |  | ||||||
| 
 |  | ||||||
|    When generating GOT code without explicit relocation operators, |  | ||||||
|    all calls should use assembly macros.  Otherwise, all indirect |  | ||||||
|    calls should use "jr" or "jalr"; we will arrange to restore $gp |  | ||||||
|    afterwards if necessary.  Finally, we can only generate direct |  | ||||||
|    calls for -mabicalls by temporarily switching to non-PIC mode. |  | ||||||
| 
 |  | ||||||
|    For microMIPS jal(r), we try to generate jal(r)s when a 16-bit |  | ||||||
|    instruction is in the delay slot of jal(r).  */ |  | ||||||
| #define MIPS_CALL(INSN, OPERANDS, TARGET_OPNO, SIZE_OPNO)	\ |  | ||||||
|   (TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS			\ |  | ||||||
|    ? "%*" INSN "\t%" #TARGET_OPNO "%/"				\ |  | ||||||
|    : REG_P (OPERANDS[TARGET_OPNO])				\ |  | ||||||
|    ? (mips_get_pic_call_symbol (OPERANDS, SIZE_OPNO)		\ |  | ||||||
|       ? ("%*.reloc\t1f,R_MIPS_JALR,%" #SIZE_OPNO "\n"		\ |  | ||||||
| 	 "1:\t" INSN "r\t%" #TARGET_OPNO "%/")			\ |  | ||||||
|       : TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED	\ |  | ||||||
|       ? "%*" INSN "r%!\t%" #TARGET_OPNO "%/"			\ |  | ||||||
|       : "%*" INSN "r\t%" #TARGET_OPNO "%/")			\ |  | ||||||
|    : TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED		\ |  | ||||||
|      ? MIPS_ABSOLUTE_JUMP ("%*" INSN "%!\t%" #TARGET_OPNO "%/")	\ |  | ||||||
|      : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #TARGET_OPNO "%/"))	\ |  | ||||||
| 
 |  | ||||||
| /* Similar to MIPS_CALL, but this is for MICROMIPS "j" to generate
 |  | ||||||
|    "jrc" when nop is in the delay slot of "jr".  */ |  | ||||||
| 
 |  | ||||||
| #define MICROMIPS_J(INSN, OPERANDS, OPNO)			\ |  | ||||||
|   (TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS			\ |  | ||||||
|    ? "%*j\t%" #OPNO "%/"					\ |  | ||||||
|    : REG_P (OPERANDS[OPNO])					\ |  | ||||||
|    ? "%*jr%:\t%" #OPNO						\ |  | ||||||
|    : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #OPNO "%/")) |  | ||||||
| 
 |  | ||||||
|  |  | ||||||
| /* Control the assembler format that we output.  */ | /* Control the assembler format that we output.  */ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -409,6 +409,15 @@ | ||||||
| 	 (eq_attr "sync_mem" "!none") (const_string "syncloop")] | 	 (eq_attr "sync_mem" "!none") (const_string "syncloop")] | ||||||
| 	(const_string "unknown"))) | 	(const_string "unknown"))) | ||||||
| 
 | 
 | ||||||
|  | (define_attr "compact_form" "always,maybe,never" | ||||||
|  |   (cond [(eq_attr "jal" "direct") | ||||||
|  | 	 (const_string "always") | ||||||
|  | 	 (eq_attr "jal" "indirect") | ||||||
|  | 	 (const_string "maybe") | ||||||
|  | 	 (eq_attr "type" "jump") | ||||||
|  | 	 (const_string "maybe")] | ||||||
|  | 	(const_string "never"))) | ||||||
|  | 
 | ||||||
| ;; Mode for conversion types (fcvt) | ;; Mode for conversion types (fcvt) | ||||||
| ;; I2S          integer to float single (SI/DI to SF) | ;; I2S          integer to float single (SI/DI to SF) | ||||||
| ;; I2D          integer to float double (SI/DI to DF) | ;; I2D          integer to float double (SI/DI to DF) | ||||||
|  | @ -694,7 +703,7 @@ | ||||||
| ;; DELAY means that the next instruction cannot read the result | ;; DELAY means that the next instruction cannot read the result | ||||||
| ;; of this one.  HILO means that the next two instructions cannot | ;; of this one.  HILO means that the next two instructions cannot | ||||||
| ;; write to HI or LO. | ;; write to HI or LO. | ||||||
| (define_attr "hazard" "none,delay,hilo" | (define_attr "hazard" "none,delay,hilo,forbidden_slot" | ||||||
|   (cond [(and (eq_attr "type" "load,fpload,fpidxload") |   (cond [(and (eq_attr "type" "load,fpload,fpidxload") | ||||||
| 	      (match_test "ISA_HAS_LOAD_DELAY")) | 	      (match_test "ISA_HAS_LOAD_DELAY")) | ||||||
| 	 (const_string "delay") | 	 (const_string "delay") | ||||||
|  | @ -1045,21 +1054,37 @@ | ||||||
|    (nil) |    (nil) | ||||||
|    (eq_attr "can_delay" "yes")]) |    (eq_attr "can_delay" "yes")]) | ||||||
| 
 | 
 | ||||||
| ;; Branches that don't have likely variants do not annul on false. | ;; Branches that have delay slots and don't have likely variants do | ||||||
|  | ;; not annul on false. | ||||||
| (define_delay (and (eq_attr "type" "branch") | (define_delay (and (eq_attr "type" "branch") | ||||||
| 		   (not (match_test "TARGET_MIPS16")) | 		   (not (match_test "TARGET_MIPS16")) | ||||||
|  | 		   (ior (match_test "TARGET_CB_NEVER") | ||||||
|  | 			(and (eq_attr "compact_form" "maybe") | ||||||
|  | 			     (not (match_test "TARGET_CB_ALWAYS"))) | ||||||
|  | 			(eq_attr "compact_form" "never")) | ||||||
| 		   (eq_attr "branch_likely" "no")) | 		   (eq_attr "branch_likely" "no")) | ||||||
|   [(eq_attr "can_delay" "yes") |   [(eq_attr "can_delay" "yes") | ||||||
|    (nil) |    (nil) | ||||||
|    (nil)]) |    (nil)]) | ||||||
| 
 | 
 | ||||||
| (define_delay (eq_attr "type" "jump") | (define_delay (and (eq_attr "type" "jump") | ||||||
|  | 		   (ior (match_test "TARGET_CB_NEVER") | ||||||
|  | 			(and (eq_attr "compact_form" "maybe") | ||||||
|  | 			     (not (match_test "TARGET_CB_ALWAYS"))) | ||||||
|  | 			(eq_attr "compact_form" "never"))) | ||||||
|   [(eq_attr "can_delay" "yes") |   [(eq_attr "can_delay" "yes") | ||||||
|    (nil) |    (nil) | ||||||
|    (nil)]) |    (nil)]) | ||||||
| 
 | 
 | ||||||
|  | ;; Call type instructions should never have a compact form as the | ||||||
|  | ;; type is only used for MIPS16 patterns.  For safety put the compact | ||||||
|  | ;; branch detection condition in anyway. | ||||||
| (define_delay (and (eq_attr "type" "call") | (define_delay (and (eq_attr "type" "call") | ||||||
| 		   (eq_attr "jal_macro" "no")) | 		   (eq_attr "jal_macro" "no") | ||||||
|  | 		   (ior (match_test "TARGET_CB_NEVER") | ||||||
|  | 			(and (eq_attr "compact_form" "maybe") | ||||||
|  | 			     (not (match_test "TARGET_CB_ALWAYS"))) | ||||||
|  | 			(eq_attr "compact_form" "never"))) | ||||||
|   [(eq_attr "can_delay" "yes") |   [(eq_attr "can_delay" "yes") | ||||||
|    (nil) |    (nil) | ||||||
|    (nil)]) |    (nil)]) | ||||||
|  | @ -5813,25 +5838,29 @@ | ||||||
|   [(set (pc) |   [(set (pc) | ||||||
| 	(if_then_else | 	(if_then_else | ||||||
| 	 (match_operator 1 "order_operator" | 	 (match_operator 1 "order_operator" | ||||||
| 			 [(match_operand:GPR 2 "register_operand" "d") | 			 [(match_operand:GPR 2 "register_operand" "d,d") | ||||||
| 			  (const_int 0)]) | 			  (match_operand:GPR 3 "reg_or_0_operand" "J,d")]) | ||||||
| 	 (label_ref (match_operand 0 "" "")) | 	 (label_ref (match_operand 0 "" "")) | ||||||
| 	 (pc)))] | 	 (pc)))] | ||||||
|   "!TARGET_MIPS16" |   "!TARGET_MIPS16" | ||||||
|   { return mips_output_order_conditional_branch (insn, operands, false); } |   { return mips_output_order_conditional_branch (insn, operands, false); } | ||||||
|   [(set_attr "type" "branch")]) |   [(set_attr "type" "branch") | ||||||
|  |    (set_attr "compact_form" "maybe,always") | ||||||
|  |    (set_attr "hazard" "forbidden_slot")]) | ||||||
| 
 | 
 | ||||||
| (define_insn "*branch_order<mode>_inverted" | (define_insn "*branch_order<mode>_inverted" | ||||||
|   [(set (pc) |   [(set (pc) | ||||||
| 	(if_then_else | 	(if_then_else | ||||||
| 	 (match_operator 1 "order_operator" | 	 (match_operator 1 "order_operator" | ||||||
| 			 [(match_operand:GPR 2 "register_operand" "d") | 			 [(match_operand:GPR 2 "register_operand" "d,d") | ||||||
| 			  (const_int 0)]) | 			  (match_operand:GPR 3 "reg_or_0_operand" "J,d")]) | ||||||
| 	 (pc) | 	 (pc) | ||||||
| 	 (label_ref (match_operand 0 "" ""))))] | 	 (label_ref (match_operand 0 "" ""))))] | ||||||
|   "!TARGET_MIPS16" |   "!TARGET_MIPS16" | ||||||
|   { return mips_output_order_conditional_branch (insn, operands, true); } |   { return mips_output_order_conditional_branch (insn, operands, true); } | ||||||
|   [(set_attr "type" "branch")]) |   [(set_attr "type" "branch") | ||||||
|  |    (set_attr "compact_form" "maybe,always") | ||||||
|  |    (set_attr "hazard" "forbidden_slot")]) | ||||||
| 
 | 
 | ||||||
| ;; Conditional branch on equality comparison. | ;; Conditional branch on equality comparison. | ||||||
| 
 | 
 | ||||||
|  | @ -5844,20 +5873,10 @@ | ||||||
| 	 (label_ref (match_operand 0 "" "")) | 	 (label_ref (match_operand 0 "" "")) | ||||||
| 	 (pc)))] | 	 (pc)))] | ||||||
|   "!TARGET_MIPS16" |   "!TARGET_MIPS16" | ||||||
| { |   { return mips_output_equal_conditional_branch (insn, operands, false); } | ||||||
|   /* For a simple BNEZ or BEQZ microMIPS branch.  */ |   [(set_attr "type" "branch") | ||||||
|   if (TARGET_MICROMIPS |    (set_attr "compact_form" "maybe") | ||||||
|       && operands[3] == const0_rtx |    (set_attr "hazard" "forbidden_slot")]) | ||||||
|       && get_attr_length (insn) <= 8) |  | ||||||
|     return mips_output_conditional_branch (insn, operands, |  | ||||||
| 					   "%*b%C1z%:\t%2,%0", |  | ||||||
| 					   "%*b%N1z%:\t%2,%0"); |  | ||||||
| 
 |  | ||||||
|   return mips_output_conditional_branch (insn, operands, |  | ||||||
| 					 MIPS_BRANCH ("b%C1", "%2,%z3,%0"), |  | ||||||
| 					 MIPS_BRANCH ("b%N1", "%2,%z3,%0")); |  | ||||||
| } |  | ||||||
|   [(set_attr "type" "branch")]) |  | ||||||
| 
 | 
 | ||||||
| (define_insn "*branch_equality<mode>_inverted" | (define_insn "*branch_equality<mode>_inverted" | ||||||
|   [(set (pc) |   [(set (pc) | ||||||
|  | @ -5868,20 +5887,10 @@ | ||||||
| 	 (pc) | 	 (pc) | ||||||
| 	 (label_ref (match_operand 0 "" ""))))] | 	 (label_ref (match_operand 0 "" ""))))] | ||||||
|   "!TARGET_MIPS16" |   "!TARGET_MIPS16" | ||||||
| { |   { return mips_output_equal_conditional_branch (insn, operands, true); } | ||||||
|   /* For a simple BNEZ or BEQZ microMIPS branch.  */ |   [(set_attr "type" "branch") | ||||||
|   if (TARGET_MICROMIPS |    (set_attr "compact_form" "maybe") | ||||||
|       && operands[3] == const0_rtx |    (set_attr "hazard" "forbidden_slot")]) | ||||||
|       && get_attr_length (insn) <= 8) |  | ||||||
|     return mips_output_conditional_branch (insn, operands, |  | ||||||
| 					   "%*b%N0z%:\t%2,%1", |  | ||||||
| 					   "%*b%C0z%:\t%2,%1"); |  | ||||||
| 
 |  | ||||||
|   return mips_output_conditional_branch (insn, operands, |  | ||||||
| 					 MIPS_BRANCH ("b%N1", "%2,%z3,%0"), |  | ||||||
| 					 MIPS_BRANCH ("b%C1", "%2,%z3,%0")); |  | ||||||
| } |  | ||||||
|   [(set_attr "type" "branch")]) |  | ||||||
| 
 | 
 | ||||||
| ;; MIPS16 branches | ;; MIPS16 branches | ||||||
| 
 | 
 | ||||||
|  | @ -6176,11 +6185,22 @@ | ||||||
|   "!TARGET_MIPS16 && TARGET_ABSOLUTE_JUMPS" |   "!TARGET_MIPS16 && TARGET_ABSOLUTE_JUMPS" | ||||||
| { | { | ||||||
|   if (get_attr_length (insn) <= 8) |   if (get_attr_length (insn) <= 8) | ||||||
|     return "%*b\t%l0%/"; |     { | ||||||
|  |       if (TARGET_CB_MAYBE) | ||||||
|  | 	return MIPS_ABSOLUTE_JUMP ("%*b%:\t%l0"); | ||||||
|  |       else | ||||||
|  | 	return MIPS_ABSOLUTE_JUMP ("%*b\t%l0%/"); | ||||||
|  |     } | ||||||
|   else |   else | ||||||
|     return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/"); |     { | ||||||
|  |       if (TARGET_CB_MAYBE && !final_sequence) | ||||||
|  | 	return MIPS_ABSOLUTE_JUMP ("%*bc\t%l0"); | ||||||
|  |       else | ||||||
|  | 	return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/"); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   [(set_attr "type" "branch")]) |   [(set_attr "type" "branch") | ||||||
|  |    (set_attr "compact_form" "maybe")]) | ||||||
| 
 | 
 | ||||||
| (define_insn "*jump_pic" | (define_insn "*jump_pic" | ||||||
|   [(set (pc) |   [(set (pc) | ||||||
|  | @ -6188,14 +6208,23 @@ | ||||||
|   "!TARGET_MIPS16 && !TARGET_ABSOLUTE_JUMPS" |   "!TARGET_MIPS16 && !TARGET_ABSOLUTE_JUMPS" | ||||||
| { | { | ||||||
|   if (get_attr_length (insn) <= 8) |   if (get_attr_length (insn) <= 8) | ||||||
|     return "%*b\t%l0%/"; |     { | ||||||
|  |       if (TARGET_CB_MAYBE) | ||||||
|  | 	return "%*b%:\t%l0"; | ||||||
|  |       else | ||||||
|  | 	return "%*b\t%l0%/"; | ||||||
|  |     } | ||||||
|   else |   else | ||||||
|     { |     { | ||||||
|       mips_output_load_label (operands[0]); |       mips_output_load_label (operands[0]); | ||||||
|       return "%*jr\t%@%/%]"; |       if (TARGET_CB_MAYBE) | ||||||
|  | 	return "%*jr%:\t%@%]"; | ||||||
|  |       else | ||||||
|  | 	return "%*jr\t%@%/%]"; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   [(set_attr "type" "branch")]) |   [(set_attr "type" "branch") | ||||||
|  |    (set_attr "compact_form" "maybe")]) | ||||||
| 
 | 
 | ||||||
| ;; We need a different insn for the mips16, because a mips16 branch | ;; We need a different insn for the mips16, because a mips16 branch | ||||||
| ;; does not have a delay slot. | ;; does not have a delay slot. | ||||||
|  | @ -6242,12 +6271,9 @@ | ||||||
| (define_insn "indirect_jump_<mode>" | (define_insn "indirect_jump_<mode>" | ||||||
|   [(set (pc) (match_operand:P 0 "register_operand" "d"))] |   [(set (pc) (match_operand:P 0 "register_operand" "d"))] | ||||||
|   "" |   "" | ||||||
| { |   { | ||||||
|   if (TARGET_MICROMIPS) |     return mips_output_jump (operands, 0, -1, false); | ||||||
|     return "%*jr%:\t%0"; |   } | ||||||
|   else |  | ||||||
|     return "%*j\t%0%/"; |  | ||||||
| } |  | ||||||
|   [(set_attr "type" "jump") |   [(set_attr "type" "jump") | ||||||
|    (set_attr "mode" "none")]) |    (set_attr "mode" "none")]) | ||||||
| 
 | 
 | ||||||
|  | @ -6291,12 +6317,9 @@ | ||||||
| 	(match_operand:P 0 "register_operand" "d")) | 	(match_operand:P 0 "register_operand" "d")) | ||||||
|    (use (label_ref (match_operand 1 "" "")))] |    (use (label_ref (match_operand 1 "" "")))] | ||||||
|   "" |   "" | ||||||
| { |   { | ||||||
|   if (TARGET_MICROMIPS) |     return mips_output_jump (operands, 0, -1, false); | ||||||
|     return "%*jr%:\t%0"; |   } | ||||||
|   else |  | ||||||
|     return "%*j\t%0%/"; |  | ||||||
| } |  | ||||||
|   [(set_attr "type" "jump") |   [(set_attr "type" "jump") | ||||||
|    (set_attr "mode" "none")]) |    (set_attr "mode" "none")]) | ||||||
| 
 | 
 | ||||||
|  | @ -6508,10 +6531,8 @@ | ||||||
|   [(any_return)] |   [(any_return)] | ||||||
|   "" |   "" | ||||||
|   { |   { | ||||||
|     if (TARGET_MICROMIPS) |     operands[0] = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); | ||||||
|       return "%*jr%:\t$31"; |     return mips_output_jump (operands, 0, -1, false); | ||||||
|     else |  | ||||||
|       return "%*j\t$31%/"; |  | ||||||
|   } |   } | ||||||
|   [(set_attr "type"	"jump") |   [(set_attr "type"	"jump") | ||||||
|    (set_attr "mode"	"none")]) |    (set_attr "mode"	"none")]) | ||||||
|  | @ -6522,12 +6543,10 @@ | ||||||
|   [(any_return) |   [(any_return) | ||||||
|    (use (match_operand 0 "pmode_register_operand" ""))] |    (use (match_operand 0 "pmode_register_operand" ""))] | ||||||
|   "" |   "" | ||||||
| { |   { | ||||||
|   if (TARGET_MICROMIPS) |     operands[0] = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); | ||||||
|     return "%*jr%:\t%0"; |     return mips_output_jump (operands, 0, -1, false); | ||||||
|   else |   } | ||||||
|     return "%*j\t%0%/"; |  | ||||||
| } |  | ||||||
|   [(set_attr "type"	"jump") |   [(set_attr "type"	"jump") | ||||||
|    (set_attr "mode"	"none")]) |    (set_attr "mode"	"none")]) | ||||||
| 
 | 
 | ||||||
|  | @ -6783,12 +6802,7 @@ | ||||||
|   [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S")) |   [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S")) | ||||||
| 	 (match_operand 1 "" ""))] | 	 (match_operand 1 "" ""))] | ||||||
|   "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" |   "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" | ||||||
| { |   { return mips_output_jump (operands, 0, 1, false); } | ||||||
|   if (TARGET_MICROMIPS) |  | ||||||
|     return MICROMIPS_J ("j", operands, 0); |  | ||||||
|   else |  | ||||||
|     return MIPS_CALL ("j", operands, 0, 1); |  | ||||||
| } |  | ||||||
|   [(set_attr "jal" "indirect,direct") |   [(set_attr "jal" "indirect,direct") | ||||||
|    (set_attr "jal_macro" "no")]) |    (set_attr "jal_macro" "no")]) | ||||||
| 
 | 
 | ||||||
|  | @ -6809,12 +6823,7 @@ | ||||||
|         (call (mem:SI (match_operand 1 "call_insn_operand" "j,S")) |         (call (mem:SI (match_operand 1 "call_insn_operand" "j,S")) | ||||||
|               (match_operand 2 "" "")))] |               (match_operand 2 "" "")))] | ||||||
|   "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" |   "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" | ||||||
| { |   { return mips_output_jump (operands, 1, 2, false); } | ||||||
|   if (TARGET_MICROMIPS) |  | ||||||
|     return MICROMIPS_J ("j", operands, 1); |  | ||||||
|   else |  | ||||||
|     return MIPS_CALL ("j", operands, 1, 2); |  | ||||||
| } |  | ||||||
|   [(set_attr "jal" "indirect,direct") |   [(set_attr "jal" "indirect,direct") | ||||||
|    (set_attr "jal_macro" "no")]) |    (set_attr "jal_macro" "no")]) | ||||||
| 
 | 
 | ||||||
|  | @ -6826,12 +6835,7 @@ | ||||||
| 	(call (mem:SI (match_dup 1)) | 	(call (mem:SI (match_dup 1)) | ||||||
| 	      (match_dup 2)))] | 	      (match_dup 2)))] | ||||||
|   "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" |   "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" | ||||||
| { |   { return mips_output_jump (operands, 1, 2, false); } | ||||||
|   if (TARGET_MICROMIPS) |  | ||||||
|     return MICROMIPS_J ("j", operands, 1); |  | ||||||
|   else |  | ||||||
|     return MIPS_CALL ("j", operands, 1, 2); |  | ||||||
| } |  | ||||||
|   [(set_attr "jal" "indirect,direct") |   [(set_attr "jal" "indirect,direct") | ||||||
|    (set_attr "jal_macro" "no")]) |    (set_attr "jal_macro" "no")]) | ||||||
| 
 | 
 | ||||||
|  | @ -6887,7 +6891,10 @@ | ||||||
| 	 (match_operand 1 "" "")) | 	 (match_operand 1 "" "")) | ||||||
|    (clobber (reg:SI RETURN_ADDR_REGNUM))] |    (clobber (reg:SI RETURN_ADDR_REGNUM))] | ||||||
|   "" |   "" | ||||||
|   { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0, 1); } |   { | ||||||
|  |     return (TARGET_SPLIT_CALLS ? "#" | ||||||
|  | 	    : mips_output_jump (operands, 0, 1, true)); | ||||||
|  |   } | ||||||
|   "reload_completed && TARGET_SPLIT_CALLS" |   "reload_completed && TARGET_SPLIT_CALLS" | ||||||
|   [(const_int 0)] |   [(const_int 0)] | ||||||
| { | { | ||||||
|  | @ -6902,7 +6909,7 @@ | ||||||
|    (clobber (reg:SI RETURN_ADDR_REGNUM)) |    (clobber (reg:SI RETURN_ADDR_REGNUM)) | ||||||
|    (clobber (reg:SI 28))] |    (clobber (reg:SI 28))] | ||||||
|   "TARGET_SPLIT_CALLS" |   "TARGET_SPLIT_CALLS" | ||||||
|   { return MIPS_CALL ("jal", operands, 0, 1); } |   { return mips_output_jump (operands, 0, 1, true); } | ||||||
|   [(set_attr "jal" "indirect,direct") |   [(set_attr "jal" "indirect,direct") | ||||||
|    (set_attr "jal_macro" "no")]) |    (set_attr "jal_macro" "no")]) | ||||||
| 
 | 
 | ||||||
|  | @ -6916,7 +6923,10 @@ | ||||||
|    (const_int 1) |    (const_int 1) | ||||||
|    (clobber (reg:SI RETURN_ADDR_REGNUM))] |    (clobber (reg:SI RETURN_ADDR_REGNUM))] | ||||||
|   "" |   "" | ||||||
|   { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0, -1); } |   { | ||||||
|  |     return (TARGET_SPLIT_CALLS ? "#" | ||||||
|  | 	    : mips_output_jump (operands, 0, -1, true)); | ||||||
|  |   } | ||||||
|   "reload_completed && TARGET_SPLIT_CALLS" |   "reload_completed && TARGET_SPLIT_CALLS" | ||||||
|   [(const_int 0)] |   [(const_int 0)] | ||||||
| { | { | ||||||
|  | @ -6933,7 +6943,7 @@ | ||||||
|    (clobber (reg:SI RETURN_ADDR_REGNUM)) |    (clobber (reg:SI RETURN_ADDR_REGNUM)) | ||||||
|    (clobber (reg:SI 28))] |    (clobber (reg:SI 28))] | ||||||
|   "TARGET_SPLIT_CALLS" |   "TARGET_SPLIT_CALLS" | ||||||
|   { return MIPS_CALL ("jal", operands, 0, -1); } |   { return mips_output_jump (operands, 0, -1, true); } | ||||||
|   [(set_attr "jal" "direct") |   [(set_attr "jal" "direct") | ||||||
|    (set_attr "jal_macro" "no")]) |    (set_attr "jal_macro" "no")]) | ||||||
| 
 | 
 | ||||||
|  | @ -6956,7 +6966,10 @@ | ||||||
|               (match_operand 2 "" ""))) |               (match_operand 2 "" ""))) | ||||||
|    (clobber (reg:SI RETURN_ADDR_REGNUM))] |    (clobber (reg:SI RETURN_ADDR_REGNUM))] | ||||||
|   "" |   "" | ||||||
|   { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, 2); } |   { | ||||||
|  |     return (TARGET_SPLIT_CALLS ? "#" | ||||||
|  | 	    : mips_output_jump (operands, 1, 2, true)); | ||||||
|  |   } | ||||||
|   "reload_completed && TARGET_SPLIT_CALLS" |   "reload_completed && TARGET_SPLIT_CALLS" | ||||||
|   [(const_int 0)] |   [(const_int 0)] | ||||||
| { | { | ||||||
|  | @ -6974,7 +6987,7 @@ | ||||||
|    (clobber (reg:SI RETURN_ADDR_REGNUM)) |    (clobber (reg:SI RETURN_ADDR_REGNUM)) | ||||||
|    (clobber (reg:SI 28))] |    (clobber (reg:SI 28))] | ||||||
|   "TARGET_SPLIT_CALLS" |   "TARGET_SPLIT_CALLS" | ||||||
|   { return MIPS_CALL ("jal", operands, 1, 2); } |   { return mips_output_jump (operands, 1, 2, true); } | ||||||
|   [(set_attr "jal" "indirect,direct") |   [(set_attr "jal" "indirect,direct") | ||||||
|    (set_attr "jal_macro" "no")]) |    (set_attr "jal_macro" "no")]) | ||||||
| 
 | 
 | ||||||
|  | @ -6986,7 +6999,10 @@ | ||||||
|    (const_int 1) |    (const_int 1) | ||||||
|    (clobber (reg:SI RETURN_ADDR_REGNUM))] |    (clobber (reg:SI RETURN_ADDR_REGNUM))] | ||||||
|   "" |   "" | ||||||
|   { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, -1); } |   { | ||||||
|  |     return (TARGET_SPLIT_CALLS ? "#" | ||||||
|  | 	    : mips_output_jump (operands, 1, -1, true)); | ||||||
|  |   } | ||||||
|   "reload_completed && TARGET_SPLIT_CALLS" |   "reload_completed && TARGET_SPLIT_CALLS" | ||||||
|   [(const_int 0)] |   [(const_int 0)] | ||||||
| { | { | ||||||
|  | @ -7005,7 +7021,7 @@ | ||||||
|    (clobber (reg:SI RETURN_ADDR_REGNUM)) |    (clobber (reg:SI RETURN_ADDR_REGNUM)) | ||||||
|    (clobber (reg:SI 28))] |    (clobber (reg:SI 28))] | ||||||
|   "TARGET_SPLIT_CALLS" |   "TARGET_SPLIT_CALLS" | ||||||
|   { return MIPS_CALL ("jal", operands, 1, -1); } |   { return mips_output_jump (operands, 1, -1, true); } | ||||||
|   [(set_attr "jal" "direct") |   [(set_attr "jal" "direct") | ||||||
|    (set_attr "jal_macro" "no")]) |    (set_attr "jal_macro" "no")]) | ||||||
| 
 | 
 | ||||||
|  | @ -7019,7 +7035,10 @@ | ||||||
| 	      (match_dup 2))) | 	      (match_dup 2))) | ||||||
|    (clobber (reg:SI RETURN_ADDR_REGNUM))] |    (clobber (reg:SI RETURN_ADDR_REGNUM))] | ||||||
|   "" |   "" | ||||||
|   { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, 2); } |   { | ||||||
|  |     return (TARGET_SPLIT_CALLS ? "#" | ||||||
|  | 	    : mips_output_jump (operands, 1, 2, true)); | ||||||
|  |   } | ||||||
|   "reload_completed && TARGET_SPLIT_CALLS" |   "reload_completed && TARGET_SPLIT_CALLS" | ||||||
|   [(const_int 0)] |   [(const_int 0)] | ||||||
| { | { | ||||||
|  | @ -7040,7 +7059,7 @@ | ||||||
|    (clobber (reg:SI RETURN_ADDR_REGNUM)) |    (clobber (reg:SI RETURN_ADDR_REGNUM)) | ||||||
|    (clobber (reg:SI 28))] |    (clobber (reg:SI 28))] | ||||||
|   "TARGET_SPLIT_CALLS" |   "TARGET_SPLIT_CALLS" | ||||||
|   { return MIPS_CALL ("jal", operands, 1, 2); } |   { return mips_output_jump (operands, 1, 2, true); } | ||||||
|   [(set_attr "jal" "indirect,direct") |   [(set_attr "jal" "indirect,direct") | ||||||
|    (set_attr "jal_macro" "no")]) |    (set_attr "jal_macro" "no")]) | ||||||
| 
 | 
 | ||||||
|  | @ -7411,7 +7430,7 @@ | ||||||
|    (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) |    (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) | ||||||
|    (clobber (reg:P RETURN_ADDR_REGNUM))] |    (clobber (reg:P RETURN_ADDR_REGNUM))] | ||||||
|   "HAVE_AS_TLS && TARGET_MIPS16" |   "HAVE_AS_TLS && TARGET_MIPS16" | ||||||
|   { return MIPS_CALL ("jal", operands, 0, -1); } |   { return mips_output_jump (operands, 0, -1, true); } | ||||||
|   [(set_attr "type" "call") |   [(set_attr "type" "call") | ||||||
|    (set_attr "insn_count" "3") |    (set_attr "insn_count" "3") | ||||||
|    (set_attr "mode" "<MODE>")]) |    (set_attr "mode" "<MODE>")]) | ||||||
|  | @ -7452,7 +7471,7 @@ | ||||||
|    (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) |    (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) | ||||||
|    (clobber (reg:P RETURN_ADDR_REGNUM))] |    (clobber (reg:P RETURN_ADDR_REGNUM))] | ||||||
|   "TARGET_HARD_FLOAT_ABI && TARGET_MIPS16" |   "TARGET_HARD_FLOAT_ABI && TARGET_MIPS16" | ||||||
|   { return MIPS_CALL ("jal", operands, 0, -1); } |   { return mips_output_jump (operands, 0, -1, true); } | ||||||
|   [(set_attr "type" "call") |   [(set_attr "type" "call") | ||||||
|    (set_attr "insn_count" "3")]) |    (set_attr "insn_count" "3")]) | ||||||
| 
 | 
 | ||||||
|  | @ -7482,7 +7501,7 @@ | ||||||
|    (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) |    (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) | ||||||
|    (clobber (reg:P RETURN_ADDR_REGNUM))] |    (clobber (reg:P RETURN_ADDR_REGNUM))] | ||||||
|   "TARGET_HARD_FLOAT_ABI && TARGET_MIPS16" |   "TARGET_HARD_FLOAT_ABI && TARGET_MIPS16" | ||||||
|   { return MIPS_CALL ("jal", operands, 0, -1); } |   { return mips_output_jump (operands, 0, -1, true); } | ||||||
|   [(set_attr "type" "call") |   [(set_attr "type" "call") | ||||||
|    (set_attr "insn_count" "3")]) |    (set_attr "insn_count" "3")]) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -418,3 +418,20 @@ Driver | ||||||
| mload-store-pairs | mload-store-pairs | ||||||
| Target Report Var(TARGET_LOAD_STORE_PAIRS) Init(1) | Target Report Var(TARGET_LOAD_STORE_PAIRS) Init(1) | ||||||
| Enable load/store bonding. | Enable load/store bonding. | ||||||
|  | 
 | ||||||
|  | mcompact-branches= | ||||||
|  | Target RejectNegative JoinedOrMissing Var(mips_cb) Report Enum(mips_cb_setting) Init(MIPS_CB_OPTIMAL) | ||||||
|  | Specify the compact branch usage policy | ||||||
|  | 
 | ||||||
|  | Enum | ||||||
|  | Name(mips_cb_setting) Type(enum mips_cb_setting) | ||||||
|  | Policies available for use with -mcompact-branches=: | ||||||
|  | 
 | ||||||
|  | EnumValue | ||||||
|  | Enum(mips_cb_setting) String(never) Value(MIPS_CB_NEVER) | ||||||
|  | 
 | ||||||
|  | EnumValue | ||||||
|  | Enum(mips_cb_setting) String(optimal) Value(MIPS_CB_OPTIMAL) | ||||||
|  | 
 | ||||||
|  | EnumValue | ||||||
|  | Enum(mips_cb_setting) String(always) Value(MIPS_CB_ALWAYS) | ||||||
|  |  | ||||||
|  | @ -475,7 +475,18 @@ | ||||||
|   (match_code "eq,ne,lt,ltu,ge,geu")) |   (match_code "eq,ne,lt,ltu,ge,geu")) | ||||||
| 
 | 
 | ||||||
| (define_predicate "order_operator" | (define_predicate "order_operator" | ||||||
|   (match_code "lt,ltu,le,leu,ge,geu,gt,gtu")) |   (match_code "lt,ltu,le,leu,ge,geu,gt,gtu") | ||||||
|  | { | ||||||
|  |   if (XEXP (op, 1) == const0_rtx) | ||||||
|  |     return true; | ||||||
|  | 
 | ||||||
|  |   if (TARGET_CB_MAYBE | ||||||
|  |       && (GET_CODE (op) == LT || GET_CODE (op) == LTU | ||||||
|  | 	  || GET_CODE (op) == GE || GET_CODE (op) == GEU)) | ||||||
|  |     return true; | ||||||
|  | 
 | ||||||
|  |   return false; | ||||||
|  | }) | ||||||
| 
 | 
 | ||||||
| ;; For NE, cstore uses sltu instructions in which the first operand is $0. | ;; For NE, cstore uses sltu instructions in which the first operand is $0. | ||||||
| ;; This isn't possible in mips16 code. | ;; This isn't possible in mips16 code. | ||||||
|  |  | ||||||
|  | @ -782,6 +782,7 @@ Objective-C and Objective-C++ Dialects}. | ||||||
| -mgp32  -mgp64  -mfp32  -mfpxx  -mfp64  -mhard-float  -msoft-float @gol | -mgp32  -mgp64  -mfp32  -mfpxx  -mfp64  -mhard-float  -msoft-float @gol | ||||||
| -mno-float  -msingle-float  -mdouble-float @gol | -mno-float  -msingle-float  -mdouble-float @gol | ||||||
| -modd-spreg -mno-odd-spreg @gol | -modd-spreg -mno-odd-spreg @gol | ||||||
|  | -mcompact-branches=@var{policy} @gol | ||||||
| -mabs=@var{mode}  -mnan=@var{encoding} @gol | -mabs=@var{mode}  -mnan=@var{encoding} @gol | ||||||
| -mdsp  -mno-dsp  -mdspr2  -mno-dspr2 @gol | -mdsp  -mno-dsp  -mdspr2  -mno-dspr2 @gol | ||||||
| -mmcu -mmno-mcu @gol | -mmcu -mmno-mcu @gol | ||||||
|  | @ -17303,6 +17304,30 @@ for the o32 ABI.  This is the default for processors that are known to | ||||||
| support these registers.  When using the o32 FPXX ABI, @option{-mno-odd-spreg} | support these registers.  When using the o32 FPXX ABI, @option{-mno-odd-spreg} | ||||||
| is set by default. | is set by default. | ||||||
| 
 | 
 | ||||||
|  | @item -mcompact-branches=never | ||||||
|  | @itemx -mcompact-branches=optimal | ||||||
|  | @itemx -mcompact-branches=always | ||||||
|  | @opindex mcompact-branches=never | ||||||
|  | @opindex mcompact-branches=optimal | ||||||
|  | @opindex mcompact-branches=always | ||||||
|  | These options control which form of branches will be generated.  The | ||||||
|  | default is @option{-mcompact-branches=optimal}. | ||||||
|  | 
 | ||||||
|  | The @option{-mcompact-branches=never} option ensures that compact branch | ||||||
|  | instructions will never be generated. | ||||||
|  | 
 | ||||||
|  | The @option{-mcompact-branches=always} option ensures that a compact | ||||||
|  | branch instruction will be generated if available.  If a compact branch | ||||||
|  | instruction is not available, a delay slot form of the branch will be | ||||||
|  | used instead. | ||||||
|  | 
 | ||||||
|  | This option is supported from MIPS Release 6 onwards. | ||||||
|  | 
 | ||||||
|  | The @option{-mcompact-branches=optimal} option will cause a delay slot | ||||||
|  | branch to be used if one is available in the current ISA and the delay | ||||||
|  | slot is successfully filled.  If the delay slot is not filled, a compact | ||||||
|  | branch will be chosen if one is available. | ||||||
|  | 
 | ||||||
| @item -mabs=2008 | @item -mabs=2008 | ||||||
| @itemx -mabs=legacy | @itemx -mabs=legacy | ||||||
| @opindex mabs=2008 | @opindex mabs=2008 | ||||||
|  |  | ||||||
|  | @ -1,3 +1,42 @@ | ||||||
|  | 2015-09-01  Matthew Fortune  <matthew.fortune@imgtec.com> | ||||||
|  | 	    Andrew Bennett  <andrew.bennett@imgtec.com> | ||||||
|  | 
 | ||||||
|  | 	* gcc.target/mips/mips.exp (mips-dg-options): Handle the | ||||||
|  | 	dependencies between ISA level and compact-branches. | ||||||
|  | 	* gcc.target/mips/branch-10.c: Update expected output to allow | ||||||
|  | 	compact forms of b/bal. | ||||||
|  | 	* gcc.target/mips/branch-11.c: Likewise. | ||||||
|  | 	* gcc.target/mips/branch-12.c: Likewise. | ||||||
|  | 	* gcc.target/mips/branch-13.c: Likewise. | ||||||
|  | 	* gcc.target/mips/branch-3.c: Likewise. | ||||||
|  | 	* gcc.target/mips/branch-4.c: Likewise. | ||||||
|  | 	* gcc.target/mips/branch-5.c: Likewise. | ||||||
|  | 	* gcc.target/mips/branch-6.c: Likewise. | ||||||
|  | 	* gcc.target/mips/branch-7.c: Likewise. | ||||||
|  | 	* gcc.target/mips/branch-8.c: Likewise. | ||||||
|  | 	* gcc.target/mips/branch-9.c: Likewise. | ||||||
|  | 	* gcc.target/mips/branch-cost-1.c: Likewise. | ||||||
|  | 	* gcc.target/mips/call-1.c: Likewise. | ||||||
|  | 	* gcc.target/mips/call-2.c: Likewise. | ||||||
|  | 	* gcc.target/mips/call-3.c: Likewise. | ||||||
|  | 	* gcc.target/mips/call-4.c: Likewise. | ||||||
|  | 	* gcc.target/mips/call-5.c: Likewise. | ||||||
|  | 	* gcc.target/mips/call-6.c: Likewise. | ||||||
|  | 	* gcc.target/mips/lazy-binding-1.c: Likewise. | ||||||
|  | 	* gcc.target/mips/near-far-1.c: Likewise. | ||||||
|  | 	* gcc.target/mips/near-far-2.c: Likewise. | ||||||
|  | 	* gcc.target/mips/near-far-3.c: Likewise. | ||||||
|  | 	* gcc.target/mips/near-far-4.c: Likewise. | ||||||
|  | 	* gcc.target/mips/umips-branch-3.c: Ensure the test is | ||||||
|  | 	run with compact branches allowed. | ||||||
|  | 	* gcc.target/mips/compact-branches-1.c: New file. | ||||||
|  | 	* gcc.target/mips/compact-branches-2.c: Likewise. | ||||||
|  | 	* gcc.target/mips/compact-branches-3.c: Likewise. | ||||||
|  | 	* gcc.target/mips/compact-branches-4.c: Likewise. | ||||||
|  | 	* gcc.target/mips/compact-branches-5.c: Likewise. | ||||||
|  | 	* gcc.target/mips/compact-branches-6.c: Likewise. | ||||||
|  | 	* gcc.target/mips/compact-branches-7.c: Likewise. | ||||||
|  | 
 | ||||||
| 2015-09-01  Steven G. Kargl  <kargl@gcc.gnu.org> | 2015-09-01  Steven G. Kargl  <kargl@gcc.gnu.org> | ||||||
| 
 | 
 | ||||||
| 	* gfortran.dg/read_dir.f90: XFAIL this testcase on FreeBSD. | 	* gfortran.dg/read_dir.f90: XFAIL this testcase on FreeBSD. | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /* { dg-options "-mshared -mabi=n32" } */ | /* { dg-options "-mshared -mabi=n32" } */ | ||||||
| /* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */ | /* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */ | /* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */ | ||||||
| 
 | 
 | ||||||
| #include "branch-helper.h" | #include "branch-helper.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| /* { dg-final { scan-assembler "\taddiu\t\\\$28,\\\$28,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ | /* { dg-final { scan-assembler "\taddiu\t\\\$28,\\\$28,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tlw\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$28\\)\n" } } */ | /* { dg-final { scan-assembler "\tlw\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$28\\)\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\taddiu\t\\\$1,\\\$1,%got_ofst\\(\[^)\]*\\)\n" } } */ | /* { dg-final { scan-assembler "\taddiu\t\\\$1,\\\$1,%got_ofst\\(\[^)\]*\\)\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ | /* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ | ||||||
| 
 | 
 | ||||||
| #include "branch-helper.h" | #include "branch-helper.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /* { dg-options "-mshared -mabi=64" } */ | /* { dg-options "-mshared -mabi=64" } */ | ||||||
| /* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */ | /* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */ | /* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */ | ||||||
| 
 | 
 | ||||||
| #include "branch-helper.h" | #include "branch-helper.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| /* { dg-final { scan-assembler "\tdaddiu\t\\\$28,\\\$28,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ | /* { dg-final { scan-assembler "\tdaddiu\t\\\$28,\\\$28,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tld\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$28\\)\n" } } */ | /* { dg-final { scan-assembler "\tld\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$28\\)\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tdaddiu\t\\\$1,\\\$1,%got_ofst\\(\[^)\]*\\)\n" } } */ | /* { dg-final { scan-assembler "\tdaddiu\t\\\$1,\\\$1,%got_ofst\\(\[^)\]*\\)\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ | /* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ | ||||||
| 
 | 
 | ||||||
| #include "branch-helper.h" | #include "branch-helper.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /* { dg-options "-mshared -mabi=32" } */ | /* { dg-options "-mshared -mabi=32" } */ | ||||||
| /* { dg-final { scan-assembler "\t\\.cpload\t\\\$25\n" } } */ | /* { dg-final { scan-assembler "\t\\.cpload\t\\\$25\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ | /* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\\.cprestore" } } */ | /* { dg-final { scan-assembler-not "\\.cprestore" } } */ | ||||||
| 
 | 
 | ||||||
| #include "branch-helper.h" | #include "branch-helper.h" | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /* { dg-options "-mshared -mabi=n32" } */ | /* { dg-options "-mshared -mabi=n32" } */ | ||||||
| /* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */ | /* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */ | /* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */ | ||||||
| 
 | 
 | ||||||
| #include "branch-helper.h" | #include "branch-helper.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| /* { dg-options "-mshared -mabi=n32" } */ | /* { dg-options "-mshared -mabi=n32" } */ | ||||||
| /* { dg-final { scan-assembler "\taddiu\t\\\$3,\\\$3,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ | /* { dg-final { scan-assembler "\taddiu\t\\\$3,\\\$3,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tlw\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$3\\)\\n" } } */ | /* { dg-final { scan-assembler "\tlw\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$3\\)\\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ | /* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\\\$28" } } */ | /* { dg-final { scan-assembler-not "\\\$28" } } */ | ||||||
| 
 | 
 | ||||||
| #include "branch-helper.h" | #include "branch-helper.h" | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /* { dg-options "-mshared -mabi=64" } */ | /* { dg-options "-mshared -mabi=64" } */ | ||||||
| /* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */ | /* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */ | /* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */ | ||||||
| 
 | 
 | ||||||
| #include "branch-helper.h" | #include "branch-helper.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| /* { dg-options "-mshared -mabi=64" } */ | /* { dg-options "-mshared -mabi=64" } */ | ||||||
| /* { dg-final { scan-assembler "\tdaddiu\t\\\$3,\\\$3,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ | /* { dg-final { scan-assembler "\tdaddiu\t\\\$3,\\\$3,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tld\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$3\\)\\n" } } */ | /* { dg-final { scan-assembler "\tld\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$3\\)\\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ | /* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\\\$28" } } */ | /* { dg-final { scan-assembler-not "\\\$28" } } */ | ||||||
| 
 | 
 | ||||||
| #include "branch-helper.h" | #include "branch-helper.h" | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /* { dg-options "-mshared -mabi=32" } */ | /* { dg-options "-mshared -mabi=32" } */ | ||||||
| /* { dg-final { scan-assembler-not "(\\\$28|cpload|cprestore)" } } */ | /* { dg-final { scan-assembler-not "(\\\$28|cpload|cprestore)" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */ | /* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */ | ||||||
| 
 | 
 | ||||||
| #include "branch-helper.h" | #include "branch-helper.h" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| /* { dg-final { scan-assembler "\tlw\t\\\$1,16\\(\\\$(fp|sp)\\)\n" } } */ | /* { dg-final { scan-assembler "\tlw\t\\\$1,16\\(\\\$(fp|sp)\\)\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tlw\t\\\$1,%got\\(\[^)\]*\\)\\(\\\$1\\)\n" } } */ | /* { dg-final { scan-assembler "\tlw\t\\\$1,%got\\(\[^)\]*\\)\\(\\\$1\\)\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\taddiu\t\\\$1,\\\$1,%lo\\(\[^)\]*\\)\n" } } */ | /* { dg-final { scan-assembler "\taddiu\t\\\$1,\\\$1,%lo\\(\[^)\]*\\)\n" } } */ | ||||||
| /* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ | /* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\\\$28" } } */ | /* { dg-final { scan-assembler-not "\\\$28" } } */ | ||||||
| 
 | 
 | ||||||
| #include "branch-helper.h" | #include "branch-helper.h" | ||||||
|  |  | ||||||
|  | @ -6,4 +6,4 @@ foo (int x, int y, int z, int k) | ||||||
|   return x == k ? x + y : z - x; |   return x == k ? x + y : z - x; | ||||||
| } | } | ||||||
| /* { dg-final { scan-assembler-not "\t(movz|movn)\t" } } */ | /* { dg-final { scan-assembler-not "\t(movz|movn)\t" } } */ | ||||||
| /* { dg-final { scan-assembler "\t(bne|beq)\t" } } */ | /* { dg-final { scan-assembler "\t(bnec?|beqc?)\t" } } */ | ||||||
|  |  | ||||||
|  | @ -1,12 +1,12 @@ | ||||||
| /* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=32" } */ | /* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=32" } */ | ||||||
| /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */ | /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrs?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?s?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrs?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?s?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrs?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrc?s?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail\n1:)?\tjrc?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail2\n1:)?\tjrc?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail3\n1:)?\tjrc?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail3\n1:\tjrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail4\n1:)?\tjrc?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail4\n1:\tjrc?\t" } } */ | ||||||
| 
 | 
 | ||||||
| __attribute__ ((noinline)) static void staticfunc () { asm (""); } | __attribute__ ((noinline)) static void staticfunc () { asm (""); } | ||||||
| int normal (); | int normal (); | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /* See through some simple data-flow.  */ | /* See through some simple data-flow.  */ | ||||||
| /* { dg-options "-mrelax-pic-calls" } */ | /* { dg-options "-mrelax-pic-calls" } */ | ||||||
| /* { dg-final { scan-assembler-times "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrs?\t" 2 } } */ | /* { dg-final { scan-assembler-times "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?s?\t" 2 } } */ | ||||||
| 
 | 
 | ||||||
| extern void g (void); | extern void g (void); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| /* { dg-options "-mrelax-pic-calls -mno-shared" } */ | /* { dg-options "-mrelax-pic-calls -mno-shared" } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrs?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?s?\t" } } */ | ||||||
| /* { dg-require-visibility "" } */ | /* { dg-require-visibility "" } */ | ||||||
| 
 | 
 | ||||||
| __attribute__ ((visibility ("hidden"))) void g (); | __attribute__ ((visibility ("hidden"))) void g (); | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /* See through some simple data-flow.  */ | /* See through some simple data-flow.  */ | ||||||
| /* { dg-options "-mrelax-pic-calls" } */ | /* { dg-options "-mrelax-pic-calls" } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalr\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?\t" } } */ | ||||||
| 
 | 
 | ||||||
| extern void g (void); | extern void g (void); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,13 +2,13 @@ | ||||||
|    in this case (PR target/57260).  */ |    in this case (PR target/57260).  */ | ||||||
| /* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=n32" } */ | /* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=n32" } */ | ||||||
| /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */ | /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalr\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalr\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalr\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalr\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalr\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail3\n1:)?\tjrc?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail3\n1:\tjrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail4\n1:)?\tjrc?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail4\n1:\tjrc?\t" } } */ | ||||||
| 
 | 
 | ||||||
| __attribute__ ((noinline)) static void staticfunc () { asm (""); } | __attribute__ ((noinline)) static void staticfunc () { asm (""); } | ||||||
| int normal (); | int normal (); | ||||||
|  |  | ||||||
|  | @ -1,13 +1,13 @@ | ||||||
| /* Like call-5.c, but for n64.  */ | /* Like call-5.c, but for n64.  */ | ||||||
| /* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=64" } */ | /* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=64" } */ | ||||||
| /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */ | /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalr\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalr\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalr\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalr\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalr\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail3\n1:)?\tjrc?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail3\n1:\tjrc?\t" } } */ | ||||||
| /* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail4\n1:)?\tjrc?\t" } } */ | /* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail4\n1:\tjrc?\t" } } */ | ||||||
| 
 | 
 | ||||||
| __attribute__ ((noinline)) static void staticfunc () { asm (""); } | __attribute__ ((noinline)) static void staticfunc () { asm (""); } | ||||||
| int normal (); | int normal (); | ||||||
|  |  | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | /* { dg-options "-mcompact-branches=always -mno-micromips" } */ | ||||||
|  | int glob; | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | foo (int a, int b) | ||||||
|  | { | ||||||
|  |   if (a < b) | ||||||
|  |     glob = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* { dg-final { scan-assembler "\tbgec\t\\\$\[0-9\]*,\\\$\[0-9\]*" } } */ | ||||||
|  | /* { dg-final { scan-assembler "\tjrc\t\\\$31" } } */ | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | /* { dg-options "-mcompact-branches=never" } */ | ||||||
|  | int glob; | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | foo (int a, int b) | ||||||
|  | { | ||||||
|  |   if (a < b) | ||||||
|  |     glob = 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* { dg-final { scan-assembler-not "\tb\[^ \t\]*c" } } */ | ||||||
|  | /* { dg-final { scan-assembler-not "\tj\[^ \t\]*c" } } */ | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | /* { dg-options "-mcompact-branches=never isa_rev>=6" } */ | ||||||
|  | int glob; | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | foo (int a, int b, volatile int * bar) | ||||||
|  | { | ||||||
|  |   if (a < b) | ||||||
|  |     glob = *bar; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* { dg-final { scan-assembler "\tnop" } } */ | ||||||
|  | /* { dg-final { scan-assembler-not "\tb\[^ \t\]*c" } } */ | ||||||
|  | /* { dg-final { scan-assembler-not "\tj\[^ \t\]*c" } } */ | ||||||
|  | @ -0,0 +1,11 @@ | ||||||
|  | /* { dg-options "-mcompact-branches=optimal isa_rev>=6" } */ | ||||||
|  | int glob; | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | foo (int a, int b, volatile int * bar) | ||||||
|  | { | ||||||
|  |   if (a < b) | ||||||
|  |     glob = *bar; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* { dg-final { scan-assembler "\tb\[^ \t\]*c" } } */ | ||||||
|  | @ -0,0 +1,10 @@ | ||||||
|  | /* { dg-options "-mno-abicalls -mcompact-branches=never isa_rev>=6" } */ | ||||||
|  | void bar (int); | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | foo () | ||||||
|  | { | ||||||
|  |   bar (1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* { dg-final { scan-assembler "\t(j|jal)\t" } } */ | ||||||
|  | @ -0,0 +1,10 @@ | ||||||
|  | /* { dg-options "-mno-abicalls -mcompact-branches=optimal isa_rev>=6" } */ | ||||||
|  | void bar (int); | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | foo () | ||||||
|  | { | ||||||
|  |   bar (1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* { dg-final { scan-assembler "\t(bc|balc)\t" } } */ | ||||||
|  | @ -0,0 +1,12 @@ | ||||||
|  | /* { dg-options "-mhard-float -mcompact-branches=always isa_rev>=6 -mno-micromips" } */ | ||||||
|  | int bar; | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | foo (float a, volatile int * b) | ||||||
|  | { | ||||||
|  |   if (a < 0.1) | ||||||
|  |     bar = *b; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* { dg-final { scan-assembler "\t(bc1eqz|bc1nez)\t" } } */ | ||||||
|  | /* { dg-final { scan-assembler "\tnop" } } */ | ||||||
|  | @ -19,6 +19,6 @@ foo (int n) | ||||||
| /* There should be exactly five uses of $25: one to set up $gp, two to
 | /* There should be exactly five uses of $25: one to set up $gp, two to
 | ||||||
|    load the address of bar (), and two to call it.  */ |    load the address of bar (), and two to call it.  */ | ||||||
| /* { dg-final { scan-assembler-times "\tl.\t\\\$25,%call16\\\(bar\\\)" 2 } } */ | /* { dg-final { scan-assembler-times "\tl.\t\\\$25,%call16\\\(bar\\\)" 2 } } */ | ||||||
| /* { dg-final { scan-assembler-times "\tjalrs?\t\\\$25" 2 } } */ | /* { dg-final { scan-assembler-times "\tjalrc?s?\t\\\$25" 2 } } */ | ||||||
| /* { dg-final { scan-assembler "(\\\$28,|\t.cpload\t)\\\$25" } } */ | /* { dg-final { scan-assembler "(\\\$28,|\t.cpload\t)\\\$25" } } */ | ||||||
| /* { dg-final { scan-assembler-times "\\\$25" 5 } } */ | /* { dg-final { scan-assembler-times "\\\$25" 5 } } */ | ||||||
|  |  | ||||||
|  | @ -243,6 +243,7 @@ set mips_option_groups { | ||||||
|     mips16 "-mips16|-mno-mips16|-mflip-mips16" |     mips16 "-mips16|-mno-mips16|-mflip-mips16" | ||||||
|     mips3d "-mips3d|-mno-mips3d" |     mips3d "-mips3d|-mno-mips3d" | ||||||
|     pic "-f(no-|)(pic|PIC)" |     pic "-f(no-|)(pic|PIC)" | ||||||
|  |     cb "-mcompact-branches=.*" | ||||||
|     profiling "-pg" |     profiling "-pg" | ||||||
|     small-data "-G[0-9]+" |     small-data "-G[0-9]+" | ||||||
|     warnings "-w" |     warnings "-w" | ||||||
|  | @ -1068,8 +1069,10 @@ proc mips-dg-options { args } { | ||||||
| 	# We need a revision 6 or better ISA for: | 	# We need a revision 6 or better ISA for: | ||||||
| 	# | 	# | ||||||
| 	#   - When the LSA instruction is required | 	#   - When the LSA instruction is required | ||||||
|  | 	#   - When only using compact branches | ||||||
| 	if { $isa_rev < 6 | 	if { $isa_rev < 6 | ||||||
| 	     && ([mips_have_test_option_p options "HAS_LSA"]) } { | 	     && ([mips_have_test_option_p options "HAS_LSA"] | ||||||
|  | 		 || [mips_have_test_option_p options "-mcompact-branches=always"]) } { | ||||||
| 	    if { $gp_size == 32 } { | 	    if { $gp_size == 32 } { | ||||||
| 		mips_make_test_option options "-mips32r6" | 		mips_make_test_option options "-mips32r6" | ||||||
| 	    } else { | 	    } else { | ||||||
|  | @ -1164,6 +1167,9 @@ proc mips-dg-options { args } { | ||||||
| 		mips_make_test_option options "-mips64r5" | 		mips_make_test_option options "-mips64r5" | ||||||
| 	    } | 	    } | ||||||
| 	    mips_make_test_option options "-mnan=2008" | 	    mips_make_test_option options "-mnan=2008" | ||||||
|  | 	    if { [mips_have_option_p options "-mcompact-branches=always"] } { | ||||||
|  | 		mips_make_test_option options "-mcompact-branches=optimal" | ||||||
|  | 	    } | ||||||
| 	# Check whether we need to switch from a 32-bit processor to the | 	# Check whether we need to switch from a 32-bit processor to the | ||||||
| 	# "nearest" 64-bit processor. | 	# "nearest" 64-bit processor. | ||||||
| 	} elseif { $gp_size == 64 && [mips_32bit_arch_p $arch] } { | 	} elseif { $gp_size == 64 && [mips_32bit_arch_p $arch] } { | ||||||
|  | @ -1308,6 +1314,11 @@ proc mips-dg-options { args } { | ||||||
| 	    mips_make_test_option options "-mno-micromips" | 	    mips_make_test_option options "-mno-micromips" | ||||||
| 	    mips_make_test_option options "-mnan=legacy" | 	    mips_make_test_option options "-mnan=legacy" | ||||||
| 	} | 	} | ||||||
|  | 	if { $isa_rev < 6 } { | ||||||
|  | 	    if { [mips_have_option_p options "-mcompact-branches=always"] } { | ||||||
|  | 		mips_make_test_option options "-mcompact-branches=optimal" | ||||||
|  | 	    } | ||||||
|  | 	} | ||||||
|         if { $isa_rev > 5 } { |         if { $isa_rev > 5 } { | ||||||
| 	    mips_make_test_option options "-mno-dsp" | 	    mips_make_test_option options "-mno-dsp" | ||||||
| 	    mips_make_test_option options "-mno-mips16" | 	    mips_make_test_option options "-mno-mips16" | ||||||
|  |  | ||||||
|  | @ -16,5 +16,5 @@ int test () | ||||||
| 
 | 
 | ||||||
| /* { dg-final { scan-assembler-not "\tjal\tlong_call_func\n" } } */ | /* { dg-final { scan-assembler-not "\tjal\tlong_call_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\tjal\tfar_func\n" } } */ | /* { dg-final { scan-assembler-not "\tjal\tfar_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler     "\tjal(|s)\tnear_func\n" } } */ | /* { dg-final { scan-assembler     "\t(jal(|s)|balc)\tnear_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\tjal\tnormal_func\n" } } */ | /* { dg-final { scan-assembler-not "\tjal\tnormal_func\n" } } */ | ||||||
|  |  | ||||||
|  | @ -16,5 +16,5 @@ int test () | ||||||
| 
 | 
 | ||||||
| /* { dg-final { scan-assembler-not "\tjal(|s)\tlong_call_func\n" } } */ | /* { dg-final { scan-assembler-not "\tjal(|s)\tlong_call_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\tjal(|s)\tfar_func\n" } } */ | /* { dg-final { scan-assembler-not "\tjal(|s)\tfar_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler     "\tjal(|s)\tnear_func\n" } } */ | /* { dg-final { scan-assembler     "\t(jal(|s)|balc)\tnear_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler     "\tjal(|s)\tnormal_func\n" } } */ | /* { dg-final { scan-assembler     "\t(jal(|s)|balc)\tnormal_func\n" } } */ | ||||||
|  |  | ||||||
|  | @ -13,5 +13,5 @@ NOMIPS16 int test4 () { return normal_func (); } | ||||||
| 
 | 
 | ||||||
| /* { dg-final { scan-assembler-not "\tj\tlong_call_func\n" } } */ | /* { dg-final { scan-assembler-not "\tj\tlong_call_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\tj\tfar_func\n" } } */ | /* { dg-final { scan-assembler-not "\tj\tfar_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler     "\tj(|al|als)\tnear_func\n" } } */ | /* { dg-final { scan-assembler     "\t(j(|al|als)|b(|al)c)\tnear_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\tj\tnormal_func\n" } } */ | /* { dg-final { scan-assembler-not "\tj\tnormal_func\n" } } */ | ||||||
|  |  | ||||||
|  | @ -13,5 +13,5 @@ NOMIPS16 int test4 () { return normal_func (); } | ||||||
| 
 | 
 | ||||||
| /* { dg-final { scan-assembler-not "\tj\tlong_call_func\n" } } */ | /* { dg-final { scan-assembler-not "\tj\tlong_call_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler-not "\tj\tfar_func\n" } } */ | /* { dg-final { scan-assembler-not "\tj\tfar_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler     "\tj(|al|als)\tnear_func\n" } } */ | /* { dg-final { scan-assembler     "\t(j(|al|als)|b(|al)c)\tnear_func\n" } } */ | ||||||
| /* { dg-final { scan-assembler     "\tj(|al|als)\tnormal_func\n" } } */ | /* { dg-final { scan-assembler     "\t(j(|al|als)|b(|al)c)\tnormal_func\n" } } */ | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| /* { dg-options "(-mmicromips)" } */ | /* { dg-options "(-mmicromips) -mcompact-branches=optimal" } */ | ||||||
| /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ | /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ | ||||||
| 
 | 
 | ||||||
| void MICROMIPS | void MICROMIPS | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	 Matthew Fortune
						Matthew Fortune