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

📄 h8300.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
   <args>   PC   FP			<- fp   <locals>   <saved registers>	<- sp   This is what the stack looks like after the prolog of   a function which doesn't have a frame:   <args>   PC   <locals>   <saved registers>	<- sp*//* Output assembly language code for the function prologue.  */static voidh8300_output_function_prologue (file, size)     FILE *file;     HOST_WIDE_INT size;{  int fsize = round_frame_size (size);  int regno;  int saved_regs;  int n_regs;  /* Note a function with the interrupt attribute and set interrupt_handler     accordingly.  */  if (h8300_interrupt_function_p (current_function_decl))    interrupt_handler = 1;  /* If the current function has the OS_Task attribute set, then     we have a naked prologue.  */  if (h8300_os_task_function_p (current_function_decl))    {      fprintf (file, ";OS_Task prologue\n");      os_task = 1;      return;    }  if (h8300_monitor_function_p (current_function_decl))    {      /* My understanding of monitor functions is they act just	 like interrupt functions, except the prologue must	 mask interrupts.  */      fprintf (file, ";monitor prologue\n");      interrupt_handler = 1;      monitor = 1;      if (TARGET_H8300)	{	  fprintf (file, "\tsubs\t#2,sp\n");	  push (file, 0);	  fprintf (file, "\tstc\tccr,r0l\n");	  fprintf (file, "\tmov.b\tr0l,@(2,sp)\n");	  pop (file, 0);	  fprintf (file, "\torc\t#128,ccr\n");	}      else if (TARGET_H8300H)	{	  push (file, 0);	  fprintf (file, "\tstc\tccr,r0l\n");	  fprintf (file, "\tmov.b\tr0l,@(4,sp)\n");	  pop (file, 0);	  fprintf (file, "\torc\t#128,ccr\n");	}      else if (TARGET_H8300S)	{	  fprintf (file, "\tstc\texr,@-sp\n");	  push (file, 0);	  fprintf (file, "\tstc\tccr,r0l\n");	  fprintf (file, "\tmov.b\tr0l,@(6,sp)\n");	  pop (file, 0);	  fprintf (file, "\torc\t#128,ccr\n");	}      else	abort ();    }  if (frame_pointer_needed)    {      /* Push fp.  */      push (file, FRAME_POINTER_REGNUM);      fprintf (file, "\t%s\t%s,%s\n", h8_mov_op,	       h8_reg_names[STACK_POINTER_REGNUM],	       h8_reg_names[FRAME_POINTER_REGNUM]);    }  /* Leave room for locals.  */  dosize (file, -1, fsize);  /* Push the rest of the registers in ascending order.  */  saved_regs = compute_saved_regs ();  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno += n_regs)    {      n_regs = 1;      if (saved_regs & (1 << regno))	{	  if (TARGET_H8300S)	    {	      /* See how many registers we can push at the same time.  */	      if ((regno == 0 || regno == 4)		  && ((saved_regs >> regno) & 0x0f) == 0x0f)		n_regs = 4;	      else if ((regno == 0 || regno == 4)		       && ((saved_regs >> regno) & 0x07) == 0x07)		n_regs = 3;	      else if ((regno == 0 || regno == 2 || regno == 4 || regno == 6)		       && ((saved_regs >> regno) & 0x03) == 0x03)		n_regs = 2;	    }	  switch (n_regs)	    {	    case 1:	      push (file, regno);	      break;	    case 2:	      fprintf (file, "\tstm.l\t%s-%s,@-er7\n",		       h8_reg_names[regno],		       h8_reg_names[regno + 1]);	      break;	    case 3:	      fprintf (file, "\tstm.l\t%s-%s,@-er7\n",		       h8_reg_names[regno],		       h8_reg_names[regno + 2]);	      break;	    case 4:	      fprintf (file, "\tstm.l\t%s-%s,@-er7\n",		       h8_reg_names[regno],		       h8_reg_names[regno + 3]);	      break;	    default:	      abort ();	    }	}    }}/* Output assembly language code for the function epilogue.  */static voidh8300_output_function_epilogue (file, size)     FILE *file;     HOST_WIDE_INT size;{  int fsize = round_frame_size (size);  int regno;  rtx insn = get_last_insn ();  int saved_regs;  int n_regs;  if (os_task)    {      /* OS_Task epilogues are nearly naked -- they just have an	 rts instruction.  */      fprintf (file, ";OS_task epilogue\n");      fprintf (file, "\trts\n");      goto out;    }  /* Monitor epilogues are the same as interrupt function epilogues.     Just make a note that we're in an monitor epilogue.  */  if (monitor)    fprintf (file, ";monitor epilogue\n");  /* If the last insn was a BARRIER, we don't have to write any code.  */  if (GET_CODE (insn) == NOTE)    insn = prev_nonnote_insn (insn);  if (insn && GET_CODE (insn) == BARRIER)    goto out;  /* Pop the saved registers in descending order.  */  saved_regs = compute_saved_regs ();  for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno -= n_regs)    {      n_regs = 1;      if (saved_regs & (1 << regno))	{	  if (TARGET_H8300S)	    {	      /* See how many registers we can pop at the same time.  */	      if ((regno == 7 || regno == 3)		  && ((saved_regs >> (regno - 3)) & 0x0f) == 0x0f)		n_regs = 4;	      else if ((regno == 6 || regno == 2)		       && ((saved_regs >> (regno - 2)) & 0x07) == 0x07)		n_regs = 3;	      else if ((regno == 7 || regno == 5 || regno == 3 || regno == 1)		       && ((saved_regs >> (regno - 1)) & 0x03) == 0x03)		n_regs = 2;	    }	  switch (n_regs)	    {	    case 1:	      pop (file, regno);	      break;	    case 2:	      fprintf (file, "\tldm.l\t@er7+,%s-%s\n",		       h8_reg_names[regno - 1],		       h8_reg_names[regno]);	      break;	    case 3:	      fprintf (file, "\tldm.l\t@er7+,%s-%s\n",		       h8_reg_names[regno - 2],		       h8_reg_names[regno]);	      break;	    case 4:	      fprintf (file, "\tldm.l\t@er7+,%s-%s\n",		       h8_reg_names[regno - 3],		       h8_reg_names[regno]);	      break;	    default:	      abort ();	    }	}    }  /* Deallocate locals.  */  dosize (file, 1, fsize);  /* Pop frame pointer if we had one.  */  if (frame_pointer_needed)    pop (file, FRAME_POINTER_REGNUM);  if (interrupt_handler)    fprintf (file, "\trte\n");  else    fprintf (file, "\trts\n"); out:  interrupt_handler = 0;  os_task = 0;  monitor = 0;  pragma_saveall = 0;}/* Output assembly code for the start of the file.  */voidasm_file_start (file)     FILE *file;{  fprintf (file, ";\tGCC For the Hitachi H8/300\n");  fprintf (file, ";\tBy Hitachi America Ltd and Cygnus Support\n");  if (optimize_size)    fprintf (file, "; -Os\n");  else if (optimize)    fprintf (file, "; -O%d\n", optimize);  if (TARGET_H8300H)    fprintf (file, TARGET_NORMAL_MODE ? "\n\t.h8300hn\n" : "\n\t.h8300h\n");  else if (TARGET_H8300S)    fprintf (file, TARGET_NORMAL_MODE ? "\n\t.h8300sn\n" : "\n\t.h8300s\n");  else    fprintf (file, "\n\n");  output_file_directive (file, main_input_filename);}/* Output assembly language code for the end of file.  */voidasm_file_end (file)     FILE *file;{  fprintf (file, "\t.end\n");}/* Return true if OP is a valid source operand for an integer move   instruction.  */intgeneral_operand_src (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_MODE (op) == mode      && GET_CODE (op) == MEM      && GET_CODE (XEXP (op, 0)) == POST_INC)    return 1;  return general_operand (op, mode);}/* Return true if OP is a valid destination operand for an integer move   instruction.  */intgeneral_operand_dst (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_MODE (op) == mode      && GET_CODE (op) == MEM      && GET_CODE (XEXP (op, 0)) == PRE_DEC)    return 1;  return general_operand (op, mode);}/* Return true if OP is a constant that contains only one 1 in its   binary representation.  */intsingle_one_operand (operand, mode)     rtx operand;     enum machine_mode mode ATTRIBUTE_UNUSED;{  if (GET_CODE (operand) == CONST_INT)    {      /* We really need to do this masking because 0x80 in QImode is	 represented as -128 for example.  */      unsigned HOST_WIDE_INT mask =	(GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)	? ((unsigned HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (mode)) - 1	: ~(unsigned HOST_WIDE_INT) 0;      unsigned HOST_WIDE_INT value = INTVAL (operand);      if (exact_log2 (value & mask) >= 0)	return 1;    }  return 0;}/* Return true if OP is a constant that contains only one 0 in its   binary representation.  */intsingle_zero_operand (operand, mode)     rtx operand;     enum machine_mode mode ATTRIBUTE_UNUSED;{  if (GET_CODE (operand) == CONST_INT)    {      /* We really need to do this masking because 0x80 in QImode is	 represented as -128 for example.  */      unsigned HOST_WIDE_INT mask =	(GET_MODE_BITSIZE (mode) < HOST_BITS_PER_WIDE_INT)	? ((unsigned HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (mode)) - 1	: ~(unsigned HOST_WIDE_INT) 0;      unsigned HOST_WIDE_INT value = INTVAL (operand);      if (exact_log2 (~value & mask) >= 0)	return 1;    }  return 0;}/* Return true if OP is a valid call operand.  */intcall_insn_operand (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  if (GET_CODE (op) == MEM)    {      rtx inside = XEXP (op, 0);      if (register_operand (inside, Pmode))	return 1;      if (CONSTANT_ADDRESS_P (inside))	return 1;    }  return 0;}/* Return 1 if an addition/subtraction of a constant integer can be   transformed into two consecutive adds/subs that are faster than the   straightforward way.  Otherwise, return 0.  */inttwo_insn_adds_subs_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == CONST_INT)    {      HOST_WIDE_INT value = INTVAL (op);      /* Force VALUE to be positive so that we do not have to consider         the negative case.  */      if (value < 0)	value = -value;      if (TARGET_H8300H || TARGET_H8300S)	{	  /* A constant addition/subtraction takes 2 states in QImode,	     4 states in HImode, and 6 states in SImode.  Thus, the	     only case we can win is when SImode is used, in which	     case, two adds/subs are used, taking 4 states.  */	  if (mode == SImode	      && (value == 2 + 1		  || value == 4 + 1		  || value == 4 + 2		  || value == 4 + 4))	    return 1;	}      else	{	  /* We do not profit directly by splitting addition or	     subtraction of 3 and 4.  However, since these are	     implemented as a sequence of adds or subs, they do not	     clobber (cc0) unlike a sequence of add.b and add.x.  */	  if (mode == HImode	      && (value == 2 + 1		  || value == 2 + 2))	    return 1;	}    }  return 0;}/* Split an add of a small constant into two adds/subs insns.  */voidsplit_adds_subs (mode, operands)     enum machine_mode mode;     rtx *operands;{  HOST_WIDE_INT val = INTVAL (operands[1]);  rtx reg = operands[0];  HOST_WIDE_INT sign = 1;  HOST_WIDE_INT amount;  /* Force VAL to be positive so that we do not have to consider the     sign.  */  if (val < 0)    {      val = -val;      sign = -1;    }  /* Try different amounts in descending order.  */  for (amount = (TARGET_H8300H || TARGET_H8300S) ? 4 : 2;       amount > 0;       amount /= 2)    {      for (; val >= amount; val -= amount)	{	  rtx tmp = gen_rtx_PLUS (mode, reg, GEN_INT (sign * amount));	  emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));	}    }  return;}/* Return true if OP is a valid call operand, and OP represents   an operand for a small call (4 bytes instead of 6 bytes).  */intsmall_call_insn_operand (op, mode)     rtx op;     enum machine_mode mode ATTRIBUTE_UNUSED;{  if (GET_CODE (op) == MEM)    {      rtx inside = XEXP (op, 0);      /* Register indirect is a small call.  */      if (register_operand (inside, Pmode))	return 1;      /* A call through the function vector is a small	 call too.  */      if (GET_CODE (inside) == SYMBOL_REF	  && SYMBOL_REF_FLAG (inside))	return 1;    }  /* Otherwise it's a large call.  */  return 0;}/* Return true if OP is a valid jump operand.  */intjump_address_operand (op, mode)     rtx op;     enum machine_mode mode;{  if (GET_CODE (op) == REG)    return mode == Pmode;  if (GET_CODE (op) == MEM)    {      rtx inside = XEXP (op, 0);      if (register_operand (inside, Pmode))	return 1;      if (CONSTANT_ADDRESS_P (inside))	return 1;    }  return 0;}/* Recognize valid operands for bit-field instructions.  */extern int rtx_equal_function_value_matters;

⌨️ 快捷键说明

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