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

📄 stormy16.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
xstormy16_compute_stack_layout (){  struct xstormy16_stack_layout layout;  int regno;  const int ifun = xstormy16_interrupt_function_p ();  layout.locals_size = get_frame_size ();    layout.register_save_size = 0;  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)    if (REG_NEEDS_SAVE (regno, ifun))      layout.register_save_size += UNITS_PER_WORD;    if (current_function_stdarg)    layout.stdarg_save_size = NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD;  else    layout.stdarg_save_size = 0;    layout.frame_size = (layout.locals_size 		       + layout.register_save_size 		       + layout.stdarg_save_size);    if (current_function_args_size <= 2048 && current_function_args_size != -1)    {      if (layout.frame_size + INCOMING_FRAME_SP_OFFSET 	  + current_function_args_size <= 2048)	layout.fp_minus_ap = layout.frame_size + INCOMING_FRAME_SP_OFFSET;      else	layout.fp_minus_ap = 2048 - current_function_args_size;    }  else    layout.fp_minus_ap = (layout.stdarg_save_size 			  + layout.register_save_size			  + INCOMING_FRAME_SP_OFFSET);  layout.sp_minus_fp = (layout.frame_size + INCOMING_FRAME_SP_OFFSET 			- layout.fp_minus_ap);  layout.first_local_minus_ap = layout.sp_minus_fp - layout.locals_size;  return layout;}/* Determine how all the special registers get eliminated.  */intxstormy16_initial_elimination_offset (from, to)     int from, to;{  struct xstormy16_stack_layout layout;  int result;    layout = xstormy16_compute_stack_layout ();  if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)    result = layout.sp_minus_fp - layout.locals_size;  else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)    result = -layout.locals_size;  else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)    result = -layout.fp_minus_ap;  else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)    result = -(layout.sp_minus_fp + layout.fp_minus_ap);  else    abort ();  return result;}static rtxemit_addhi3_postreload (dest, src0, src1)     rtx dest;     rtx src0;     rtx src1;{  rtx set, clobber, insn;    set = gen_rtx_SET (VOIDmode, dest, gen_rtx_PLUS (HImode, src0, src1));  clobber = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (BImode, 16));  insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, clobber)));  return insn;}/* Called after register allocation to add any instructions needed for   the prologue.  Using a prologue insn is favored compared to putting   all of the instructions in the TARGET_ASM_FUNCTION_PROLOGUE macro,   since it allows the scheduler to intermix instructions with the   saves of the caller saved registers.  In some cases, it might be   necessary to emit a barrier instruction as the last insn to prevent   such scheduling.   Also any insns generated here should have RTX_FRAME_RELATED_P(insn) = 1   so that the debug info generation code can handle them properly.  */voidxstormy16_expand_prologue (){  struct xstormy16_stack_layout layout;  int regno;  rtx insn;  rtx mem_push_rtx;  rtx mem_fake_push_rtx;  const int ifun = xstormy16_interrupt_function_p ();    mem_push_rtx = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);  mem_push_rtx = gen_rtx_MEM (HImode, mem_push_rtx);  mem_fake_push_rtx = gen_rtx_PRE_INC (Pmode, stack_pointer_rtx);  mem_fake_push_rtx = gen_rtx_MEM (HImode, mem_fake_push_rtx);      layout = xstormy16_compute_stack_layout ();  /* Save the argument registers if necessary.  */  if (layout.stdarg_save_size)    for (regno = FIRST_ARGUMENT_REGISTER; 	 regno < FIRST_ARGUMENT_REGISTER + NUM_ARGUMENT_REGISTERS;	 regno++)      {	rtx reg = gen_rtx_REG (HImode, regno);	insn = emit_move_insn (mem_push_rtx, reg);	RTX_FRAME_RELATED_P (insn) = 1;	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,					      gen_rtx_SET (VOIDmode,							   mem_fake_push_rtx,							   reg),					      REG_NOTES (insn));      }    /* Push each of the registers to save.  */  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)    if (REG_NEEDS_SAVE (regno, ifun))      {	rtx reg = gen_rtx_REG (HImode, regno);	insn = emit_move_insn (mem_push_rtx, reg);	RTX_FRAME_RELATED_P (insn) = 1;	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,					      gen_rtx_SET (VOIDmode,							   mem_fake_push_rtx,							   reg),					      REG_NOTES (insn));      }  /* It's just possible that the SP here might be what we need for     the new FP...  */  if (frame_pointer_needed && layout.sp_minus_fp == layout.locals_size)    {      insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);      RTX_FRAME_RELATED_P (insn) = 1;    }  /* Allocate space for local variables.  */  if (layout.locals_size)    {      insn = emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx,				     GEN_INT (layout.locals_size));      RTX_FRAME_RELATED_P (insn) = 1;    }  /* Set up the frame pointer, if required.  */  if (frame_pointer_needed && layout.sp_minus_fp != layout.locals_size)    {      insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);      RTX_FRAME_RELATED_P (insn) = 1;      if (layout.sp_minus_fp)	{	  insn = emit_addhi3_postreload (hard_frame_pointer_rtx,					 hard_frame_pointer_rtx,					 GEN_INT (-layout.sp_minus_fp));	  RTX_FRAME_RELATED_P (insn) = 1;	}    }}/* Do we need an epilogue at all?  */intdirect_return (){  return (reload_completed 	  && xstormy16_compute_stack_layout ().frame_size == 0);}/* Called after register allocation to add any instructions needed for   the epilogue.  Using an epilogue insn is favored compared to putting   all of the instructions in the TARGET_ASM_FUNCTION_PROLOGUE macro,   since it allows the scheduler to intermix instructions with the   saves of the caller saved registers.  In some cases, it might be   necessary to emit a barrier instruction as the last insn to prevent   such scheduling.  */voidxstormy16_expand_epilogue (){  struct xstormy16_stack_layout layout;  rtx mem_pop_rtx;  int regno;  const int ifun = xstormy16_interrupt_function_p ();    mem_pop_rtx = gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx);  mem_pop_rtx = gen_rtx_MEM (HImode, mem_pop_rtx);    layout = xstormy16_compute_stack_layout ();  /* Pop the stack for the locals.  */  if (layout.locals_size)    {      if (frame_pointer_needed && layout.sp_minus_fp == layout.locals_size)	emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);      else	emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx,				GEN_INT (- layout.locals_size));    }  /* Restore any call-saved registers.  */  for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)    if (REG_NEEDS_SAVE (regno, ifun))      emit_move_insn (gen_rtx_REG (HImode, regno), mem_pop_rtx);    /* Pop the stack for the stdarg save area.  */  if (layout.stdarg_save_size)    emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx,			    GEN_INT (- layout.stdarg_save_size));  /* Return.  */  if (ifun)    emit_jump_insn (gen_return_internal_interrupt ());  else    emit_jump_insn (gen_return_internal ());}intxstormy16_epilogue_uses (regno)     int regno;{  if (reload_completed && call_used_regs[regno])    {      const int ifun = xstormy16_interrupt_function_p ();      return REG_NEEDS_SAVE (regno, ifun);    }  return 0;}/* Return an updated summarizer variable CUM to advance past an   argument in the argument list.  The values MODE, TYPE and NAMED   describe that argument.  Once this is done, the variable CUM is   suitable for analyzing the *following* argument with   `FUNCTION_ARG', etc.   This function need not do anything if the argument in question was   passed on the stack.  The compiler knows how to track the amount of   stack space used for arguments without any special help.  However,   it makes life easier for xstormy16_build_va_list if it does update   the word count.  */CUMULATIVE_ARGSxstormy16_function_arg_advance (cum, mode, type, named)     CUMULATIVE_ARGS cum;     enum machine_mode mode;     tree type;     int named ATTRIBUTE_UNUSED;{  /* If an argument would otherwise be passed partially in registers,     and partially on the stack, the whole of it is passed on the     stack.  */  if (cum < NUM_ARGUMENT_REGISTERS      && cum + XSTORMY16_WORD_SIZE (type, mode) > NUM_ARGUMENT_REGISTERS)    cum = NUM_ARGUMENT_REGISTERS;    cum += XSTORMY16_WORD_SIZE (type, mode);    return cum;}/* Do any needed setup for a variadic function.  CUM has not been updated   for the last named argument which has type TYPE and mode MODE.  */voidxstormy16_setup_incoming_varargs (cum, int_mode, type, pretend_size)     CUMULATIVE_ARGS cum ATTRIBUTE_UNUSED;     int             int_mode ATTRIBUTE_UNUSED;     tree            type ATTRIBUTE_UNUSED;     int *           pretend_size ATTRIBUTE_UNUSED;{}/* Build the va_list type.   For this chip, va_list is a record containing a counter and a pointer.   The counter is of type 'int' and indicates how many bytes   have been used to date.  The pointer indicates the stack position   for arguments that have not been passed in registers.     To keep the layout nice, the pointer is first in the structure.  */treexstormy16_build_va_list (){  tree f_1, f_2, record, type_decl;  record = (*lang_hooks.types.make_type) (RECORD_TYPE);  type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);  f_1 = build_decl (FIELD_DECL, get_identifier ("base"),		      ptr_type_node);  f_2 = build_decl (FIELD_DECL, get_identifier ("count"), 		      unsigned_type_node);  DECL_FIELD_CONTEXT (f_1) = record;  DECL_FIELD_CONTEXT (f_2) = record;  TREE_CHAIN (record) = type_decl;  TYPE_NAME (record) = type_decl;  TYPE_FIELDS (record) = f_1;  TREE_CHAIN (f_1) = f_2;  layout_type (record);  return record;}/* Implement the stdarg/varargs va_start macro.  STDARG_P is nonzero if this   is stdarg.h instead of varargs.h.  VALIST is the tree of the va_list   variable to initialize.  NEXTARG is the machine independent notion of the   'next' argument after the variable arguments.  */voidxstormy16_expand_builtin_va_start (valist, nextarg)     tree valist;     rtx nextarg ATTRIBUTE_UNUSED;{  tree f_base, f_count;  tree base, count;  tree t;  if (xstormy16_interrupt_function_p ())    error ("cannot use va_start in interrupt function");    f_base = TYPE_FIELDS (va_list_type_node);  f_count = TREE_CHAIN (f_base);    base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base);  count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count);  t = make_tree (TREE_TYPE (base), virtual_incoming_args_rtx);  t = build (PLUS_EXPR, TREE_TYPE (base), t, 	     build_int_2 (INCOMING_FRAME_SP_OFFSET, 0));  t = build (MODIFY_EXPR, TREE_TYPE (base), base, t);  TREE_SIDE_EFFECTS (t) = 1;  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);  t = build (MODIFY_EXPR, TREE_TYPE (count), count, 	     build_int_2 (current_function_args_info * UNITS_PER_WORD, 0));  TREE_SIDE_EFFECTS (t) = 1;  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);}/* Implement the stdarg/varargs va_arg macro.  VALIST is the variable   of type va_list as a tree, TYPE is the type passed to va_arg.   Note:  This algorithm is documented in stormy-abi.  */   rtxxstormy16_expand_builtin_va_arg (valist, type)     tree valist;     tree type;{  tree f_base, f_count;  tree base, count;  rtx count_rtx, addr_rtx, r;  rtx lab_gotaddr, lab_fromstack;  tree t;  int size, size_of_reg_args;  tree size_tree, count_plus_size;  rtx count_plus_size_rtx;    f_base = TYPE_FIELDS (va_list_type_node);  f_count = TREE_CHAIN (f_base);    base = build (COMPONENT_REF, TREE_TYPE (f_base), valist, f_base);  count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count);  size = PUSH_ROUNDING (int_size_in_bytes (type));  size_tree = round_up (size_in_bytes (type), UNITS_PER_WORD);    size_of_reg_args = NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD;  count_rtx = expand_expr (count, NULL_RTX, HImode, EXPAND_NORMAL);  lab_gotaddr = gen_label_rtx ();  lab_fromstack = gen_label_rtx ();  addr_rtx = gen_reg_rtx (Pmode);  count_plus_size = build (PLUS_EXPR, TREE_TYPE (count), count, size_tree);  count_plus_size_rtx = expand_expr (count_plus_size, NULL_RTX, HImode, EXPAND_NORMAL);  emit_cmp_and_jump_insns (count_plus_size_rtx, GEN_INT (size_of_reg_args),			   GTU, const1_rtx, HImode, 1, lab_fromstack);    t = build (PLUS_EXPR, ptr_type_node, base, count);  r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);  if (r != addr_rtx)    emit_move_insn (addr_rtx, r);  emit_jump_insn (gen_jump (lab_gotaddr));  emit_barrier ();  emit_label (lab_fromstack);    /* Arguments larger than a word might need to skip over some     registers, since arguments are either passed entirely in     registers or entirely on the stack.  */  if (size > 2 || size < 0)    {      rtx lab_notransition = gen_label_rtx ();      emit_cmp_and_jump_insns (count_rtx, GEN_INT (NUM_ARGUMENT_REGISTERS 						   * UNITS_PER_WORD),			       GEU, const1_rtx, HImode, 1, lab_notransition);            t = build (MODIFY_EXPR, TREE_TYPE (count), count, 		 build_int_2 (NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD, 0));      TREE_SIDE_EFFECTS (t) = 1;      expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);            emit_label (lab_notransition);    }  t = build (PLUS_EXPR, sizetype, size_tree,	     build_int_2 ((- NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD			   + INCOMING_FRAME_SP_OFFSET),			  -1));  t = build (PLUS_EXPR, TREE_TYPE (count), count, fold (t));  t = build (MINUS_EXPR, TREE_TYPE (base), base, t);  r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);  if (r != addr_rtx)    emit_move_insn (addr_rtx, r);	       emit_label (lab_gotaddr);  count_plus_size = build (PLUS_EXPR, TREE_TYPE (count), count, size_tree);  t = build (MODIFY_EXPR, TREE_TYPE (count), count, count_plus_size);  TREE_SIDE_EFFECTS (t) = 1;  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);  return addr_rtx;}/* Initialize the variable parts of a trampoline.  ADDR is an RTX for   the address of the trampoline; FNADDR is an RTX for the address of   the nested function; STATIC_CHAIN is an RTX for the static chain   value that should be passed to the function when it is called.  */

⌨️ 快捷键说明

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