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

📄 xtensa.c

📁 linux下编程用 编译软件
💻 C
📖 第 1 页 / 共 5 页
字号:
    {      if (cfun->machine->set_frame_ptr_insn)	{	  rtx first, insn;	  push_topmost_sequence ();	  first = get_insns ();	  pop_topmost_sequence ();	  /* For all instructions prior to set_frame_ptr_insn, replace	     hard_frame_pointer references with stack_pointer.  */	  for (insn = first;	       insn != cfun->machine->set_frame_ptr_insn;	       insn = NEXT_INSN (insn))	    {	      if (INSN_P (insn))		PATTERN (insn) = replace_rtx (copy_rtx (PATTERN (insn)),					      hard_frame_pointer_rtx,					      stack_pointer_rtx);	    }	}      else	emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);    }}/* Clear variables at function end.  */voidxtensa_function_epilogue (FILE *file ATTRIBUTE_UNUSED,			  HOST_WIDE_INT size ATTRIBUTE_UNUSED){  xtensa_current_frame_size = 0;}rtxxtensa_return_addr (int count, rtx frame){  rtx result, retaddr;  if (count == -1)    retaddr = gen_rtx_REG (Pmode, A0_REG);  else    {      rtx addr = plus_constant (frame, -4 * UNITS_PER_WORD);      addr = memory_address (Pmode, addr);      retaddr = gen_reg_rtx (Pmode);      emit_move_insn (retaddr, gen_rtx_MEM (Pmode, addr));    }  /* The 2 most-significant bits of the return address on Xtensa hold     the register window size.  To get the real return address, these     bits must be replaced with the high bits from the current PC.  */  result = gen_reg_rtx (Pmode);  emit_insn (gen_fix_return_addr (result, retaddr));  return result;}/* Create the va_list data type.   This structure is set up by __builtin_saveregs.  The __va_reg field   points to a stack-allocated region holding the contents of the   incoming argument registers.  The __va_ndx field is an index   initialized to the position of the first unnamed (variable)   argument.  This same index is also used to address the arguments   passed in memory.  Thus, the __va_stk field is initialized to point   to the position of the first argument in memory offset to account   for the arguments passed in registers and to account for the size   of the argument registers not being 16-byte aligned.  E.G., there   are 6 argument registers of 4 bytes each, but we want the __va_ndx   for the first stack argument to have the maximal alignment of 16   bytes, so we offset the __va_stk address by 32 bytes so that   __va_stk[32] references the first argument on the stack.  */static treextensa_build_builtin_va_list (void){  tree f_stk, f_reg, f_ndx, record, type_decl;  record = (*lang_hooks.types.make_type) (RECORD_TYPE);  type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);  f_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),		      ptr_type_node);  f_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),		      ptr_type_node);  f_ndx = build_decl (FIELD_DECL, get_identifier ("__va_ndx"),		      integer_type_node);  DECL_FIELD_CONTEXT (f_stk) = record;  DECL_FIELD_CONTEXT (f_reg) = record;  DECL_FIELD_CONTEXT (f_ndx) = record;  TREE_CHAIN (record) = type_decl;  TYPE_NAME (record) = type_decl;  TYPE_FIELDS (record) = f_stk;  TREE_CHAIN (f_stk) = f_reg;  TREE_CHAIN (f_reg) = f_ndx;  layout_type (record);  return record;}/* Save the incoming argument registers on the stack.  Returns the   address of the saved registers.  */static rtxxtensa_builtin_saveregs (void){  rtx gp_regs, dest;  int arg_words = current_function_args_info.arg_words;  int gp_left = MAX_ARGS_IN_REGISTERS - arg_words;  if (gp_left <= 0)    return const0_rtx;  /* Allocate the general-purpose register space.  */  gp_regs = assign_stack_local    (BLKmode, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, -1);  set_mem_alias_set (gp_regs, get_varargs_alias_set ());  /* Now store the incoming registers.  */  dest = change_address (gp_regs, SImode,			 plus_constant (XEXP (gp_regs, 0),					arg_words * UNITS_PER_WORD));  cfun->machine->need_a7_copy = true;  cfun->machine->vararg_a7 = true;  move_block_from_reg (GP_ARG_FIRST + arg_words, dest, gp_left);  return XEXP (gp_regs, 0);}/* Implement `va_start' for varargs and stdarg.  We look at the   current function to fill in an initial va_list.  */voidxtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED){  tree f_stk, stk;  tree f_reg, reg;  tree f_ndx, ndx;  tree t, u;  int arg_words;  arg_words = current_function_args_info.arg_words;  f_stk = TYPE_FIELDS (va_list_type_node);  f_reg = TREE_CHAIN (f_stk);  f_ndx = TREE_CHAIN (f_reg);  stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);  reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE);  ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE);  /* Call __builtin_saveregs; save the result in __va_reg */  u = make_tree (ptr_type_node, expand_builtin_saveregs ());  t = build (MODIFY_EXPR, ptr_type_node, reg, u);  TREE_SIDE_EFFECTS (t) = 1;  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);  /* Set the __va_stk member to ($arg_ptr - 32).  */  u = make_tree (ptr_type_node, virtual_incoming_args_rtx);  u = fold (build (PLUS_EXPR, ptr_type_node, u,		   build_int_cst (NULL_TREE, -32)));  t = build (MODIFY_EXPR, ptr_type_node, stk, u);  TREE_SIDE_EFFECTS (t) = 1;  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);  /* Set the __va_ndx member.  If the first variable argument is on     the stack, adjust __va_ndx by 2 words to account for the extra     alignment offset for __va_stk.  */  if (arg_words >= MAX_ARGS_IN_REGISTERS)    arg_words += 2;  u = build_int_cst (NULL_TREE, arg_words * UNITS_PER_WORD);  t = build (MODIFY_EXPR, integer_type_node, ndx, u);  TREE_SIDE_EFFECTS (t) = 1;  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);}/* Implement `va_arg'.  */static treextensa_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,			     tree *post_p ATTRIBUTE_UNUSED){  tree f_stk, stk;  tree f_reg, reg;  tree f_ndx, ndx;  tree type_size, array, orig_ndx, addr, size, va_size, t;  tree lab_false, lab_over, lab_false2;  bool indirect;  indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);  if (indirect)    type = build_pointer_type (type);  /* Handle complex values as separate real and imaginary parts.  */  if (TREE_CODE (type) == COMPLEX_TYPE)    {      tree real_part, imag_part;      real_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),					       pre_p, NULL);      real_part = get_initialized_tmp_var (real_part, pre_p, NULL);      imag_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),					       pre_p, NULL);      imag_part = get_initialized_tmp_var (imag_part, pre_p, NULL);      return build (COMPLEX_EXPR, type, real_part, imag_part);    }  f_stk = TYPE_FIELDS (va_list_type_node);  f_reg = TREE_CHAIN (f_stk);  f_ndx = TREE_CHAIN (f_reg);  stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);  reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE);  ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE);  type_size = size_in_bytes (type);  va_size = round_up (type_size, UNITS_PER_WORD);  gimplify_expr (&va_size, pre_p, NULL, is_gimple_val, fb_rvalue);  /* First align __va_ndx if necessary for this arg:     orig_ndx = (AP).__va_ndx;     if (__alignof__ (TYPE) > 4 )       orig_ndx = ((orig_ndx + __alignof__ (TYPE) - 1)			& -__alignof__ (TYPE)); */  orig_ndx = get_initialized_tmp_var (ndx, pre_p, NULL);  if (TYPE_ALIGN (type) > BITS_PER_WORD)    {      int align = TYPE_ALIGN (type) / BITS_PER_UNIT;      t = build (PLUS_EXPR, integer_type_node, orig_ndx,		 build_int_cst (NULL_TREE, align - 1));      t = build (BIT_AND_EXPR, integer_type_node, t,		 build_int_cst (NULL_TREE, -align));      t = build (MODIFY_EXPR, integer_type_node, orig_ndx, t);      gimplify_and_add (t, pre_p);    }  /* Increment __va_ndx to point past the argument:     (AP).__va_ndx = orig_ndx + __va_size (TYPE); */  t = fold_convert (integer_type_node, va_size);  t = build (PLUS_EXPR, integer_type_node, orig_ndx, t);  t = build (MODIFY_EXPR, integer_type_node, ndx, t);  gimplify_and_add (t, pre_p);  /* Check if the argument is in registers:     if ((AP).__va_ndx <= __MAX_ARGS_IN_REGISTERS * 4         && !must_pass_in_stack (type))        __array = (AP).__va_reg; */  array = create_tmp_var (ptr_type_node, NULL);  lab_over = NULL;  if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))    {      lab_false = create_artificial_label ();      lab_over = create_artificial_label ();      t = build_int_cst (NULL_TREE, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD);      t = build (GT_EXPR, boolean_type_node, ndx, t);      t = build (COND_EXPR, void_type_node, t,		 build (GOTO_EXPR, void_type_node, lab_false),		 NULL);      gimplify_and_add (t, pre_p);      t = build (MODIFY_EXPR, void_type_node, array, reg);      gimplify_and_add (t, pre_p);      t = build (GOTO_EXPR, void_type_node, lab_over);      gimplify_and_add (t, pre_p);      t = build (LABEL_EXPR, void_type_node, lab_false);      gimplify_and_add (t, pre_p);    }  /* ...otherwise, the argument is on the stack (never split between     registers and the stack -- change __va_ndx if necessary):     else       {	 if (orig_ndx <= __MAX_ARGS_IN_REGISTERS * 4)	     (AP).__va_ndx = 32 + __va_size (TYPE);	 __array = (AP).__va_stk;       } */  lab_false2 = create_artificial_label ();  t = build_int_cst (NULL_TREE, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD);  t = build (GT_EXPR, boolean_type_node, orig_ndx, t);  t = build (COND_EXPR, void_type_node, t,	     build (GOTO_EXPR, void_type_node, lab_false2),	     NULL);  gimplify_and_add (t, pre_p);  t = size_binop (PLUS_EXPR, va_size, size_int (32));  t = fold_convert (integer_type_node, t);  t = build (MODIFY_EXPR, integer_type_node, ndx, t);  gimplify_and_add (t, pre_p);  t = build (LABEL_EXPR, void_type_node, lab_false2);  gimplify_and_add (t, pre_p);  t = build (MODIFY_EXPR, void_type_node, array, stk);  gimplify_and_add (t, pre_p);  if (lab_over)    {      t = build (LABEL_EXPR, void_type_node, lab_over);      gimplify_and_add (t, pre_p);    }  /* Given the base array pointer (__array) and index to the subsequent     argument (__va_ndx), find the address:     __array + (AP).__va_ndx - (BYTES_BIG_ENDIAN && sizeof (TYPE) < 4				? sizeof (TYPE)				: __va_size (TYPE))     The results are endian-dependent because values smaller than one word     are aligned differently.  */  if (BYTES_BIG_ENDIAN && TREE_CODE (type_size) == INTEGER_CST)    {      t = size_int (PARM_BOUNDARY / BITS_PER_UNIT);      t = fold (build (GE_EXPR, boolean_type_node, type_size, t));      t = fold (build (COND_EXPR, sizetype, t, va_size, type_size));      size = t;    }  else    size = va_size;  t = fold_convert (ptr_type_node, ndx);  addr = build (PLUS_EXPR, ptr_type_node, array, t);  t = fold_convert (ptr_type_node, size);  addr = build (MINUS_EXPR, ptr_type_node, addr, t);  addr = fold_convert (build_pointer_type (type), addr);  if (indirect)    addr = build_va_arg_indirect_ref (addr);  return build_va_arg_indirect_ref (addr);}enum reg_classxtensa_preferred_reload_class (rtx x, enum reg_class class, int isoutput){  if (!isoutput && CONSTANT_P (x) && GET_CODE (x) == CONST_DOUBLE)    return NO_REGS;  /* Don't use the stack pointer or hard frame pointer for reloads!     The hard frame pointer would normally be OK except that it may     briefly hold an incoming argument in the prologue, and reload     won't know that it is live because the hard frame pointer is     treated specially.  */  if (class == AR_REGS || class == GR_REGS)    return RL_REGS;  return class;}enum reg_classxtensa_secondary_reload_class (enum reg_class class,			       enum machine_mode mode ATTRIBUTE_UNUSED,			       rtx x, int isoutput){  int regno;  if (GET_CODE (x) == SIGN_EXTEND)    x = XEXP (x, 0);  regno = xt_true_regnum (x);  if (!isoutput)    {      if (class == FP_REGS && constantpool_mem_p (x))	return RL_REGS;    }  if (ACC_REG_P (regno))    return ((class == GR_REGS || class == RL_REGS) ? NO_REGS : RL_REGS);  if (class == ACC_REG)    return (GP_REG_P (regno) ? NO_REGS : RL_REGS);  return NO_REGS;}voidorder_regs_for_local_alloc (void){  if (!leaf_function_p ())    {      memcpy (reg_alloc_order, reg_nonleaf_alloc_order,	      FIRST_PSEUDO_REGISTER * sizeof (int));    }  else    {      int i, num_arg_regs;      int nxt = 0;      /* Use the AR registers in increasing order (skipping a0 and a1)	 but save the incoming argument registers for a last resort.  */      num_arg_regs = current_function_args_info.arg_words;      if (num_arg_regs > MAX_ARGS_IN_REGISTERS)	num_arg_regs = MAX_ARGS_IN_REGISTERS;      for (i = GP_ARG_FIRST; i < 16 - num_arg_regs; i++)	reg_alloc_order[nxt++] = i + num_arg_regs;      for (i = 0; i < num_arg_regs; i++)	reg_alloc_order[nxt++] = GP_ARG_FIRST + i;      /* List the coprocessor registers in order.  */      for (i = 0; i < BR_REG_NUM; i++)	reg_alloc_order[nxt++] = BR_REG_FIRST + i;      /* List the FP registers in order for now.  */      for (i = 0; i < 16; i++)	reg_alloc_order[nxt++] = FP_REG_FIRST + i;      /* GCC requires that we list *all* the registers....  */      reg_alloc_order[nxt++] = 0;	/* a0 = return address */      reg_alloc_order[nxt++] = 1;	/* a1 = stack pointer */      reg_alloc_order[nxt++] = 16;	/* pseudo frame pointer */      reg_alloc_order[nxt++] = 17;	/* pseudo arg pointer */      reg_alloc_order[nxt++] = ACC_REG_FIRST;	/* MAC16 accumulator */    }}/* Some Xtensa targets support multiple bss sections.  If the section   name ends with ".bss", add SECTION_BSS to the flags.  */static unsigned intxtensa_multibss_section_type_flags (tree decl, const char *name, int reloc){  unsigned int flags = default_section_type_flags (decl, name, reloc);  const char *suffix;  suffix = strrchr (name, '.');  if (suffix && strcmp (suffix, ".bss") == 0)    {      if (!decl || (TREE_CODE (decl) == VAR_DECL		    && DECL_INITIAL (decl) == NULL_TREE))	flags |= SECTION_BSS;  /* @nobits */      else	warning (0, "only uninitialized variables can be placed in a "		 ".bss section");    }  return flags;}/* The literal pool stays with the function.  */static voidxtensa_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,			   rtx x ATTRIBUTE_UNUSED,			   unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED){  function_section (current_f

⌨️ 快捷键说明

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