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

📄 avr.c

📁 俄罗斯高人Mamaich的Pocket gcc编译器(运行在PocketPC上)的全部源代码。
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Output to FILE the asm instructions to adjust the frame pointer by   ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative   (epilogue).  Returns the number of instructions generated.  */static intout_adj_frame_ptr (file, adj)     FILE *file;     int adj;{  int size = 0;  if (adj)    {      if (TARGET_TINY_STACK)	{	  if (adj < -63 || adj > 63)	    warning ("large frame pointer change (%d) with -mtiny-stack", adj);	  /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)	     over "sbiw" (2 cycles, same size).  */	  fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);	  size++;	}      else if (adj < -63 || adj > 63)	{	  fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB			  AS2 (sbci, r29, hi8(%d)) CR_TAB),		   adj, adj);	  size += 2;	}      else if (adj < 0)	{	  fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);	  size++;	}      else	{	  fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);	  size++;	}    }  return size;}/* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,   handling various cases of interrupt enable flag state BEFORE and AFTER   (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.   Returns the number of instructions generated.  */static intout_set_stack_ptr (file, before, after)     FILE *file;     int before;     int after;{  int do_sph, do_cli, do_save, do_sei, lock_sph, size;  /* The logic here is so that -mno-interrupts actually means     "it is safe to write SPH in one instruction, then SPL in the     next instruction, without disabling interrupts first".     The after != -1 case (interrupt/signal) is not affected.  */  do_sph = !TARGET_TINY_STACK;  lock_sph = do_sph && !TARGET_NO_INTERRUPTS;  do_cli = (before != 0 && (after == 0 || lock_sph));  do_save = (do_cli && before == -1 && after == -1);  do_sei = ((do_cli || before != 1) && after == 1);  size = 1;  if (do_save)    {      fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);      size++;    }  if (do_cli)    {      fprintf (file, "cli" CR_TAB);      size++;    }  /* Do SPH first - maybe this will disable interrupts for one instruction     someday (a suggestion has been sent to avr@atmel.com for consideration     in future devices - that would make -mno-interrupts always safe).  */  if (do_sph)    {      fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);      size++;    }  /* Set/restore the I flag now - interrupts will be really enabled only     after the next instruction.  This is not clearly documented, but     believed to be true for all AVR devices.  */  if (do_save)    {      fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);      size++;    }  else if (do_sei)    {      fprintf (file, "sei" CR_TAB);      size++;    }  fprintf (file, AS2 (out, __SP_L__, r28) "\n");  return size;}/* Output function prologue */static voidavr_output_function_prologue (file, size)     FILE *file;     HOST_WIDE_INT size;{  int reg;  int interrupt_func_p;  int signal_func_p;  int main_p;  int live_seq;  int minimize;  last_insn_address = 0;  jump_tables_size = 0;  prologue_size = 0;  fprintf (file, "/* prologue: frame size=%d */\n", size);  if (avr_naked_function_p (current_function_decl))    {      fputs ("/* prologue: naked */\n", file);      goto out;    }  interrupt_func_p = interrupt_function_p (current_function_decl);  signal_func_p = signal_function_p (current_function_decl);  main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));  live_seq = sequent_regs_live ();  minimize = (TARGET_CALL_PROLOGUES	      && !interrupt_func_p && !signal_func_p && live_seq);  if (interrupt_func_p)    {      fprintf (file,"\tsei\n");      ++prologue_size;    }  if (interrupt_func_p || signal_func_p)    {      fprintf (file, "\t"               AS1 (push,__zero_reg__)   CR_TAB               AS1 (push,__tmp_reg__)    CR_TAB	       AS2 (in,__tmp_reg__,__SREG__) CR_TAB	       AS1 (push,__tmp_reg__)    CR_TAB	       AS1 (clr,__zero_reg__)    "\n");      prologue_size += 5;    }  if (main_p)    {      fprintf (file, ("\t" 		      AS2 (ldi,r28,lo8(%s - %d)) CR_TAB		      AS2 (ldi,r29,hi8(%s - %d)) CR_TAB		      AS2 (out,__SP_H__,r29)     CR_TAB		      AS2 (out,__SP_L__,r28) "\n"),	       avr_init_stack, size, avr_init_stack, size);            prologue_size += 4;    }  else if (minimize && (frame_pointer_needed || live_seq > 6))     {      fprintf (file, ("\t"		      AS2 (ldi, r26, lo8(%d)) CR_TAB		      AS2 (ldi, r27, hi8(%d)) CR_TAB), size, size);      fprintf (file, (AS2 (ldi, r30, pm_lo8(.L_%s_body)) CR_TAB		      AS2 (ldi, r31, pm_hi8(.L_%s_body)) CR_TAB)	       ,current_function_name, current_function_name);            prologue_size += 4;            if (AVR_MEGA)	{	  fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",		   (18 - live_seq) * 2);	  prologue_size += 2;	}      else	{	  fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",		   (18 - live_seq) * 2);	  ++prologue_size;	}      fprintf (file, ".L_%s_body:\n", current_function_name);    }  else    {      HARD_REG_SET set;      prologue_size += avr_regs_to_save (&set);      for (reg = 0; reg < 32; ++reg)	{	  if (TEST_HARD_REG_BIT (set, reg))	    {	      fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);	    }	}      if (frame_pointer_needed)	{	  {	    fprintf (file, "\t"		     AS1 (push,r28) CR_TAB		     AS1 (push,r29) CR_TAB		     AS2 (in,r28,__SP_L__) CR_TAB		     AS2 (in,r29,__SP_H__) "\n");	    prologue_size += 4;	    if (size)	      {		fputs ("\t", file);		prologue_size += out_adj_frame_ptr (file, size);		if (interrupt_func_p)		  {		    prologue_size += out_set_stack_ptr (file, 1, 1);		  }		else if (signal_func_p)		  {		    prologue_size += out_set_stack_ptr (file, 0, 0);		  }		else		  {		    prologue_size += out_set_stack_ptr (file, -1, -1);		  }	      }	  }	}    } out:  fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);}/* Output function epilogue */static voidavr_output_function_epilogue (file, size)     FILE *file;     HOST_WIDE_INT size;{  int reg;  int interrupt_func_p;  int signal_func_p;  int main_p;  int function_size;  int live_seq;  int minimize;  rtx last = get_last_nonnote_insn ();  function_size = jump_tables_size;  if (last)    {      rtx first = get_first_nonnote_insn ();      function_size += (INSN_ADDRESSES (INSN_UID (last)) -			INSN_ADDRESSES (INSN_UID (first)));      function_size += get_attr_length (last);    }  fprintf (file, "/* epilogue: frame size=%d */\n", size);  epilogue_size = 0;  if (avr_naked_function_p (current_function_decl))    {      fputs ("/* epilogue: naked */\n", file);      goto out;    }  if (last && GET_CODE (last) == BARRIER)    {      fputs ("/* epilogue: noreturn */\n", file);      goto out;    }  interrupt_func_p = interrupt_function_p (current_function_decl);  signal_func_p = signal_function_p (current_function_decl);  main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));  live_seq = sequent_regs_live ();  minimize = (TARGET_CALL_PROLOGUES	      && !interrupt_func_p && !signal_func_p && live_seq);    if (main_p)    {      /* Return value from main() is already in the correct registers	 (r25:r24) as the exit() argument.  */      if (AVR_MEGA)	{	  fputs ("\t" AS1 (jmp,exit) "\n", file);	  epilogue_size += 2;	}      else	{	  fputs ("\t" AS1 (rjmp,exit) "\n", file);	  ++epilogue_size;	}    }  else if (minimize && (frame_pointer_needed || live_seq > 4))    {      fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);      ++epilogue_size;      if (frame_pointer_needed)	{	  epilogue_size += out_adj_frame_ptr (file, -size);	}      else	{	  fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB			  AS2 (in , r29, __SP_H__) CR_TAB));	  epilogue_size += 2;	}            if (AVR_MEGA)	{	  fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",		   (18 - live_seq) * 2);	  epilogue_size += 2;	}      else	{	  fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",		   (18 - live_seq) * 2);	  ++epilogue_size;	}    }  else    {      HARD_REG_SET set;      if (frame_pointer_needed)	{	  if (size)	    {	      fputs ("\t", file);	      epilogue_size += out_adj_frame_ptr (file, -size);	      if (interrupt_func_p || signal_func_p)		{		  epilogue_size += out_set_stack_ptr (file, -1, 0);		}	      else		{		  epilogue_size += out_set_stack_ptr (file, -1, -1);		}	    }	  fprintf (file, "\t"		   AS1 (pop,r29) CR_TAB		   AS1 (pop,r28) "\n");	  epilogue_size += 2;	}      epilogue_size += avr_regs_to_save (&set);      for (reg = 31; reg >= 0; --reg)	{	  if (TEST_HARD_REG_BIT (set, reg))	    {	      fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);	    }	}      if (interrupt_func_p || signal_func_p)	{	  fprintf (file, "\t"		   AS1 (pop,__tmp_reg__)      CR_TAB		   AS2 (out,__SREG__,__tmp_reg__) CR_TAB		   AS1 (pop,__tmp_reg__)      CR_TAB		   AS1 (pop,__zero_reg__)     "\n");	  epilogue_size += 4;	  fprintf (file, "\treti\n");	}      else	fprintf (file, "\tret\n");      ++epilogue_size;    } out:  fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);  fprintf (file, "/* function %s size %d (%d) */\n", current_function_name,	   prologue_size + function_size + epilogue_size, function_size);  commands_in_file += prologue_size + function_size + epilogue_size;  commands_in_prologues += prologue_size;  commands_in_epilogues += epilogue_size;}/* Return nonzero if X (an RTX) is a legitimate memory address on the target   machine for a memory operand of mode MODE.  */intlegitimate_address_p (mode, x, strict)     enum machine_mode mode;     rtx x;     int strict;{  enum reg_class r = NO_REGS;    if (TARGET_ALL_DEBUG)    {      fprintf (stderr, "mode: (%s) %s %s %s %s:",	       GET_MODE_NAME(mode),	       strict ? "(strict)": "",	       reload_completed ? "(reload_completed)": "",	       reload_in_progress ? "(reload_in_progress)": "",	       reg_renumber ? "(reg_renumber)" : "");      if (GET_CODE (x) == PLUS	  && REG_P (XEXP (x, 0))	  && GET_CODE (XEXP (x, 1)) == CONST_INT	  && INTVAL (XEXP (x, 1)) >= 0	  && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)	  && reg_renumber	  )	fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),		 true_regnum (XEXP (x, 0)));      debug_rtx (x);    }  if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)                    : REG_OK_FOR_BASE_NOSTRICT_P (x)))    r = POINTER_REGS;  else if (CONSTANT_ADDRESS_P (x))    r = ALL_REGS;  else if (GET_CODE (x) == PLUS           && REG_P (XEXP (x, 0))	   && GET_CODE (XEXP (x, 1)) == CONST_INT	   && INTVAL (XEXP (x, 1)) >= 0)    {      int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);      if (fit)	{	  if (! strict	      || REGNO (XEXP (x,0)) == REG_Y	      || REGNO (XEXP (x,0)) == REG_Z)	    r = BASE_POINTER_REGS;	  if (XEXP (x,0) == frame_pointer_rtx	      || XEXP (x,0) == arg_pointer_rtx)	    r = BASE_POINTER_REGS;	}      else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)	r = POINTER_Y_REGS;    }  else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)           && REG_P (XEXP (x, 0))           && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))               : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))    {      r = POINTER_REGS;    }  if (TARGET_ALL_DEBUG)    {      fprintf (stderr, "   ret = %c\n", r);    }  return r == NO_REGS ? 0 : (int)r;}/* Attempts to replace X with a valid   memory address for an operand of mode MODE  */rtxlegitimize_address (x, oldx, mode)     rtx x;     rtx oldx;     enum machine_mode mode;{  x = oldx;  if (TARGET_ALL_DEBUG)    {      fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));      debug_rtx (oldx);    }    if (GET_CODE (oldx) == PLUS      && REG_P (XEXP (oldx,0)))    {      if (REG_P (XEXP (oldx,1)))	x = force_reg (GET_MODE (oldx), oldx);      else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)	{	  int offs = INTVAL (XEXP (oldx,1));	  if (frame_pointer_rtx != XEXP (oldx,0))	    if (offs > MAX_LD_OFFSET (mode))	      {		if (TARGET_ALL_DEBUG)		  fprintf (stderr, "force_reg (big offset)\n");		x = force_reg (GET_MODE (oldx), oldx);	      }	}    }  return x;}/* Return a pointer register name as a string */static const char *ptrreg_to_str (regno)     int regno;{  switch (regno)    {    case REG_X: return "X";    case REG_Y: return "Y";    case REG_Z: return "Z";

⌨️ 快捷键说明

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