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

📄 i370.c

📁 linux下的gcc编译器
💻 C
📖 第 1 页 / 共 4 页
字号:
inti370_short_branch (insn)     rtx insn;{  int base_offset;  base_offset = i370_branch_length(insn);  if (0 > base_offset)     {      base_offset += mvs_page_code;    }   else     {      /* avoid bumping into lit pool; use 2x to estimate max possible lits */      base_offset *= 2;      base_offset += mvs_page_code + mvs_page_lit;    }    /* make a conservative estimate of room left on page */  if ((4060 >base_offset) && ( 0 < base_offset)) return 1;  return 0;}/* The i370_label_scan() routine is supposed to loop over   all labels and label references in a compilation unit,   and determine whether all label refs appear on the same    code page as the label. If they do, then we can avoid    a reload of the base register for that label.     Note that the instruction addresses used here are only    approximate, and make the sizes of the jumps appear   farther apart then they will actually be.  This makes    this code far more conservative than it needs to be. */#define I370_RECORD_LABEL_REF(label,addr) {				\	label_node_t *lp;						\	int labelno = CODE_LABEL_NUMBER (label);			\	lp = mvs_get_label (labelno);					\	if (addr < lp -> label_first_ref) lp->label_first_ref = addr;	\	if (addr > lp -> label_last_ref) lp->label_last_ref = addr;	\}static void i370_label_scan () {   rtx insn;   label_node_t *lp;   int tablejump_offset = 0;   for (insn = get_insns(); insn; insn = NEXT_INSN(insn))     {       int here = INSN_ADDRESSES (INSN_UID (insn));       enum rtx_code code = GET_CODE(insn);       /* ??? adjust for tables embedded in the .text section that        * the compiler didn't take into account */       here += tablejump_offset;       INSN_ADDRESSES (INSN_UID (insn)) = here;       /* check to see if this insn is a label ...  */       if (CODE_LABEL == code)         {           int labelno = CODE_LABEL_NUMBER (insn);           lp = mvs_get_label (labelno);           lp -> label_addr = here;#if 0           /* Supposedly, labels are supposed to have circular              lists of label-refs that reference them,               setup in flow.c, but this does not appear to be the case.  */           rtx labelref = LABEL_REFS (insn);           rtx ref = labelref;           do              {               rtx linsn = CONTAINING_INSN(ref);               ref =  LABEL_NEXTREF(ref);             } while (ref && (ref != labelref));#endif         }       else       if (JUMP_INSN == code)         {           rtx label = JUMP_LABEL (insn);           /* If there is no label for this jump, then this              had better be a ADDR_VEC or an ADDR_DIFF_VEC              and there had better be a vector of labels.  */           if (!label)              {               int j;               rtx body = PATTERN (insn);               if (ADDR_VEC == GET_CODE(body))                  {                    for (j=0; j < XVECLEN (body, 0); j++)                      {                         rtx lref = XVECEXP (body, 0, j);                         if (LABEL_REF != GET_CODE (lref)) abort ();                         label = XEXP (lref,0);                         if (CODE_LABEL != GET_CODE (label)) abort ();                         tablejump_offset += 4;                         here += 4;                         I370_RECORD_LABEL_REF(label,here);                      }                    /* finished with the vector go do next insn */                    continue;                 }               else               if (ADDR_DIFF_VEC == GET_CODE(body))                 {/* XXX hack alert.   Right now, we leave this as a no-op, but strictly speaking,   this is incorrect.  It is possible that a table-jump   driven off of a relative address could take us off-page,   to a place where we need to reload the base reg.  So really,   we need to examing both labels, and compare thier values   to the current basereg value.     More generally, this brings up a troubling issue overall:   what happens if a tablejump is split across two pages? I do    not beleive that this case is handled correctly at all, and   can only lead to horrible results if this were to occur.     However, the current situation is not any worse than it was    last week, and so we punt for now.  */                    debug_rtx (insn);                    for (j=0; j < XVECLEN (body, 0); j++)                      {                      }                    /* finished with the vector go do next insn */                    continue;                 }               else                  {/* XXX hack alert.   Compiling the exception handling (L_eh) in libgcc2.a will trip   up right here, with something that looks like   (set (pc) (mem:SI (plus:SI (reg/v:SI 1 r1) (const_int 4))))      {indirect_jump}    I'm not sure of what leads up to this, but it looks like   the makings of a long jump which will surely get us into trouble   because the base & page registers don't get reloaded.  For now   I'm not sure of what to do ... again we punt ... we are not worse   off than yesterday.  */                    /* print_rtl_single (stdout, insn); */                    debug_rtx (insn);                    /* abort(); */                    continue;                 }            }          else            {              /* At this point, this jump_insn had better be a plain-old                 ordinary one, grap the label id and go */              if (CODE_LABEL != GET_CODE (label)) abort ();              I370_RECORD_LABEL_REF(label,here);            }        }      /* Sometimes, we take addresses of labels and use them         as instruction operands ... these show up as REG_NOTES */      else      if (INSN == code)       {         if ('i' == GET_RTX_CLASS (code))            {              rtx note;              for (note = REG_NOTES (insn); note;  note = XEXP(note,1))                {                   if (REG_LABEL == REG_NOTE_KIND(note))                     {                        rtx label = XEXP (note,0);                        if (!label || CODE_LABEL != GET_CODE (label)) abort ();                        I370_RECORD_LABEL_REF(label,here);                     }                }           }       }   }}/* ===================================================== *//* Emit reload of base register if indicated.  This is to eliminate multiple   reloads when several labels are generated pointing to the same place   in the code.     The page table is written at the end of the function.    The entries in the page table look like     .LPGT0:          // PGT0 EQU *     .long .LPG0      // DC A(PG0)     .long .LPG1      // DC A(PG1)  while the prologue generates      L       r4,=A(.LPGT0)  Note that this paging scheme breaks down if a single subroutine   has more than about 10MB of code in it ... as long as humans write  code, this shouldn't be a problem ... */voidcheck_label_emit (){  if (mvs_need_base_reload)    {      mvs_need_base_reload = 0;      mvs_page_code += 4;      fprintf (assembler_source, "\tL\t%d,%d(,%d)\n",	  BASE_REGISTER, (mvs_page_num - function_base_page) * 4,	  PAGE_REGISTER);    }}/* Add the label to the current page label list.  If a free element is available   it will be used for the new label.  Otherwise, a label element will be   allocated from memory.   ID is the label number of the label being added to the list.  */static label_node_t *mvs_get_label (id)     int id;{  label_node_t *lp;  /* first, lets see if we already go one, if so, use that.  */  for (lp = label_anchor; lp; lp = lp->label_next)    {      if (lp->label_id == id) return lp;    }  /* not found, get a new one */  if (free_anchor)    {      lp = free_anchor;      free_anchor = lp->label_next;    }  else    {      lp = (label_node_t *) xmalloc (sizeof (label_node_t));    }  /* initialize for new label */  lp->label_id = id;  lp->label_page = -1;  lp->label_next = label_anchor;  lp->label_first_ref = 2000123123;  lp->label_last_ref = -1;  lp->label_addr = -1;  lp->first_ref_page = -1;  label_anchor = lp;  return lp;}voidmvs_add_label (id)     int id;{  label_node_t *lp;  int fwd_distance;  lp = mvs_get_label (id);  lp->label_page = mvs_page_num;  /* OK, we just saw the label.  Determine if this label   * needs a reload of the base register */  if ((-1 != lp->first_ref_page) &&       (lp->first_ref_page != mvs_page_num))     {      /* Yep; the first label_ref was on a different page.  */      mvs_need_base_reload ++;      return;    }  /* Hmm.  Try to see if the estimated address of the last     label_ref is on the current page.  If it is, then we     don't need a base reg reload.  Note that this estimate     is very conservatively handled; we'll tend to have      a good bit more reloads than actually needed.  Someday,     we should tighten the estimates (which are driven by     the (set_att "length") insn attibute.         Currently, we estimate that number of page literals      same as number of insns, which is a vast overestimate,     esp that the estimate of each insn size is its max size.  */  /* if latest ref comes before label, we are clear */  if (lp->label_last_ref < lp->label_addr) return;  fwd_distance = lp->label_last_ref - lp->label_addr;  if (mvs_page_code + 2 * fwd_distance + mvs_page_lit < 4060) return;  mvs_need_base_reload ++;}/* Check to see if the label is in the list and in the current   page.  If not found, we have to make worst case assumption    that label will be on a different page, and thus will have to   generate a load and branch on register.  This is rather   ugly for forward-jumps, but what can we do? For backward   jumps on the same page we can branch directly to address.   ID is the label number of the label being checked.  */intmvs_check_label (id)     int id;{  label_node_t *lp;  for (lp = label_anchor; lp; lp = lp->label_next)    {      if (lp->label_id == id)         {          if (lp->label_page == mvs_page_num)             {               return 1;            }           else             {	       return 0;            }         }    }  return 0;}/* Get the page on which the label sits.  This will be used to    determine is a register reload is really needed.  */#if 0intmvs_get_label_page(int id){  label_node_t *lp;  for (lp = label_anchor; lp; lp = lp->label_next)    {      if (lp->label_id == id)	return lp->label_page;    }  return -1;}#endif/* The label list for the current page freed by linking the list onto the free   label element chain.  */voidmvs_free_label_list (){  if (label_anchor)    {      label_node_t *last_lp = label_anchor;      while (last_lp->label_next) last_lp = last_lp->label_next;      last_lp->label_next = free_anchor;      free_anchor = label_anchor;    }  label_anchor = 0;}/* ====================================================================== *//* If the page size limit is reached a new code page is started, and the base   register is set to it.  This page break point is counted conservatively,   most literals that have the same value are collapsed by the assembler.   True is returned when a new page is started.   FILE is the assembler output file descriptor.   CODE is the length, in bytes, of the instruction to be emitted.   LIT is the length of the literal to be emitted.  */#ifdef TARGET_HLASMintmvs_check_page (file, code, lit)     FILE *file;     int code, lit;{  if (file)    assembler_source = file;  if (mvs_page_code + code + mvs_page_lit + lit > MAX_MVS_PAGE_LENGTH)    {      fprintf (assembler_source, "\tB\tPGE%d\n", mvs_page_num);      fprintf (assembler_source, "\tDS\t0F\n");      fprintf (assembler_source, "\tLTORG\n");      fprintf (assembler_source, "\tDS\t0F\n");      fprintf (assembler_source, "PGE%d\tEQU\t*\n", mvs_page_num);      fprintf (assembler_source, "\tDROP\t%d\n", BASE_REGISTER);      mvs_page_num++;      /* Safe to use BASR not BALR, since we are       * not switching addressing mode here ...  */      fprintf (assembler_source, "\tBASR\t%d,0\n", BASE_REGISTER);      fprintf (assembler_source, "PG%d\tEQU\t*\n", mvs_page_num);      fprintf (assembler_source, "\tUSING\t*,%d\n", BASE_REGISTER);

⌨️ 快捷键说明

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