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

📄 mcore.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
  sreg = copy_to_mode_reg (SImode, operands[3]);  /* Extract src as same width as dst (needed for signed values).  We     always have to do this since we widen everything to SImode.     We don't have to mask if we're shifting this up against the     MSB of the register (e.g., the shift will push out any hi-order     bits.  */  if (width + posn != (int) GET_MODE_SIZE (SImode))    {      ereg = force_reg (SImode, GEN_INT ((1 << width) - 1));            emit_insn (gen_rtx_SET (SImode, sreg,                          gen_rtx_AND (SImode, sreg, ereg)));    }  /* Insert source value in dest.  */  if (posn != 0)    emit_insn (gen_rtx_SET (SImode, sreg,		        gen_rtx_ASHIFT (SImode, sreg, GEN_INT (posn))));    emit_insn (gen_rtx_SET (SImode, operands[0],		      gen_rtx_IOR (SImode, operands[0], sreg)));  return 1;}/* ??? Block move stuff stolen from m88k.  This code has not been   verified for correctness.  *//* Emit code to perform a block move.  Choose the best method.   OPERANDS[0] is the destination.   OPERANDS[1] is the source.   OPERANDS[2] is the size.   OPERANDS[3] is the alignment safe to use.  *//* Emit code to perform a block move with an offset sequence of ldw/st   instructions (..., ldw 0, stw 1, ldw 1, stw 0, ...).  SIZE and ALIGN are   known constants.  DEST and SRC are registers.  OFFSET is the known   starting point for the output pattern.  */static const enum machine_mode mode_from_align[] ={  VOIDmode, QImode, HImode, VOIDmode, SImode,};static voidblock_move_sequence (rtx dst_mem, rtx src_mem, int size, int align){  rtx temp[2];  enum machine_mode mode[2];  int amount[2];  bool active[2];  int phase = 0;  int next;  int offset_ld = 0;  int offset_st = 0;  rtx x;  x = XEXP (dst_mem, 0);  if (!REG_P (x))    {      x = force_reg (Pmode, x);      dst_mem = replace_equiv_address (dst_mem, x);    }  x = XEXP (src_mem, 0);  if (!REG_P (x))    {      x = force_reg (Pmode, x);      src_mem = replace_equiv_address (src_mem, x);    }  active[0] = active[1] = false;  do    {      next = phase;      phase ^= 1;      if (size > 0)	{	  int next_amount;	  next_amount = (size >= 4 ? 4 : (size >= 2 ? 2 : 1));	  next_amount = MIN (next_amount, align);	  amount[next] = next_amount;	  mode[next] = mode_from_align[next_amount];	  temp[next] = gen_reg_rtx (mode[next]);	  x = adjust_address (src_mem, mode[next], offset_ld);	  emit_insn (gen_rtx_SET (VOIDmode, temp[next], x));	  offset_ld += next_amount;	  size -= next_amount;	  active[next] = true;	}      if (active[phase])	{	  active[phase] = false;	  	  x = adjust_address (dst_mem, mode[phase], offset_st);	  emit_insn (gen_rtx_SET (VOIDmode, x, temp[phase]));	  offset_st += amount[phase];	}    }  while (active[next]);}boolmcore_expand_block_move (rtx *operands){  HOST_WIDE_INT align, bytes, max;  if (GET_CODE (operands[2]) != CONST_INT)    return false;  bytes = INTVAL (operands[2]);  align = INTVAL (operands[3]);  if (bytes <= 0)    return false;  if (align > 4)    align = 4;  switch (align)    {    case 4:      if (bytes & 1)	max = 4*4;      else if (bytes & 3)	max = 8*4;      else	max = 16*4;      break;    case 2:      max = 4*2;      break;    case 1:      max = 4*1;      break;    default:      gcc_unreachable ();    }  if (bytes <= max)    {      block_move_sequence (operands[0], operands[1], bytes, align);      return true;    }  return false;}/* Code to generate prologue and epilogue sequences.  */static int number_of_regs_before_varargs;/* Set by TARGET_SETUP_INCOMING_VARARGS to indicate to prolog that this is   for a varargs function.  */static int current_function_anonymous_args;#define	STACK_BYTES (STACK_BOUNDARY/BITS_PER_UNIT)#define	STORE_REACH (64)	/* Maximum displace of word store + 4.  */#define	ADDI_REACH (32)		/* Maximum addi operand.  */static voidlayout_mcore_frame (struct mcore_frame * infp){  int n;  unsigned int i;  int nbytes;  int regarg;  int localregarg;  int localreg;  int outbounds;  unsigned int growths;  int step;  /* Might have to spill bytes to re-assemble a big argument that     was passed partially in registers and partially on the stack.  */  nbytes = current_function_pretend_args_size;    /* Determine how much space for spilled anonymous args (e.g., stdarg).  */  if (current_function_anonymous_args)    nbytes += (NPARM_REGS - number_of_regs_before_varargs) * UNITS_PER_WORD;    infp->arg_size = nbytes;  /* How much space to save non-volatile registers we stomp.  */  infp->reg_mask = calc_live_regs (& n);  infp->reg_size = n * 4;  /* And the rest of it... locals and space for overflowed outbounds.  */  infp->local_size = get_frame_size ();  infp->outbound_size = current_function_outgoing_args_size;  /* Make sure we have a whole number of words for the locals.  */  if (infp->local_size % STACK_BYTES)    infp->local_size = (infp->local_size + STACK_BYTES - 1) & ~ (STACK_BYTES -1);    /* Only thing we know we have to pad is the outbound space, since     we've aligned our locals assuming that base of locals is aligned.  */  infp->pad_local = 0;  infp->pad_reg = 0;  infp->pad_outbound = 0;  if (infp->outbound_size % STACK_BYTES)    infp->pad_outbound = STACK_BYTES - (infp->outbound_size % STACK_BYTES);  /* Now we see how we want to stage the prologue so that it does     the most appropriate stack growth and register saves to either:     (1) run fast,     (2) reduce instruction space, or     (3) reduce stack space.  */  for (i = 0; i < ARRAY_SIZE (infp->growth); i++)    infp->growth[i] = 0;  regarg      = infp->reg_size + infp->arg_size;  localregarg = infp->local_size + regarg;  localreg    = infp->local_size + infp->reg_size;  outbounds   = infp->outbound_size + infp->pad_outbound;  growths     = 0;  /* XXX: Consider one where we consider localregarg + outbound too! */  /* Frame of <= 32 bytes and using stm would get <= 2 registers.     use stw's with offsets and buy the frame in one shot.  */  if (localregarg <= ADDI_REACH      && (infp->reg_size <= 8 || (infp->reg_mask & 0xc000) != 0xc000))    {      /* Make sure we'll be aligned.  */      if (localregarg % STACK_BYTES)	infp->pad_reg = STACK_BYTES - (localregarg % STACK_BYTES);      step = localregarg + infp->pad_reg;      infp->reg_offset = infp->local_size;            if (outbounds + step <= ADDI_REACH && !frame_pointer_needed)	{	  step += outbounds;	  infp->reg_offset += outbounds;	  outbounds = 0;	}            infp->arg_offset = step - 4;      infp->growth[growths++] = step;      infp->reg_growth = growths;      infp->local_growth = growths;            /* If we haven't already folded it in.  */      if (outbounds)	infp->growth[growths++] = outbounds;            goto finish;    }  /* Frame can't be done with a single subi, but can be done with 2     insns.  If the 'stm' is getting <= 2 registers, we use stw's and     shift some of the stack purchase into the first subi, so both are     single instructions.  */  if (localregarg <= STORE_REACH      && (infp->local_size > ADDI_REACH)      && (infp->reg_size <= 8 || (infp->reg_mask & 0xc000) != 0xc000))    {      int all;      /* Make sure we'll be aligned; use either pad_reg or pad_local.  */      if (localregarg % STACK_BYTES)	infp->pad_reg = STACK_BYTES - (localregarg % STACK_BYTES);      all = localregarg + infp->pad_reg + infp->pad_local;      step = ADDI_REACH;	/* As much up front as we can.  */      if (step > all)	step = all;            /* XXX: Consider whether step will still be aligned; we believe so.  */      infp->arg_offset = step - 4;      infp->growth[growths++] = step;      infp->reg_growth = growths;      infp->reg_offset = step - infp->pad_reg - infp->reg_size;      all -= step;      /* Can we fold in any space required for outbounds?  */      if (outbounds + all <= ADDI_REACH && !frame_pointer_needed)	{	  all += outbounds;	  outbounds = 0;	}      /* Get the rest of the locals in place.  */      step = all;      infp->growth[growths++] = step;      infp->local_growth = growths;      all -= step;      assert (all == 0);      /* Finish off if we need to do so.  */      if (outbounds)	infp->growth[growths++] = outbounds;            goto finish;    }  /* Registers + args is nicely aligned, so we'll buy that in one shot.     Then we buy the rest of the frame in 1 or 2 steps depending on     whether we need a frame pointer.  */  if ((regarg % STACK_BYTES) == 0)    {      infp->growth[growths++] = regarg;      infp->reg_growth = growths;      infp->arg_offset = regarg - 4;      infp->reg_offset = 0;      if (infp->local_size % STACK_BYTES)	infp->pad_local = STACK_BYTES - (infp->local_size % STACK_BYTES);            step = infp->local_size + infp->pad_local;            if (!frame_pointer_needed)	{	  step += outbounds;	  outbounds = 0;	}            infp->growth[growths++] = step;      infp->local_growth = growths;      /* If there's any left to be done.  */      if (outbounds)	infp->growth[growths++] = outbounds;            goto finish;    }  /* XXX: optimizations that we'll want to play with....     -- regarg is not aligned, but it's a small number of registers;    	use some of localsize so that regarg is aligned and then     	save the registers.  */  /* Simple encoding; plods down the stack buying the pieces as it goes.     -- does not optimize space consumption.     -- does not attempt to optimize instruction counts.     -- but it is safe for all alignments.  */  if (regarg % STACK_BYTES != 0)    infp->pad_reg = STACK_BYTES - (regarg % STACK_BYTES);    infp->growth[growths++] = infp->arg_size + infp->reg_size + infp->pad_reg;  infp->reg_growth = growths;  infp->arg_offset = infp->growth[0] - 4;  infp->reg_offset = 0;    if (frame_pointer_needed)    {      if (infp->local_size % STACK_BYTES != 0)	infp->pad_local = STACK_BYTES - (infp->local_size % STACK_BYTES);            infp->growth[growths++] = infp->local_size + infp->pad_local;      infp->local_growth = growths;            infp->growth[growths++] = outbounds;    }  else    {      if ((infp->local_size + outbounds) % STACK_BYTES != 0)	infp->pad_local = STACK_BYTES - ((infp->local_size + outbounds) % STACK_BYTES);            infp->growth[growths++] = infp->local_size + infp->pad_local + outbounds;      infp->local_growth = growths;    }  /* Anything else that we've forgotten?, plus a few consistency checks.  */ finish:  assert (infp->reg_offset >= 0);  assert (growths <= MAX_STACK_GROWS);    for (i = 0; i < growths; i++)    gcc_assert (!(infp->growth[i] % STACK_BYTES));}/* Define the offset between two registers, one to be eliminated, and   the other its replacement, at the start of a routine.  */intmcore_initial_elimination_offset (int from, int to){  int above_frame;  int below_frame;  struct mcore_frame fi;  layout_mcore_frame (& fi);  /* fp to ap */  above_frame = fi.local_size + fi.pad_local + fi.reg_size + fi.pad_reg;  /* sp to fp */  below_frame = fi.outbound_size + fi.pad_outbound;  if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)    return above_frame;  if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)    return above_frame + below_frame;  if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)    return below_frame;  gcc_unreachable ();}/* Keep track of some information about varargs for the prolog.  */static voidmcore_setup_incoming_varargs (CUMULATIVE_ARGS *args_so_far,			      enum machine_mode mode, tree type,			      int * ptr_pretend_size ATTRIBUTE_UNUSED,			      int second_time ATTRIBUTE_UNUSED){  current_function_anonymous_args = 1;  /* We need to know how many argument registers are used before     the varargs start, so that we can push the remaining argument     registers during the prologue.  */  number_of_regs_before_varargs = *args_so_far + mcore_num_arg_regs (mode, type);    /* There is a bug somewhere in the arg handling code.     Until I can find it this workaround always pushes the     last named argument onto the stack.  */  number_of_regs_before_varargs = *args_so_far;    /* The last named argument may be split between argument registers     and the stack.  Allow for this here.  */  if (number_of_regs_before_varargs > NPARM_REGS)    number_of_regs_before_varargs = NPARM_REGS;}voidmcore_expand_prolog (void){  struct mcore_frame fi;  int space_allocated = 0;  int growth = 0;  /* Find out what we're doing.  */  layout_mcore_frame (&fi);    space_allocated = fi.arg_size + fi.reg_size + fi.local_size +    fi.outbound_size + fi.pad_outbound + fi.pad_local + fi.pad_reg;  if (TARGET_CG_DATA)    {      /* Emit a symbol for this routine's frame size.  */      rtx x;      x = DECL_RTL (current_function_decl);            gcc_assert (GET_CODE (x) == MEM);            x = XEXP (x, 0);            gcc_assert (GET_CODE (x) == SYMBOL_REF);            if (mcore_current_function_name)	free (mcore_current_function_name);            mcore_current_function_name = xstrdup (XSTR (x, 0));            ASM_OUTPUT_CG_NODE (asm_out_file, mcore_current_function_name, space_allocated);      if (current_function_calls_alloca)	ASM_OUTPUT_CG_EDGE (asm_out_file, mcore_current_function_name, "alloca", 1);      /* 970425: RBE:         We're looking at how the 8byte alignment affects stack layout         and where we had to pad things. This emits information we can         extract which tells us about frame sizes and the like.  */      fprintf (asm_out_file,	       "\t.equ\t__$frame$info$_%s_$_%d_%d_x%x_%d_%d_%d,0\n",	       mcore_current_function_name,	       fi.arg_size, fi.reg_size, fi.reg_mask,	       fi.local_size, fi.outbound_size,	       frame_pointer_needed);    }  if (mcore_naked_function_p ())    return;    /* Handle stdarg+regsaves in one shot: can't be more than 64 bytes.  */  output_stack_adjust (-1, fi.growth[growth++]);	/* Grows it.  */

⌨️ 快捷键说明

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