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

📄 m32c.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
  { 0, "i", "#0" },  { 0, "s", "#0" },  { 0, "+si", "#1+2" },  { 0, "l", "#0" },  { 'l', "l", "0" },  { 'd', "i", "0" },  { 'd', "s", "0" },  { 'd', "+si", "1+2" },  { 'D', "i", "0" },  { 'D', "s", "0" },  { 'D', "+si", "1+2" },  { 'x', "i", "#0" },  { 'X', "i", "#0" },  { 'm', "i", "#0" },  { 'b', "i", "#0" },  { 'p', "i", "0" },  { 0, 0, 0 }};/* This is in order according to the bitfield that pushm/popm use.  */static char const *pushm_regs[] = {  "fb", "sb", "a1", "a0", "r3", "r2", "r1", "r0"};/* Implements PRINT_OPERAND.  */voidm32c_print_operand (FILE * file, rtx x, int code){  int i, j, b;  const char *comma;  HOST_WIDE_INT ival;  int unsigned_const = 0;  /* Multiplies; constants are converted to sign-extended format but   we need unsigned, so 'u' and 'U' tell us what size unsigned we   need.  */  if (code == 'u')    {      unsigned_const = 2;      code = 0;    }  if (code == 'U')    {      unsigned_const = 1;      code = 0;    }  /* This one is only for debugging; you can put it in a pattern to     force this error.  */  if (code == '!')    {      fprintf (stderr, "dj: unreviewed pattern:");      if (current_output_insn)	debug_rtx (current_output_insn);      gcc_unreachable ();    }  /* PSImode operations are either .w or .l depending on the target.  */  if (code == '&')    {      if (TARGET_A16)	fprintf (file, "w");      else	fprintf (file, "l");      return;    }  /* Inverted conditionals.  */  if (code == 'C')    {      switch (GET_CODE (x))	{	case LE:	  fputs ("gt", file);	  break;	case LEU:	  fputs ("gtu", file);	  break;	case LT:	  fputs ("ge", file);	  break;	case LTU:	  fputs ("geu", file);	  break;	case GT:	  fputs ("le", file);	  break;	case GTU:	  fputs ("leu", file);	  break;	case GE:	  fputs ("lt", file);	  break;	case GEU:	  fputs ("ltu", file);	  break;	case NE:	  fputs ("eq", file);	  break;	case EQ:	  fputs ("ne", file);	  break;	default:	  gcc_unreachable ();	}      return;    }  /* Regular conditionals.  */  if (code == 'c')    {      switch (GET_CODE (x))	{	case LE:	  fputs ("le", file);	  break;	case LEU:	  fputs ("leu", file);	  break;	case LT:	  fputs ("lt", file);	  break;	case LTU:	  fputs ("ltu", file);	  break;	case GT:	  fputs ("gt", file);	  break;	case GTU:	  fputs ("gtu", file);	  break;	case GE:	  fputs ("ge", file);	  break;	case GEU:	  fputs ("geu", file);	  break;	case NE:	  fputs ("ne", file);	  break;	case EQ:	  fputs ("eq", file);	  break;	default:	  gcc_unreachable ();	}      return;    }  /* Used in negsi2 to do HImode ops on the two parts of an SImode     operand.  */  if (code == 'h' && GET_MODE (x) == SImode)    {      x = m32c_subreg (HImode, x, SImode, 0);      code = 0;    }  if (code == 'H' && GET_MODE (x) == SImode)    {      x = m32c_subreg (HImode, x, SImode, 2);      code = 0;    }  /* 'x' and 'X' need to be ignored for non-immediates.  */  if ((code == 'x' || code == 'X') && GET_CODE (x) != CONST_INT)    code = 0;  encode_pattern (x);  for (i = 0; conversions[i].pattern; i++)    if (conversions[i].code == code	&& streq (conversions[i].pattern, pattern))      {	for (j = 0; conversions[i].format[j]; j++)	  /* backslash quotes the next character in the output pattern.  */	  if (conversions[i].format[j] == '\\')	    {	      fputc (conversions[i].format[j + 1], file);	      j++;	    }	  /* Digits in the output pattern indicate that the	     corresponding RTX is to be output at that point.  */	  else if (ISDIGIT (conversions[i].format[j]))	    {	      rtx r = patternr[conversions[i].format[j] - '0'];	      switch (GET_CODE (r))		{		case REG:		  fprintf (file, "%s",			   reg_name_with_mode (REGNO (r), GET_MODE (r)));		  break;		case CONST_INT:		  switch (code)		    {		    case 'b':		      /* Bit position.  */		      fprintf (file, "%d", (int) exact_log2 (INTVAL (r)));		      break;		    case 'x':		      /* Unsigned byte.  */		      fprintf (file, HOST_WIDE_INT_PRINT_HEX,			       INTVAL (r) & 0xff);		      break;		    case 'X':		      /* Unsigned word.  */		      fprintf (file, HOST_WIDE_INT_PRINT_HEX,			       INTVAL (r) & 0xffff);		      break;		    case 'p':		      /* pushm and popm encode a register set into a single byte.  */		      comma = "";		      for (b = 7; b >= 0; b--)			if (INTVAL (r) & (1 << b))			  {			    fprintf (file, "%s%s", comma, pushm_regs[b]);			    comma = ",";			  }		      break;		    case 'm':		      /* "Minus".  Output -X  */		      ival = (-INTVAL (r) & 0xffff);		      if (ival & 0x8000)			ival = ival - 0x10000;		      fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);		      break;		    default:		      ival = INTVAL (r);		      if (conversions[i].format[j + 1] == '[' && ival < 0)			{			  /* We can simulate negative displacements by			     taking advantage of address space			     wrapping when the offset can span the			     entire address range.  */			  rtx base =			    patternr[conversions[i].format[j + 2] - '0'];			  if (GET_CODE (base) == REG)			    switch (REGNO (base))			      {			      case A0_REGNO:			      case A1_REGNO:				if (TARGET_A24)				  ival = 0x1000000 + ival;				else				  ival = 0x10000 + ival;				break;			      case SB_REGNO:				if (TARGET_A16)				  ival = 0x10000 + ival;				break;			      }			}		      else if (code == 'd' && ival < 0 && j == 0)			/* The "mova" opcode is used to do addition by			   computing displacements, but again, we need			   displacements to be unsigned *if* they're			   the only component of the displacement			   (i.e. no "symbol-4" type displacement).  */			ival = (TARGET_A24 ? 0x1000000 : 0x10000) + ival;		      if (conversions[i].format[j] == '0')			{			  /* More conversions to unsigned.  */			  if (unsigned_const == 2)			    ival &= 0xffff;			  if (unsigned_const == 1)			    ival &= 0xff;			}		      if (streq (conversions[i].pattern, "mi")			  || streq (conversions[i].pattern, "mmi"))			{			  /* Integers used as addresses are unsigned.  */			  ival &= (TARGET_A24 ? 0xffffff : 0xffff);			}		      fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);		      break;		    }		  break;		case CONST_DOUBLE:		  /* We don't have const_double constants.  If it		     happens, make it obvious.  */		  fprintf (file, "[const_double 0x%lx]",			   (unsigned long) CONST_DOUBLE_HIGH (r));		  break;		case SYMBOL_REF:		  assemble_name (file, XSTR (r, 0));		  break;		case LABEL_REF:		  output_asm_label (r);		  break;		default:		  fprintf (stderr, "don't know how to print this operand:");		  debug_rtx (r);		  gcc_unreachable ();		}	    }	  else	    {	      if (conversions[i].format[j] == 'z')		{		  /* Some addressing modes *must* have a displacement,		     so insert a zero here if needed.  */		  int k;		  for (k = j + 1; conversions[i].format[k]; k++)		    if (ISDIGIT (conversions[i].format[k]))		      {			rtx reg = patternr[conversions[i].format[k] - '0'];			if (GET_CODE (reg) == REG			    && (REGNO (reg) == SB_REGNO				|| REGNO (reg) == FB_REGNO				|| REGNO (reg) == SP_REGNO))			  fputc ('0', file);		      }		  continue;		}	      /* Signed displacements off symbols need to have signs		 blended cleanly.  */	      if (conversions[i].format[j] == '+'		  && (!code || code == 'I')		  && ISDIGIT (conversions[i].format[j + 1])		  && GET_CODE (patternr[conversions[i].format[j + 1] - '0'])		  == CONST_INT		  && INTVAL (patternr[conversions[i].format[j + 1] - '0']) <		  0)		continue;	      fputc (conversions[i].format[j], file);	    }	break;      }  if (!conversions[i].pattern)    {      fprintf (stderr, "unconvertible operand %c `%s'", code ? code : '-',	       pattern);      debug_rtx (x);      fprintf (file, "[%c.%s]", code ? code : '-', pattern);    }  return;}/* Implements PRINT_OPERAND_PUNCT_VALID_P.  See m32c_print_operand   above for descriptions of what these do.  */intm32c_print_operand_punct_valid_p (int c){  if (c == '&' || c == '!')    return 1;  return 0;}/* Implements PRINT_OPERAND_ADDRESS.  Nothing unusual here.  */voidm32c_print_operand_address (FILE * stream, rtx address){  gcc_assert (GET_CODE (address) == MEM);  m32c_print_operand (stream, XEXP (address, 0), 0);}/* Implements ASM_OUTPUT_REG_PUSH.  Control registers are pushed   differently than general registers.  */voidm32c_output_reg_push (FILE * s, int regno){  if (regno == FLG_REGNO)    fprintf (s, "\tpushc\tflg\n");  else    fprintf (s, "\tpush.%c\t%s",	     " bwll"[reg_push_size (regno)], reg_names[regno]);}/* Likewise for ASM_OUTPUT_REG_POP.  */voidm32c_output_reg_pop (FILE * s, int regno){  if (regno == FLG_REGNO)    fprintf (s, "\tpopc\tflg\n");  else    fprintf (s, "\tpop.%c\t%s",	     " bwll"[reg_push_size (regno)], reg_names[regno]);}/* Defining target-specific uses of `__attribute__' *//* Used to simplify the logic below.  Find the attributes wherever   they may be.  */#define M32C_ATTRIBUTES(decl) \  (TYPE_P (decl)) ? TYPE_ATTRIBUTES (decl) \                : DECL_ATTRIBUTES (decl) \                  ? (DECL_ATTRIBUTES (decl)) \		  : TYPE_ATTRIBUTES (TREE_TYPE (decl))/* Returns TRUE if the given tree has the "interrupt" attribute.  */static intinterrupt_p (tree node ATTRIBUTE_UNUSED){  tree list = M32C_ATTRIBUTES (node);  while (list)    {      if (is_attribute_p ("interrupt", TREE_PURPOSE (list)))	return 1;      list = TREE_CHAIN (list);    }  return 0;}static treeinterrupt_handler (tree * node ATTRIBUTE_UNUSED,		   tree name ATTRIBUTE_UNUSED,		   tree args ATTRIBUTE_UNUSED,		   int flags ATTRIBUTE_UNUSED,		   bool * no_add_attrs ATTRIBUTE_UNUSED){  return NULL_TREE;}#undef TARGET_ATTRIBUTE_TABLE#define TARGET_ATTRIBUTE_TABLE m32c_attribute_tablestatic const struct attribute_spec m32c_attribute_table[] = {  {"interrupt", 0, 0, false, false, false, interrupt_handler},  {0, 0, 0, 0, 0, 0, 0}};#undef TARGET_COMP_TYPE_ATTRIBUTES#define TARGET_COMP_TYPE_ATTRIBUTES m32c_comp_type_attributesstatic intm32c_comp_type_attributes (tree type1 ATTRIBUTE_UNUSED,			   tree type2 ATTRIBUTE_UNUSED){  /* 0=incompatible 1=compatible 2=warning */  return 1;}#undef TARGET_INSERT_ATTRIBUTES#define TARGET_INSERT_ATTRIBUTES m32c_insert_attributesstatic voidm32c_insert_attributes (tree node ATTRIBUTE_UNUSED,			tree * attr_ptr ATTRIBUTE_UNUSED){  /* Nothing to do here.  */}/* Predicates *//* Returns TRUE if we support a move between the first two operands.   At the moment, we just want to discourage mem to mem moves until   after reload, because reload has a hard time with our limited   number of address registers, and we can get into a situation where   we need three of them when we only have two.  */boolm32c_mov_ok (rtx * operands, enum machine_mode mode ATTRIBUTE_UNUSED){  rtx op0 = operands[0];  rtx op1 = operands[1];  if (TARGET_A24)    return true;#define DEBUG_MOV_OK 0#if DEBUG_MOV_OK  fprintf (stderr, "m32c_mov_ok %s\n", mode_name[mode]);  debug_rtx (op0);  debug_rtx (op1);#endif  if (GET_CODE (op0) == SUBREG)    op0 = XEXP (op0, 0);  if (GET_CODE (op1) == SUBREG)    op1 = XEXP (op1, 0);  if (GET_CODE (op0) == MEM      && GET_CODE (op1) == MEM      && ! reload_completed)    {#if DEBUG_MOV_OK      fprintf (stderr, " - no, mem to mem\n");#endif      return false;    }#if DEBUG_MOV_OK  fprintf (stderr, " - ok\n");#endif  return true;}/* Expanders *//* Subregs are non-orthogonal for us, because our registers are all   different sizes.  */static rtxm32c_subreg (enum machine_mode outer,	     rtx x, enum machine_mode inner, int byte){  int r, nr = -1;  /* Converting MEMs to different types that are the same size, we     just rewrite them.  */  if (GET_CODE (x) == SUBREG      && SUBREG_BYTE (x) == 0      && GET_CODE (SUBREG_REG (x)) == MEM      && (GET_MODE_SIZE (GET_MODE (x))	  == GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))    {      rtx oldx = x;      x = gen_rtx_MEM (GET_MODE (x), XEXP (SUBREG_REG (x), 0));      MEM_COPY_ATTRIBUTES (x, SUBREG_REG (oldx));    }  /* Push/pop get done as smaller push/pops.  */  if (GET_CODE (x) == MEM      && (GET_CODE (XEXP (x, 0)) == PRE_DEC	  || GET_

⌨️ 快捷键说明

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