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

📄 thumb.c

📁 gcc编译工具没有什么特别
💻 C
📖 第 1 页 / 共 4 页
字号:
	    asm_fprintf (asm_out_file, reg_names[regno]);	    if (live_regs_mask & ~1)		asm_fprintf (asm_out_file, ", ");	  }      if (   TARGET_THUMB_INTERWORK	  || TARGET_BACKTRACE	  || is_called_in_ARM_mode (current_function_decl))	{	  asm_fprintf (asm_out_file, "}\n");	  thumb_exit (asm_out_file, -1);	}      else	asm_fprintf (asm_out_file, ", pc}\n");    }    return "";}voidthumb_function_prologue (f, frame_size)     FILE *f;     int frame_size;{  int amount = frame_size + current_function_outgoing_args_size;  int live_regs_mask = 0;  int high_regs_pushed = 0;  int store_arg_regs = 0;  int regno;  if (is_called_in_ARM_mode (current_function_decl))    {      char * name;      if (GET_CODE (DECL_RTL (current_function_decl)) != MEM)	abort();      if (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0)) != SYMBOL_REF)	abort();      name = XSTR  (XEXP (DECL_RTL (current_function_decl), 0), 0);            /* Generate code sequence to switch us into Thumb mode.  */      /* The .code 32 directive has already been emitted by	 ASM_DECLARE_FUNCITON_NAME */      asm_fprintf (f, "\torr\tr12, pc, #1\n");      asm_fprintf (f, "\tbx\tr12\n");      /* Generate a label, so that the debugger will notice the	 change in instruction sets.  This label is also used by	 the assembler to bypass the ARM code when this function	 is called from a Thumb encoded function elsewhere in the	 same file.  Hence the definition of STUB_NAME here must	 agree with the definition in gas/config/tc-arm.c  */      #define STUB_NAME ".real_start_of"            asm_fprintf (f, "\t.code\t16\n");      asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);      asm_fprintf (f, "\t.thumb_func\n");      asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);    }      if (current_function_anonymous_args && current_function_pretend_args_size)    store_arg_regs = 1;  if (current_function_pretend_args_size)    {      if (store_arg_regs)	{	  asm_fprintf (f, "\tpush\t{");	  for (regno = 4 - current_function_pretend_args_size / 4 ; regno < 4;	       regno++)	    asm_fprintf (f, "%s%s", reg_names[regno], regno == 3 ? "" : ", ");	  asm_fprintf (f, "}\n");	}      else	asm_fprintf (f, "\tsub\t%Rsp, %Rsp, #%d\n", 		     current_function_pretend_args_size);    }  for (regno = 0; regno < 8; regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      live_regs_mask |= 1 << regno;  if (live_regs_mask || ! leaf_function_p () || far_jump_used_p())    live_regs_mask |= 1 << 14;  if (TARGET_BACKTRACE)    {      char * name;      int    offset;      int    work_register = 0;                  /* We have been asked to create a stack backtrace structure.         The code looks like this:	 	 0   .align 2	 0   func:         0     sub   SP, #16         Reserve space for 4 registers.	 2     push  {R7}            Get a work register.         4     add   R7, SP, #20     Get the stack pointer before the push.         6     str   R7, [SP, #8]    Store the stack pointer (before reserving the space).         8     mov   R7, PC          Get hold of the start of this code plus 12.        10     str   R7, [SP, #16]   Store it.        12     mov   R7, FP          Get hold of the current frame pointer.        14     str   R7, [SP, #4]    Store it.        16     mov   R7, LR          Get hold of the current return address.        18     str   R7, [SP, #12]   Store it.        20     add   R7, SP, #16     Point at the start of the backtrace structure.        22     mov   FP, R7          Put this value into the frame pointer.  */      if ((live_regs_mask & 0xFF) == 0)	{	  /* See if the a4 register is free.  */	  if (regs_ever_live[ 3 ] == 0)	    work_register = 3;	  else	  /* We must push a register of our own */	    live_regs_mask |= (1 << 7);	}      if (work_register == 0)	{	  /* Select a register from the list that will be pushed to use as our work register. */	  for (work_register = 8; work_register--;)	    if ((1 << work_register) & live_regs_mask)	      break;	}            name = reg_names[ work_register ];            asm_fprintf (f, "\tsub\tsp, sp, #16\t@ Create stack backtrace structure\n");            if (live_regs_mask)	thumb_pushpop (f, live_regs_mask, 1);            for (offset = 0, work_register = 1 << 15; work_register; work_register >>= 1)	if (work_register & live_regs_mask)	  offset += 4;            asm_fprintf (f, "\tadd\t%s, sp, #%d\n",		   name, offset + 16 + current_function_pretend_args_size);            asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 4);      /* Make sure that the instruction fetching the PC is in the right place	 to calculate "start of backtrace creation code + 12".  */            if (live_regs_mask)	{	  asm_fprintf (f, "\tmov\t%s, pc\n", name);	  asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);	  asm_fprintf (f, "\tmov\t%s, fp\n", name);	  asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);	}      else	{	  asm_fprintf (f, "\tmov\t%s, fp\n", name);	  asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset);	  asm_fprintf (f, "\tmov\t%s, pc\n", name);	  asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 12);	}            asm_fprintf (f, "\tmov\t%s, lr\n", name);      asm_fprintf (f, "\tstr\t%s, [sp, #%d]\n", name, offset + 8);      asm_fprintf (f, "\tadd\t%s, sp, #%d\n", name, offset + 12);      asm_fprintf (f, "\tmov\tfp, %s\t\t@ Backtrace structure created\n", name);    }  else if (live_regs_mask)    thumb_pushpop (f, live_regs_mask, 1);  for (regno = 8; regno < 13; regno++)    {      if (regs_ever_live[regno] && ! call_used_regs[regno])	high_regs_pushed++;    }  if (high_regs_pushed)    {      int pushable_regs = 0;      int mask = live_regs_mask & 0xff;      int next_hi_reg;      for (next_hi_reg = 12; next_hi_reg > 7; next_hi_reg--)	{	  if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])	    break;	}      pushable_regs = mask;      if (pushable_regs == 0)	{	  /* desperation time -- this probably will never happen */	  if (regs_ever_live[3] || ! call_used_regs[3])	    asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[12], reg_names[3]);	  mask = 1 << 3;	}      while (high_regs_pushed > 0)	{	  for (regno = 7; regno >= 0; regno--)	    {	      if (mask & (1 << regno))		{		  asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[regno],			       reg_names[next_hi_reg]);		  high_regs_pushed--;		  if (high_regs_pushed)		    for (next_hi_reg--; next_hi_reg > 7; next_hi_reg--)		      {			if (regs_ever_live[next_hi_reg]			    && ! call_used_regs[next_hi_reg])			  break;		      }		  else		    {		      mask &= ~ ((1 << regno) - 1);		      break;		    }		}	    }	  thumb_pushpop (f, mask, 1);	}      if (pushable_regs == 0 && (regs_ever_live[3] || ! call_used_regs[3]))	    asm_fprintf (f, "\tmov\t%s, %s\n", reg_names[3], reg_names[12]);    }}voidthumb_expand_prologue (){  HOST_WIDE_INT amount = (get_frame_size ()			  + current_function_outgoing_args_size);  int regno;  int live_regs_mask;  if (amount)    {      live_regs_mask = 0;      for (regno = 0; regno < 8; regno++)	if (regs_ever_live[regno] && ! call_used_regs[regno])	  live_regs_mask |= 1 << regno;      if (amount < 512)	emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,			       GEN_INT (-amount)));      else	{	  rtx reg, spare;	  if ((live_regs_mask & 0xff) == 0) /* Very unlikely */	    emit_insn (gen_movsi (spare = gen_rtx (REG, SImode, 12),				  reg = gen_rtx (REG, SImode, 4)));	  else	    {	      for (regno = 0; regno < 8; regno++)		if (live_regs_mask & (1 << regno))		  break;	      reg = gen_rtx (REG, SImode, regno);	    }	  emit_insn (gen_movsi (reg, GEN_INT (-amount)));	  emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));	  if ((live_regs_mask & 0xff) == 0)	    emit_insn (gen_movsi (reg, spare));	}    }  if (frame_pointer_needed)    {      if (current_function_outgoing_args_size)	{	  rtx offset = GEN_INT (current_function_outgoing_args_size);	  if (current_function_outgoing_args_size < 1024)	    emit_insn (gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,				   offset));	  else	    {	      emit_insn (gen_movsi (frame_pointer_rtx, offset));	      emit_insn (gen_addsi3 (frame_pointer_rtx, frame_pointer_rtx,				     stack_pointer_rtx));	    }	}      else	emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));    }  /* if (profile_flag || profile_block_flag) */  emit_insn (gen_blockage ());}voidthumb_expand_epilogue (){  HOST_WIDE_INT amount = (get_frame_size ()			  + current_function_outgoing_args_size);  int regno;  if (amount)    {      if (amount < 512)	emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,			       GEN_INT (amount)));      else	{	  rtx reg = gen_rtx (REG, SImode, 3); /* Always free in the epilogue */	  emit_insn (gen_movsi (reg, GEN_INT (amount)));	  emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));	}      /* if (profile_flag || profile_block_flag) */      emit_insn (gen_blockage ());    }}voidthumb_function_epilogue (f, frame_size)     FILE *f;     int frame_size;{  /* ??? Probably not safe to set this here, since it assumes that a     function will be emitted as assembly immediately after we generate     RTL for it.  This does not happen for inline functions.  */  return_used_this_function = 0;#if 0 /* TODO : comment not really needed */  fprintf (f, "%s THUMB Epilogue\n", ASM_COMMENT_START);#endif}/* The bits which aren't usefully expanded as rtl. */char *thumb_unexpanded_epilogue (){  int regno;  int live_regs_mask = 0;  int high_regs_pushed = 0;  int leaf_function = leaf_function_p ();  int had_to_push_lr;  if (return_used_this_function)    return "";  for (regno = 0; regno < 8; regno++)    if (regs_ever_live[regno] && ! call_used_regs[regno])      live_regs_mask |= 1 << regno;  for (regno = 8; regno < 13; regno++)    {      if (regs_ever_live[regno] && ! call_used_regs[regno])	high_regs_pushed ++;    }  /* The prolog may have pushed some high registers to use as     work registers.  eg the testuite file:     gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c     compiles to produce:	push	{r4, r5, r6, r7, lr}	mov	r7, r9	mov	r6, r8	push	{r6, r7}     as part of the prolog.  We have to undo that pushing here.  */    if (high_regs_pushed)    {      int mask = live_regs_mask;      int next_hi_reg;      int size;      int mode;       #ifdef RTX_CODE      /* If we can deduce the registers used from the function's return value.	 This is more reliable that examining regs_ever_live[] because that	 will be set if the register is ever used in the function, not just if	 the register is used to hold a return value.  */      if (current_function_return_rtx != 0)	{	  mode = GET_MODE (current_function_return_rtx);	}      else#endif	{	  mode = DECL_MODE (DECL_RESULT (current_function_decl));	}      size = GET_MODE_SIZE (mode);      /* Unless we are returning a type of size > 12 register r3 is available.  */      if (size < 13)	mask |=  1 << 3;      if (mask == 0)	{	  /* Oh dear!  We have no low registers into which we can pop high registers!  */	  fatal ("No low registers available for popping high registers");	}            for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)	if (regs_ever_live[next_hi_reg] && ! call_used_regs[next_hi_reg])	  break;      while (high_regs_pushed)	{	  /* Find low register(s) into which the high register(s) can be popped.  */	  for (regno = 0; regno < 8; regno++)	    {	      if (mask & (1 << regno))		high_regs_pushed--;	      if (high_regs_pushed == 0)		break;	    }	  mask &= (2 << regno) - 1;	/* A noop if regno == 8 */	  /* Pop the values into the low register(s). */	  thumb_pushpop (asm_out_file, mask, 0);	  /* Move the value(s) into the high registers.  */	  for (regno = 0; regno < 8; regno++)	    {	      if (mask & (1 << regno))		{		  asm_fprintf (asm_out_file, "\tmov\t%s, %s\n", 			       reg_names[next_hi_reg], reg_names[regno]);		  for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)		    if (regs_ever_live[next_hi_reg] && 			! call_used_regs[next_hi_reg])		      break;		}	    }	}    }  had_to_push_lr = (live_regs_mask || ! leaf_function || far_jump_used_p());    if (TARGET_BACKTRACE && ((live_regs_mask & 0xFF) == 0) && regs_ever_live[ ARG_4_REGISTER ] != 0)    {      /* The stack backtrace structure creation code had to	 push R7 in order to get a work register, so we pop	 it now.   */            live_regs_mask |= (1 << WORK_REGISTER);    }    if (current_function_pretend_args_size == 0 || TARGET_BACKTRACE)    {      if (had_to_push_lr	  && ! is_called_in_ARM_mode (current_function_decl))	live_regs_mask |= 1 << PROGRAM_COUNTER;      /* Either no argument registers were pushed or a backtrace	 structure was created which includes an adjusted stack	 pointer, so just pop everything.  */            if (live_regs_mask)	thumb_pushpop (asm_out_file, live_regs_mask, FALSE);            /* We have either just popped the return address into the	 PC or it is was kept in LR for the entire function or	 it is still on the stack because we do not want to	 return by doing a pop {pc}.  */            if ((live_regs_mask & (1 << PROGRAM_COUNTER)) == 0)	thumb_exit (asm_out_file,		    (had_to_push_lr		     && is_called_in_ARM_mode (current_function_decl)) ?		    -1 : LINK_REGISTER);    }  else    {      /* Pop everything but the return address.  */      live_regs_mask &= ~ (1 << PROGRAM_COUNTER);            if (live_regs_mask)	thumb_pushpop (asm_out_file, live_regs_mask, FALSE);      if (had_to_push_lr)	{	  /* Get the return address into a temporary register.  */	  thumb_pushpop (asm_out_file, 1 << ARG_4_REGISTER, 0);	}            /* Remove the argument registers that were pushed onto the stack.  */      asm_fprintf (asm_out_file, "\tadd\t%s, %s, #%d\n",		   reg_names [STACK_POINTER],		   reg_names [STACK_POINTER],		   current_function_pretend_args_size);            thumb_exit (asm_out_file, had_to_push_lr ? ARG_4_REGISTER : LINK_REGISTER);    }  return "";}/* Handle the case of a double word load into a low register from

⌨️ 快捷键说明

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