⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sh.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    {      far = 1;      if (flag_pic)	{	  if (TARGET_SH2)	    jump = "mov.l	%O0,%1; braf	%1";	  else	    jump = "mov.l	r0,@-r15; mova	%O0,r0; mov.l	@r0,%1; add	r0,%1; mov.l	@r15+,r0; jmp	@%1";	}      else	jump = "mov.l	%O0,%1; jmp	@%1";    }  /* If we have a scratch register available, use it.  */  if (GET_CODE ((prev = prev_nonnote_insn (insn))) == INSN      && INSN_CODE (prev) == CODE_FOR_indirect_jump_scratch)    {      this.reg = SET_DEST (XVECEXP (PATTERN (prev), 0, 0));      if (REGNO (this.reg) == R0_REG && flag_pic && ! TARGET_SH2)	jump = "mov.l	r1,@-r15; mova	%O0,r0; mov.l	@r0,r1; add	r1,r0; mov.l	@r15+,r1; jmp	@%1";      output_asm_insn (jump, &this.lab);      if (dbr_sequence_length ())	print_slot (final_sequence);      else	output_asm_insn ("nop", 0);    }  else    {      /* Output the delay slot insn first if any.  */      if (dbr_sequence_length ())	print_slot (final_sequence);      this.reg = gen_rtx_REG (SImode, 13);      /* We must keep the stack aligned to 8-byte boundaries on SH5.	 Fortunately, MACL is fixed and call-clobbered, and we never	 need its value across jumps, so save r13 in it instead of in	 the stack.  */      if (TARGET_SH5)	output_asm_insn ("lds	r13, macl", 0);      else	output_asm_insn ("mov.l	r13,@-r15", 0);      output_asm_insn (jump, &this.lab);      if (TARGET_SH5)	output_asm_insn ("sts	macl, r13", 0);      else	output_asm_insn ("mov.l	@r15+,r13", 0);    }  if (far && flag_pic && TARGET_SH2)    {      braf_base_lab = gen_label_rtx ();      (*targetm.asm_out.internal_label) (asm_out_file, "L",				 CODE_LABEL_NUMBER (braf_base_lab));    }  if (far)    output_asm_insn (".align	2", 0);  (*targetm.asm_out.internal_label) (asm_out_file, "L", CODE_LABEL_NUMBER (this.lab));  this.op = op;  if (far && flag_pic)    {      if (TARGET_SH2)	this.lab = braf_base_lab;      output_asm_insn (".long	%O2-%O0", &this.lab);    }  else    output_asm_insn (far ? ".long	%O2" : ".word %O2-%O0", &this.lab);  return "";}/* Local label counter, used for constants in the pool and inside   pattern branches.  */static int lf = 100;/* Output code for ordinary branches.  */const char *output_branch (int logic, rtx insn, rtx *operands){  switch (get_attr_length (insn))    {    case 6:      /* This can happen if filling the delay slot has caused a forward	 branch to exceed its range (we could reverse it, but only	 when we know we won't overextend other branches; this should	 best be handled by relaxation).	 It can also happen when other condbranches hoist delay slot insn	 from their destination, thus leading to code size increase.	 But the branch will still be in the range -4092..+4098 bytes.  */      if (! TARGET_RELAX)	{	  int label = lf++;	  /* The call to print_slot will clobber the operands.  */	  rtx op0 = operands[0];	  /* If the instruction in the delay slot is annulled (true), then	     there is no delay slot where we can put it now.  The only safe	     place for it is after the label.  final will do that by default.  */	  if (final_sequence	      && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0))	      && get_attr_length (XVECEXP (final_sequence, 0, 1)))	    {	      asm_fprintf (asm_out_file, "\tb%s%ss\t%LLF%d\n", logic ? "f" : "t",	                   ASSEMBLER_DIALECT ? "/" : ".", label);	      print_slot (final_sequence);	    }	  else	    asm_fprintf (asm_out_file, "\tb%s\t%LLF%d\n", logic ? "f" : "t", label);	  output_asm_insn ("bra\t%l0", &op0);	  fprintf (asm_out_file, "\tnop\n");	  (*targetm.asm_out.internal_label) (asm_out_file, "LF", label);	  return "";	}      /* When relaxing, handle this like a short branch.  The linker	 will fix it up if it still doesn't fit after relaxation.  */    case 2:      return logic ? "bt%.\t%l0" : "bf%.\t%l0";      /* These are for SH2e, in which we have to account for the	 extra nop because of the hardware bug in annulled branches.  */    case 8:      if (! TARGET_RELAX)	{	  int label = lf++;	  if (final_sequence	      && INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))	    abort ();	  asm_fprintf (asm_out_file, "b%s%ss\t%LLF%d\n",		       logic ? "f" : "t",		       ASSEMBLER_DIALECT ? "/" : ".", label);	  fprintf (asm_out_file, "\tnop\n");	  output_asm_insn ("bra\t%l0", operands);	  fprintf (asm_out_file, "\tnop\n");	  (*targetm.asm_out.internal_label) (asm_out_file, "LF", label);	  return "";	}      /* When relaxing, fall through.  */    case 4:      {	char buffer[10];	sprintf (buffer, "b%s%ss\t%%l0",		 logic ? "t" : "f",		 ASSEMBLER_DIALECT ? "/" : ".");	output_asm_insn (buffer, &operands[0]);	return "nop";      }    default:      /* There should be no longer branches now - that would	 indicate that something has destroyed the branches set	 up in machine_dependent_reorg.  */      abort ();    }}const char *output_branchy_insn (enum rtx_code code, const char *template,		     rtx insn, rtx *operands){  rtx next_insn = NEXT_INSN (insn);  if (next_insn && GET_CODE (next_insn) == JUMP_INSN && condjump_p (next_insn))    {      rtx src = SET_SRC (PATTERN (next_insn));      if (GET_CODE (src) == IF_THEN_ELSE && GET_CODE (XEXP (src, 0)) != code)	{	  /* Following branch not taken */	  operands[9] = gen_label_rtx ();	  emit_label_after (operands[9], next_insn);	  INSN_ADDRESSES_NEW (operands[9],			      INSN_ADDRESSES (INSN_UID (next_insn))			      + get_attr_length (next_insn));	  return template;	}      else	{	  int offset = (branch_dest (next_insn)			- INSN_ADDRESSES (INSN_UID (next_insn)) + 4);	  if (offset >= -252 && offset <= 258)	    {	      if (GET_CODE (src) == IF_THEN_ELSE)		/* branch_true */		src = XEXP (src, 1);	      operands[9] = src;	      return template;	    }	}    }  operands[9] = gen_label_rtx ();  emit_label_after (operands[9], insn);  INSN_ADDRESSES_NEW (operands[9],		      INSN_ADDRESSES (INSN_UID (insn))		      + get_attr_length (insn));  return template;}const char *output_ieee_ccmpeq (rtx insn, rtx *operands){  return output_branchy_insn (NE, "bt\t%l9\\;fcmp/eq\t%1,%0", insn, operands);}/* Output the start of the assembler file.  */static voidsh_file_start (void){  default_file_start ();#ifdef SYMBIAN  /* Declare the .directive section before it is used.  */  fputs ("\t.section .directive, \"SM\", @progbits, 1\n", asm_out_file);  fputs ("\t.asciz \"#<SYMEDIT>#\\n\"\n", asm_out_file);#endif  if (TARGET_ELF)    /* We need to show the text section with the proper       attributes as in TEXT_SECTION_ASM_OP, before dwarf2out       emits it without attributes in TEXT_SECTION_ASM_OP, else GAS       will complain.  We can teach GAS specifically about the       default attributes for our choice of text section, but       then we would have to change GAS again if/when we change       the text section name.  */    fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);  else    /* Switch to the data section so that the coffsem symbol       isn't in the text section.  */    data_section ();  if (TARGET_LITTLE_ENDIAN)    fputs ("\t.little\n", asm_out_file);  if (!TARGET_ELF)    {      if (TARGET_SHCOMPACT)	fputs ("\t.mode\tSHcompact\n", asm_out_file);      else if (TARGET_SHMEDIA)	fprintf (asm_out_file, "\t.mode\tSHmedia\n\t.abi\t%i\n",		 TARGET_SHMEDIA64 ? 64 : 32);    }}/* Check if PAT includes UNSPEC_CALLER unspec pattern.  */static boolunspec_caller_rtx_p (rtx pat){  switch (GET_CODE (pat))    {    case CONST:      return unspec_caller_rtx_p (XEXP (pat, 0));    case PLUS:    case MINUS:      if (unspec_caller_rtx_p (XEXP (pat, 0)))	return true;      return unspec_caller_rtx_p (XEXP (pat, 1));    case UNSPEC:      if (XINT (pat, 1) == UNSPEC_CALLER)	return true;    default:      break;    }  return false;}/* Indicate that INSN cannot be duplicated.  This is true for insn   that generates an unique label.  */static boolsh_cannot_copy_insn_p (rtx insn){  rtx pat;  if (!reload_completed || !flag_pic)    return false;  if (GET_CODE (insn) != INSN)    return false;  if (asm_noperands (insn) >= 0)    return false;  pat = PATTERN (insn);  if (GET_CODE (pat) != SET)    return false;  pat = SET_SRC (pat);  if (unspec_caller_rtx_p (pat))    return true;  return false;}/* Actual number of instructions used to make a shift by N.  */static const char ashiftrt_insns[] =  { 0,1,2,3,4,5,8,8,8,8,8,8,8,8,8,8,2,3,4,5,8,8,8,8,8,8,8,8,8,8,8,2};/* Left shift and logical right shift are the same.  */static const char shift_insns[]    =  { 0,1,1,2,2,3,3,4,1,2,2,3,3,4,3,3,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3};/* Individual shift amounts needed to get the above length sequences.   One bit right shifts clobber the T bit, so when possible, put one bit   shifts in the middle of the sequence, so the ends are eligible for   branch delay slots.  */static const short shift_amounts[32][5] = {  {0}, {1}, {2}, {2, 1},  {2, 2}, {2, 1, 2}, {2, 2, 2}, {2, 2, 1, 2},  {8}, {8, 1}, {8, 2}, {8, 1, 2},  {8, 2, 2}, {8, 2, 1, 2}, {8, -2, 8}, {8, -1, 8},  {16}, {16, 1}, {16, 2}, {16, 1, 2},  {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8},  {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2},  {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}};/* Likewise, but for shift amounts < 16, up to three highmost bits   might be clobbered.  This is typically used when combined with some   kind of sign or zero extension.  */static const char ext_shift_insns[]    =  { 0,1,1,2,2,3,2,2,1,2,2,3,3,3,2,2,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3};static const short ext_shift_amounts[32][4] = {  {0}, {1}, {2}, {2, 1},  {2, 2}, {2, 1, 2}, {8, -2}, {8, -1},  {8}, {8, 1}, {8, 2}, {8, 1, 2},  {8, 2, 2}, {16, -2, -1}, {16, -2}, {16, -1},  {16}, {16, 1}, {16, 2}, {16, 1, 2},  {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8},  {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2},  {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}};/* Assuming we have a value that has been sign-extended by at least one bit,   can we use the ext_shift_amounts with the last shift turned to an arithmetic shift   to shift it by N without data loss, and quicker than by other means?  */#define EXT_SHIFT_SIGNED(n) (((n) | 8) == 15)/* This is used in length attributes in sh.md to help compute the length   of arbitrary constant shift instructions.  */intshift_insns_rtx (rtx insn){  rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));  int shift_count = INTVAL (XEXP (set_src, 1));  enum rtx_code shift_code = GET_CODE (set_src);  switch (shift_code)    {    case ASHIFTRT:      return ashiftrt_insns[shift_count];    case LSHIFTRT:    case ASHIFT:      return shift_insns[shift_count];    default:      abort ();    }}/* Return the cost of a shift.  */static inline intshiftcosts (rtx x){  int value;  if (TARGET_SHMEDIA)    return 1;  if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)    {      if (GET_MODE (x) == DImode	  && GET_CODE (XEXP (x, 1)) == CONST_INT	  && INTVAL (XEXP (x, 1)) == 1)	return 2;      /* Everything else is invalid, because there is no pattern for it.  */      return 10000;    }  /* If shift by a non constant, then this will be expensive.  */  if (GET_CODE (XEXP (x, 1)) != CONST_INT)    return SH_DYNAMIC_SHIFT_COST;  value = INTVAL (XEXP (x, 1));  /* Otherwise, return the true cost in instructions.  */  if (GET_CODE (x) == ASHIFTRT)    {      int cost = ashiftrt_insns[value];      /* If SH3, then we put the constant in a reg and use shad.  */      if (cost > 1 + SH_DYNAMIC_SHIFT_COST)	cost = 1 + SH_DYNAMIC_SHIFT_COST;      return cost;    }  else    return shift_insns[value];}/* Return the cost of an AND operation.  */static inline intandcosts (rtx x){  int i;  /* Anding with a register is a single cycle and instruction.  */  if (GET_CODE (XEXP (x, 1)) != CONST_INT)    return 1;  i = INTVAL (XEXP (x, 1));  if (TARGET_SHMEDIA)    {      if ((GET_CODE (XEXP (x, 1)) == CONST_INT	   && CONST_OK_FOR_I16 (INTVAL (XEXP (x, 1))))	  || EXTRA_CONSTRAINT_C16 (XEXP (x, 1)))	return 1;      else	return 2;    }  /* These constants are single cycle extu.[bw] instructions.  */  if (i == 0xff || i == 0xffff)    return 1;  /* Constants that can be used in an and immediate instruction in a single     cycle, but this requires r0, so make it a little more expensive.  */  if (CONST_OK_FOR_K08 (i))    return 2;  /* Constants that can be loaded with a mov immediate and an and.     This case is probably unnecessary.  */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -