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

📄 xtensa.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
    case LABEL_REF:    case SYMBOL_REF:    case CONST_INT:    case CONST:      output_addr_const (file, addr);      break;    }}voidxtensa_output_literal (file, x, mode, labelno)     FILE *file;     rtx x;     enum machine_mode mode;     int labelno;{  long value_long[2];  REAL_VALUE_TYPE r;  int size;  fprintf (file, "\t.literal .LC%u, ", (unsigned) labelno);  switch (GET_MODE_CLASS (mode))    {    case MODE_FLOAT:      if (GET_CODE (x) != CONST_DOUBLE)	abort ();      REAL_VALUE_FROM_CONST_DOUBLE (r, x);      switch (mode)	{	case SFmode:	  REAL_VALUE_TO_TARGET_SINGLE (r, value_long[0]);	  fprintf (file, "0x%08lx\n", value_long[0]);	  break;	case DFmode:	  REAL_VALUE_TO_TARGET_DOUBLE (r, value_long);	  fprintf (file, "0x%08lx, 0x%08lx\n",		   value_long[0], value_long[1]);	  break;	default:	  abort ();	}      break;    case MODE_INT:    case MODE_PARTIAL_INT:      size = GET_MODE_SIZE (mode);      if (size == 4)	{	  output_addr_const (file, x);	  fputs ("\n", file);	}      else if (size == 8)	{	  output_addr_const (file, operand_subword (x, 0, 0, DImode));	  fputs (", ", file);	  output_addr_const (file, operand_subword (x, 1, 0, DImode));	  fputs ("\n", file);	}      else	abort ();      break;    default:      abort ();    }}/* Return the bytes needed to compute the frame pointer from the current   stack pointer. */#define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)#define XTENSA_STACK_ALIGN(LOC) (((LOC) + STACK_BYTES-1) & ~(STACK_BYTES-1))longcompute_frame_size (size)     int size;			/* # of var. bytes allocated */{  /* add space for the incoming static chain value */  if (current_function_needs_context)    size += (1 * UNITS_PER_WORD);  xtensa_current_frame_size =    XTENSA_STACK_ALIGN (size			+ current_function_outgoing_args_size			+ (WINDOW_SIZE * UNITS_PER_WORD));  return xtensa_current_frame_size;}intxtensa_frame_pointer_required (){  /* The code to expand builtin_frame_addr and builtin_return_addr     currently uses the hard_frame_pointer instead of frame_pointer.     This seems wrong but maybe it's necessary for other architectures.     This function is derived from the i386 code. */  if (cfun->machine->accesses_prev_frame)    return 1;  return 0;}voidxtensa_reorg (first)    rtx first;{  unsigned long tsize = compute_frame_size (get_frame_size ());  if (tsize < (1 << (12+3)))    frame_size_const = 0;  else    {      frame_size_const = force_const_mem (SImode, GEN_INT (tsize - 16));;      /* make sure the constant is used so it doesn't get eliminated	 from the constant pool */      emit_insn_before (gen_rtx_USE (SImode, frame_size_const), first);    }  if (!frame_pointer_needed)    return;  if (cfun->machine->set_frame_ptr_insn)    {      rtx insn;      /* 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 the frame pointer move immediately after the NOTE that starts	 the function */      emit_insn_after (gen_movsi (hard_frame_pointer_rtx,				  stack_pointer_rtx), first);    }}/* Set up the stack and frame (if desired) for the function.  */voidxtensa_function_prologue (file, size)     FILE *file;     int size ATTRIBUTE_UNUSED;{  unsigned long tsize = compute_frame_size (get_frame_size ());  if (frame_pointer_needed)    fprintf (file, "\t.frame\ta7, %ld\n", tsize);  else    fprintf (file, "\t.frame\tsp, %ld\n", tsize);   if (tsize < (1 << (12+3)))    {      fprintf (file, "\tentry\tsp, %ld\n", tsize);    }  else    {      fprintf (file, "\tentry\tsp, 16\n");      /* use a8 as a temporary since a0-a7 may be live */      fprintf (file, "\tl32r\ta8, ");      print_operand (file, frame_size_const, 0);      fprintf (file, "\n\tsub\ta8, sp, a8\n");      fprintf (file, "\tmovsp\tsp, a8\n");    }}/* Do any necessary cleanup after a function to restore   stack, frame, and regs. */voidxtensa_function_epilogue (file, size)     FILE *file;     int size ATTRIBUTE_UNUSED;{  rtx insn = get_last_insn ();  /* If the last insn was a BARRIER, we don't have to write anything. */  if (GET_CODE (insn) == NOTE)    insn = prev_nonnote_insn (insn);  if (insn == 0 || GET_CODE (insn) != BARRIER)    fprintf (file, TARGET_DENSITY ? "\tretw.n\n" : "\tretw\n");  xtensa_current_frame_size = 0;}rtxxtensa_return_addr (count, frame)     int count;     rtx frame;{  rtx result, retaddr;  if (count == -1)    retaddr = gen_rtx_REG (Pmode, 0);  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.  E.G., if there are 6 argument registers, and each register is   4 bytes, then __va_stk is set to $sp - (6 * 4); then __va_reg[N*4]   references argument word N for 0 <= N < 6, and __va_stk[N*4] references   argument word N for N >= 6. */treextensa_build_va_list (){  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. */rtxxtensa_builtin_saveregs (){  rtx gp_regs, dest;  int arg_words = current_function_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,		       gp_left * UNITS_PER_WORD);  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 (valist, nextarg)     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);  reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg);  ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx);  /* Call __builtin_saveregs; save the result in __va_reg */  current_function_arg_words = arg_words;  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 - (size of __va_reg area) */  u = make_tree (ptr_type_node, virtual_incoming_args_rtx);  u = fold (build (PLUS_EXPR, ptr_type_node, u,		   build_int_2 (-MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, -1)));  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. */  u = build_int_2 (arg_words * UNITS_PER_WORD, 0);  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'.  */rtxxtensa_va_arg (valist, type)     tree valist, type;{  tree f_stk, stk;  tree f_reg, reg;  tree f_ndx, ndx;  tree tmp, addr_tree, type_size;  rtx array, orig_ndx, r, addr, size, va_size;  rtx lab_false, lab_over, lab_false2;  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);  reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg);  ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx);  type_size = TYPE_SIZE_UNIT (TYPE_MAIN_VARIANT (type));  va_size = gen_reg_rtx (SImode);  tmp = fold (build (MULT_EXPR, sizetype,		     fold (build (TRUNC_DIV_EXPR, sizetype,				  fold (build (PLUS_EXPR, sizetype,					       type_size,					       size_int (UNITS_PER_WORD - 1))),				  size_int (UNITS_PER_WORD))),		     size_int (UNITS_PER_WORD)));  r = expand_expr (tmp, va_size, SImode, EXPAND_NORMAL);  if (r != va_size)    emit_move_insn (va_size, r);  /* First align __va_ndx to a double word boundary if necessary for this arg:     if (__alignof__ (TYPE) > 4)       (AP).__va_ndx = (((AP).__va_ndx + 7) & -8)  */  if (TYPE_ALIGN (type) > BITS_PER_WORD)    {      tmp = build (PLUS_EXPR, integer_type_node, ndx,		   build_int_2 ((2 * UNITS_PER_WORD) - 1, 0));      tmp = build (BIT_AND_EXPR, integer_type_node, tmp,		   build_int_2 (-2 * UNITS_PER_WORD, -1));      tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp);      TREE_SIDE_EFFECTS (tmp) = 1;      expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);    }  /* Increment __va_ndx to point past the argument:     orig_ndx = (AP).__va_ndx;     (AP).__va_ndx += __va_size (TYPE);  */  orig_ndx = gen_reg_rtx (SImode);  r = expand_expr (ndx, orig_ndx, SImode, EXPAND_NORMAL);  if (r != orig_ndx)    emit_move_insn (orig_ndx, r);  tmp = build (PLUS_EXPR, integer_type_node, ndx,	       make_tree (intSI_type_node, va_size));  tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp);  TREE_SIDE_EFFECTS (tmp) = 1;  expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);  /* 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 = gen_reg_rtx (Pmode);  lab_over = NULL_RTX;  if (!MUST_PASS_IN_STACK (VOIDmode, type))    {      lab_false = gen_label_rtx ();      lab_over = gen_label_rtx ();      emit_cmp_and_jump_insns (expand_expr (ndx, NULL_RTX, SImode,					    EXPAND_NORMAL),			       GEN_INT (MAX_ARGS_IN_REGISTERS					* UNITS_PER_WORD),			       GT, const1_rtx, SImode, 0, lab_false);      r = expand_expr (reg, array, Pmode, EXPAND_NORMAL);      if (r != array)	emit_move_insn (array, r);      emit_jump_insn (gen_jump (lab_over));      emit_barrier ();      emit_label (lab_false);    }  /* ...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 = __MAX_ARGS_IN_REGISTERS * 4 + __va_size (TYPE);	 __array = (AP).__va_stk;       }  */  lab_false2 = gen_label_rtx ();  emit_cmp_and_jump_insns (orig_ndx,			   GEN_INT (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD),			   GE, const1_rtx, SImode, 0, lab_false2);  tmp = build (PLUS_EXPR, sizetype, make_tree (intSI_type_node, va_size),	       build_int_2 (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, 0));  tmp = build (MODIFY_EXPR, integer_type_node, ndx, tmp);  TREE_SIDE_EFFECTS (tmp) = 1;  expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);  emit_label (lab_false2);  r = expand_expr (stk, array, Pmode, EXPAND_NORMAL);  if (r != array)    emit_move_insn (array, r);  if (lab_over != NULL_RTX)    emit_label (lab_over);  /* 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.  */  size = gen_reg_rtx (SImode);  emit_move_insn (size, va_size);    if (BYTES_BIG_ENDIAN)    {      rtx lab_use_va_size = gen_label_rtx ();      emit_cmp_and_jump_insns (expand_expr (type_size, NULL_RTX, SImode,					    EXPAND_NORMAL),			       GEN_INT (PARM_BOUNDARY / BITS_PER_UNIT),			       GE, const1_rtx, SImode, 0, lab_use_va_size);      r = expand_expr (type_size, size, SImode, EXPAND_NORMAL);      if (r != size)	emit_move_insn (size, r);      emit_label (lab_use_va_size);    }  ad

⌨️ 快捷键说明

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