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

📄 i860.c

📁 Mac OS X 10.4.9 for x86 Source Code gcc 实现源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  frame_upper_bytes = must_preserve_bytes + preserved_reg_bytes;  /* Round-up frame_upper_bytes so that t is a multiple of 16.  */  frame_upper_bytes    = (frame_upper_bytes + STACK_ALIGNMENT - 1) & -STACK_ALIGNMENT;  /* Restore all of the "preserved" registers that need restoring.  */  mask = 2;  for (i = 1; i < 32; i++, mask<<=1)    if (regs_ever_live[i] && ! call_used_regs[i]) {      fprintf (asm_file, "\tld.l %d(%sfp),%s%s\n",	must_preserve_bytes + (4 * restored_so_far++),	i860_reg_prefix, i860_reg_prefix, reg_names[i]);      if (i > 3 && i < 16)	flags->iregs |= mask;    }  int_restored = restored_so_far;  mask = 1;  for (i = 32; i < 64; i++) {    if (regs_ever_live[i] && ! call_used_regs[i]) {      fprintf (asm_file, "\tfld.l %d(%sfp),%s%s\n",	must_preserve_bytes + (4 * restored_so_far++),	i860_reg_prefix, i860_reg_prefix, reg_names[i]);      if (i > 33 && i < 40)	flags->fregs |= mask;    }    if (i > 33 && i < 40)      mask<<=1;  }  /* Get the value we plan to use to restore the stack pointer into r31.  */  fprintf (asm_file, "\tadds " HOST_WIDE_INT_PRINT_DEC ",%sfp,%sr31\n",    frame_upper_bytes, i860_reg_prefix, i860_reg_prefix);  /* Restore the return address and the old frame pointer.  */  if (must_preserve_r1) {    fprintf (asm_file, "\tld.l 4(%sfp),%sr1\n",      i860_reg_prefix, i860_reg_prefix);    flags->iregs |= 2;  }  fprintf (asm_file, "\tld.l 0(%sfp),%sfp\n",    i860_reg_prefix, i860_reg_prefix);  /* Return and restore the old stack pointer value.  */  fprintf (asm_file, "\tbri %sr1\n\tmov %sr31,%ssp\n",    i860_reg_prefix, i860_reg_prefix, i860_reg_prefix);#ifdef	OUTPUT_TDESC	/* Output an ABI-compliant TDESC entry.  */  if (! frame_lower_bytes) {    flags->version--;    if (! frame_upper_bytes) {      flags->version--;      if (restored_so_far == int_restored)	/* No FP saves.  */	flags->version--;    }  }  assemble_name(asm_file,current_function_original_name);  fputs(".TDESC:\n", asm_file);  fprintf(asm_file, "%s 0x%0x\n", long_op, intflags);  fprintf(asm_file, "%s %d\n", long_op,	int_restored ? must_preserve_bytes : 0);  if (flags->version > 1) {    fprintf(asm_file, "%s %d\n", long_op,	(restored_so_far == int_restored) ? 0 : must_preserve_bytes +	  (4 * int_restored));    if (flags->version > 2) {      fprintf(asm_file, "%s %d\n", long_op, frame_upper_bytes);      if (flags->version > 3)	fprintf(asm_file, "%s %d\n", long_op, frame_lower_bytes);    }  }  tdesc_section();  fprintf(asm_file, "%s ", long_op);  assemble_name(asm_file, current_function_original_name);  fprintf(asm_file, "\n%s ", long_op);  assemble_name(asm_file, current_function_original_name);  fputs(".TDESC\n", asm_file);  text_section();#endif}/* Expand a library call to __builtin_saveregs.  */static rtxi860_saveregs (void){  rtx fn = gen_rtx_SYMBOL_REF (Pmode, "__builtin_saveregs");  rtx save = gen_reg_rtx (Pmode);  rtx valreg = LIBCALL_VALUE (Pmode);  rtx ret;  /* The return value register overlaps the first argument register.     Save and restore it around the call.  */  emit_move_insn (save, valreg);  ret = emit_library_call_value (fn, NULL_RTX, 1, Pmode, 0);  if (GET_CODE (ret) != REG || REGNO (ret) < FIRST_PSEUDO_REGISTER)    ret = copy_to_reg (ret);  emit_move_insn (valreg, save);  return ret;}/* Create the va_list data type.   The SVR4 ABI requires the following structure:        typedef struct {            unsigned long  ireg_used;            unsigned long  freg_used;            long          *reg_base;            long          *mem_ptr;        } va_list;   Otherwise, this structure is used:        typedef struct {            long          *reg_base;            long          *mem_ptr;            unsigned long  ireg_used;            unsigned long  freg_used;        } va_list;   The tree representing the va_list declaration is returned.  */static treei860_build_builtin_va_list (void){  tree f_gpr, f_fpr, f_mem, f_sav, record, type_decl;  record = (*lang_hooks.types.make_type) (RECORD_TYPE);  type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);  f_gpr = build_decl (FIELD_DECL, get_identifier ("__ireg_used"),		      unsigned_type_node);  f_fpr = build_decl (FIELD_DECL, get_identifier ("__freg_used"),		      unsigned_type_node);  f_sav = build_decl (FIELD_DECL, get_identifier ("__reg_base"),		      ptr_type_node);  f_mem = build_decl (FIELD_DECL, get_identifier ("__mem_ptr"),		      ptr_type_node);  DECL_FIELD_CONTEXT (f_gpr) = record;  DECL_FIELD_CONTEXT (f_fpr) = record;  DECL_FIELD_CONTEXT (f_sav) = record;  DECL_FIELD_CONTEXT (f_mem) = record;  TREE_CHAIN (record) = type_decl;  TYPE_NAME (record) = type_decl;#ifdef I860_SVR4_VA_LIST  TYPE_FIELDS (record) = f_gpr;  TREE_CHAIN (f_gpr) = f_fpr;  TREE_CHAIN (f_fpr) = f_sav;  TREE_CHAIN (f_sav) = f_mem;#else  TYPE_FIELDS (record) = f_sav;  TREE_CHAIN (f_sav) = f_mem;  TREE_CHAIN (f_mem) = f_gpr;  TREE_CHAIN (f_gpr) = f_fpr;#endif  layout_type (record);  return record;}/* Initialize the va_list structure.  */voidi860_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED){  tree saveregs, t;  tree f_gpr, f_fpr, f_mem, f_sav;  tree gpr, fpr, mem, sav;  int off = 0;  saveregs = make_tree (ptr_type_node, expand_builtin_saveregs ());#ifdef I860_SVR4_VA_LIST  f_gpr = TYPE_FIELDS (va_list_type_node);  f_fpr = TREE_CHAIN (f_gpr);  f_sav = TREE_CHAIN (f_fpr);  f_mem = TREE_CHAIN (f_sav);#else  f_sav = TYPE_FIELDS (va_list_type_node);  f_mem = TREE_CHAIN (f_sav);  f_gpr = TREE_CHAIN (f_mem);  f_fpr = TREE_CHAIN (f_gpr);#endif  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);  mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem, NULL_TREE);  /* Initialize the `mem_ptr' field to the address of the first anonymous     stack argument.  */  t = make_tree (TREE_TYPE (mem), virtual_incoming_args_rtx);  off = INTVAL (current_function_arg_offset_rtx);  off = off < 0 ? 0 : off;  t = build (PLUS_EXPR, TREE_TYPE (mem), t, build_int_cst (NULL_TREE, off, 0));  t = build (MODIFY_EXPR, TREE_TYPE (mem), mem, t);  TREE_SIDE_EFFECTS (t) = 1;  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);  /* Initialize the `ireg_used' field.  */  t = build_int_cst (NULL_TREE,		     current_function_args_info.ints / UNITS_PER_WORD, 0);  t = build (MODIFY_EXPR, TREE_TYPE (gpr), gpr, t);  TREE_SIDE_EFFECTS (t) = 1;  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);       /* Initialize the `freg_used' field.  */  t = build_int_cst (NULL_TREE,		     current_function_args_info.floats / UNITS_PER_WORD, 0);  t = build (MODIFY_EXPR, TREE_TYPE (fpr), fpr, t);  TREE_SIDE_EFFECTS (t) = 1;  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);        /* Initialize the `reg_base' field.  */  t = build (MODIFY_EXPR, TREE_TYPE (sav), sav, saveregs);  TREE_SIDE_EFFECTS (t) = 1;  expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);}#define NUM_PARM_FREGS	8#define NUM_PARM_IREGS	12#ifdef I860_SVR4_VA_LIST#define FREG_OFFSET 0#define IREG_OFFSET (NUM_PARM_FREGS * UNITS_PER_WORD)#else#define FREG_OFFSET (NUM_PARM_IREGS * UNITS_PER_WORD)#define IREG_OFFSET 0#endif/* Update the VALIST structure as necessary for an   argument of the given TYPE, and return the argument.  */static treei860_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p){  tree f_gpr, f_fpr, f_mem, f_sav;  tree gpr, fpr, mem, sav;  tree size, t, u, addr, type_ptr;  tree reg, n_reg, sav_ofs, lim_reg;  HOST_WIDE_INT isize;  bool indirect;#ifdef I860_SVR4_VA_LIST  f_gpr = TYPE_FIELDS (va_list_type_node);  f_fpr = TREE_CHAIN (f_gpr);  f_sav = TREE_CHAIN (f_fpr);  f_mem = TREE_CHAIN (f_sav);#else  f_sav = TYPE_FIELDS (va_list_type_node);  f_mem = TREE_CHAIN (f_sav);  f_gpr = TREE_CHAIN (f_mem);  f_fpr = TREE_CHAIN (f_gpr);#endif  gpr = build (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);  fpr = build (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);  mem = build (COMPONENT_REF, TREE_TYPE (f_mem), valist, f_mem, NULL_TREE);  sav = build (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);  indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);  if (indirect)    type = build_pointer_type (type);  size = size_in_bytes (type);  type_ptr = build_pointer_type (type);  if (AGGREGATE_TYPE_P (type))    {      /* Aggregates are passed on the stack.  */      HOST_WIDE_INT align;      align = TYPE_ALIGN (type);      if (align < BITS_PER_WORD)        align = BITS_PER_WORD;      align /= BITS_PER_UNIT;      u = fold_convert (ptr_type_node, size_int (align - 1));      t = build (PLUS_EXPR, ptr_type_node, mem, u);      u = fold (build (BIT_NOT_EXPR, ptr_type_node, u));      t = build (BIT_AND_EXPR, ptr_type_node, t, u);      addr = get_initialized_tmp_var (t, pre_p, post_p);      u = fold_convert (ptr_type_node, size);      t = build (PLUS_EXPR, ptr_type_node, addr, size);      t = build (MODIFY_EXPR, ptr_type_node, mem, t);      gimplify_and_add (t, pre_p);    }  else    {      isize = tree_low_cst (size, 0);      if (FLOAT_TYPE_P (type) || (INTEGRAL_TYPE_P (type) && isize == 8))	{	  /* Floats and long longs are passed in the fp registers.  */	  reg = fpr;	  n_reg = size_int (isize / UNITS_PER_WORD);	  n_reg = fold_convert (unsigned_type_node, n_reg);	  lim_reg = size_int (NUM_PARM_FREGS - (isize / UNITS_PER_WORD));	  lim_reg = fold_convert (unsigned_type_node, lim_reg);	  sav_ofs = size_int (FREG_OFFSET);	}      else	{	  /* Everything else is passed in general registers.  */	  reg = gpr;	  if ((isize + UNITS_PER_WORD - 1) / UNITS_PER_WORD > 1)	    abort ();	  n_reg = fold_convert (unsigned_type_node, integer_one_node);	  lim_reg = size_int (NUM_PARM_IREGS - 1);	  lim_reg = fold_convert (unsigned_type_node, lim_reg);	  sav_ofs = size_int (IREG_OFFSET);	}      u = build (LE_EXPR, boolean_type_node, reg, lim_reg);      addr = build (COND_EXPR, ptr_type_node, u, NULL, NULL);      /* The value was passed in a register, so read it from the register	 save area initialized by __builtin_saveregs.  */      sav_ofs = fold_convert (ptr_type_node, sav_ofs);      sav_ofs = fold (build (PLUS_EXPR, ptr_type_node, sav, sav_ofs));      u = fold_convert (unsigned_type_node, size_int (UNITS_PER_WORD));      u = build (MULT_EXPR, unsigned_type_node, reg, u);      u = fold_convert (ptr_type_node, u);      u = build (PLUS_EXPR, ptr_type_node, sav_ofs, u);      COND_EXPR_THEN (addr) = u;      /* The value was passed in memory, so read it from the overflow area.  */      t = fold_convert (ptr_type_node, size);      u = build (POSTINCREMENT_EXPR, ptr_type_node, mem, t);      COND_EXPR_ELSE (addr) = u;      /* Increment either the ireg_used or freg_used field.  */      t = build (PLUS_EXPR, unsigned_type_node, reg, n_reg);      t = build (MODIFY_EXPR, unsigned_type_node, reg, t);      gimplify_and_add (t, post_p);    }  addr = fold_convert (type_ptr, addr);  if (indirect)    addr = build_fold_indirect_ref (addr);  return build_fold_indirect_ref (addr);}/* Compute a (partial) cost for rtx X.  Return true if the complete   cost has been computed, and false if subexpressions should be   scanned.  In either case, *TOTAL contains the cost result.  */static booli860_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total){  switch (code)    {    case CONST_INT:      if (INTVAL (x) == 0)        *total = 0;      else if (INTVAL (x) < 0x2000 && INTVAL (x) >= -0x2000)        *total = 1;      return true;    case CONST:    case LABEL_REF:    case SYMBOL_REF:      *total = 4;      return true;    case CONST_DOUBLE:      *total = 6;      return true;    default:      return false;    }}static voidi860_internal_label (FILE *stream, const char *prefix, unsigned long labelno){  fprintf (stream, ".%s%ld:\n", prefix, labelno);}static voidi860_file_start (void){  output_file_directive (asm_out_file, main_input_filename);  fprintf (asm_out_file, "\t.version\t\"01.01\"\n");}static voidi860_init_libfuncs (void){  set_optab_libfunc (sdiv_optab, SImode, "*.div");  set_optab_libfunc (udiv_optab, SImode, "*.udiv");  set_optab_libfunc (smod_optab, SImode, "*.rem");  set_optab_libfunc (umod_optab, SImode, "*.urem");}static rtxi860_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,		       int incoming ATTRIBUTE_UNUSED){  return gen_rtx_REG (Pmode, I860_STRUCT_VALUE_REGNUM);}/* Initialize the GCC target structure.  */#undef TARGET_RTX_COSTS#define TARGET_RTX_COSTS i860_rtx_costs#undef  TARGET_ASM_INTERNAL_LABEL#define TARGET_ASM_INTERNAL_LABEL i8

⌨️ 快捷键说明

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