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

📄 sh.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
{  return output_branchy_insn (NE, "bt\t%l9\n\tfcmp/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 a 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:      gcc_unreachable ();    }}/* 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.  */  if (CONST_OK_FOR_I08 (i))    return 2;  /* Any other constants requires a 2 cycle pc-relative load plus an and.     This case is probably unnecessary.  */  return 3;}/* Return the cost of an addition or a subtraction.  */static inline intaddsubcosts (rtx x){  /* Adding a register is a single cycle insn.  */  if (GET_CODE (XEXP (x, 1)) == REG      || GET_CODE (XEXP (x, 1)) == SUBREG)    return 1;  /* Likewise for small constants.  */  if (GET_CODE (XEXP (x, 1)) == CONST_INT      && CONST_OK_FOR_ADD (INTVAL (XEXP (x, 1))))    return 1;  if (TARGET_SHMEDIA)    switch (GET_CODE (XEXP (x, 1)))      {      case CONST:      case LABEL_REF:      case SYMBOL_REF:	return TARGET_SHMEDIA64 ? 5 : 3;      case CONST_INT:	if (CONST_OK_FOR_I16 (INTVAL (XEXP (x, 1))))          return 2;	else if (CONST_OK_FOR_I16 (INTVAL (XEXP (x, 1)) >> 16))	  return 3;	else if (CONST_OK_FOR_I16 ((INTVAL (XEXP (x, 1)) >> 16) >> 16))	  return 4;	/* Fall through.  */      default:	return 5;      }  /* Any other constant requires a 2 cycle pc-relative load plus an     addition.  */  return 3;}/* Return the cost of a multiply.  */static inline intmultcosts (rtx x ATTRIBUTE_UNUSED){  if (sh_multcost >= 0)    return sh_multcost;  if (TARGET_SHMEDIA)    /* ??? We have a mul insn, but it has a latency of three, and doesn't       accept constants.  Ideally, we would use a cost of one or two and       add the cost of the operand, but disregard the latter when inside loops       and loop invariant code motion is still to follow.       Using a multiply first and splitting it later if it's a loss       doesn't work because of different sign / zero extension semantics       of multiplies vs. shifts.  */    return TARGET_SMALLCODE ? 2 : 3;  if (TARGET_SH2)    {      /* We have a mul insn, so we can never take more than the mul and the	 read of the mac reg, but count more because of the latency and extra	 reg usage.  */      if (TARGET_SMALLCODE)	return 2;      return 3;    }  /* If we're aiming at small code, then just count the number of     insns in a multiply call sequence.  */  if (TARGET_SMALLCODE)    return 5;  /* Otherwise count all the insns in the routine we'd be calling too.  */  return 20;}/* Compute a (partial) cost for rtx X.  Return true if the complete   cost has been computed, and false if subexpressions should be   scanned.  In either case, *TOTAL contains the cost result.  */static boolsh_rtx_costs (rtx x, int code, int outer_code, int *total){  switch (code)    {    case CONST_INT:      if (TARGET_SHMEDIA)        {	  if (INTVAL (x) == 0)	    *total = 0;	  else if (outer_code == AND && and_operand ((x), DImode))	    *total = 0;	  else if ((outer_code == IOR || outer_code == XOR	            || outer_code == PLUS)		   && CONST_OK_FOR_I10 (INTVAL (x)))	    *total = 0;	  else if (CONST_OK_FOR_I16 (INTVAL (x)))            *total = COSTS_N_INSNS (outer_code != SET);	  else if (CONST_OK_FOR_I16 (INTVAL (x) >> 16))	    *total = COSTS_N_INSNS ((outer_code != SET) + 1);	  else if (CONST_OK_FOR_I16 ((INTVAL (x) >> 16) >> 16))	    *total = COSTS_N_INSNS (3);          else	    *total = COSTS_N_INSNS (4);	  return true;        }      if (CONST_OK_FOR_I08 (INTVAL (x)))        *total = 0;      else if ((outer_code == AND || outer_code == IOR || outer_code == XOR)	       && CONST_OK_FOR_K08 (INTVAL (x)))        *total = 1;      else        *total = 8;      return true;    case CONST:    case LABEL_REF:    case SYMBOL_REF:      if (TARGET_SHMEDIA64)        *total = COSTS_N_INSNS (4);      else if (TARGET_SHMEDIA32)        *total = COSTS_N_INSNS (2);      else	*total = 5;      return true;    case CONST_DOUBLE:      if (TARGET_SHMEDIA)        *total = COSTS_N_INSNS (4);      else        *total = 10;      return true;    case CONST_VECTOR:      if (x == CONST0_RTX (GET_MODE (x)))	*total = 0;      else if (sh_1el_vec (x, VOIDmode))	*total = outer_code != SET;      if (sh_rep_vec (x, VOIDmode))	*total = ((GET_MODE_UNIT_SIZE (GET_MODE (x)) + 3) / 4		  + (outer_code != SET));      *total = COSTS_N_INSNS (3) + (outer_code != SET);      return true;    case PLUS:    case MINUS:      *total = COSTS_N_INSNS (addsubcosts (x));      return true;    case AND:      *total = COSTS_N_INSNS (andcosts (x));      return true;    case MULT:      *total = COSTS_N_INSNS (multcosts (x));      return true;    case ASHIFT:    case ASHIFTRT:    case LSHIFTRT:      *total = COSTS_N_INSNS (shiftcosts (x));      return true;    case DIV:    case UDIV:    case MOD:    case UMOD:      *total = COSTS_N_INSNS (20);      return true;    case PARALLEL:      if (sh_1el_vec (x, VOIDmode))	*total = outer_code != SET;      if (sh_rep_vec (x, VOIDmode))	*total = ((GET_MODE_UNIT_SIZE (GET_MODE (x)) + 3) / 4		  + (outer_code != SET));      *total = COSTS_N_INSNS (3) + (outer_code != SET);      return true;    case FLOAT:    case FIX:      *total = 100;      return true;    default:      return false;    }}/* Compute 

⌨️ 快捷键说明

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