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

📄 mn10200.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 3 页
字号:
  char *assembler;  int cc_valid;};/* Assembler instruction shift table.   These tables are used to look up the basic shifts.   They are indexed by cpu, shift_type, and mode.*/static const struct shift_insn shift_one[3][3] ={  {/* SHIFT_ASHIFT */      { "add\t%0,%0", CC_OVERFLOW_UNUSABLE | CC_NO_CARRY },  },/* SHIFT_LSHIFTRT */  {      { "lsr\t%0", CC_NO_CARRY },  },/* SHIFT_ASHIFTRT */  {      { "asr\t%0", CC_NO_CARRY },  },};/* Given CPU, MODE, SHIFT_TYPE, and shift count COUNT, determine the best   algorithm for doing the shift.  The assembler code is stored in ASSEMBLER.   We don't achieve maximum efficiency in all cases, but the hooks are here   to do so.   For now we just use lots of switch statements.  Since we don't even come   close to supporting all the cases, this is simplest.  If this function ever   gets too big, perhaps resort to a more table based lookup.  Of course,   at this point you may just wish to do it all in rtl.  */static enum shift_algget_shift_alg (shift_type, mode, count, assembler_p, cc_valid_p)     enum shift_type shift_type;     enum machine_mode mode;     int count;     const char **assembler_p;     int *cc_valid_p;{  /* The default is to loop.  */  enum shift_alg alg = SHIFT_LOOP;  enum shift_mode shift_mode;  /* We don't handle negative shifts or shifts greater than the word size,     they should have been handled already.  */  if (count < 0 || count > GET_MODE_BITSIZE (mode))    abort ();  switch (mode)    {    case HImode:      shift_mode = HIshift;      break;    default:      abort ();    }  /* Assume either SHIFT_LOOP or SHIFT_INLINE.     It is up to the caller to know that looping clobbers cc.  */  *assembler_p = shift_one[shift_type][shift_mode].assembler;  *cc_valid_p = shift_one[shift_type][shift_mode].cc_valid;  /* Now look for cases we want to optimize.  */  switch (shift_mode)    {    case HIshift:      if (count <= 4)	return SHIFT_INLINE;      else if (count < 15 && shift_type != SHIFT_ASHIFTRT)	{	  switch (count)	    {	    case 5:	      if (shift_type == SHIFT_ASHIFT)		*assembler_p = "mov 32,%4\n\tmul %4,%0";	      else if (shift_type == SHIFT_LSHIFTRT)		*assembler_p		  = "sub %4,%4\n\tmov %4,mdr\n\tmov 32,%4\n\tdivu %4,%0";	      *cc_valid_p = CC_NO_CARRY;	      return SHIFT_SPECIAL;	    case 6:	      if (shift_type == SHIFT_ASHIFT)		*assembler_p = "mov 64,%4\n\tmul %4,%0";	      else if (shift_type == SHIFT_LSHIFTRT)		*assembler_p		  = "sub %4,%4\n\tmov %4,mdr\n\tmov 64,%4\n\tdivu %4,%0";	      *cc_valid_p = CC_NO_CARRY;	      return SHIFT_SPECIAL;	    case 7:	      if (shift_type == SHIFT_ASHIFT)		*assembler_p = "mov 128,%4\n\tmul %4,%0";	      else if (shift_type == SHIFT_LSHIFTRT)		*assembler_p		  = "sub %4,%4\n\tmov %4,mdr\n\tmov 128,%4\n\tdivu %4,%0";	      *cc_valid_p = CC_NO_CARRY;	      return SHIFT_SPECIAL;	    case 8:	      if (shift_type == SHIFT_ASHIFT)		*assembler_p = "mov 256,%4\n\tmul %4,%0";	      else if (shift_type == SHIFT_LSHIFTRT)		*assembler_p		  = "sub %4,%4\n\tmov %4,mdr\n\tmov 256,%4\n\tdivu %4,%0";	      *cc_valid_p = CC_NO_CARRY;	      return SHIFT_SPECIAL;	    case 9:	      if (shift_type == SHIFT_ASHIFT)		*assembler_p = "mov 512,%4\n\tmul %4,%0";	      else if (shift_type == SHIFT_LSHIFTRT)		*assembler_p		  = "sub %4,%4\n\tmov %4,mdr\n\tmov 512,%4\n\tdivu %4,%0";	      *cc_valid_p = CC_NO_CARRY;	      return SHIFT_SPECIAL;	    case 10:	      if (shift_type == SHIFT_ASHIFT)		*assembler_p = "mov 1024,%4\n\tmul %4,%0";	      else if (shift_type == SHIFT_LSHIFTRT)		*assembler_p		  = "sub %4,%4\n\tmov %4,mdr\n\tmov 1024,%4\n\tdivu %4,%0";	      *cc_valid_p = CC_NO_CARRY;	      return SHIFT_SPECIAL;	    case 11:	      if (shift_type == SHIFT_ASHIFT)		*assembler_p = "mov 2048,%4\n\tmul %4,%0";	      else if (shift_type == SHIFT_LSHIFTRT)		*assembler_p		  = "sub %4,%4\n\tmov %4,mdr\n\tmov 2048,%4\n\tdivu %4,%0";	      *cc_valid_p = CC_NO_CARRY;	      return SHIFT_SPECIAL;	    case 12:	      if (shift_type == SHIFT_ASHIFT)		*assembler_p = "mov 4096,%4\n\tmul %4,%0";	      else if (shift_type == SHIFT_LSHIFTRT)		*assembler_p		  = "sub %4,%4\n\tmov %4,mdr\n\tmov 4096,%4\n\tdivu %4,%0";	      *cc_valid_p = CC_NO_CARRY;	      return SHIFT_SPECIAL;	    case 13:	      if (shift_type == SHIFT_ASHIFT)		*assembler_p = "mov 8192,%4\n\tmul %4,%0";	      else if (shift_type == SHIFT_LSHIFTRT)		*assembler_p		  = "sub %4,%4\n\tmov %4,mdr\n\tmov 8192,%4\n\tdivu %4,%0";	      *cc_valid_p = CC_NO_CARRY;	      return SHIFT_SPECIAL;	    case 14:	      if (shift_type == SHIFT_ASHIFT)		*assembler_p = "mov 16384,%4\n\tmul %4,%0";	      else if (shift_type == SHIFT_LSHIFTRT)		*assembler_p		  = "sub %4,%4\n\tmov %4,mdr\n\tmov 16384,%4\n\tdivu %4,%0";	      *cc_valid_p = CC_NO_CARRY;	      return SHIFT_SPECIAL;	    }	}      else if (count == 15)	{          if (shift_type == SHIFT_ASHIFTRT)            {              *assembler_p = "add\t%0,%0\n\tsubc\t%0,%0\n";              *cc_valid_p = CC_NO_CARRY;              return SHIFT_SPECIAL;	    }          if (shift_type == SHIFT_LSHIFTRT)            {              *assembler_p = "add\t%0,%0\n\tmov 0,%0\n\trol %0\n";              *cc_valid_p = CC_NO_CARRY;              return SHIFT_SPECIAL;	    }          if (shift_type == SHIFT_ASHIFT)            {              *assembler_p = "ror\t%0\n\tmov 0,%0\n\tror %0\n";              *cc_valid_p = CC_NO_CARRY;              return SHIFT_SPECIAL;	    }	}      break;    default:      abort ();    }  return alg;}/* Emit the assembler code for doing shifts.  */char *emit_a_shift (insn, operands)     rtx insn;     rtx *operands;{  static int loopend_lab;  char *assembler;  int cc_valid;  rtx inside = PATTERN (insn);  rtx shift = operands[3];  enum machine_mode mode = GET_MODE (shift);  enum rtx_code code = GET_CODE (shift);  enum shift_type shift_type;  enum shift_mode shift_mode;  loopend_lab++;  switch (mode)    {    case HImode:      shift_mode = HIshift;      break;    default:      abort ();    }  switch (code)    {    case ASHIFTRT:      shift_type = SHIFT_ASHIFTRT;      break;    case LSHIFTRT:      shift_type = SHIFT_LSHIFTRT;      break;    case ASHIFT:      shift_type = SHIFT_ASHIFT;      break;    default:      abort ();    }  if (GET_CODE (operands[2]) != CONST_INT)    {      /* Indexing by reg, so have to loop and test at top */      output_asm_insn ("mov	%2,%4", operands);      output_asm_insn ("cmp	0,%4", operands);      fprintf (asm_out_file, "\tble	.Lle%d\n", loopend_lab);      /* Get the assembler code to do one shift.  */      get_shift_alg (shift_type, mode, 1, &assembler, &cc_valid);    }  else    {      int n = INTVAL (operands[2]);      enum shift_alg alg;      /* If the count is negative, make it 0.  */      if (n < 0)	n = 0;      /* If the count is too big, truncate it.         ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to	 do the intuitive thing.  */      else if (n > GET_MODE_BITSIZE (mode))	n = GET_MODE_BITSIZE (mode);      alg = get_shift_alg (shift_type, mode, n, &assembler, &cc_valid);      switch (alg)	{	case SHIFT_INLINE:	  /* Emit one bit shifts.  */	  while (n > 0)	    {	      output_asm_insn (assembler, operands);	      n -= 1;	    }	  /* Keep track of CC.  */	  if (cc_valid)	    {	      cc_status.value1 = operands[0];	      cc_status.flags |= cc_valid;	    }	  return "";	case SHIFT_SPECIAL:	  output_asm_insn (assembler, operands);	  /* Keep track of CC.  */	  if (cc_valid)	    {	      cc_status.value1 = operands[0];	      cc_status.flags |= cc_valid;	    }	  return "";	}	{	  fprintf (asm_out_file, "\tmov	%d,%s\n", n,		   reg_names[REGNO (operands[4])]);	  fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);	  output_asm_insn (assembler, operands);	  output_asm_insn ("add	-1,%4", operands);	  fprintf (asm_out_file, "\tbne	.Llt%d\n", loopend_lab);	  return "";	}    }  fprintf (asm_out_file, ".Llt%d:\n", loopend_lab);  output_asm_insn (assembler, operands);  output_asm_insn ("add	-1,%4", operands);  fprintf (asm_out_file, "\tbne	.Llt%d\n", loopend_lab);  fprintf (asm_out_file, ".Lle%d:\n", loopend_lab);  return "";}/* Return an RTX to represent where a value with mode MODE will be returned   from a function.  If the result is 0, the argument is pushed.  */rtxfunction_arg (cum, mode, type, named)     CUMULATIVE_ARGS *cum;     enum machine_mode mode;     tree type;     int named;{  rtx result = 0;  int size, align;  /* We only support using 2 data registers as argument registers.  */  int nregs = 2;  /* Only pass named arguments in registers.  */  if (!named)    return NULL_RTX;  /* Figure out the size of the object to be passed.  We lie and claim     PSImode values are only two bytes since they fit in a single     register.  */  if (mode == BLKmode)    size = int_size_in_bytes (type);  else if (mode == PSImode)    size = 2;  else    size = GET_MODE_SIZE (mode);  /* Figure out the alignment of the object to be passed.  */    align = size;  cum->nbytes = (cum->nbytes + 1) & ~1;  /* Don't pass this arg via a register if all the argument registers     are used up.  */  if (cum->nbytes + size > nregs * UNITS_PER_WORD)    return 0;  switch (cum->nbytes / UNITS_PER_WORD)    {    case 0:      result = gen_rtx (REG, mode, 0);      break;    case 1:      result = gen_rtx (REG, mode, 1);      break;    default:      result = 0;    }  return result;}/* Return the number of registers to use for an argument passed partially   in registers and partially in memory.  */intfunction_arg_partial_nregs (cum, mode, type, named)     CUMULATIVE_ARGS *cum;     enum machine_mode mode;     tree type;     int named;{  int size, align;  /* We only support using 2 data registers as argument registers.  */  int nregs = 2;  return 0;  /* Only pass named arguments in registers.  */  if (!named)    return 0;  /* Figure out the size of the object to be passed.  */  if (mode == BLKmode)    size = int_size_in_bytes (type);  else if (mode == PSImode)    size = 2;  else    size = GET_MODE_SIZE (mode);  /* Figure out the alignment of the object to be passed.  */  align = size;  cum->nbytes = (cum->nbytes + 1) & ~1;  /* Don't pass this arg via a register if all the argument registers     are used up.  */  if (cum->nbytes > nregs * UNITS_PER_WORD)    return 0;  if (cum->nbytes + size <= nregs * UNITS_PER_WORD)    return 0;  /* Don't pass this arg via a register if it would be split between     registers and memory.  */  if (type == NULL_TREE      && cum->nbytes + size > nregs * UNITS_PER_WORD)    return 0;  return (nregs * UNITS_PER_WORD - cum->nbytes) / UNITS_PER_WORD;}char *output_tst (operand, insn)     rtx operand, insn;{    rtx temp;  int past_call = 0;  /* Only tst insns using address registers can be optimized.  */  if (REGNO_REG_CLASS (REGNO (operand)) != ADDRESS_REGS)    return "cmp 0,%0";  /* If testing an address register against zero, we can do better if     we know there's a register already holding the value zero.  First     see if a global register has been set to zero, else we do a search     for a register holding zero, if both of those fail, then we use a     compare against zero.  */  if (zero_dreg || zero_areg)    {      rtx xoperands[2];      xoperands[0] = operand;      xoperands[1] = zero_dreg ? zero_dreg : zero_areg;      output_asm_insn ("cmp %1,%0", xoperands);      return "";    }  /* We can save a byte if we can find a register which has the value     zero in it.  */  temp = PREV_INSN (insn);  while (temp)    {      rtx set;      /* We allow the search to go through call insns.  We record	 the fact that we've past a CALL_INSN and reject matches which	 use call clobbered registers.  */      if (GET_CODE (temp) == CODE_LABEL	  || GET_CODE (temp) == JUMP_INSN	  || GET_CODE (temp) == BARRIER)	break;      if (GET_CODE (temp) == CALL_INSN)	past_call = 1;      if (GET_CODE (temp) == NOTE)	{	  temp = PREV_INSN (temp);	  continue;	}      /* It must be an insn, see if it is a simple set. */      set = single_set (temp);      if (!set)	{	  temp = PREV_INSN (temp);	  continue;	}      /* Are we setting a register to zero?	 If it's a call clobbered register, have we past a call?  */      if (REG_P (SET_DEST (set))	  && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))	  && !reg_set_between_p (SET_DEST (set), temp, insn)	  && (!past_call 	      || !call_used_regs[REGNO (SET_DEST (set))]))	{	  rtx xoperands[2];	  xoperands[0] = operand;	  xoperands[1] = SET_DEST (set);	  output_asm_insn ("cmp %1,%0", xoperands);	  return "";	}      temp = PREV_INSN (temp);    }  return "cmp 0,%0";}/* Return nonzero if OP is a valid operand for a {zero,sign}_extendpsisi   instruction.   It accepts anything that is a general operand or the sum of the   stack pointer and a general operand.  */extendpsi_operand (op, mode)     rtx op;     enum machine_mode mode;{  return (general_operand (op, mode)	  || (GET_CODE (op) == PLUS	      && XEXP (op, 0) == stack_pointer_rtx	      && general_operand (XEXP (op, 1), VOIDmode)));}

⌨️ 快捷键说明

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