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

📄 pa.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
  fprintf (file, "\"\n");}/* You may have trouble believing this, but this is the HP-PA stack   layout.  Wow.   Offset		Contents   Variable arguments	(optional; any number may be allocated)   SP-(4*(N+9))		arg word N   	:		    :      SP-56		arg word 5      SP-52		arg word 4   Fixed arguments	(must be allocated; may remain unused)      SP-48		arg word 3      SP-44		arg word 2      SP-40		arg word 1      SP-36		arg word 0   Frame Marker      SP-32		External Data Pointer (DP)      SP-28		External sr4      SP-24		External/stub RP (RP')      SP-20		Current RP      SP-16		Static Link      SP-12		Clean up      SP-8		Calling Stub RP (RP'')      SP-4		Previous SP   Top of Frame      SP-0		Stack Pointer (points to next available address)*//* This function saves registers as follows.  Registers marked with ' are   this function's registers (as opposed to the previous function's).   If a frame_pointer isn't needed, r4 is saved as a general register;   the space for the frame pointer is still allocated, though, to keep   things simple.   Top of Frame       SP (FP')		Previous FP       SP + 4		Alignment filler (sigh)       SP + 8		Space for locals reserved here.       .       .       .       SP + n		All call saved register used.       .       .       .       SP + o		All call saved fp registers used.       .       .       .       SP + p (SP')	points to next available address.*//* Emit RTL to store REG at the memory location specified by BASE+DISP.   Handle case where DISP > 8k by using the add_high_const pattern.   Note in DISP > 8k case, we will leave the high part of the address   in %r1.  There is code in expand_hppa_{prologue,epilogue} that knows this.*/static voidstore_reg (reg, disp, base)     int reg, disp, base;{  if (VAL_14_BITS_P (disp))    {      emit_move_insn (gen_rtx (MEM, SImode,			       gen_rtx (PLUS, SImode,				        gen_rtx (REG, SImode, base),				        GEN_INT (disp))),		      gen_rtx (REG, SImode, reg));    }  else    {      emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1),				     gen_rtx (REG, SImode, base),				     GEN_INT (disp)));      emit_move_insn (gen_rtx (MEM, SImode,			       gen_rtx (LO_SUM, SImode,					gen_rtx (REG, SImode, 1),					GEN_INT (disp))),		      gen_rtx (REG, SImode, reg));    }}/* Emit RTL to load REG from the memory location specified by BASE+DISP.   Handle case where DISP > 8k by using the add_high_const pattern.   Note in DISP > 8k case, we will leave the high part of the address   in %r1.  There is code in expand_hppa_{prologue,epilogue} that knows this.*/static voidload_reg (reg, disp, base)     int reg, disp, base;{  if (VAL_14_BITS_P (disp))    {      emit_move_insn (gen_rtx (REG, SImode, reg),		      gen_rtx (MEM, SImode,			       gen_rtx (PLUS, SImode,				        gen_rtx (REG, SImode, base),				        GEN_INT (disp))));    }  else    {      emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1),				     gen_rtx (REG, SImode, base),				     GEN_INT (disp)));      emit_move_insn (gen_rtx (REG, SImode, reg),		      gen_rtx (MEM, SImode,			       gen_rtx (LO_SUM, SImode,					gen_rtx (REG, SImode, 1),					GEN_INT (disp))));    }}/* Emit RTL to set REG to the value specified by BASE+DISP.   Handle case where DISP > 8k by using the add_high_const pattern.   Note in DISP > 8k case, we will leave the high part of the address   in %r1.  There is code in expand_hppa_{prologue,epilogue} that knows this.*/static voidset_reg_plus_d(reg, base, disp)     int reg, base, disp;{  if (VAL_14_BITS_P (disp))    {      emit_move_insn (gen_rtx (REG, SImode, reg),		      gen_rtx (PLUS, SImode,			       gen_rtx (REG, SImode, base),			       GEN_INT (disp)));    }  else    {      emit_insn (gen_add_high_const (gen_rtx (REG, SImode, 1),				     gen_rtx (REG, SImode, base),				     GEN_INT (disp)));      emit_move_insn (gen_rtx (REG, SImode, reg),		      gen_rtx (LO_SUM, SImode,					gen_rtx (REG, SImode, 1),					GEN_INT (disp)));    }}/* Global variables set by FUNCTION_PROLOGUE.  *//* Size of frame.  Need to know this to emit return insns from   leaf procedures.  */static int actual_fsize;static int local_fsize, save_fregs;intcompute_frame_size (size, fregs_live)     int size;     int *fregs_live;{  extern int current_function_outgoing_args_size;  int i, fsize;  /* 8 is space for frame pointer + filler. If any frame is allocated     we need to add this in because of STARTING_FRAME_OFFSET. */  fsize = size + (size || frame_pointer_needed ? 8 : 0);  for (i = 18; i >= 4; i--)    {      if (regs_ever_live[i])	fsize += 4;    }  /* If we don't have a frame pointer, the register normally used for that     purpose is saved just like other registers, not in the "frame marker".  */  if (! frame_pointer_needed)    {      if (regs_ever_live[FRAME_POINTER_REGNUM])	fsize += 4;    }  fsize = (fsize + 7) & ~7;  for (i = 66; i >= 48; i -= 2)    if (regs_ever_live[i] || regs_ever_live[i + 1])      {	fsize += 8;	if (fregs_live)	  *fregs_live = 1;      }  fsize += current_function_outgoing_args_size;  if (! leaf_function_p () || fsize)    fsize += 32;  return (fsize + 63) & ~63;}rtx hp_profile_label_rtx;static char hp_profile_label_name[8];voidoutput_function_prologue (file, size)     FILE *file;     int size;{  /* The function's label and associated .PROC must never be     separated and must be output *after* any profiling declarations     to avoid changing spaces/subspaces within a procedure.  */  ASM_OUTPUT_LABEL (file, XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));  fputs ("\t.PROC\n", file);  /* hppa_expand_prologue does the dirty work now.  We just need     to output the assembler directives which denote the start     of a function.  */  fprintf (file, "\t.CALLINFO FRAME=%d", actual_fsize);  if (regs_ever_live[2] || profile_flag)    fprintf (file, ",CALLS,SAVE_RP");  else    fprintf (file, ",NO_CALLS");  if (frame_pointer_needed)    fprintf (file, ",SAVE_SP");  /* Pass on information about the number of callee register saves     performed in the prologue.     The compiler is supposed to pass the highest register number     saved, the assembler then has to adjust that number before     entering it into the unwind descriptor (to account for any     caller saved registers with lower register numbers than the     first callee saved register).  */  if (gr_saved)    fprintf (file, ",ENTRY_GR=%d", gr_saved + 2);  if (fr_saved)    fprintf (file, ",ENTRY_FR=%d", fr_saved + 11);  fprintf (file, "\n\t.ENTRY\n");  /* Horrid hack.  emit_function_prologue will modify this RTL in     place to get the expected results.  */  if (profile_flag)    ASM_GENERATE_INTERNAL_LABEL (hp_profile_label_name, "LP",				 hp_profile_labelno);  if (insn_addresses)    {      unsigned int old_total = total_code_bytes;      total_code_bytes += insn_addresses[INSN_UID (get_last_insn())];      total_code_bytes += FUNCTION_BOUNDARY /BITS_PER_UNIT;      /* Be prepared to handle overflows.  */      total_code_bytes = old_total > total_code_bytes ? -1 : total_code_bytes;    }  else    total_code_bytes = -1;}voidhppa_expand_prologue(){  extern char call_used_regs[];  int size = get_frame_size ();  int merge_sp_adjust_with_store = 0;  int i, offset;  rtx tmpreg, size_rtx;  gr_saved = 0;  fr_saved = 0;  save_fregs = 0;  local_fsize =  size + (size || frame_pointer_needed ? 8 : 0);  actual_fsize = compute_frame_size (size, &save_fregs);  /* Compute a few things we will use often.  */  tmpreg = gen_rtx (REG, SImode, 1);  size_rtx = GEN_INT (actual_fsize);  /* Save RP first.  The calling conventions manual states RP will     always be stored into the caller's frame at sp-20.  */  if (regs_ever_live[2] || profile_flag)    store_reg (2, -20, STACK_POINTER_REGNUM);  /* Allocate the local frame and set up the frame pointer if needed.  */  if (actual_fsize)    if (frame_pointer_needed)      {	/* Copy the old frame pointer temporarily into %r1.  Set up the	   new stack pointer, then store away the saved old frame pointer	   into the stack at sp+actual_fsize and at the same time update	   the stack pointer by actual_fsize bytes.  Two versions, first	   handles small (<8k) frames.  The second handles large (>8k)	   frames.  */	emit_move_insn (tmpreg, frame_pointer_rtx);	emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);	if (VAL_14_BITS_P (actual_fsize))	  emit_insn (gen_post_stwm (stack_pointer_rtx,				    stack_pointer_rtx,				    size_rtx, tmpreg));	else	  {	    /* It is incorrect to store the saved frame pointer at *sp,	       then increment sp (writes beyond the current stack boundary).	       So instead use stwm to store at *sp and post-increment the	       stack pointer as an atomic operation.  Then increment sp to	       finish allocating the new frame.  */	    emit_insn (gen_post_stwm (stack_pointer_rtx,				      stack_pointer_rtx,				      GEN_INT (64), tmpreg));	    set_reg_plus_d (STACK_POINTER_REGNUM,			    STACK_POINTER_REGNUM,			    actual_fsize - 64);	  }      }    /* no frame pointer needed.  */    else      {	/* In some cases we can perform the first callee register save	   and allocating the stack frame at the same time.   If so, just	   make a note of it and defer allocating the frame until saving	   the callee registers.  */	if (VAL_14_BITS_P (-actual_fsize)	    && local_fsize == 0	    && ! profile_flag	    && ! flag_pic)	  merge_sp_adjust_with_store = 1;	/* Can not optimize.  Adjust the stack frame by actual_fsize bytes.  */	else if (actual_fsize != 0)	  set_reg_plus_d (STACK_POINTER_REGNUM,			  STACK_POINTER_REGNUM,			  actual_fsize);      }  /* The hppa calling conventions say that that %r19, the pic offset     register, is saved at sp - 32 (in this function's frame)  when     generating PIC code.  FIXME:  What is the correct thing to do     for functions which make no calls and allocate no frame?  Do     we need to allocate a frame, or can we just omit the save?   For     now we'll just omit the save.  */  if (actual_fsize != 0 && flag_pic)    store_reg (PIC_OFFSET_TABLE_REGNUM, -32, STACK_POINTER_REGNUM);  /* Profiling code.     Instead of taking one argument, the counter label, as most normal     mcounts do, _mcount appears to behave differently on the HPPA.  It     takes the return address of the caller, the address of this routine,     and the address of the label.  Also, it isn't magic, so     argument registers have to be preserved.  */  if (profile_flag)    {      int pc_offset, i, arg_offset, basereg, offsetadj;      pc_offset = 4 + (frame_pointer_needed		       ? (VAL_14_BITS_P (actual_fsize) ? 12 : 20)		       : (VAL_14_BITS_P (actual_fsize) ? 4 : 8));      /* When the function has a frame pointer, use it as the base	 register for saving/restore registers.  Else use the stack	 pointer.  Adjust the offset according to the frame size if	 this function does not have a frame pointer.  */      basereg = frame_pointer_needed ? FRAME_POINTER_REGNUM				     : STACK_POINTER_REGNUM;      offsetadj = frame_pointer_needed ? 0 : actual_fsize;      /* Horrid hack.  emit_function_prologue will modify this RTL in	 place to get the expected results.   sprintf here is just to	 put something in the name.  */      sprintf(hp_profile_label_name, "LP$%04d", -1);      hp_profile_label_rtx = gen_rtx (SYMBOL_REF, SImode,				      hp_profile_label_name);      if (current_function_returns_struct)	store_reg (STRUCT_VALUE_REGNUM, - 12 - offsetadj, basereg);      for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)	if (regs_ever_live [i])	  {	    store_reg (i, arg_offset, basereg);	    /* Deal with arg_offset not fitting in 14 bits.  */	    pc_offset += VAL_14_BITS_P (arg_offset) ? 4 : 8;	  }      emit_move_insn (gen_rtx (REG, SImode, 26), gen_rtx (REG, SImode, 2));      emit_move_insn (tmpreg, gen_rtx (HIGH, SImode, hp_profile_label_rtx));      emit_move_insn (gen_rtx (REG, SImode, 24),		      gen_rtx (LO_SUM, SImode, tmpreg, hp_profile_label_rtx));      /* %r25 is set from within the output pattern.  */      emit_insn (gen_call_profiler (GEN_INT (- pc_offset - 20)));      /* Restore argument registers.  */      for (i = 26, arg_offset = -36 - offsetadj; i >= 23; i--, arg_offset -= 4)	if (regs_ever_live [i])	  load_reg (i, arg_offset, basereg);      if (current_function_returns_struct)	load_reg (STRUCT_VALUE_REGNUM, -12 - offsetadj, basereg);    }  /* Normal register save.     Do not save the frame pointer in the frame_pointer_needed case.  It     was done earlier.  */  if (frame_pointer_needed)    {      for (i = 18, offset = local_fsize; i >= 4; i--)	if (regs_ever_live[i] && ! call_used_regs[i])	  {	    store_reg (i, offset, FRAME_POINTER_REGNUM);	    offset += 4;	    gr_saved++;	  }      /* Account for %r4 which is saved in a special place.  */      gr_saved++;    }  /* No frame pointer needed.  */  else    {      for (i = 18, offset = local_fsize - actual_fsize; i >= 3; i--)      	if (regs_ever_live[i] && ! call_used_regs[i])	  {	    /* If merge_sp_adjust_with_store is nonzero, then we can	       optimize the first GR save.  */	    if (merge_sp_adjust_with_store)	      {		merge_sp_adjust_with_store = 0;	        emit_insn (gen_post_stwm (stack_pointer_rtx,					  stack_pointer_rtx,					  GEN_INT (-offset),					  gen_rtx (REG, SImode, i)));	      }	    else	      store_reg (i, offset, STACK_POINTER_REGNUM);	    offset += 4;	    gr_saved++;	  }      /* If we wanted to merge the SP adjustment with a GR save, but we never	 did any GR saves, then just emit the adjustment here.  */      if (merge_sp_adjust_with_store)	set_reg_plus_d (STACK_POINTER_REGNUM,			STACK_POINTER_REGNUM,			actual_fsize);    }  /* Align pointer properly (doubleword boundary).  */  offset = (offset + 7) & ~7;  /* Floating point register store.  */  if (save_fregs)    {      /* First get the frame or stack pointer to the start of the FP register	 save area.  */      if (frame_pointer_needed)	set_reg_plus_d (1, FRAME_POINTER_REGNUM, offset);      else	set_reg_plus_d (1, STACK_POINTER_REGNUM, offset);      /* Now actually save the FP registers.  */      for (i = 66; i >= 48; i -= 2)	if (regs_ever_live[i] || regs_ever_live[i + 1])	  {	    emit_move_insn (gen_rtx (MEM, DFmode,				   

⌨️ 快捷键说明

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