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

📄 stormy16.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
   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 (void){  struct xstormy16_stack_layout layout;  rtx mem_pop_rtx, insn;  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        {	  insn = emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx,					 GEN_INT (- layout.locals_size));	  RTX_FRAME_RELATED_P (insn) = 1;	}    }  /* Restore any call-saved registers.  */  for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)    if (REG_NEEDS_SAVE (regno, ifun))      {        rtx dwarf;	insn = emit_move_insn (gen_rtx_REG (HImode, regno), mem_pop_rtx);	RTX_FRAME_RELATED_P (insn) = 1;	dwarf = gen_rtx_SET (Pmode, stack_pointer_rtx,			     plus_constant (stack_pointer_rtx,					    -GET_MODE_SIZE (Pmode)));	REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,					      dwarf,					      REG_NOTES (insn));      }    /* Pop the stack for the stdarg save area.  */  if (layout.stdarg_save_size)    {      insn = emit_addhi3_postreload (stack_pointer_rtx, stack_pointer_rtx,				     GEN_INT (- layout.stdarg_save_size));      RTX_FRAME_RELATED_P (insn) = 1;    }  /* Return.  */  if (ifun)    emit_jump_insn (gen_return_internal_interrupt ());  else    emit_jump_insn (gen_return_internal ());}intxstormy16_epilogue_uses (int regno){  if (reload_completed && call_used_regs[regno])    {      const int ifun = xstormy16_interrupt_function_p ();      return REG_NEEDS_SAVE (regno, ifun);    }  return 0;}voidxstormy16_function_profiler (void){  sorry ("function_profiler support");}/* 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 (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;}rtxxstormy16_function_arg (CUMULATIVE_ARGS cum, enum machine_mode mode,			tree type, int named ATTRIBUTE_UNUSED){  if (mode == VOIDmode)    return const0_rtx;  if (targetm.calls.must_pass_in_stack (mode, type)      || cum + XSTORMY16_WORD_SIZE (type, mode) > NUM_ARGUMENT_REGISTERS)    return 0;  return gen_rtx_REG (mode, cum + 2);}/* 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.  */static treexstormy16_build_builtin_va_list (void){  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 (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, NULL_TREE);  count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count,		 NULL_TREE);  t = make_tree (TREE_TYPE (base), virtual_incoming_args_rtx);  t = build (PLUS_EXPR, TREE_TYPE (base), t, 	     build_int_cst (NULL_TREE, INCOMING_FRAME_SP_OFFSET));  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_cst (NULL_TREE,			    current_function_args_info * UNITS_PER_WORD));  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.  */   static treexstormy16_expand_builtin_va_arg (tree valist, tree type, tree *pre_p,				 tree *post_p ATTRIBUTE_UNUSED){  tree f_base, f_count;  tree base, count;  tree count_tmp, addr, t;  tree lab_gotaddr, lab_fromstack;  int size, size_of_reg_args, must_stack;  tree size_tree;  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, NULL_TREE);  count = build (COMPONENT_REF, TREE_TYPE (f_count), valist, f_count,		 NULL_TREE);  must_stack = targetm.calls.must_pass_in_stack (TYPE_MODE (type), type);  size_tree = round_up (size_in_bytes (type), UNITS_PER_WORD);  gimplify_expr (&size_tree, pre_p, NULL, is_gimple_val, fb_rvalue);    size_of_reg_args = NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD;  count_tmp = get_initialized_tmp_var (count, pre_p, NULL);  lab_gotaddr = create_artificial_label ();  lab_fromstack = create_artificial_label ();  addr = create_tmp_var (ptr_type_node, NULL);  if (!must_stack)    {      tree r;      t = fold_convert (TREE_TYPE (count), size_tree);      t = build (PLUS_EXPR, TREE_TYPE (count), count_tmp, t);      r = fold_convert (TREE_TYPE (count), size_int (size_of_reg_args));      t = build (GT_EXPR, boolean_type_node, t, r);      t = build (COND_EXPR, void_type_node, t,		 build (GOTO_EXPR, void_type_node, lab_fromstack),		 NULL);      gimplify_and_add (t, pre_p);        t = fold_convert (ptr_type_node, count_tmp);      t = build (PLUS_EXPR, ptr_type_node, base, t);      t = build (MODIFY_EXPR, void_type_node, addr, t);      gimplify_and_add (t, pre_p);      t = build (GOTO_EXPR, void_type_node, lab_gotaddr);      gimplify_and_add (t, pre_p);      t = build (LABEL_EXPR, void_type_node, lab_fromstack);      gimplify_and_add (t, pre_p);    }    /* 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.  */  size = PUSH_ROUNDING (int_size_in_bytes (type));  if (size > 2 || size < 0 || must_stack)    {      tree r, u;      r = size_int (NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD);      u = build (MODIFY_EXPR, void_type_node, count_tmp, r);      t = fold_convert (TREE_TYPE (count), r);      t = build (GE_EXPR, boolean_type_node, count_tmp, t);      t = build (COND_EXPR, void_type_node, t, NULL, u);      gimplify_and_add (t, pre_p);    }  t = size_int (NUM_ARGUMENT_REGISTERS * UNITS_PER_WORD		- INCOMING_FRAME_SP_OFFSET);  t = fold_convert (TREE_TYPE (count), t);  t = build (MINUS_EXPR, TREE_TYPE (count), count_tmp, t);  t = build (PLUS_EXPR, TREE_TYPE (count), t,	     fold_convert (TREE_TYPE (count), size_tree));  t = fold_convert (TREE_TYPE (base), fold (t));  t = build (MINUS_EXPR, TREE_TYPE (base), base, t);  t = build (MODIFY_EXPR, void_type_node, addr, t);  gimplify_and_add (t, pre_p);  t = build (LABEL_EXPR, void_type_node, lab_gotaddr);  gimplify_and_add (t, pre_p);  t = fold_convert (TREE_TYPE (count), size_tree);  t = build (PLUS_EXPR, TREE_TYPE (count), count_tmp, t);  t = build (MODIFY_EXPR, TREE_TYPE (count), count, t);  gimplify_and_add (t, pre_p);    addr = fold_convert (build_pointer_type (type), addr);  return build_fold_indirect_ref (addr);}/* 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.  */voidxstormy16_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain){  rtx reg_addr = gen_reg_rtx (Pmode);  rtx temp = gen_reg_rtx (HImode);  rtx reg_fnaddr = gen_reg_rtx (HImode);  rtx reg_addr_mem;  reg_addr_mem = gen_rtx_MEM (HImode, reg_addr);      emit_move_insn (reg_addr, addr);  emit_move_insn (temp, GEN_INT (0x3130 | STATIC_CHAIN_REGNUM));  emit_move_insn (reg_addr_mem, temp);  emit_insn (gen_addhi3 (reg_addr, reg_addr, const2_rtx));  emit_move_insn (temp, static_chain);  emit_move_insn (reg_addr_mem, temp);  emit_insn (gen_addhi3 (reg_addr, reg_addr, const2_rtx));  emit_move_insn (reg_fnaddr, fnaddr);  emit_move_insn (temp, reg_fnaddr);  emit_insn (gen_andhi3 (temp, temp, GEN_INT (0xFF)));  emit_insn (gen_iorhi3 (temp, temp, GEN_INT (0x0200)));  emit_move_insn (reg_addr_mem, temp);  emit_insn (gen_addhi3 (reg_addr, reg_addr, const2_rtx));  emit_insn (gen_lshrhi3 (reg_fnaddr, reg_fnaddr, GEN_INT (8)));  emit_move_insn (reg_addr_mem, reg_fnaddr);}/* Worker function for FUNCTION_VALUE.  */rtxxstormy16_function_value (tree valtype, tree func ATTRIBUTE_UNUSED){  enum machine_mode mode;  mode = TYPE_MODE (valtype);  PROMOTE_MODE (mode, 0, valtype);  return gen_rtx_REG (mode, RETURN_VALUE_REGNUM);}/* A C compound statement that outputs the assembler code for a thunk function,   used to implement C++ virtual function calls with multiple inheritance.  The   thunk acts as a wrapper around a virtual function, adjusting the implicit   object parameter before handing control off to the real function.   First, emit code to add the integer DELTA to the location that contains the   incoming first argument.  Assume that this argument contains a pointer, and   is the one used to pass the `this' pointer in C++.  This is the incoming   argument *before* the function prologue, e.g. `%o0' on a sparc.  The   addition must preserve the values of all other incoming arguments.   After the addition, emit code to jump to FUNCTION, which is a   `FUNCTION_DECL'.  This is a direct pure jump, not a call, and does not touch   the return address.  Hence returning from FUNCTION will return to whoever   called the current `thunk'.   The effect must be as if @var{function} had been called directly   with the adjusted first argument.  This macro is responsible for   emitting all of the code for a thunk function;   TARGET_ASM_FUNCTION_PROLOGUE and TARGET_ASM_FUNCTION_EPILOGUE are   not invoked.   The THUNK_FNDECL is redundant.  (DELTA and FUNCTION have already been   extracted from it.)  It might possibly be useful on some targets, but   probably not.  */static voidxstormy16_asm_output_mi_thunk (FILE *file,			       tree thunk_fndecl ATTRIBUTE_UNUSED,			       HOST_WIDE_INT delta,			       HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,			       tree function){  int regnum = FIRST_ARGUMENT_REGISTER;    /* There might be a hidden first argument for a returned structure.  */  if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))    regnum += 1;    fprintf (file, "\tadd %s,#0x%x\n", reg_names[regnum], (int) delta & 0xFFFF);  fputs ("\tjmpf ", file);  assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));  putc ('\n', file);}/* The purpose of this function is to override the default behavior of   BSS objects.  Normally, they go into .bss or .sbss via ".common"   directives, but we need to override that and put them in   .bss_below100.  We can't just use a section override (like we do   for .data_below100), because that makes them initialized rather   than uninitialized.  */voidxstormy16_asm_output_aligned_common (FILE *stream,				     tree decl ATTRIBUTE_UNUSED,				     const char *name,				     int size,				     int align,				     int global){  if (name[0] == '@' && name[2] == '.')    {      const char *op = 0;      switch (name[1])	{	case 'b':	  bss100_section();	  op = "space";	  break;	}      if (op)	{	  const char *name2;	  int p2align = 0;	  while (align > 8)	    {	      align /= 2;	      p2align ++;	    }	  name2 = xstormy16_strip_name_encoding (name);	  if (global)	    fprintf (stream, "\t.globl\t%s\n", name2);	  if (p2align)	    fprintf (stream, "\t.p2align %d\n", p2align);	  fprintf (stream, "\t.type\t%s, @object\n", name2);	  fprintf (stream, "\t.size\t%s, %d\n", name2, size);	  fprintf (stream, "%s:\n\t.%s\t%d\n", name2, op, size);	  return;	}    }  if (!global)    {      fprintf (stream, "\t.local\t");      assemble_name (stream, name);      fprintf (stream, "\n");    }  fprintf (stream, "\t.comm\t");  assemble_name (stream, name);  fprintf (stream, ",%u,%u\n", size, align / BITS_PER_UNIT);}/* Mark symbols with the "below100" attribute so that we can use the   special addressing modes for them.  */static voidxstormy16_encode_section_info (tree decl,			       rtx r,			       int first ATTRIBUTE_UNUSED){  if (TREE_CODE (decl) == VAR_DECL

⌨️ 快捷键说明

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