Annotation of researchv10dc/cmd/gcc/genrecog.c, revision 1.1

1.1     ! root        1: /* Generate code from machine description to emit insns as rtl.
        !             2:    Copyright (C) 1987,1988 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GNU CC.
        !             5: 
        !             6: GNU CC is distributed in the hope that it will be useful,
        !             7: but WITHOUT ANY WARRANTY.  No author or distributor
        !             8: accepts responsibility to anyone for the consequences of using it
        !             9: or for whether it serves any particular purpose or works at all,
        !            10: unless he says so in writing.  Refer to the GNU CC General Public
        !            11: License for full details.
        !            12: 
        !            13: Everyone is granted permission to copy, modify and redistribute
        !            14: GNU CC, but only under the conditions described in the
        !            15: GNU CC General Public License.   A copy of this license is
        !            16: supposed to have been given to you along with GNU CC so you
        !            17: can know your rights and responsibilities.  It should be in a
        !            18: file named COPYING.  Among other things, the copyright notice
        !            19: and this notice must be preserved on all copies.  */
        !            20: 
        !            21: 
        !            22: /* This program is used to produce insn-recog.c, which contains
        !            23:    a function called `recog' plus its subroutines.
        !            24:    These functions contain a decision tree
        !            25:    that recognizes whether an rtx, the argument given to recog,
        !            26:    is a valid instruction.
        !            27: 
        !            28:    recog returns -1 if the rtx is not valid.
        !            29:    If the rtx is valid, recog returns a nonnegative number
        !            30:    which is the insn code number for the pattern that matched.
        !            31:    This is the same as the order in the machine description of the
        !            32:    entry that matched.  This number can be used as an index into
        !            33:    insn_templates and insn_n_operands (found in insn-output.c)
        !            34:    or as an argument to output_insn_hairy (also in insn-output.c).  */
        !            35: 
        !            36: #include <stdio.h>
        !            37: #include "config.h"
        !            38: #include "rtl.h"
        !            39: #include "obstack.h"
        !            40: 
        !            41: struct obstack obstack;
        !            42: struct obstack *rtl_obstack = &obstack;
        !            43: 
        !            44: #define obstack_chunk_alloc xmalloc
        !            45: #define obstack_chunk_free free
        !            46: extern int xmalloc ();
        !            47: extern void free ();
        !            48: 
        !            49: /* Data structure for decision tree for recognizing
        !            50:    legitimate instructions.  */
        !            51: 
        !            52: struct decision
        !            53: {
        !            54:   int number;
        !            55:   char *position;
        !            56:   RTX_CODE code;
        !            57:   char *exact;
        !            58:   enum machine_mode mode;
        !            59:   char *tests;
        !            60:   int insn_code_number;
        !            61:   struct decision *next;
        !            62:   struct decision *success;
        !            63:   int opno;
        !            64:   int dupno;
        !            65:   int dupcount;
        !            66:   int test_elt_zero_int;
        !            67:   int elt_zero_int;
        !            68:   int test_elt_one_int;
        !            69:   int elt_one_int;
        !            70:   int ignmode;
        !            71:   struct decision *afterward;
        !            72:   int label_needed;
        !            73:   char *c_test;
        !            74:   char *reg_class;
        !            75:   char enforce_mode;
        !            76:   int veclen;
        !            77:   int subroutine_number;
        !            78: };
        !            79: 
        !            80: #define SUBROUTINE_THRESHOLD 50
        !            81: 
        !            82: int next_subroutine_number;
        !            83: 
        !            84: /*
        !            85: recognize (top)
        !            86: {
        !            87:  staten:
        !            88:   x = XVECEXP (top, 0, 3);
        !            89:   if (test_code (GET_CODE (x))
        !            90:       && test_mode (MODE (x))
        !            91:       && whatever_else)
        !            92:     goto statep;
        !            93:   else if (next one...)
        !            94:     goto statem:
        !            95:   goto stater;
        !            96: 
        !            97:  statep:
        !            98:   actions...;
        !            99:   return 1;
        !           100: 
        !           101:  statem:
        !           102:   x = stack[depth--];
        !           103:   more tests...;
        !           104: 
        !           105:  stateq:
        !           106:   stack[++depth] = x;
        !           107:   x = XEXP (stack[depth], 0);
        !           108:   more tests...;
        !           109: 
        !           110:  stater:
        !           111:   x = XEXP (stack[depth], 1);
        !           112: }
        !           113: 
        !           114: */
        !           115: 
        !           116: int next_number;
        !           117: 
        !           118: int next_insn_code;
        !           119: 
        !           120: /* Number of MATCH_DUP's seen so far in this instruction.  */
        !           121: int dupcount;
        !           122: 
        !           123: struct decision *add_to_sequence ();
        !           124: struct decision *try_merge_2 ();
        !           125: void write_subroutine ();
        !           126: void print_code ();
        !           127: void clear_codes ();
        !           128: void clear_modes ();
        !           129: void change_state ();
        !           130: void write_tree ();
        !           131: char *copystr ();
        !           132: char *concat ();
        !           133: void fatal ();
        !           134: void mybzero ();
        !           135: 
        !           136: struct decision *first;
        !           137: 
        !           138: /* Construct and return a sequence of decisions
        !           139:    that will recognize INSN.  */
        !           140: 
        !           141: struct decision *
        !           142: make_insn_sequence (insn)
        !           143:      rtx insn;
        !           144: {
        !           145:   rtx x;
        !           146:   char *c_test = XSTR (insn, 2);
        !           147:   struct decision *last;
        !           148: 
        !           149:   dupcount = 0;
        !           150: 
        !           151:   if (XVECLEN (insn, 1) == 1)
        !           152:     x = XVECEXP (insn, 1, 0);
        !           153:   else
        !           154:     {
        !           155:       x = rtx_alloc (PARALLEL);
        !           156:       XVEC (x, 0) = XVEC (insn, 1);
        !           157:       PUT_MODE (x, VOIDmode);
        !           158:     }
        !           159: 
        !           160:   last = add_to_sequence (x, 0, "");
        !           161: 
        !           162:   if (c_test[0])
        !           163:     last->c_test = c_test;
        !           164:   last->insn_code_number = next_insn_code++;
        !           165: 
        !           166:   return first;
        !           167: }
        !           168: 
        !           169: struct decision *
        !           170: add_to_sequence (pattern, last, position)
        !           171:      rtx pattern;
        !           172:      struct decision *last;
        !           173:      char *position;
        !           174: {
        !           175:   register RTX_CODE code;
        !           176:   register struct decision *new
        !           177:     = (struct decision *) xmalloc (sizeof (struct decision));
        !           178:   struct decision *this;
        !           179:   char *newpos;
        !           180:   register char *fmt;
        !           181:   register int i;
        !           182:   int depth;
        !           183:   int len;
        !           184: 
        !           185:   new->number = next_number++;
        !           186:   new->position = copystr (position);
        !           187:   new->exact = 0;
        !           188:   new->next = 0;
        !           189:   new->success = 0;
        !           190:   new->insn_code_number = -1;
        !           191:   new->tests = 0;
        !           192:   new->opno = -1;
        !           193:   new->dupno = -1;
        !           194:   new->dupcount = -1;
        !           195:   new->test_elt_zero_int = 0;
        !           196:   new->test_elt_one_int = 0;
        !           197:   new->elt_zero_int = 0;
        !           198:   new->elt_one_int = 0;
        !           199:   new->enforce_mode = 0;
        !           200:   new->ignmode = 0;
        !           201:   new->afterward = 0;
        !           202:   new->label_needed = 0;
        !           203:   new->c_test = 0;
        !           204:   new->reg_class = 0;
        !           205:   new->veclen = 0;
        !           206:   new->subroutine_number = 0;
        !           207: 
        !           208:   this = new;
        !           209: 
        !           210:   if (last == 0)
        !           211:     first = new;
        !           212:   else
        !           213:     last->success = new;
        !           214: 
        !           215:   depth = strlen (position);
        !           216:   newpos = (char *) alloca (depth + 2);
        !           217:   strcpy (newpos, position);
        !           218:   newpos[depth + 1] = 0;
        !           219: 
        !           220:  restart:
        !           221: 
        !           222:   if (pattern == 0)
        !           223:     {
        !           224:       new->exact = "0";
        !           225:       new->code = UNKNOWN;
        !           226:       new->mode = VOIDmode;
        !           227:       return new;
        !           228:     }
        !           229: 
        !           230:   switch (GET_MODE (pattern))
        !           231:     {
        !           232:     case 0:
        !           233:       new->mode = VOIDmode;
        !           234:       break;
        !           235: 
        !           236:     default:
        !           237:       new->mode = GET_MODE (pattern);
        !           238:       break;
        !           239:     }
        !           240: 
        !           241:   new->code = code = GET_CODE (pattern);;
        !           242: 
        !           243:   switch (code)
        !           244:     {
        !           245:     case MATCH_OPERAND:
        !           246:       new->opno = XINT (pattern, 0);
        !           247:       new->code = UNKNOWN;
        !           248:       new->tests = XSTR (pattern, 1);
        !           249:       if (*new->tests == 0)
        !           250:        new->tests = 0;
        !           251:       new->reg_class = XSTR (pattern, 2);
        !           252:       if (*new->reg_class == 0)
        !           253:        new->reg_class = 0;
        !           254:       return new;
        !           255: 
        !           256:     case MATCH_DUP:
        !           257:       new->dupno = XINT (pattern, 0);
        !           258:       new->dupcount = dupcount++;
        !           259:       new->code = UNKNOWN;
        !           260:       return new;
        !           261: 
        !           262:     case ADDRESS:
        !           263:       pattern = XEXP (pattern, 0);
        !           264:       goto restart;
        !           265: 
        !           266:     case PC:
        !           267:       new->exact = "pc_rtx";
        !           268:       return new;
        !           269: 
        !           270:     case CC0:
        !           271:       new->exact = "cc0_rtx";
        !           272:       return new;
        !           273: 
        !           274:     case CONST_INT:
        !           275:       if (INTVAL (pattern) == 0)
        !           276:        {
        !           277:          new->exact = "const0_rtx";
        !           278:          return new;
        !           279:        }
        !           280:       if (INTVAL (pattern) == 1)
        !           281:        {
        !           282:          new->exact = "const1_rtx";
        !           283:          return new;
        !           284:        }
        !           285:       break;
        !           286: 
        !           287:     case SET:
        !           288:       newpos[depth] = '0';
        !           289:       new = add_to_sequence (SET_DEST (pattern), new, newpos);
        !           290:       this->success->enforce_mode = 1;
        !           291:       newpos[depth] = '1';
        !           292:       new = add_to_sequence (SET_SRC (pattern), new, newpos);
        !           293:       return new;
        !           294: 
        !           295:     case STRICT_LOW_PART:
        !           296:       newpos[depth] = '0';
        !           297:       new = add_to_sequence (XEXP (pattern, 0), new, newpos);
        !           298:       this->success->enforce_mode = 1;
        !           299:       return new;
        !           300: 
        !           301:     case SUBREG:
        !           302:       this->test_elt_one_int = 1;
        !           303:       this->elt_one_int = XINT (pattern, 1);
        !           304:       newpos[depth] = '0';
        !           305:       new = add_to_sequence (XEXP (pattern, 0), new, newpos);
        !           306:       this->success->enforce_mode = 1;
        !           307:       return new;
        !           308: 
        !           309:     case ZERO_EXTRACT:
        !           310:     case SIGN_EXTRACT:
        !           311:       newpos[depth] = '0';
        !           312:       new = add_to_sequence (XEXP (pattern, 0), new, newpos);
        !           313:       this->success->enforce_mode = 1;
        !           314:       newpos[depth] = '1';
        !           315:       new = add_to_sequence (XEXP (pattern, 1), new, newpos);
        !           316:       newpos[depth] = '2';
        !           317:       new = add_to_sequence (XEXP (pattern, 2), new, newpos);
        !           318:       return new;
        !           319:     }
        !           320: 
        !           321:   fmt = GET_RTX_FORMAT (code);
        !           322:   len = GET_RTX_LENGTH (code);
        !           323:   for (i = 0; i < len; i++)
        !           324:     {
        !           325:       newpos[depth] = '0' + i;
        !           326:       if (fmt[i] == 'e' || fmt[i] == 'u')
        !           327:        new = add_to_sequence (XEXP (pattern, i), new, newpos);
        !           328:       else if (fmt[i] == 'i' && i == 0)
        !           329:        {
        !           330:          this->test_elt_zero_int = 1;
        !           331:          this->elt_zero_int = XINT (pattern, i);
        !           332:        }
        !           333:       else if (fmt[i] == 'i' && i == 1)
        !           334:        {
        !           335:          this->test_elt_one_int = 1;
        !           336:          this->elt_one_int = XINT (pattern, i);
        !           337:        }
        !           338:       else if (fmt[i] == 'E')
        !           339:        {
        !           340:          register int j;
        !           341:          /* We do not handle a vector appearing as other than
        !           342:             the first item, just because nothing uses them
        !           343:             and by handling only the special case
        !           344:             we can use one element in newpos for either
        !           345:             the item number of a subexpression
        !           346:             or the element number in a vector.  */
        !           347:          if (i != 0)
        !           348:            abort ();
        !           349:          this->veclen = XVECLEN (pattern, i);
        !           350:          for (j = 0; j < XVECLEN (pattern, i); j++)
        !           351:            {
        !           352:              newpos[depth] = 'a' + j;
        !           353:              new = add_to_sequence (XVECEXP (pattern, i, j),
        !           354:                                     new, newpos);
        !           355:            }
        !           356:        }
        !           357:       else if (fmt[i] != '0')
        !           358:        abort ();
        !           359:     }
        !           360:   return new;
        !           361: }
        !           362: 
        !           363: /* Merge two decision trees OLD and ADD,
        !           364:    modifying OLD destructively,
        !           365:    and return the merged tree.  */
        !           366: 
        !           367: struct decision *
        !           368: merge_trees (old, add)
        !           369:      register struct decision *old, *add;
        !           370: {
        !           371:   while (add)
        !           372:     {
        !           373:       register struct decision *next = add->next;
        !           374:       add->next = 0;
        !           375:       if (!try_merge_1 (old, add))
        !           376:        old = try_merge_2 (old, add);
        !           377:       add = next;
        !           378:     }
        !           379:   return old;
        !           380: }
        !           381: 
        !           382: /* Merge ADD into the next-chain starting with OLD
        !           383:    only if it overlaps a condition already tested in OLD.
        !           384:    Returns 1 if successful (OLD is modified),
        !           385:    0 if nothing has been done.  */
        !           386: 
        !           387: int
        !           388: try_merge_1 (old, add)
        !           389:      register struct decision *old, *add;
        !           390: {
        !           391:   while (old)
        !           392:     {
        !           393:       if ((old->position == add->position
        !           394:           || (old->position && add->position
        !           395:               && !strcmp (old->position, add->position)))
        !           396:          && (old->tests == add->tests
        !           397:              || (old->tests && add->tests && !strcmp (old->tests, add->tests)))
        !           398:          && (old->c_test == add->c_test
        !           399:              || (old->c_test && add->c_test && !strcmp (old->c_test, add->c_test)))
        !           400:          && old->test_elt_zero_int == add->test_elt_zero_int
        !           401:          && old->elt_zero_int == add->elt_zero_int
        !           402:          && old->test_elt_one_int == add->test_elt_one_int
        !           403:          && old->elt_one_int == add->elt_one_int
        !           404:          && old->veclen == add->veclen
        !           405:          && old->dupno == add->dupno
        !           406:          && old->opno == add->opno
        !           407:          && (old->tests == 0
        !           408:              || (add->enforce_mode ? no_same_mode (old) : old->next == 0))
        !           409:          && old->code == add->code
        !           410:          && old->mode == add->mode)
        !           411:        {
        !           412:          old->success = merge_trees (old->success, add->success);
        !           413:          if (old->insn_code_number >= 0 && add->insn_code_number >= 0)
        !           414:            fatal ("Two actions at one point in tree.");
        !           415:          if (old->insn_code_number == -1)
        !           416:            old->insn_code_number = add->insn_code_number;
        !           417:          return 1;
        !           418:        }
        !           419:       old = old->next;
        !           420:     }
        !           421:   return 0;
        !           422: }
        !           423: 
        !           424: /* Merge ADD into the next-chain that starts with OLD,
        !           425:    preferably after something that tests the same place
        !           426:    that ADD does.
        !           427:    The next-chain of ADD itself is ignored, and it is set
        !           428:    up for entering ADD into the new chain.
        !           429:    Returns the new chain.  */
        !           430: 
        !           431: struct decision *
        !           432: try_merge_2 (old, add)
        !           433:      struct decision *old, *add;
        !           434: {
        !           435:   register struct decision *p;
        !           436:   struct decision *last = 0;
        !           437:   struct decision *last_same_place = 0;
        !           438: 
        !           439:   /* Put this in after the others that test the same place,
        !           440:      if there are any.  If not, find the last chain element
        !           441:      and insert there.
        !           442: 
        !           443:      One modification: if this one is NOT a MATCH_OPERAND,
        !           444:      put it before any MATCH_OPERANDS that test the same place.
        !           445: 
        !           446:      Another: if enforce_mode (i.e. this is first operand of a SET),
        !           447:      put this after the last thing that tests the same place for
        !           448:      the same mode.  */
        !           449: 
        !           450:   int operand = 0 != add->tests;
        !           451: 
        !           452:   for (p = old; p; p = p->next)
        !           453:     {
        !           454:       if (p->position == add->position
        !           455:          || (p->position && add->position
        !           456:              && !strcmp (p->position, add->position)))
        !           457:        {
        !           458:          last_same_place = p;
        !           459:          /* If enforce_mode, segregate the modes in numerical order.  */
        !           460:          if (p->enforce_mode && (int) add->mode < (int) p->mode)
        !           461:            break;
        !           462:          /* Keep explicit decompositions before those that test predicates.
        !           463:             If enforce_mode, do this separately within each mode.  */
        !           464:          if (! p->enforce_mode || p->mode == add->mode)
        !           465:            if (!operand && p->tests)
        !           466:              break;
        !           467:        }
        !           468:       /* If this is past the end of the decisions at the same place as ADD,
        !           469:         stop looking now; add ADD before here.  */
        !           470:       else if (last_same_place)
        !           471:        break;
        !           472:       last = p;
        !           473:     }
        !           474: 
        !           475:   /* Insert before P, which means after LAST.  */
        !           476: 
        !           477:   if (last)
        !           478:     {
        !           479:       add->next = last->next;
        !           480:       last->next = add;
        !           481:       return old;
        !           482:     }
        !           483: 
        !           484:   add->next = old;
        !           485:   return add;
        !           486: }
        !           487: 
        !           488: int
        !           489: no_same_mode (node)
        !           490:      struct decision *node;
        !           491: {
        !           492:   register struct decision *p;
        !           493:   register enum machine_mode mode = node->mode;
        !           494: 
        !           495:   for (p = node->next; p; p = p->next)
        !           496:     if (p->mode == mode)
        !           497:       return 0;
        !           498: 
        !           499:   return 1;
        !           500: }
        !           501: 
        !           502: /* Count the number of subnodes of node NODE, assumed to be the start
        !           503:    of a next-chain.  If the number is high enough, make NODE start
        !           504:    a separate subroutine in the C code that is generated.  */
        !           505: 
        !           506: int
        !           507: break_out_subroutines (node)
        !           508:      struct decision *node;
        !           509: {
        !           510:   int size = 0;
        !           511:   struct decision *sub;
        !           512:   for (sub = node; sub; sub = sub->next)
        !           513:     size += 1 + break_out_subroutines (sub->success);
        !           514:   if (size > SUBROUTINE_THRESHOLD)
        !           515:     {
        !           516:       node->subroutine_number = ++next_subroutine_number;
        !           517:       write_subroutine (node);
        !           518:       size = 1;
        !           519:     }
        !           520:   return size;
        !           521: }
        !           522: 
        !           523: void
        !           524: write_subroutine (tree)
        !           525:      struct decision *tree;
        !           526: {
        !           527:   printf ("int\nrecog_%d (x0, insn)\n     register rtx x0;\n     rtx insn;\n{\n",
        !           528:          tree->subroutine_number);
        !           529:   printf ("  register rtx x1, x2, x3, x4, x5;\n  rtx x6, x7, x8, x9, x10, x11;\n");
        !           530:   printf ("  int tem;\n");
        !           531:   write_tree (tree, "", 0, "", 1);
        !           532:   printf (" ret0: return -1;\n}\n\n");
        !           533: }
        !           534: 
        !           535: /* Write out C code to perform the decisions in the tree.  */
        !           536: 
        !           537: void
        !           538: write_tree (tree, prevpos, afterward, afterpos, initial)
        !           539:      struct decision *tree;
        !           540:      char *prevpos;
        !           541:      int afterward;
        !           542:      char *afterpos;
        !           543:      int initial;
        !           544: {
        !           545:   register struct decision *p, *p1;
        !           546:   char *pos;
        !           547:   register int depth;
        !           548:   int ignmode;
        !           549:   enum { NO_SWITCH, CODE_SWITCH, MODE_SWITCH } in_switch = NO_SWITCH;
        !           550:   char modemap[NUM_MACHINE_MODES];
        !           551:   char codemap[NUM_RTX_CODE];
        !           552: 
        !           553:   pos = prevpos;
        !           554: 
        !           555:   if (tree->subroutine_number > 0 && ! initial)
        !           556:     {
        !           557:       printf (" L%d:\n", tree->number);
        !           558: 
        !           559:       if (afterward)
        !           560:        {
        !           561:          printf ("  tem = recog_%d (x0, insn);\n",
        !           562:                  tree->subroutine_number);
        !           563:          printf ("  if (tem >= 0) return tem;\n");
        !           564:          change_state (pos, afterpos);
        !           565:          printf ("  goto L%d;\n", afterward);
        !           566:        }
        !           567:       else
        !           568:        printf ("  return recog_%d (x0, insn);\n",
        !           569:                tree->subroutine_number);
        !           570:       return;
        !           571:     }
        !           572: 
        !           573:   tree->label_needed = 1;
        !           574:   for (p = tree; p; p = p->next)
        !           575:     {
        !           576:       /* Find the next alternative to p
        !           577:         that might be true when p is true.
        !           578:         Test that one next if p's successors fail.
        !           579:         Note that when the `tests' field is nonzero
        !           580:         it is up to the specified test-function to compare machine modes
        !           581:         and some (such as general_operand) don't always do so.
        !           582:         But when inside a switch-on-modes we ignore this and
        !           583:         consider all modes mutually exclusive.  */
        !           584:       for (p1 = p->next; p1; p1 = p1->next)
        !           585:        if (((p->code == UNKNOWN || p1->code == UNKNOWN || p->code == p1->code)
        !           586:             && (p->mode == VOIDmode || p1->mode == VOIDmode
        !           587:                 || p->mode == p1->mode
        !           588:                 || (in_switch != MODE_SWITCH && (p->tests || p1->tests))))
        !           589:            || strcmp (p1->position, p->position))
        !           590:          break;
        !           591:       p->afterward = p1;
        !           592:       if (p1) p1->label_needed = 1;
        !           593: 
        !           594:       if (in_switch == MODE_SWITCH
        !           595:          && (p->mode == VOIDmode || (! p->enforce_mode && p->tests != 0)))
        !           596:        {
        !           597:          in_switch = NO_SWITCH;
        !           598:          printf ("  }\n");
        !           599:        }
        !           600:       if (in_switch == CODE_SWITCH && p->code == UNKNOWN)
        !           601:        {
        !           602:          in_switch = NO_SWITCH;
        !           603:          printf ("  }\n");
        !           604:        }
        !           605: 
        !           606:       if (p->label_needed)
        !           607:        printf (" L%d:\n", p->number);
        !           608: 
        !           609:       if (p->success == 0 && p->insn_code_number < 0)
        !           610:        abort ();
        !           611: 
        !           612:       change_state (pos, p->position);
        !           613:       pos = p->position;
        !           614:       depth = strlen (pos);
        !           615: 
        !           616:       ignmode = p->ignmode || pos[depth - 1] == '*' || p->tests;
        !           617: 
        !           618:       if (in_switch == NO_SWITCH)
        !           619:        {
        !           620:          /* If p and its alternatives all want the same mode,
        !           621:             reject all others at once, first, then ignore the mode.  */
        !           622:          if (!ignmode && p->mode != VOIDmode && p->next && same_modes (p, p->mode))
        !           623:            {
        !           624:              printf ("  if (GET_MODE (x%d) != %smode)\n",
        !           625:                      depth, GET_MODE_NAME (p->mode));
        !           626:              if (afterward)
        !           627:                {
        !           628:                  printf ("    {\n    ");
        !           629:                  change_state (pos, afterpos);
        !           630:                  printf ("      goto L%d;\n    }\n", afterward);
        !           631:                }
        !           632:              else
        !           633:                printf ("    goto ret0;\n");
        !           634:              clear_modes (p);
        !           635:              ignmode = 1;
        !           636:            }
        !           637: 
        !           638:          /* If p and its alternatives all want the same code,
        !           639:             reject all others at once, first, then ignore the code.  */
        !           640:          if (p->code != UNKNOWN && p->next && same_codes (p, p->code))
        !           641:            {
        !           642:              printf ("  if (GET_CODE (x%d) != ", depth);
        !           643:              print_code (p->code);
        !           644:              printf (")\n");
        !           645:              if (afterward)
        !           646:                {
        !           647:                  printf ("    {");
        !           648:                  change_state (pos, afterpos);
        !           649:                  printf ("    goto L%d; }\n", afterward);
        !           650:                }
        !           651:              else
        !           652:                printf ("    goto ret0;\n");
        !           653:              clear_codes (p);
        !           654:            }
        !           655:        }
        !           656: 
        !           657:       /* If p and its alternatives all have different modes
        !           658:         and there are at least 4 of them, make a switch.  */
        !           659:       if (in_switch == NO_SWITCH && pos[depth-1] != '*')
        !           660:        {
        !           661:          register int i;
        !           662:          int lose = 0;
        !           663: 
        !           664:          mybzero (modemap, sizeof modemap);
        !           665:          for (p1 = p, i = 0;
        !           666:               (p1 && p1->mode != VOIDmode
        !           667:                && (p1->tests == 0 || p1->enforce_mode));
        !           668:               p1 = p1->next, i++)
        !           669:            {
        !           670:              if (! p->enforce_mode && modemap[(int) p1->mode])
        !           671:                {
        !           672:                  lose = 1;
        !           673:                  break;
        !           674:                }
        !           675:              modemap[(int) p1->mode] = 1;
        !           676:            }
        !           677:          if (!lose && i >= 4)
        !           678:            {
        !           679:              in_switch = MODE_SWITCH;
        !           680:              printf (" switch (GET_MODE (x%d))\n  {\n", depth);
        !           681:            }
        !           682:        }
        !           683: 
        !           684:       if (in_switch == NO_SWITCH)
        !           685:        {
        !           686:          register int i;
        !           687:          mybzero (codemap, sizeof codemap);
        !           688:          for (p1 = p, i = 0; p1 && p1->code != UNKNOWN; p1 = p1->next, i++)
        !           689:            {
        !           690:              if (codemap[(int) p1->code])
        !           691:                break;
        !           692:              codemap[(int) p1->code] = 1;
        !           693:            }
        !           694:          if ((p1 == 0 || p1->code == UNKNOWN) && i >= 4)
        !           695:            {
        !           696:              in_switch = CODE_SWITCH;
        !           697:              printf (" switch (GET_CODE (x%d))\n  {\n", depth);
        !           698:            }
        !           699:        }
        !           700: 
        !           701:       if (in_switch == MODE_SWITCH)
        !           702:        {
        !           703:          if (modemap[(int) p->mode])
        !           704:            {
        !           705:              printf ("  case %smode:\n", GET_MODE_NAME (p->mode));
        !           706:              modemap[(int) p->mode] = 0;
        !           707:            }
        !           708:        }
        !           709:       if (in_switch == CODE_SWITCH)
        !           710:        {
        !           711:          if (codemap[(int) p->code])
        !           712:            {
        !           713:              printf ("  case ");
        !           714:              print_code (p->code);
        !           715:              printf (":\n");
        !           716:              codemap[(int) p->code] = 0;
        !           717:            }
        !           718:        }
        !           719: 
        !           720:       printf ("  if (");
        !           721:       if (p->exact || (p->code != UNKNOWN && in_switch != CODE_SWITCH))
        !           722:        {
        !           723:          if (p->exact)
        !           724:            printf ("x%d == %s", depth, p->exact);
        !           725:          else
        !           726:            {
        !           727:              printf ("GET_CODE (x%d) == ", depth);
        !           728:              print_code (p->code);
        !           729:            }
        !           730:          printf (" && ");
        !           731:        }
        !           732:       if (p->mode && !ignmode && in_switch != MODE_SWITCH)
        !           733:        printf ("GET_MODE (x%d) == %smode && ",
        !           734:                depth, GET_MODE_NAME (p->mode));
        !           735:       if (p->test_elt_zero_int)
        !           736:        printf ("XINT (x%d, 0) == %d && ", depth, p->elt_zero_int);
        !           737:       if (p->veclen)
        !           738:        printf ("XVECLEN (x%d, 0) == %d && ", depth, p->veclen);
        !           739:       if (p->test_elt_one_int)
        !           740:        printf ("XINT (x%d, 1) == %d && ", depth, p->elt_one_int);
        !           741:       if (p->dupno >= 0)
        !           742:        printf ("rtx_equal_p (x%d, recog_operand[%d]) && ", depth, p->dupno);
        !           743:       if (p->tests)
        !           744:        printf ("%s (x%d, %smode)", p->tests, depth,
        !           745:                GET_MODE_NAME (p->mode));
        !           746:       else
        !           747:        printf ("1");
        !           748: 
        !           749:       if (p->opno >= 0)
        !           750:        printf (")\n    { recog_operand[%d] = x%d; ",
        !           751:                p->opno, depth);
        !           752:       else
        !           753:        printf (")\n    ");
        !           754: 
        !           755:       if (p->c_test)
        !           756:        printf ("if (%s) ", p->c_test);
        !           757: 
        !           758:       if (p->insn_code_number >= 0)
        !           759:        printf ("return %d;", p->insn_code_number);
        !           760:       else
        !           761:        printf ("goto L%d;", p->success->number);
        !           762: 
        !           763:       if (p->opno >= 0)
        !           764:        printf (" }\n");
        !           765:       else
        !           766:        printf ("\n");
        !           767: 
        !           768:       /* Now, if inside a switch, branch to next switch member
        !           769:         that might also need to be tested if this one fails.  */
        !           770: 
        !           771:       if (in_switch == CODE_SWITCH)
        !           772:        {
        !           773:          /* Find the next alternative to p
        !           774:             that might be applicable if p was applicable.  */
        !           775:          for (p1 = p->next; p1; p1 = p1->next)
        !           776:            if (p1->code == UNKNOWN || p->code == p1->code)
        !           777:              break;
        !           778:          if (p1 == 0 || p1->code == UNKNOWN)
        !           779:            printf ("  break;\n");
        !           780:          else if (p1 != p->next)
        !           781:            {
        !           782:              printf (" goto L%d;\n", p1->number);
        !           783:              p1->label_needed = 1;
        !           784:            }
        !           785:        }
        !           786: 
        !           787:       if (in_switch == MODE_SWITCH)
        !           788:        {
        !           789:          /* Find the next alternative to p
        !           790:             that might be applicable if p was applicable.  */
        !           791:          for (p1 = p->next; p1; p1 = p1->next)
        !           792:            if (p1->mode == VOIDmode || p->mode == p1->mode)
        !           793:              break;
        !           794:          if (p1 == 0 || p1->mode == VOIDmode)
        !           795:            printf ("  break;\n");
        !           796:          else if (p1 != p->next)
        !           797:            {
        !           798:              printf (" goto L%d;\n", p1->number);
        !           799:              p1->label_needed = 1;
        !           800:            }
        !           801:        }
        !           802:     }
        !           803: 
        !           804:   if (in_switch != NO_SWITCH)
        !           805:     printf ("  }\n");
        !           806: 
        !           807:   if (afterward)
        !           808:     {
        !           809:       change_state (pos, afterpos);
        !           810:       printf ("  goto L%d;\n", afterward);
        !           811:     }
        !           812:   else
        !           813:     printf ("  goto ret0;\n");
        !           814: 
        !           815:   for (p = tree; p; p = p->next)
        !           816:     if (p->success)
        !           817:       {
        !           818:          {
        !           819:            pos = p->position;
        !           820:            write_tree (p->success, pos,
        !           821:                        p->afterward ? p->afterward->number : afterward,
        !           822:                        p->afterward ? pos : afterpos,
        !           823:                        0);
        !           824:          }
        !           825:       }
        !           826: }
        !           827: 
        !           828: void
        !           829: print_code (code)
        !           830:      RTX_CODE code;
        !           831: {
        !           832:   register char *p1;
        !           833:   for (p1 = GET_RTX_NAME (code); *p1; p1++)
        !           834:     {
        !           835:       if (*p1 >= 'a' && *p1 <= 'z')
        !           836:        putchar (*p1 + 'A' - 'a');
        !           837:       else
        !           838:        putchar (*p1);
        !           839:     }
        !           840: }
        !           841: 
        !           842: int
        !           843: same_codes (p, code)
        !           844:      register struct decision *p;
        !           845:      register RTX_CODE code;
        !           846: {
        !           847:   for (; p; p = p->next)
        !           848:     if (p->code != code)
        !           849:       return 0;
        !           850: 
        !           851:   return 1;
        !           852: }
        !           853: 
        !           854: void
        !           855: clear_codes (p)
        !           856:      register struct decision *p;
        !           857: {
        !           858:   for (; p; p = p->next)
        !           859:     p->code = UNKNOWN;
        !           860: }
        !           861: 
        !           862: int
        !           863: same_modes (p, mode)
        !           864:      register struct decision *p;
        !           865:      register enum machine_mode mode;
        !           866: {
        !           867:   for (; p; p = p->next)
        !           868:     if (p->mode != mode || p->tests)
        !           869:       return 0;
        !           870: 
        !           871:   return 1;
        !           872: }
        !           873: 
        !           874: void
        !           875: clear_modes (p)
        !           876:      register struct decision *p;
        !           877: {
        !           878:   for (; p; p = p->next)
        !           879:     p->ignmode = 1;
        !           880: }
        !           881: 
        !           882: void
        !           883: change_state (oldpos, newpos)
        !           884:      char *oldpos;
        !           885:      char *newpos;
        !           886: {
        !           887:   int odepth = strlen (oldpos);
        !           888:   int depth = odepth;
        !           889:   int ndepth = strlen (newpos);
        !           890: 
        !           891:   /* Pop up as many levels as necessary.  */
        !           892: 
        !           893:   while (strncmp (oldpos, newpos, depth))
        !           894:     --depth;
        !           895: 
        !           896:   /* Go down to desired level.  */
        !           897: 
        !           898:   while (depth < ndepth)
        !           899:     {
        !           900:       if (newpos[depth] == '*')
        !           901:        printf ("  x%d = recog_addr_dummy;\n  XEXP (x%d, 0) = x%d;\n",
        !           902:                depth + 1, depth + 1, depth);
        !           903:       else if (newpos[depth] >= 'a' && newpos[depth] <= 'z')
        !           904:        printf ("  x%d = XVECEXP (x%d, 0, %c);\n",
        !           905:                depth + 1, depth, '0' + newpos[depth] - 'a');
        !           906:       else
        !           907:        printf ("  x%d = XEXP (x%d, %c);\n",
        !           908:                depth + 1, depth, newpos[depth]);
        !           909:       ++depth;
        !           910:     }
        !           911: }
        !           912: 
        !           913: char *
        !           914: copystr (s1)
        !           915:      char *s1;
        !           916: {
        !           917:   register char *tem;
        !           918: 
        !           919:   if (s1 == 0)
        !           920:     return 0;
        !           921: 
        !           922:   tem = (char *) xmalloc (strlen (s1) + 1);
        !           923:   strcpy (tem, s1);
        !           924: 
        !           925:   return tem;
        !           926: }
        !           927: 
        !           928: void
        !           929: mybzero (b, length)
        !           930:      register char *b;
        !           931:      register int length;
        !           932: {
        !           933:   while (length-- > 0)
        !           934:     *b++ = 0;
        !           935: }
        !           936: 
        !           937: char *
        !           938: concat (s1, s2)
        !           939:      char *s1, *s2;
        !           940: {
        !           941:   register char *tem;
        !           942: 
        !           943:   if (s1 == 0)
        !           944:     return s2;
        !           945:   if (s2 == 0)
        !           946:     return s1;
        !           947: 
        !           948:   tem = (char *) xmalloc (strlen (s1) + strlen (s2) + 2);
        !           949:   strcpy (tem, s1);
        !           950:   strcat (tem, " ");
        !           951:   strcat (tem, s2);
        !           952: 
        !           953:   return tem;
        !           954: }
        !           955: 
        !           956: int
        !           957: xrealloc (ptr, size)
        !           958:      char *ptr;
        !           959:      int size;
        !           960: {
        !           961:   int result = realloc (ptr, size);
        !           962:   if (!result)
        !           963:     fatal ("virtual memory exhausted");
        !           964:   return result;
        !           965: }
        !           966: 
        !           967: int
        !           968: xmalloc (size)
        !           969: {
        !           970:   register int val = malloc (size);
        !           971: 
        !           972:   if (val == 0)
        !           973:     fatal ("virtual memory exhausted");
        !           974:   return val;
        !           975: }
        !           976: 
        !           977: void
        !           978: fatal (s, a1, a2)
        !           979: {
        !           980:   fprintf (stderr, "genrecog: ");
        !           981:   fprintf (stderr, s, a1, a2);
        !           982:   fprintf (stderr, "\n");
        !           983:   fprintf (stderr, "after %d instruction definitions\n",
        !           984:           next_insn_code);
        !           985:   exit (FATAL_EXIT_CODE);
        !           986: }
        !           987: 
        !           988: int
        !           989: main (argc, argv)
        !           990:      int argc;
        !           991:      char **argv;
        !           992: {
        !           993:   rtx desc;
        !           994:   struct decision *tree = 0;
        !           995:   FILE *infile;
        !           996:   extern rtx read_rtx ();
        !           997:   register int c;
        !           998: 
        !           999:   obstack_init (rtl_obstack);
        !          1000: 
        !          1001:   if (argc <= 1)
        !          1002:     fatal ("No input file name.");
        !          1003: 
        !          1004:   infile = fopen (argv[1], "r");
        !          1005:   if (infile == 0)
        !          1006:     {
        !          1007:       perror (argv[1]);
        !          1008:       exit (FATAL_EXIT_CODE);
        !          1009:     }
        !          1010: 
        !          1011:   init_rtl ();
        !          1012:   next_insn_code = 0;
        !          1013: 
        !          1014:   printf ("/* Generated automatically by the program `genrecog'\n\
        !          1015: from the machine description file `md'.  */\n\n");
        !          1016: 
        !          1017:   /* Read the machine description.  */
        !          1018: 
        !          1019:   while (1)
        !          1020:     {
        !          1021:       c = read_skip_spaces (infile);
        !          1022:       if (c == EOF)
        !          1023:        break;
        !          1024:       ungetc (c, infile);
        !          1025: 
        !          1026:       desc = read_rtx (infile);
        !          1027:       if (GET_CODE (desc) == DEFINE_INSN)
        !          1028:        tree = merge_trees (tree, make_insn_sequence (desc));
        !          1029:       if (GET_CODE (desc) == DEFINE_PEEPHOLE
        !          1030:          || GET_CODE (desc) == DEFINE_EXPAND)
        !          1031:        next_insn_code++;
        !          1032:     }
        !          1033: 
        !          1034:   printf ("#include \"config.h\"\n");
        !          1035:   printf ("#include \"rtl.h\"\n");
        !          1036:   printf ("#include \"insn-config.h\"\n");
        !          1037:   printf ("#include \"recog.h\"\n");
        !          1038:   printf ("\n\
        !          1039: /* `recog' contains a decision tree\n\
        !          1040:    that recognizes whether the rtx X0 is a valid instruction.\n\
        !          1041: \n\
        !          1042:    recog returns -1 if the rtx is not valid.\n\
        !          1043:    If the rtx is valid, recog returns a nonnegative number\n\
        !          1044:    which is the insn code number for the pattern that matched.\n");
        !          1045:   printf ("   This is the same as the order in the machine description of\n\
        !          1046:    the entry that matched.  This number can be used as an index into\n\
        !          1047:    insn_templates and insn_n_operands (found in insn-output.c)\n\
        !          1048:    or as an argument to output_insn_hairy (also in insn-output.c).  */\n\n");
        !          1049: 
        !          1050:   printf ("rtx recog_operand[MAX_RECOG_OPERANDS];\n\n");
        !          1051:   printf ("rtx *recog_operand_loc[MAX_RECOG_OPERANDS];\n\n");
        !          1052:   printf ("rtx *recog_dup_loc[MAX_DUP_OPERANDS];\n\n");
        !          1053:   printf ("char recog_dup_num[MAX_DUP_OPERANDS];\n\n");
        !          1054:   printf ("extern rtx recog_addr_dummy;\n\n");
        !          1055:   printf ("#define operands recog_operand\n\n");
        !          1056: 
        !          1057:   break_out_subroutines (tree);
        !          1058: 
        !          1059:   printf ("int\nrecog (x0, insn)\n     register rtx x0;\n     rtx insn;\n{\n");
        !          1060:   printf ("  register rtx x1, x2, x3, x4, x5;\n  rtx x6, x7, x8, x9, x10, x11;\n");
        !          1061:   printf ("  int tem;\n");
        !          1062: 
        !          1063:   write_tree (tree, "", 0, "", 1);
        !          1064:   printf (" ret0: return -1;\n}\n");
        !          1065: 
        !          1066:   fflush (stdout);
        !          1067:   exit (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
        !          1068: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.