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

📄 crx.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 3 页
字号:
	    }	case REG:	  if (REGNO (x) + 1 >= FIRST_PSEUDO_REGISTER) abort ();	  fprintf (file, "%s", reg_names[REGNO (x) + 1]);	  return;	case MEM:	  /* Adjust memory address to high part.  */	    {	      rtx adj_mem = x;	      adj_mem = adjust_address (adj_mem, GET_MODE (adj_mem), 4);	      output_memory_reference_mode = GET_MODE (adj_mem);	      output_address (XEXP (adj_mem, 0));	      return;	    }	default:	  abort ();	}    case 'L':      /* Print low part of a double precision value. */      switch (GET_CODE (x))	{	case CONST_DOUBLE:	  if (GET_MODE (x) == SFmode) abort ();	  if (GET_MODE (x) == DFmode)	    {	      /* High part of a DF const. */	      REAL_VALUE_TYPE r;	      long l[2];	      REAL_VALUE_FROM_CONST_DOUBLE (r, x);	      REAL_VALUE_TO_TARGET_DOUBLE (r, l);	      fprintf (file, "$0x%lx", l[0]);	      return;	    }	  /* -- Fallthrough to handle DI consts -- */	case CONST_INT:	    {	      rtx high, low;	      split_double (x, &low, &high);	      putc ('$', file);	      output_addr_const (file, low);	      return;	    }	case REG:	  fprintf (file, "%s", reg_names[REGNO (x)]);	  return;	case MEM:	  output_memory_reference_mode = GET_MODE (x);	  output_address (XEXP (x, 0));	  return;	default:	  abort ();	}    case 0 : /* default */      switch (GET_CODE (x))	{	case REG:	  fprintf (file, "%s", reg_names[REGNO (x)]);	  return;	case MEM:	  output_memory_reference_mode = GET_MODE (x);	  output_address (XEXP (x, 0));	  return;	case CONST_DOUBLE:	    {	      REAL_VALUE_TYPE r;	      long l;	      /* Always use H and L for double precision - see above */	      gcc_assert (GET_MODE (x) == SFmode);	      REAL_VALUE_FROM_CONST_DOUBLE (r, x);	      REAL_VALUE_TO_TARGET_SINGLE (r, l);	      fprintf (file, "$0x%lx", l);	      return;	    }	default:	  putc ('$', file);	  output_addr_const (file, x);	  return;	}    default:      output_operand_lossage ("invalid %%xn code");    }  abort ();}/* Implements the macro PRINT_OPERAND_ADDRESS defined in crx.h.  */voidcrx_print_operand_address (FILE * file, rtx addr){  enum crx_addrtype addrtype;  struct crx_address address;  int offset;    addrtype = crx_decompose_address (addr, &address);    if (address.disp)    offset = INTVAL (address.disp);  else    offset = 0;  switch (addrtype)    {    case CRX_REG_REL:      fprintf (file, "%d(%s)", offset, reg_names[REGNO (address.base)]);      return;          case CRX_POST_INC:      switch (GET_CODE (address.side_effect))	{	case PLUS:	  break;	case MINUS:	  offset = -offset;	  break;	case POST_INC:	  offset = GET_MODE_SIZE (output_memory_reference_mode);	  break;	case POST_DEC:	  offset = -GET_MODE_SIZE (output_memory_reference_mode);	  break;	default:	  abort ();	}	fprintf (file, "%d(%s)+", offset, reg_names[REGNO (address.base)]);      return;          case CRX_SCALED_INDX:      fprintf (file, "%d(%s, %s, %d)", offset, reg_names[REGNO (address.base)],	       reg_names[REGNO (address.index)], address.scale);      return;          case CRX_ABSOLUTE:      output_addr_const (file, address.disp);      return;          default:      abort ();    }}/*****************************************************************************//* MACHINE DESCRIPTION HELPER-FUNCTIONS					     *//*****************************************************************************/void crx_expand_movmem_single (rtx src, rtx srcbase, rtx dst, rtx dstbase,			       rtx tmp_reg, unsigned HOST_WIDE_INT *offset_p){  rtx addr, mem;  unsigned HOST_WIDE_INT offset = *offset_p;  /* Load */  addr = plus_constant (src, offset);  mem = adjust_automodify_address (srcbase, SImode, addr, offset);  emit_move_insn (tmp_reg, mem);  /* Store */  addr = plus_constant (dst, offset);  mem = adjust_automodify_address (dstbase, SImode, addr, offset);  emit_move_insn (mem, tmp_reg);  *offset_p = offset + 4;}intcrx_expand_movmem (rtx dstbase, rtx srcbase, rtx count_exp, rtx align_exp){  unsigned HOST_WIDE_INT count = 0, offset, si_moves, i;  HOST_WIDE_INT align = 0;  rtx src, dst;  rtx tmp_reg;  if (GET_CODE (align_exp) == CONST_INT)    { /* Only if aligned */      align = INTVAL (align_exp);      if (align & 3)	return 0;    }  if (GET_CODE (count_exp) == CONST_INT)    { /* No more than 16 SImode moves */      count = INTVAL (count_exp);      if (count > 64)	return 0;    }  tmp_reg = gen_reg_rtx (SImode);  /* Create psrs for the src and dest pointers */  dst = copy_to_mode_reg (Pmode, XEXP (dstbase, 0));  if (dst != XEXP (dstbase, 0))    dstbase = replace_equiv_address_nv (dstbase, dst);  src = copy_to_mode_reg (Pmode, XEXP (srcbase, 0));  if (src != XEXP (srcbase, 0))    srcbase = replace_equiv_address_nv (srcbase, src);  offset = 0;  /* Emit SImode moves */  si_moves = count >> 2;  for (i = 0; i < si_moves; i++)    crx_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset);  /* Special cases */  if (count & 3)    {      offset = count - 4;      crx_expand_movmem_single (src, srcbase, dst, dstbase, tmp_reg, &offset);    }  gcc_assert (offset == count);  return 1;}rtxcrx_expand_compare (enum rtx_code code, enum machine_mode mode){  rtx op0, op1, cc_reg, ret;  op0 = crx_compare_op0;  op1 = crx_compare_op1;  /* Emit the compare that writes into CC_REGNUM) */  cc_reg = gen_rtx_REG (CCmode, CC_REGNUM);  ret = gen_rtx_COMPARE (CCmode, op0, op1);  emit_insn (gen_rtx_SET (VOIDmode, cc_reg, ret));  /* debug_rtx (get_last_insn ()); */  /* Return the rtx for using the result in CC_REGNUM */  return gen_rtx_fmt_ee (code, mode, cc_reg, const0_rtx);}voidcrx_expand_branch (enum rtx_code code, rtx label){  rtx tmp = crx_expand_compare (code, VOIDmode);  tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,			      gen_rtx_LABEL_REF (VOIDmode, label),			      pc_rtx);  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, tmp));  /* debug_rtx (get_last_insn ()); */}voidcrx_expand_scond (enum rtx_code code, rtx dest){  rtx tmp = crx_expand_compare (code, GET_MODE (dest));  emit_move_insn (dest, tmp);  /* debug_rtx (get_last_insn ()); */}static voidmpushpop_str (char *stringbuffer, const char *mnemonic, char *mask){  if (strlen (mask) > 2 || crx_interrupt_function_p ()) /* needs 2-word instr. */    sprintf (stringbuffer, "\n\t%s\tsp, {%s}", mnemonic, mask);  else /* single word instruction */    sprintf (stringbuffer, "\n\t%s\t%s", mnemonic, mask);}/* Called from crx.md. The return value depends on the parameter push_or_pop: * When push_or_pop is zero -> string for push instructions of prologue. * When push_or_pop is nonzero -> string for pop/popret/retx in epilogue. * Relies on the assumptions: * 1. RA is the last register to be saved. * 2. The maximal value of the counter is MAX_COUNT. */char *crx_prepare_push_pop_string (int push_or_pop){  /* j is the number of registers being saved, takes care that there won't be   * more than 8 in one push/pop instruction */  /* For the register mask string */  static char mask_str[50];  /* i is the index of save_regs[], going from 0 until last_reg_to_save */  int i = 0;  int ra_in_bitmask = 0;  char *return_str;  /* For reversing on the push instructions if there are more than one. */  char *temp_str;  return_str = (char *) xmalloc (120);  temp_str = (char *) xmalloc (120);  /* Initialize */  memset (return_str, 0, 3);  while (i <= last_reg_to_save)    {      /* Prepare mask for one instruction. */      mask_str[0] = 0;      if (i <= SP_REGNUM)	{ /* Add regs unit full or SP register reached */	  int j = 0;	  while (j < MAX_COUNT && i <= SP_REGNUM)	    {	      if (save_regs[i])		{		  /* TODO to use ra_in_bitmask for detecting last pop is not		   * smart it prevents things like:  popret r5 */		  if (i == RETURN_ADDRESS_REGNUM) ra_in_bitmask = 1;		  if (j > 0) strcat (mask_str, ", ");		  strcat (mask_str, reg_names[i]);		  ++j;		}	      ++i;	    }	}      else	{	  /* Handle hi/lo savings */	  while (i <= last_reg_to_save)	    {	      if (save_regs[i])		{		  strcat (mask_str, "lo, hi");		  i = last_reg_to_save + 1;		  break;		}	      ++i;	    }	}      if (strlen (mask_str) == 0) continue;       	      if (push_or_pop == 1)	{	  if (crx_interrupt_function_p ())	    mpushpop_str (temp_str, "popx", mask_str);	  else	    {	      if (ra_in_bitmask)		{		  mpushpop_str (temp_str, "popret", mask_str);		  ra_in_bitmask = 0;		}	      else mpushpop_str (temp_str, "pop", mask_str);	    }	  strcat (return_str, temp_str);	}      else	{	  /* push - We need to reverse the order of the instructions if there	   * are more than one. (since the pop will not be reversed in the	   * epilogue */      	  if (crx_interrupt_function_p ())	    mpushpop_str (temp_str, "pushx", mask_str);	  else	    mpushpop_str (temp_str, "push", mask_str);	  strcat (temp_str, return_str);	  strcpy (strcat (return_str, "\t"), temp_str);	}    }  if (push_or_pop == 1)    {      /* pop */      if (crx_interrupt_function_p ())	strcat (return_str, "\n\tretx\n");      else if (!FUNC_IS_NORETURN_P (current_function_decl)	       && !save_regs[RETURN_ADDRESS_REGNUM])	strcat (return_str, "\n\tjump\tra\n");    }  /* Skip the newline and the tab in the start of return_str. */  return_str += 2;  return return_str;}/*  CompactRISC CRX Architecture stack layout:     0 +---------------------	|	.	.	|	+==================== Sp(x)=Ap(x+1)      A | Args for functions      | | called by X and      Dynamically      | | Dynamic allocations  allocated and      | | (alloca, variable    deallocated  Stack | length arrays).  grows +-------------------- Fp(x)  down| | Local variables of X  ward| +--------------------      | | Regs saved for X-1      | +==================== Sp(x-1)=Ap(x)	| Args for func X	| pushed by X-1	+-------------------- Fp(x-1)	|	|	V*/voidcrx_expand_prologue (void){  crx_compute_frame ();  crx_compute_save_regs ();  /* If there is no need in push and adjustment to sp, return. */  if (size_for_adjusting_sp + sum_regs == 0)    return;  if (last_reg_to_save != -1)    /* If there are registers to push.  */    emit_insn (gen_push_for_prologue (GEN_INT (sum_regs)));  if (size_for_adjusting_sp > 0)    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,			   GEN_INT (-size_for_adjusting_sp)));  if (frame_pointer_needed)    /* Initialize the frame pointer with the value of the stack pointer     * pointing now to the locals. */    emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);}/* Generate insn that updates the stack for local variables and padding for * registers we save. - Generate the appropriate return insn. */voidcrx_expand_epilogue (void){  rtx return_reg;  /* Nonzero if we need to return and pop only RA. This will generate a   * different insn. This differentiate is for the peepholes for call as last   * statement in function. */  int only_popret_RA = (save_regs[RETURN_ADDRESS_REGNUM]			&& (sum_regs == UNITS_PER_WORD));  /* Return register.  */  return_reg = gen_rtx_REG (Pmode, RETURN_ADDRESS_REGNUM);  if (frame_pointer_needed)    /* Restore the stack pointer with the frame pointers value */    emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);  if (size_for_adjusting_sp > 0)    emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,			   GEN_INT (size_for_adjusting_sp)));  if (crx_interrupt_function_p ())    emit_jump_insn (gen_interrupt_return ());  else if (last_reg_to_save == -1)    /* Nothing to pop */    /* Don't output jump for interrupt routine, only retx.  */    emit_jump_insn (gen_indirect_jump_return ());  else if (only_popret_RA)    emit_jump_insn (gen_popret_RA_return ());  else    emit_jump_insn (gen_pop_and_popret_return (GEN_INT (sum_regs)));}

⌨️ 快捷键说明

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