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

📄 rs6000.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
      if (frame_pointer_needed || current_function_calls_alloca	  || total_size > 32767)	fprintf (file, "\tl 1,0(1)\n");      else if (must_push)	fprintf (file, "\tai 1,1,%d\n", total_size);      /* Get the old lr if we saved it.  */      if (regs_ever_live[65])	fprintf (file, "\tl 0,8(1)\n");      /* Get the old cr if we saved it.  */      if (must_save_cr ())	fprintf (file, "\tl 12,4(1)\n");      /* Set LR here to try to overlap restores below.  */      if (regs_ever_live[65])	fprintf (file, "\tmtlr 0\n");      /* Restore gpr's.  */      if (first_reg == 31)	fprintf (file, "\tl 31,%d(1)\n", -4 - (64 - first_fp_reg) * 8);      else if (first_reg != 32)	fprintf (file, "\tlm %d,%d(1)\n", first_reg,		 - (32 - first_reg) * 4 - (64 - first_fp_reg) * 8);      /* Restore fpr's if we can do it without calling a function.  */      if (first_fp_reg == 62)	fprintf (file, "\tlfd 30,-16(1)\n\tlfd 31,-8(1)\n");      else if (first_fp_reg == 63)	fprintf (file, "\tlfd 31,-8(1)\n");      /* If we saved cr, restore it here.  Just set cr2, cr3, and cr4.  */      if (must_save_cr ())	fprintf (file, "\tmtcrf 0x38,12\n");      /* If we have to restore more than two FP registers, branch to the	 restore function.  It will return to our caller.  */      if (first_fp_reg < 62)	fprintf (file, "\tb ._restf%d\n\tcror 15,15,15\n", first_fp_reg - 32);      else	fprintf (file, "\tbr\n");    }  /* Output a traceback table here.  See /usr/include/sys/debug.h for info     on its format.  */  {    char *fname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);    int fixed_parms, float_parms, parm_info;    int i;    /* Need label immediately before tbtab, so we can compute its offset       from the function start.  */    if (*fname == '*')      ++fname;    fprintf (file, "LT..");    ASM_OUTPUT_LABEL (file, fname);    /* The .tbtab pseudo-op can only be used for the first eight       expressions, since it can't handle the possibly variable length       fields that follow.  However, if you omit the optional fields,       the assembler outputs zeros for all optional fields anyways, giving each       variable length field is minimum length (as defined in sys/debug.h).       Thus we can not use the .tbtab pseudo-op at all.  */    /* An all-zero word flags the start of the tbtab, for debuggers that have       to find it by searching forward from the entry point or from the       current pc.  */    fprintf (file, "\t.long 0\n");    /* Tbtab format type.  Use format type 0.  */    fprintf (file, "\t.byte 0,");    /* Language type.  Unfortunately, there doesn't seem to be any official way       to get this info, so we use language_string.  C is 0.  C++ is 9.       No number defined for Obj-C, but it doesn't have its own       language_string, so we can't detect it anyways.  */    if (! strcmp (language_string, "GNU C"))      i = 0;    else if (! strcmp (language_string, "GNU F77"))      i = 1;    else if (! strcmp (language_string, "GNU Ada"))      i = 3;    else if (! strcmp (language_string, "GNU PASCAL"))      i = 2;    else if (! strcmp (language_string, "GNU C++"))      i = 9;    else      abort ();    fprintf (file, "%d,", i);    /* 8 single bit fields: global linkage (not set for C extern linkage,       apparently a PL/I convention?), out-of-line epilogue/prologue, offset       from start of procedure stored in tbtab, internal function, function       has controlled storage, function has no toc, function uses fp,       function logs/aborts fp operations.  */    /* Assume that fp operations are used if any fp reg must be saved.  */    fprintf (file, "%d,", (1 << 5) | ((first_fp_reg != 64) << 1));    /* 6 bitfields: function is interrupt handler, name present in proc table,       function calls alloca, on condition directives (controls stack walks,       3 bits), saves condition reg, saves link reg.  */    /* The `function calls alloca' bit seems to be set whenever reg 31 is       set up as a frame pointer, even when there is no alloca call.  */    fprintf (file, "%d,",	     ((1 << 6) | (frame_pointer_needed << 5)	      | (must_save_cr () << 1) | (regs_ever_live[65])));    /* 3 bitfields: saves backchain, spare bit, number of fpr saved       (6 bits).  */    fprintf (file, "%d,",	     (must_push << 7) | (64 - first_fp_reg_to_save ()));    /* 2 bitfields: spare bits (2 bits), number of gpr saved (6 bits).  */    fprintf (file, "%d,", (32 - first_reg_to_save ()));    {      /* Compute the parameter info from the function decl argument list.  */      tree decl;      int next_parm_info_bit;      next_parm_info_bit = 31;      parm_info = 0;      fixed_parms = 0;      float_parms = 0;      for (decl = DECL_ARGUMENTS (current_function_decl);	   decl; decl = TREE_CHAIN (decl))	{	  rtx parameter = DECL_INCOMING_RTL (decl);	  enum machine_mode mode = GET_MODE (parameter);	  if (GET_CODE (parameter) == REG)	    {	      if (GET_MODE_CLASS (mode) == MODE_FLOAT)		{		  int bits;		  float_parms++;		  if (mode == SFmode)		    bits = 0x2;		  else if (mode == DFmode)		    bits = 0x3;		  else		    abort ();		  /* If only one bit will fit, don't or in this entry.  */		  if (next_parm_info_bit > 0)		    parm_info |= (bits << (next_parm_info_bit - 1));		  next_parm_info_bit -= 2;		}	      else		{		  fixed_parms += ((GET_MODE_SIZE (mode) + (UNITS_PER_WORD - 1))				  / UNITS_PER_WORD);		  next_parm_info_bit -= 1;		}	    }	}    }    /* Number of fixed point parameters.  */    /* This is actually the number of words of fixed point parameters; thus       an 8 byte struct counts as 2; and thus the maximum value is 8.  */    fprintf (file, "%d,", fixed_parms);    /* 2 bitfields: number of floating point parameters (7 bits), parameters       all on stack.  */    /* This is actually the number of fp registers that hold parameters;       and thus the maximum value is 13.  */    /* Set parameters on stack bit if parameters are not in their original       registers, regardless of whether they are on the stack?  Xlc       seems to set the bit when not optimizing.  */    fprintf (file, "%d\n", ((float_parms << 1) | (! optimize)));    /* Optional fields follow.  Some are variable length.  */    /* Parameter types, left adjusted bit fields: 0 fixed, 10 single float,       11 double float.  */    /* There is an entry for each parameter in a register, in the order that       they occur in the parameter list.  Any intervening arguments on the       stack are ignored.  If the list overflows a long (max possible length       34 bits) then completely leave off all elements that don't fit.  */    /* Only emit this long if there was at least one parameter.  */    if (fixed_parms || float_parms)      fprintf (file, "\t.long %d\n", parm_info);    /* Offset from start of code to tb table.  */    fprintf (file, "\t.long LT..");    RS6000_OUTPUT_BASENAME (file, fname);    fprintf (file, "-.");    RS6000_OUTPUT_BASENAME (file, fname);    fprintf (file, "\n");    /* Interrupt handler mask.  */    /* Omit this long, since we never set the interrupt handler bit above.  */    /* Number of CTL (controlled storage) anchors.  */    /* Omit this long, since the has_ctl bit is never set above.  */    /* Displacement into stack of each CTL anchor.  */    /* Omit this list of longs, because there are no CTL anchors.  */    /* Length of function name.  */    fprintf (file, "\t.short %d\n", strlen (fname));    /* Function name.  */    assemble_string (fname, strlen (fname));    /* Register for alloca automatic storage; this is always reg 31.       Only emit this if the alloca bit was set above.  */    if (frame_pointer_needed)      fprintf (file, "\t.byte 31\n");  }}/* Output a TOC entry.  We derive the entry name from what is   being written.  */voidoutput_toc (file, x, labelno)     FILE *file;     rtx x;     int labelno;{  char buf[256];  char *name = buf;  rtx base = x;  int offset = 0;  ASM_OUTPUT_INTERNAL_LABEL (file, "LC", labelno);  /* Handle FP constants specially.  */  if (GET_CODE (x) == CONST_DOUBLE      && GET_MODE (x) == DFmode      && TARGET_FLOAT_FORMAT == HOST_FLOAT_FORMAT      && BITS_PER_WORD == HOST_BITS_PER_INT      && TARGET_FP_IN_TOC)    {      fprintf (file, "\t.tc FD_%x_%x[TC],%d,%d\n",	       CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x),	       CONST_DOUBLE_LOW (x), CONST_DOUBLE_HIGH (x));      return;    }  else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode	   && TARGET_FP_IN_TOC)    {      rtx val = operand_subword (x, 0, 0, SFmode);      if (val == 0 || GET_CODE (val) != CONST_INT)	abort ();      fprintf (file, "\t.tc FS_%x[TC],%d\n", INTVAL (val), INTVAL (val));      return;    }  if (GET_CODE (x) == CONST)    {      base = XEXP (XEXP (x, 0), 0);      offset = INTVAL (XEXP (XEXP (x, 0), 1));    }    if (GET_CODE (base) == SYMBOL_REF)    name = XSTR (base, 0);  else if (GET_CODE (base) == LABEL_REF)    ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (base, 0)));  else if (GET_CODE (base) == CODE_LABEL)    ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (base));  else    abort ();  fprintf (file, "\t.tc ");  RS6000_OUTPUT_BASENAME (file, name);  if (offset < 0)    fprintf (file, ".N%d", - offset);  else if (offset)    fprintf (file, ".P%d", offset);  fprintf (file, "[TC],");  output_addr_const (file, x);  fprintf (file, "\n");}/* Output an assembler pseudo-op to write an ASCII string of N characters   starting at P to FILE.   On the RS/6000, we have to do this using the .byte operation and   write out special characters outside the quoted string.   Also, the assembler is broken; very long strings are truncated,   so we must artificially break them up early. */voidoutput_ascii (file, p, n)     FILE *file;     char *p;     int n;{  char c;  int i, count_string;  char *for_string = "\t.byte \"";  char *for_decimal = "\t.byte ";  char *to_close = NULL;  count_string = 0;  for (i = 0; i < n; i++)    {      c = *p++;      if (c >= ' ' && c < 0177)	{	  if (for_string)	    fputs (for_string, file);	  putc (c, file);	  /* Write two quotes to get one.  */	  if (c == '"')	    {	      putc (c, file);	      ++count_string;	    }	  for_string = NULL;	  for_decimal = "\"\n\t.byte ";	  to_close = "\"\n";	  ++count_string;	  if (count_string >= 512)	    {	      fputs (to_close, file);	      for_string = "\t.byte \"";	      for_decimal = "\t.byte ";	      to_close = NULL;	      count_string = 0;	    }	}      else	{	  if (for_decimal)	    fputs (for_decimal, file);	  fprintf (file, "%d", c);	  for_string = "\n\t.byte \"";	  for_decimal = ", ";	  to_close = "\n";	  count_string = 0;	}    }  /* Now close the string if we have written one.  Then end the line.  */  if (to_close)    fprintf (file, to_close);}/* Generate a unique section name for FILENAME for a section type   represented by SECTION_DESC.  Output goes into BUF.   SECTION_DESC can be any string, as long as it is different for each   possible section type.   We name the section in the same manner as xlc.  The name begins with an   underscore followed by the filename (after stripping any leading directory   names) with the period replaced by the string SECTION_DESC.  If FILENAME   does not contain a period, SECTION_DESC is appended at the end of the   name.  */voidrs6000_gen_section_name (buf, filename, section_desc)     char **buf;     char *filename;     char *section_desc;{  char *q, *after_last_slash;  char *p;  int len;  int used_desc = 0;  after_last_slash = filename;  for (q = filename; *q; q++)    if (*q == '/')      after_last_slash = q + 1;  len = strlen (filename) + strlen (section_desc) + 2;  *buf = (char *) permalloc (len);  p = *buf;  *p++ = '_';  for (q = after_last_slash; *q; q++)    {      if (*q == '.')        {	  strcpy (p, section_desc);	  p += strlen (section_desc);	  used_desc = 1;        }      else if (isalnum (*q))        *p++ = *q;    }  if (! used_desc)    strcpy (p, section_desc);  else    *p = '\0';}/* Write function profiler code. */voidoutput_function_profiler (file, labelno)  FILE *file;  int labelno;{  /* The last used parameter register.  */  int last_parm_reg;  int i, j;  /* Set up a TOC entry for the profiler label.  */  toc_section ();  fprintf (file, "LPC..%d:\n\t.tc\tLP..%d[TC],LP..%d\n",	   labelno, labelno, labelno);  text_section ();  /* Figure out last used parameter register.  The proper thing to do is     to walk incoming args of the function.  A function might have live     parameter registers even if it has no incoming args.  */  for (last_parm_reg = 10;       last_parm_reg > 2 && ! regs_ever_live [last_parm_reg];       last_parm_reg--)    ;  /* Save parameter registers in regs 23-30.  Don't overwrite reg 31, since     it might be set up as the frame pointer.  */  for (i = 3, j = 30; i <= last_parm_reg; i++, j--)    fprintf (file, "\tai %d,%d,0\n", j, i);  /* Load location address into r3, and call mcount.  */  fprintf (file, "\tl 3,LPC..%d(2)\n\tbl .mcount\n", labelno);  /* Restore parameter registers.  */  for (i = 3, j = 30; i <= last_parm_reg; i++, j--)    fprintf (file, "\tai %d,%d,0\n", i, j);}

⌨️ 快捷键说明

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