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

📄 m68hc11.c

📁 gcc-you can use this code to learn something about gcc, and inquire further into linux,
💻 C
📖 第 1 页 / 共 5 页
字号:
      else if (mode == HImode)	{	  return gen_int_mode (val >> 16, HImode);	}    }  if (mode == QImode && D_REG_P (x))    return gen_rtx (REG, mode, HARD_A_REGNUM);  /* There is no way in GCC to represent the upper part of a word register.     To obtain the 8-bit upper part of a soft register, we change the     reg into a mem rtx.  This is possible because they are physically     located in memory.  There is no offset because we are big-endian.  */  if (mode == QImode && S_REG_P (x))    {      int pos;      /* Avoid the '*' for direct addressing mode when this         addressing mode is disabled.  */      pos = TARGET_NO_DIRECT_MODE ? 1 : 0;      return gen_rtx (MEM, QImode,		      gen_rtx (SYMBOL_REF, Pmode,			       &reg_names[REGNO (x)][pos]));    }  /* gen_highpart crashes when it is called with a SUBREG.  */  if (GET_CODE (x) == SUBREG)    {      return gen_rtx (SUBREG, mode, XEXP (x, 0), XEXP (x, 1));    }  if (GET_CODE (x) == REG)    {      if (REGNO (x) < FIRST_PSEUDO_REGISTER)        return gen_rtx (REG, mode, REGNO (x));      else        return gen_rtx_SUBREG (mode, x, 0);    }  if (GET_CODE (x) == MEM)    {      x = change_address (x, mode, 0);      /* Return a different rtx to avoid to share it in several insns	 (when used by a split pattern).  Sharing addresses within	 a MEM breaks the Z register replacement (and reloading).  */      if (GET_CODE (x) == MEM)	x = copy_rtx (x);      return x;    }  abort ();}/* Obscure register manipulation.  *//* Finds backward in the instructions to see if register 'reg' is   dead.  This is used when generating code to see if we can use 'reg'   as a scratch register.  This allows us to choose a better generation   of code when we know that some register dies or can be clobbered.  */intdead_register_here (x, reg)     rtx x;     rtx reg;{  rtx x_reg;  rtx p;  if (D_REG_P (reg))    x_reg = gen_rtx (REG, SImode, HARD_X_REGNUM);  else    x_reg = 0;  for (p = PREV_INSN (x); p && GET_CODE (p) != CODE_LABEL; p = PREV_INSN (p))    if (GET_RTX_CLASS (GET_CODE (p)) == 'i')      {	rtx body;	body = PATTERN (p);	if (GET_CODE (body) == CALL_INSN)	  break;	if (GET_CODE (body) == JUMP_INSN)	  break;	if (GET_CODE (body) == SET)	  {	    rtx dst = XEXP (body, 0);	    if (GET_CODE (dst) == REG && REGNO (dst) == REGNO (reg))	      break;	    if (x_reg && rtx_equal_p (dst, x_reg))	      break;	    if (find_regno_note (p, REG_DEAD, REGNO (reg)))	      return 1;	  }	else if (reg_mentioned_p (reg, p)		 || (x_reg && reg_mentioned_p (x_reg, p)))	  break;      }  /* Scan forward to see if the register is set in some insns and never     used since then.  */  for (p = x /*NEXT_INSN (x) */ ; p; p = NEXT_INSN (p))    {      rtx body;      if (GET_CODE (p) == CODE_LABEL	  || GET_CODE (p) == JUMP_INSN	  || GET_CODE (p) == CALL_INSN || GET_CODE (p) == BARRIER)	break;      if (GET_CODE (p) != INSN)	continue;      body = PATTERN (p);      if (GET_CODE (body) == SET)	{	  rtx src = XEXP (body, 1);	  rtx dst = XEXP (body, 0);	  if (GET_CODE (dst) == REG	      && REGNO (dst) == REGNO (reg) && !reg_mentioned_p (reg, src))	    return 1;	}      /* Register is used (may be in source or in dest).  */      if (reg_mentioned_p (reg, p)	  || (x_reg != 0 && GET_MODE (p) == SImode	      && reg_mentioned_p (x_reg, p)))	break;    }  return p == 0 ? 1 : 0;}/* Code generation operations called from machine description file.  *//* Print the name of register 'regno' in the assembly file.  */static voidasm_print_register (file, regno)     FILE *file;     int regno;{  const char *name = reg_names[regno];  if (TARGET_NO_DIRECT_MODE && name[0] == '*')    name++;  fprintf (file, "%s", name);}/* A C compound statement to output to stdio stream STREAM the   assembler syntax for an instruction operand X.  X is an RTL   expression.   CODE is a value that can be used to specify one of several ways   of printing the operand.  It is used when identical operands   must be printed differently depending on the context.  CODE   comes from the `%' specification that was used to request   printing of the operand.  If the specification was just `%DIGIT'   then CODE is 0; if the specification was `%LTR DIGIT' then CODE   is the ASCII code for LTR.   If X is a register, this macro should print the register's name.   The names can be found in an array `reg_names' whose type is   `char *[]'.  `reg_names' is initialized from `REGISTER_NAMES'.   When the machine description has a specification `%PUNCT' (a `%'   followed by a punctuation character), this macro is called with   a null pointer for X and the punctuation character for CODE.   The M68HC11 specific codes are:   'b' for the low part of the operand.   'h' for the high part of the operand       The 'b' or 'h' modifiers have no effect if the operand has       the QImode and is not a S_REG_P (soft register).  If the       operand is a hard register, these two modifiers have no effect.   't' generate the temporary scratch register.  The operand is       ignored.   'T' generate the low-part temporary scratch register.  The operand is       ignored.  */voidprint_operand (file, op, letter)     FILE *file;     rtx op;     int letter;{  if (letter == 't')    {      asm_print_register (file, SOFT_TMP_REGNUM);      return;    }  else if (letter == 'T')    {      asm_print_register (file, SOFT_TMP_REGNUM);      fprintf (file, "+1");      return;    }  else if (letter == '#')    {      asm_fprintf (file, "%0I");    }  if (GET_CODE (op) == REG)    {      if (letter == 'b' && S_REG_P (op))	{	  asm_print_register (file, REGNO (op));	  fprintf (file, "+1");	}      else if (letter == 'b' && D_REG_P (op))	{	  asm_print_register (file, HARD_B_REGNUM);	}      else	{	  asm_print_register (file, REGNO (op));	}      return;    }  if (GET_CODE (op) == SYMBOL_REF && (letter == 'b' || letter == 'h'))    {      if (letter == 'b')	asm_fprintf (file, "%0I%%lo(");      else	asm_fprintf (file, "%0I%%hi(");      output_addr_const (file, op);      fprintf (file, ")");      return;    }  /* Get the low or high part of the operand when 'b' or 'h' modifiers     are specified.  If we already have a QImode, there is nothing to do.  */  if (GET_MODE (op) == HImode || GET_MODE (op) == VOIDmode)    {      if (letter == 'b')	{	  op = m68hc11_gen_lowpart (QImode, op);	}      else if (letter == 'h')	{	  op = m68hc11_gen_highpart (QImode, op);	}    }  if (GET_CODE (op) == MEM)    {      rtx base = XEXP (op, 0);      switch (GET_CODE (base))	{	case PRE_DEC:	  if (TARGET_M6812)	    {	      fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (op)));	      asm_print_register (file, REGNO (XEXP (base, 0)));	    }	  else	    abort ();	  break;	case POST_DEC:	  if (TARGET_M6812)	    {	      fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));	      asm_print_register (file, REGNO (XEXP (base, 0)));	      fprintf (file, "-");	    }	  else	    abort ();	  break;	case POST_INC:	  if (TARGET_M6812)	    {	      fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (op)));	      asm_print_register (file, REGNO (XEXP (base, 0)));	      fprintf (file, "+");	    }	  else	    abort ();	  break;	case PRE_INC:	  if (TARGET_M6812)	    {	      fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (op)));	      asm_print_register (file, REGNO (XEXP (base, 0)));	    }	  else	    abort ();	  break;	default:	  output_address (base);	  break;	}    }  else if (GET_CODE (op) == CONST_DOUBLE && GET_MODE (op) == SFmode)    {      REAL_VALUE_TYPE r;      long l;      REAL_VALUE_FROM_CONST_DOUBLE (r, op);      REAL_VALUE_TO_TARGET_SINGLE (r, l);      asm_fprintf (file, "%I0x%lx", l);    }  else if (GET_CODE (op) == CONST_DOUBLE	   && (GET_MODE (op) == DFmode || GET_MODE (op) == XFmode))    {      char dstr[30];      real_to_decimal (dstr, CONST_DOUBLE_REAL_VALUE (op),		       sizeof (dstr), 0, 1);      asm_fprintf (file, "%I0r%s", dstr);    }  else    {      int need_parenthesize = 0;      if (letter != 'i')	asm_fprintf (file, "%0I");      else        need_parenthesize = must_parenthesize (op);      if (need_parenthesize)        fprintf (file, "(");      output_addr_const (file, op);      if (need_parenthesize)        fprintf (file, ")");    }}/* Returns true if the operand 'op' must be printed with parenthesis   arround it.  This must be done only if there is a symbol whose name   is a processor register.  */static intmust_parenthesize (op)     rtx op;{  const char *name;  switch (GET_CODE (op))    {    case SYMBOL_REF:      name = XSTR (op, 0);      /* Avoid a conflict between symbol name and a possible         register.  */      return (strcasecmp (name, "a") == 0	      || strcasecmp (name, "b") == 0	      || strcasecmp (name, "d") == 0	      || strcasecmp (name, "x") == 0	      || strcasecmp (name, "y") == 0	      || strcasecmp (name, "ix") == 0	      || strcasecmp (name, "iy") == 0	      || strcasecmp (name, "pc") == 0	      || strcasecmp (name, "sp") == 0	      || strcasecmp (name, "ccr") == 0) ? 1 : 0;    case PLUS:    case MINUS:      return must_parenthesize (XEXP (op, 0))	|| must_parenthesize (XEXP (op, 1));    case MEM:    case CONST:    case ZERO_EXTEND:    case SIGN_EXTEND:      return must_parenthesize (XEXP (op, 0));    case CONST_DOUBLE:    case CONST_INT:    case LABEL_REF:    case CODE_LABEL:    default:      return 0;    }}/* A C compound statement to output to stdio stream STREAM the   assembler syntax for an instruction operand that is a memory   reference whose address is ADDR.  ADDR is an RTL expression.  */voidprint_operand_address (file, addr)     FILE *file;     rtx addr;{  rtx base;  rtx offset;  int need_parenthesis = 0;  switch (GET_CODE (addr))    {    case REG:      if (!REG_P (addr) || !REG_OK_FOR_BASE_STRICT_P (addr))	abort ();      fprintf (file, "0,");      asm_print_register (file, REGNO (addr));      break;    case MEM:      base = XEXP (addr, 0);      switch (GET_CODE (base))	{	case PRE_DEC:	  if (TARGET_M6812)	    {	      fprintf (file, "%u,-", GET_MODE_SIZE (GET_MODE (addr)));	      asm_print_register (file, REGNO (XEXP (base, 0)));	    }	  else	    abort ();	  break;	case POST_DEC:	  if (TARGET_M6812)	    {	      fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));	      asm_print_register (file, REGNO (XEXP (base, 0)));	      fprintf (file, "-");	    }	  else	    abort ();	  break;	case POST_INC:	  if (TARGET_M6812)	    {	      fprintf (file, "%u,", GET_MODE_SIZE (GET_MODE (addr)));	      asm_print_register (file, REGNO (XEXP (base, 0)));	      fprintf (file, "+");	    }	  else	    abort ();	  break;	case PRE_INC:	  if (TARGET_M6812)	    {	      fprintf (file, "%u,+", GET_MODE_SIZE (GET_MODE (addr)));	      asm_print_register (file, REGNO (XEXP (base, 0)));	    }	  else	    abort ();	  break;	default:	  need_parenthesis = must_parenthesize (base);	  if (need_parenthesis)	    fprintf (file, "(");	  output_addr_const (file, base);	  if (need_parenthesis)	    fprintf (file, ")");	  break;	}      break;    case PLUS:      base = XEXP (addr, 0);      offset = XEXP (addr, 1);      if (!G_REG_P (base) && G_REG_P (offset))	{	  base = XEXP (addr, 1);	  offset = XEXP (addr, 0);	}      if ((CONSTANT_ADDRESS_P (base)) && (CONSTANT_ADDRESS_P (offset)))	{	  need_parenthesis = must_parenthesize (addr);	  if (need_parenthesis)	    fprintf (file, "(");	  output_addr_const (file, base);	  fprintf (file, "+");	  output_addr_const (file, offset);	  if (need_parenthesis)	    fprintf (file, ")");	}      else if (REG_P (base) && REG_OK_FOR_BASE_STRICT_P (base))	{	  if (REG_P (offset))	    {	      if (TARGET_M6812)		{		  asm_print_register (file, REGNO (offset));		  fprintf (file, ",");		  asm_print_register (file, REGNO (base));		}	      else		abort ();	    }	  else	    {              need_parenthesis = must_parenthesize

⌨️ 快捷键说明

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