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

📄 h8300.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	  }	default:	  break;	}    }}/* Output assembly language output for the address ADDR to FILE.  */voidprint_operand_address (FILE *file, rtx addr){  rtx index;  int size;  switch (GET_CODE (addr))    {    case REG:      fprintf (file, "%s", h8_reg_names[REGNO (addr)]);      break;    case PRE_DEC:      fprintf (file, "-%s", h8_reg_names[REGNO (XEXP (addr, 0))]);      break;    case POST_INC:      fprintf (file, "%s+", h8_reg_names[REGNO (XEXP (addr, 0))]);      break;    case PRE_INC:      fprintf (file, "+%s", h8_reg_names[REGNO (XEXP (addr, 0))]);      break;    case POST_DEC:      fprintf (file, "%s-", h8_reg_names[REGNO (XEXP (addr, 0))]);      break;    case PLUS:      fprintf (file, "(");      index = h8300_get_index (XEXP (addr, 0), VOIDmode, &size);      if (GET_CODE (index) == REG)	{	  /* reg,foo */	  print_operand_address (file, XEXP (addr, 1));	  fprintf (file, ",");	  switch (size)	    {	    case 0:	      print_operand_address (file, index);	      break;	    case 1:	      print_operand (file, index, 'X');	      fputs (".b", file);	      break;	    case 2:	      print_operand (file, index, 'T');	      fputs (".w", file);	      break;	    case 4:	      print_operand (file, index, 'S');	      fputs (".l", file);	      break;	    }	  /* print_operand_address (file, XEXP (addr, 0)); */	}      else	{	  /* foo+k */	  print_operand_address (file, XEXP (addr, 0));	  fprintf (file, "+");	  print_operand_address (file, XEXP (addr, 1));	}      fprintf (file, ")");      break;    case CONST_INT:      {	/* Since the H8/300 only has 16 bit pointers, negative values are also	   those >= 32768.  This happens for example with pointer minus a	   constant.  We don't want to turn (char *p - 2) into	   (char *p + 65534) because loop unrolling can build upon this	   (IE: char *p + 131068).  */	int n = INTVAL (addr);	if (TARGET_H8300)	  n = (int) (short) n;	fprintf (file, "%d", n);	break;      }    default:      output_addr_const (file, addr);      break;    }}/* Output all insn addresses and their sizes into the assembly language   output file.  This is helpful for debugging whether the length attributes   in the md file are correct.  This is not meant to be a user selectable   option.  */voidfinal_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,		    int num_operands ATTRIBUTE_UNUSED){  /* This holds the last insn address.  */  static int last_insn_address = 0;  const int uid = INSN_UID (insn);  if (TARGET_ADDRESSES)    {      fprintf (asm_out_file, "; 0x%x %d\n", INSN_ADDRESSES (uid),	       INSN_ADDRESSES (uid) - last_insn_address);      last_insn_address = INSN_ADDRESSES (uid);    }}/* Prepare for an SI sized move.  */inth8300_expand_movsi (rtx operands[]){  rtx src = operands[1];  rtx dst = operands[0];  if (!reload_in_progress && !reload_completed)    {      if (!register_operand (dst, GET_MODE (dst)))	{	  rtx tmp = gen_reg_rtx (GET_MODE (dst));	  emit_move_insn (tmp, src);	  operands[1] = tmp;	}    }  return 0;}/* Function for INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET).   Define the offset between two registers, one to be eliminated, and   the other its replacement, at the start of a routine.  */inth8300_initial_elimination_offset (int from, int to){  /* The number of bytes that the return address takes on the stack.  */  int pc_size = POINTER_SIZE / BITS_PER_UNIT;  /* The number of bytes that the saved frame pointer takes on the stack.  */  int fp_size = frame_pointer_needed * UNITS_PER_WORD;  /* The number of bytes that the saved registers, excluding the frame     pointer, take on the stack.  */  int saved_regs_size = 0;  /* The number of bytes that the locals takes on the stack.  */  int frame_size = round_frame_size (get_frame_size ());  int regno;  for (regno = 0; regno <= HARD_FRAME_POINTER_REGNUM; regno++)    if (WORD_REG_USED (regno))      saved_regs_size += UNITS_PER_WORD;  /* Adjust saved_regs_size because the above loop took the frame     pointer int account.  */  saved_regs_size -= fp_size;  if (to == HARD_FRAME_POINTER_REGNUM)    {      switch (from)	{	case ARG_POINTER_REGNUM:	  return pc_size + fp_size;	case RETURN_ADDRESS_POINTER_REGNUM:	  return fp_size;	case FRAME_POINTER_REGNUM:	  return -saved_regs_size;	default:	  abort ();	}    }  else if (to == STACK_POINTER_REGNUM)    {      switch (from)	{	case ARG_POINTER_REGNUM:	  return pc_size + saved_regs_size + frame_size;	case RETURN_ADDRESS_POINTER_REGNUM:	  return saved_regs_size + frame_size;	case FRAME_POINTER_REGNUM:	  return frame_size;	default:	  abort ();	}    }  else    abort ();}/* Worker function for RETURN_ADDR_RTX.  */rtxh8300_return_addr_rtx (int count, rtx frame){  rtx ret;  if (count == 0)    ret = gen_rtx_MEM (Pmode,		       gen_rtx_REG (Pmode, RETURN_ADDRESS_POINTER_REGNUM));  else if (flag_omit_frame_pointer)    return (rtx) 0;  else    ret = gen_rtx_MEM (Pmode,		       memory_address (Pmode,				       plus_constant (frame, UNITS_PER_WORD)));  set_mem_alias_set (ret, get_frame_alias_set ());  return ret;}/* Update the condition code from the insn.  */voidnotice_update_cc (rtx body, rtx insn){  rtx set;  switch (get_attr_cc (insn))    {    case CC_NONE:      /* Insn does not affect CC at all.  */      break;    case CC_NONE_0HIT:      /* Insn does not change CC, but the 0'th operand has been changed.  */      if (cc_status.value1 != 0	  && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))	cc_status.value1 = 0;      if (cc_status.value2 != 0	  && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value2))	cc_status.value2 = 0;      break;    case CC_SET_ZN:      /* Insn sets the Z,N flags of CC to recog_data.operand[0].	 The V flag is unusable.  The C flag may or may not be known but	 that's ok because alter_cond will change tests to use EQ/NE.  */      CC_STATUS_INIT;      cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;      set = single_set (insn);      cc_status.value1 = SET_SRC (set);      if (SET_DEST (set) != cc0_rtx)	cc_status.value2 = SET_DEST (set);      break;    case CC_SET_ZNV:      /* Insn sets the Z,N,V flags of CC to recog_data.operand[0].	 The C flag may or may not be known but that's ok because	 alter_cond will change tests to use EQ/NE.  */      CC_STATUS_INIT;      cc_status.flags |= CC_NO_CARRY;      set = single_set (insn);      cc_status.value1 = SET_SRC (set);      if (SET_DEST (set) != cc0_rtx)	{	  /* If the destination is STRICT_LOW_PART, strip off	     STRICT_LOW_PART.  */	  if (GET_CODE (SET_DEST (set)) == STRICT_LOW_PART)	    cc_status.value2 = XEXP (SET_DEST (set), 0);	  else	    cc_status.value2 = SET_DEST (set);	}      break;    case CC_COMPARE:      /* The insn is a compare instruction.  */      CC_STATUS_INIT;      cc_status.value1 = SET_SRC (body);      break;    case CC_CLOBBER:      /* Insn doesn't leave CC in a usable state.  */      CC_STATUS_INIT;      break;    }}/* Return nonzero if X is a stack pointer.  */intstack_pointer_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  return x == stack_pointer_rtx;}/* Return nonzero if X is a constant whose absolute value is greater   than 2.  */intconst_int_gt_2_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  return (GET_CODE (x) == CONST_INT	  && abs (INTVAL (x)) > 2);}/* Return nonzero if X is a constant whose absolute value is no   smaller than 8.  */intconst_int_ge_8_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  return (GET_CODE (x) == CONST_INT	  && abs (INTVAL (x)) >= 8);}/* Return nonzero if X is a constant expressible in QImode.  */intconst_int_qi_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  return (GET_CODE (x) == CONST_INT	  && (INTVAL (x) & 0xff) == INTVAL (x));}/* Return nonzero if X is a constant expressible in HImode.  */intconst_int_hi_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  return (GET_CODE (x) == CONST_INT	  && (INTVAL (x) & 0xffff) == INTVAL (x));}/* Return nonzero if X is a constant suitable for inc/dec.  */intincdec_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  return (GET_CODE (x) == CONST_INT	  && (CONST_OK_FOR_M (INTVAL (x))	      || CONST_OK_FOR_O (INTVAL (x))));}/* Return nonzero if X is either EQ or NE.  */inteqne_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  enum rtx_code code = GET_CODE (x);  return (code == EQ || code == NE);}/* Return nonzero if X is either GT or LE.  */intgtle_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  enum rtx_code code = GET_CODE (x);  return (code == GT || code == LE);}/* Return nonzero if X is either GTU or LEU.  */intgtuleu_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  enum rtx_code code = GET_CODE (x);  return (code == GTU || code == LEU);}/* Return nonzero if X is either IOR or XOR.  */intiorxor_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  enum rtx_code code = GET_CODE (x);  return (code == IOR || code == XOR);}/* Recognize valid operators for bit instructions.  */intbit_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED){  enum rtx_code code = GET_CODE (x);  return (code == XOR	  || code == AND	  || code == IOR);}/* Given that X occurs in an address of the form (plus X constant),   return the part of X that is expected to be a register.  There are   four kinds of addressing mode to recognize:	@(dd,Rn)	@(dd,RnL.b)	@(dd,Rn.w)	@(dd,ERn.l)   If SIZE is nonnull, and the address is one of the last three forms,   set *SIZE to the index multiplication factor.  Set it to 0 for   plain @(dd,Rn) addresses.   MODE is the mode of the value being accessed.  It can be VOIDmode   if the address is known to be valid, but its mode is unknown.  */rtxh8300_get_index (rtx x, enum machine_mode mode, int *size){  int dummy, factor;  if (size == 0)    size = &dummy;  factor = (mode == VOIDmode ? 0 : GET_MODE_SIZE (mode));  if (TARGET_H8300SX      && factor <= 4      && (mode == VOIDmode	  || GET_MODE_CLASS (mode) == MODE_INT	  || GET_MODE_CLASS (mode) == MODE_FLOAT))    {      if (factor <= 1 && GET_CODE (x) == ZERO_EXTEND)	{	  /* When accessing byte-sized values, the index can be	     a zero-extended QImode or HImode register.  */	  *size = GET_MODE_SIZE (GET_MODE (XEXP (x, 0)));	  return XEXP (x, 0);	}      else	{	  /* We're looking for addresses of the form:		 (mult X I)	      or (mult (zero_extend X) I)	     where I is the size of the operand being accessed.	     The canonical form of the second expression is:		 (and (mult (subreg X) I) J)	     where J == GET_MODE_MASK (GET_MODE (X)) * I.  */	  rtx index;	  if (GET_CODE (x) == AND	      && GET_CODE (XEXP (x, 1)) == CONST_INT	      && (factor == 0		  || INTVAL (XEXP (x, 1)) == 0xff * factor		  || INTVAL (XEXP (x, 1)) == 0xffff * factor))	    {	      index = XEXP (x, 0);	      *size = (INTVAL (XEXP (x, 1)) >= 0xffff ? 2 : 1);	    }	  else	    {	      index = x;	      *size = 4;	    }	  if (GET_CODE (index) == MULT	      && GET_CODE (XEXP (index, 1)) == CONST_INT	      && (factor == 0 || factor == INTVAL (XEXP (index, 1))))	    return XEXP (index, 0);	}    }  *size = 0;  return x;}static const h8300_length_table addb_length_table ={  /* #xx  Rs   @aa  @Rs  @xx  */  {  2,   2,   4,   4,   4  }, /* add.b xx,Rd  */  {  4,   4,   4,   4,   6  }, /* add.b xx,@aa */  {  4,   4,   4,   4,   6  }, /* add.b xx,@Rd */  {  6,   4,   4,   4,   6  }  /* add.b xx,@xx */};static const h8300_length_table addw_length_table ={  /* #xx  Rs   @aa  @Rs  @xx  */  {  2,   2,   4,   4,   4  }, /* add.w xx,Rd  */  {  4,   4,   4,   4,   6  }, /* add.w xx,@aa */  {  4,   4,

⌨️ 快捷键说明

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