Annotation of researchv10dc/cmd/gcc/genrecog.c, revision 1.1.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.