Annotation of gcc/expr.c, revision 1.1.1.1

1.1       root        1: /* Convert tree expression to rtl instructions, for GNU compiler.
                      2:    Copyright (C) 1987 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: #include "config.h"
                     23: #include "rtl.h"
                     24: #include "tree.h"
                     25: #include "insn-flags.h"
                     26: #include "insn-codes.h"
                     27: #include "expr.h"
                     28: 
                     29: /* If this is nonzero, we do not bother generating VOLATILE
                     30:    around volatile memory references, and we are willing to
                     31:    output indirect addresses.  If cse is to follow, we reject
                     32:    indirect addresses so a useful potential cse is generated;
                     33:    if it is used only once, instruction combination will produce
                     34:    the same indirect address eventually.  */
                     35: int cse_not_expected;
                     36: 
                     37: /* Nonzero to generate code for all the subroutines within an
                     38:    expression before generating the upper levels of the expression.
                     39:    Nowadays this is never zero.  */
                     40: int do_preexpand_calls = 1;
                     41: 
                     42: /* Number of units that we should eventually pop off the stack.
                     43:    These are the arguments to function calls that have already returned.  */
                     44: int pending_stack_adjust;
                     45: 
                     46: /* Total size of arguments already pushed for function calls that
                     47:    have not happened yet.  Also counts 1 for each level of conditional
                     48:    expression that we are inside.  When this is nonzero,
                     49:    args passed to function calls must be popped right away
                     50:    to ensure contiguity of argument lists for future calls.  */
                     51: int current_args_size;
                     52: 
                     53: static rtx store_expr ();
                     54: static rtx expand_call ();
                     55: static void gen_call_1 ();
                     56: static rtx compare ();
                     57: static rtx compare1 ();
                     58: static rtx do_store_flag ();
                     59: static void preexpand_calls ();
                     60: 
                     61: /* MOVE_RATIO is the number of move instructions that is better than
                     62:    a block move.  */
                     63: 
                     64: #if defined (HAVE_movstrhi) || defined (HAVE_movstrsi)
                     65: #define MOVE_RATIO 2
                     66: #else
                     67: #define MOVE_RATIO 6
                     68: #endif
                     69: 
                     70: /* Table indexed by tree code giving 1 if the code is for a
                     71:    comparison operation, or anything that is most easily
                     72:    computed with a conditional branch.
                     73: 
                     74:    We include tree.def to give it the proper length.
                     75:    The contents thus created are irrelevant.
                     76:    The real contents are initialized in init_comparisons.  */
                     77: 
                     78: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
                     79: 
                     80: static char comparison_code[] = {
                     81: #include "tree.def"
                     82: };
                     83: #undef DEFTREECODE
                     84: 
                     85: init_comparisons ()
                     86: {
                     87: 
                     88:   bzero (comparison_code, sizeof comparison_code);
                     89:   comparison_code[(int) EQ_EXPR] = 1;
                     90:   comparison_code[(int) NE_EXPR] = 1;
                     91:   comparison_code[(int) LT_EXPR] = 1;
                     92:   comparison_code[(int) GT_EXPR] = 1;
                     93:   comparison_code[(int) LE_EXPR] = 1;
                     94:   comparison_code[(int) GE_EXPR] = 1;
                     95: }
                     96: 
                     97: /* Manage the queue of increment instructions to be output
                     98:    for POSTINCREMENT_EXPR expressions, etc.  */
                     99: 
                    100: static rtx pending_chain;
                    101: 
                    102: /* Queue up to increment (or change) VAR later.  BODY says how:
                    103:    BODY should be the same thing you would pass to emit_insn
                    104:    to increment right away.  It will go to emit_insn later on.
                    105: 
                    106:    The value is a QUEUED expression to be used in place of VAR
                    107:    where you want to guarantee the pre-incrementation value of VAR.
                    108: 
                    109:    When constructing BODY, you should pass VAR through copy_rtx
                    110:    each time it is used.  If VAR is a MEM, this prevents BODY from
                    111:    sharing structure incorrectly with itself or with places that
                    112:    explicitly use VAR.  */
                    113: 
                    114: static rtx
                    115: enqueue_insn (var, body)
                    116:      rtx var, body;
                    117: {
                    118:   pending_chain = gen_rtx (QUEUED, GET_MODE (var),
                    119:                           var, 0, 0, body, pending_chain);
                    120:   return pending_chain;
                    121: }
                    122: 
                    123: /* Use protect_from_queue to convert a QUEUED expression
                    124:    into something that you can put immediately into an instruction.
                    125:    If the queued incrementation has not happened yet,
                    126:    protect_from_queue returns the variable itself.
                    127:    If the incrementation has happened, protect_from_queue returns a temp
                    128:    that contains a copy of the old value of the variable.
                    129: 
                    130:    Any time an rtx which might possibly be a QUEUED is to be put
                    131:    into an instruction, it must be passed through protect_from_queue first.
                    132:    QUEUED expressions are not meaningful in instructions.
                    133: 
                    134:    Do not pass a value through protect_from_queue and then hold
                    135:    on to it for a while before putting it in an instruction!
                    136:    If the queue is flushed in between, incorrect code will result.  */
                    137: 
                    138: rtx
                    139: protect_from_queue (x, modify)
                    140:      register rtx x;
                    141:      int modify;
                    142: {
                    143:   register RTX_CODE code = GET_CODE (x);
                    144:   if (code != QUEUED)
                    145:     {
                    146:       /* A special hack for read access to (MEM (QUEUED ...))
                    147:         to facilitate use of autoincrement.
                    148:         Make a copy of the contents of the memory location
                    149:         rather than a copy of the address.  */
                    150:       if (code == MEM && GET_CODE (XEXP (x, 0)) == QUEUED && !modify)
                    151:        {
                    152:          register rtx y = XEXP (x, 0);
                    153:          XEXP (x, 0) = QUEUED_VAR (y);
                    154:          if (QUEUED_INSN (y))
                    155:            {
                    156:              register rtx temp = gen_reg_rtx (GET_MODE (x));
                    157:              emit_insn_before (gen_move_insn (temp, x),
                    158:                                QUEUED_INSN (y));
                    159:              return temp;
                    160:            }
                    161:          return x;
                    162:        }
                    163:       /* Otherwise, recursively protect the subexpressions of all
                    164:         the kinds of rtx's that can contain a QUEUED.  */
                    165:       if (code == MEM)
                    166:        XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0);
                    167:       else if (code == PLUS || code == MULT)
                    168:        {
                    169:          XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0);
                    170:          XEXP (x, 1) = protect_from_queue (XEXP (x, 1), 0);
                    171:        }
                    172:       return x;
                    173:     }
                    174:   /* If the increment has not happened, use the variable itself.  */
                    175:   if (QUEUED_INSN (x) == 0)
                    176:     return QUEUED_VAR (x);
                    177:   /* If the increment has happened and a pre-increment copy exists,
                    178:      use that copy.  */
                    179:   if (QUEUED_COPY (x) != 0)
                    180:     return QUEUED_COPY (x);
                    181:   /* The increment has happened but we haven't set up a pre-increment copy.
                    182:      Set one up now, and use it.  */
                    183:   QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x)));
                    184:   emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)),
                    185:                    QUEUED_INSN (x));
                    186:   return QUEUED_COPY (x);
                    187: }
                    188: 
                    189: /* perform all the pending incrementations.  */
                    190: 
                    191: void
                    192: emit_queue ()
                    193: {
                    194:   register rtx p;
                    195:   while (p = pending_chain)
                    196:     {
                    197:       QUEUED_INSN (p) = emit_insn (QUEUED_BODY (p));
                    198:       pending_chain = QUEUED_NEXT (p);
                    199:     }
                    200: }
                    201: 
                    202: void
                    203: init_queue ()
                    204: {
                    205:   if (pending_chain)
                    206:     abort ();
                    207: }
                    208: 
                    209: /* Copy data from FROM to TO, where the machine modes are not the same.
                    210:    Both modes may be integer, or both may be floating.
                    211:    UNSIGNEDP should be nonzero if FROM is an unsigned type.
                    212:    This causes zero-extension instead of sign-extension.  */
                    213: 
                    214: void
                    215: convert_move (to, from, unsignedp)
                    216:      register rtx to, from;
                    217:      int unsignedp;
                    218: {
                    219:   enum machine_mode to_mode = GET_MODE (to);
                    220:   enum machine_mode from_mode = GET_MODE (from);
                    221:   int to_real = to_mode == SFmode || to_mode == DFmode;
                    222:   int from_real = from_mode == SFmode || from_mode == DFmode;
                    223:   int extending = (int) to_mode > (int) from_mode;
                    224: 
                    225:   to = protect_from_queue (to, 1);
                    226:   from = protect_from_queue (from, 0);
                    227: 
                    228:   if (to_real != from_real)
                    229:     abort ();
                    230: 
                    231:   if (to_mode == from_mode || GET_CODE (from) == CONST_INT)
                    232:     {
                    233:       emit_move_insn (to, from);
                    234:       return;
                    235:     }
                    236: 
                    237:   if (to_real)
                    238:     {
                    239: #ifdef HAVE_extendsfdf2
                    240:       if (HAVE_extendsfdf2 && extending)
                    241:        {
                    242:          emit_insn (gen_extendsfdf2 (to, from));
                    243:          return;
                    244:        }
                    245: #endif
                    246: #ifdef HAVE_truncdfsf2
                    247:       if (HAVE_truncdfsf2 && ! extending)
                    248:        {
                    249:          emit_insn (gen_truncdfsf2 (to, from));
                    250:          return;
                    251:        }
                    252: #endif
                    253:       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, (extending
                    254:                                                      ? "extendsfdf2"
                    255:                                                      : "truncdfsf2")),
                    256:                         1, from,  (extending ? SFmode : DFmode));
                    257:       copy_function_value (to);
                    258:       return;
                    259:     }
                    260: 
                    261:   if (to_mode == DImode)
                    262:     {
                    263:       emit_insn (gen_rtx (CLOBBER, VOIDmode, to));
                    264: 
                    265:       if (unsignedp)
                    266:        {
                    267:          convert_move (gen_lowpart (SImode, to), from, unsignedp);
                    268:          emit_clr_insn (gen_highpart (SImode, to));
                    269:        }
                    270: #ifdef HAVE_sltsi
                    271:       else if (HAVE_sltsi)
                    272:        {
                    273:          convert_move (gen_lowpart (SImode, to), from, unsignedp);
                    274:          emit_insn (gen_sltsi (gen_highpart (SImode, to)));
                    275:        }
                    276: #endif
                    277:       else
                    278:        {
                    279:          register rtx label = gen_label_rtx ();
                    280: 
                    281:          emit_clr_insn (gen_highpart (SImode, to));
                    282:          convert_move (gen_lowpart (SImode, to), from, unsignedp);
                    283:          emit_cmp_insn (gen_lowpart (SImode, to),
                    284:                         gen_rtx (CONST_INT, VOIDmode, 0),
                    285:                         0, 0);
                    286:          emit_jump_insn (gen_bge (label));
                    287:          expand_unop (SImode, one_cmpl_optab,
                    288:                       gen_highpart (SImode, to), gen_highpart (SImode, to),
                    289:                       1);
                    290:          emit_label (label);
                    291:        }
                    292:       return;
                    293:     }
                    294: 
                    295:   if (from_mode == DImode)
                    296:     {
                    297:       convert_move (to, gen_lowpart (SImode, from), 0);
                    298:       return;
                    299:     }
                    300: 
                    301:   /* Now follow all the conversions between integers
                    302:      no more than a word long.  */
                    303: 
                    304:   if (to_mode == SImode && from_mode == HImode)
                    305:     {
                    306:       if (unsignedp)
                    307:        {
                    308: #ifdef HAVE_zero_extendhisi2
                    309:          if (HAVE_zero_extendhisi2)
                    310:            emit_insn (gen_zero_extendhisi2 (to, from));
                    311:          else
                    312: #endif
                    313:            abort ();
                    314:        }
                    315:       else
                    316:        {
                    317: #ifdef HAVE_extendhisi2
                    318:          if (HAVE_extendhisi2)
                    319:            emit_insn (gen_extendhisi2 (to, from));
                    320:          else
                    321: #endif
                    322:            abort ();
                    323:        }
                    324:       return;
                    325:     }
                    326: 
                    327:   if (to_mode == SImode && from_mode == QImode)
                    328:     {
                    329:       if (unsignedp)
                    330:        {
                    331: #ifdef HAVE_zero_extendqisi2
                    332:          if (HAVE_zero_extendqisi2)
                    333:            {
                    334:              emit_insn (gen_zero_extendqisi2 (to, from));
                    335:              return;
                    336:            }
                    337: #endif
                    338: #if defined (HAVE_zero_extendqihi2) && defined (HAVE_extendhisi2)
                    339:          if (HAVE_zero_extendqihi2 && HAVE_extendhisi2)
                    340:            {
                    341:              register rtx temp = gen_reg_rtx (HImode);
                    342:              emit_insn (gen_zero_extendqihi2 (temp, from));
                    343:              emit_insn (gen_extendhisi2 (to, temp));
                    344:              return;
                    345:            }
                    346: #endif
                    347:        }
                    348:       else
                    349:        {
                    350: #ifdef HAVE_extendqisi2
                    351:          if (HAVE_extendqisi2)
                    352:            {
                    353:              emit_insn (gen_extendqisi2 (to, from));
                    354:              return;
                    355:            }
                    356: #endif
                    357: #if defined (HAVE_extendqihi2) && defined (HAVE_extendhisi2)
                    358:          if (HAVE_extendqihi2 && HAVE_extendhisi2)
                    359:            {
                    360:              register rtx temp = gen_reg_rtx (HImode);
                    361:              emit_insn (gen_extendqihi2 (temp, from));
                    362:              emit_insn (gen_extendhisi2 (to, temp));
                    363:              return;
                    364:            }
                    365: #endif
                    366:        }
                    367:       abort ();
                    368:     }
                    369: 
                    370:   if (to_mode == HImode && from_mode == QImode)
                    371:     {
                    372:       if (unsignedp)
                    373:        {
                    374: #ifdef HAVE_zero_extendqihi2
                    375:          if (HAVE_zero_extendqihi2)
                    376:            {
                    377:              emit_insn (gen_zero_extendqihi2 (to, from));
                    378:              return;
                    379:            }
                    380: #endif
                    381:        }
                    382:       else
                    383:        {
                    384: #ifdef HAVE_extendqihi2
                    385:          if (HAVE_extendqihi2)
                    386:            {
                    387:              emit_insn (gen_extendqihi2 (to, from));
                    388:              return;
                    389:            }
                    390: #endif
                    391:        }
                    392:       abort ();
                    393:     }
                    394: 
                    395:   /* Now we are truncating an integer to a smaller one.
                    396:      If the result is a temporary, we might as well just copy it,
                    397:      since only the low-order part of the result needs to be valid
                    398:      and it is valid with no change.  */
                    399: 
                    400:   if (GET_CODE (to) == REG)
                    401:     {
                    402:       if (GET_CODE (from) == REG)
                    403:        {
                    404:          emit_move_insn (to, gen_lowpart (GET_MODE (to), from));
                    405:          return;
                    406:        }
                    407: #ifndef BYTES_BIG_ENDIAN
                    408:       else if (GET_CODE (from) == MEM)
                    409:        {
                    410:          register rtx addr = XEXP (from, 0);
                    411:          GO_IF_LEGITIMATE_ADDRESS (GET_MODE (to), addr, win);
                    412:          if (0)
                    413:            {
                    414:            win:
                    415:              emit_move_insn (to, gen_rtx (MEM, GET_MODE (to), addr));
                    416:              return;
                    417:            }
                    418:        }
                    419: #endif /* not BYTES_BIG_ENDIAN */
                    420:     }
                    421: 
                    422:   if (from_mode == SImode && to_mode == HImode)
                    423:     {
                    424: #ifdef HAVE_truncsihi2
                    425:       if (HAVE_truncsihi2)
                    426:        {
                    427:          emit_insn (gen_truncsihi2 (to, from));
                    428:          return;
                    429:        }
                    430: #endif
                    431:       abort ();
                    432:     }
                    433: 
                    434:   if (from_mode == SImode && to_mode == QImode)
                    435:     {
                    436: #ifdef HAVE_truncsiqi2
                    437:       if (HAVE_truncsiqi2)
                    438:        {
                    439:          emit_insn (gen_truncsiqi2 (to, from));
                    440:          return;
                    441:        }
                    442: #endif
                    443:       abort ();
                    444:     }
                    445: 
                    446:   if (from_mode == HImode && to_mode == QImode)
                    447:     {
                    448: #ifdef HAVE_trunchiqi2
                    449:       if (HAVE_trunchiqi2)
                    450:        {
                    451:          emit_insn (gen_trunchiqi2 (to, from));
                    452:          return;
                    453:        }
                    454: #endif
                    455:       abort ();
                    456:     }
                    457: }
                    458: 
                    459: /* Return an rtx for a value that would result
                    460:    from converting X to mode MODE.
                    461:    Both X and MODE may be floating, or both integer.
                    462:    UNSIGNEDP is nonzero if X is an unsigned value.
                    463:    This can be done by referring to a part of X in place
                    464:    or by copying to a new temporary with conversion.  */
                    465: 
                    466: rtx
                    467: convert_to_mode (mode, x, unsignedp)
                    468:      enum machine_mode mode;
                    469:      rtx x;
                    470:      int unsignedp;
                    471: {
                    472:   register rtx temp;
                    473:   if (mode == GET_MODE (x))
                    474:     return x;
                    475:   if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (x)))
                    476:     return gen_lowpart (mode, x);
                    477:   temp = gen_reg_rtx (mode);
                    478:   convert_move (temp, x, unsignedp);
                    479:   return temp;
                    480: }
                    481: 
                    482: /* Generate several move instructions to copy LEN bytes
                    483:    from address FROM to address TO.  The caller must pass FROM and TO
                    484:     through protect_from_queue before calling.
                    485:    FROM_VOL and TO_VOL are nonzero if references to
                    486:     FROM and TO, respectively, should be marked VOLATILE.
                    487:    ALIGN (in bytes) is maximum alignment we can assume.  */
                    488: 
                    489: struct move_by_pieces
                    490: {
                    491:   rtx to;
                    492:   int autinc_to;
                    493:   int explicit_inc_to;
                    494:   int to_vol;
                    495:   rtx from;
                    496:   int autinc_from;
                    497:   int explicit_inc_from;
                    498:   int from_vol;
                    499:   int len;
                    500:   int offset;
                    501:   int reverse;
                    502: };
                    503: 
                    504: static void
                    505: move_by_pieces (to, from, len, align, to_vol, from_vol)
                    506:      rtx to, from;
                    507:      int len, align;
                    508:      int to_vol, from_vol;
                    509: {
                    510:   struct move_by_pieces data;
                    511: 
                    512:   data.offset = 0;
                    513:   data.to = to;
                    514:   data.from = from;
                    515:   data.to_vol = to_vol;
                    516:   data.from_vol = from_vol;
                    517:   data.autinc_to = (GET_CODE (to) == PRE_INC || GET_CODE (to) == PRE_DEC
                    518:                    || GET_CODE (to) == POST_INC || GET_CODE (to) == POST_DEC);
                    519:   data.autinc_from = (GET_CODE (from) == PRE_INC || GET_CODE (from) == PRE_DEC
                    520:                      || GET_CODE (from) == POST_INC
                    521:                      || GET_CODE (from) == POST_DEC);
                    522: 
                    523:   data.explicit_inc_from = 0;
                    524:   data.explicit_inc_to = 0;
                    525:   data.reverse = (GET_CODE (to) == PRE_DEC || GET_CODE (to) == POST_DEC);
                    526:   if (data.reverse) data.offset = len;
                    527:   data.len = len;
                    528: 
                    529:   /* If copying requires more than two move insns,
                    530:      copy addresses to registers (to make displacements shorter)
                    531:      and use post-increment if available.  */
                    532:   if (!(data.autinc_from && data.autinc_to)
                    533:       && move_by_pieces_ninsns (len, align) > 2)
                    534:     {
                    535: #ifdef HAVE_PRE_DECREMENT
                    536:       if (data.reverse && ! data.autinc_from)
                    537:        {
                    538:          data.from = copy_to_reg (plus_constant (from, len));
                    539:          data.autinc_from = 1;
                    540:          data.explicit_inc_from = -1;
                    541:        }
                    542: #endif
                    543: #ifdef HAVE_POST_INCREMENT
                    544:       if (! data.autinc_from)
                    545:        {
                    546:          data.from = copy_to_reg (from);
                    547:          data.autinc_from = 1;
                    548:          data.explicit_inc_from = 1;
                    549:        }
                    550: #endif
                    551:       if (!data.autinc_from && CONSTANT_ADDRESS_P (from))
                    552:        data.from = copy_to_reg (from);
                    553: #ifdef HAVE_PRE_DECREMENT
                    554:       if (data.reverse && ! data.autinc_to)
                    555:        {
                    556:          data.to = copy_to_reg (plus_constant (to, len));
                    557:          data.autinc_to = 1;
                    558:          data.explicit_inc_to = -1;
                    559:        }
                    560: #endif
                    561: #ifdef HAVE_POST_INCREMENT
                    562:       if (! data.reverse && ! data.autinc_to)
                    563:        {
                    564:          data.to = copy_to_reg (to);
                    565:          data.autinc_to = 1;
                    566:          data.explicit_inc_to = 1;
                    567:        }
                    568: #endif
                    569:       if (!data.autinc_to && CONSTANT_ADDRESS_P (to))
                    570:        data.to = copy_to_reg (to);
                    571:     }
                    572: 
                    573: #ifdef STRICT_ALIGNMENT
                    574:   if (align > MOVE_MAX)
                    575:     align = MOVE_MAX;
                    576: #else
                    577:   align = MOVE_MAX;
                    578: #endif
                    579: 
                    580: #ifdef HAVE_movti
                    581:   if (HAVE_movti && align >= GET_MODE_SIZE (TImode))
                    582:     move_by_pieces_1 (gen_movti, TImode, &data);
                    583: #endif
                    584: #ifdef HAVE_movdi
                    585:   if (HAVE_movdi && align >= GET_MODE_SIZE (DImode))
                    586:     move_by_pieces_1 (gen_movdi, DImode, &data);
                    587: #endif
                    588:   if (align >= GET_MODE_SIZE (SImode))
                    589:     move_by_pieces_1 (gen_movsi, SImode, &data);
                    590:   if (align >= GET_MODE_SIZE (HImode))
                    591:     move_by_pieces_1 (gen_movhi, HImode, &data);
                    592:   move_by_pieces_1 (gen_movqi, QImode, &data);
                    593: }
                    594: 
                    595: /* Return number of insns required to move L bytes by pieces.
                    596:    ALIGN (in bytes) is maximum alignment we can assume.  */
                    597: 
                    598: int
                    599: move_by_pieces_ninsns (l, align)
                    600:      unsigned int l;
                    601:      int align;
                    602: {
                    603:   register int n_insns = 0;
                    604: 
                    605: #ifdef STRICT_ALIGNMENT
                    606:   if (align > MOVE_MAX)
                    607:     align = MOVE_MAX;
                    608: #else
                    609:   align = MOVE_MAX;
                    610: #endif
                    611: 
                    612: #ifdef HAVE_movti
                    613:   if (HAVE_movti && align >= GET_MODE_SIZE (TImode))
                    614:     n_insns += l / GET_MODE_SIZE (TImode), l %= GET_MODE_SIZE (TImode);
                    615: #endif
                    616: #ifdef HAVE_movdi
                    617:   if (HAVE_movdi && align >= GET_MODE_SIZE (DImode))
                    618:     n_insns += l / GET_MODE_SIZE (DImode), l %= GET_MODE_SIZE (DImode);
                    619: #endif
                    620:   if (HAVE_movsi && align >= GET_MODE_SIZE (SImode))
                    621:     n_insns += l / GET_MODE_SIZE (SImode), l %= GET_MODE_SIZE (SImode);
                    622:   if (HAVE_movhi && align >= GET_MODE_SIZE (HImode))
                    623:     n_insns += l / GET_MODE_SIZE (HImode), l %= GET_MODE_SIZE (HImode);
                    624:   n_insns += l;
                    625: 
                    626:   return n_insns;
                    627: }
                    628: 
                    629: /* Subroutine of move_by_pieces.  Move as many bytes as appropriate
                    630:    with move instructions for mode MODE.  GENFUN is the gen_... function
                    631:    to make a move insn for that mode.  DATA has all the other info.  */
                    632: 
                    633: move_by_pieces_1 (genfun, mode, data)
                    634:      rtx (*genfun) ();
                    635:      enum machine_mode mode;
                    636:      struct move_by_pieces *data;
                    637: {
                    638:   register int size = GET_MODE_SIZE (mode);
                    639:   register rtx to1, from1;
                    640: 
                    641: #define add_offset(FLAG,X) (FLAG ? (X) : plus_constant (X, data->offset))
                    642: 
                    643:   while (data->len >= size)
                    644:     {
                    645:       to1 = gen_rtx (MEM, mode, add_offset (data->autinc_to, data->to));
                    646:       from1 = gen_rtx (MEM, mode, add_offset (data->autinc_from, data->from));
                    647: 
                    648:       if (data->to_vol) to1 = gen_rtx (VOLATILE, mode, to1);
                    649:       if (data->from_vol) from1 = gen_rtx (VOLATILE, mode, from1);
                    650: 
                    651:       if (data->reverse) data->offset -= size;
                    652: #ifdef HAVE_PRE_DECREMENT
                    653:       if (data->explicit_inc_to < 0)
                    654:        emit_insn (gen_sub2_insn (data->to,
                    655:                                  gen_rtx (CONST_INT, VOIDmode, size)));
                    656:       if (data->explicit_inc_from < 0)
                    657:        emit_insn (gen_sub2_insn (data->from,
                    658:                                  gen_rtx (CONST_INT, VOIDmode, size)));
                    659: #endif
                    660: 
                    661:       emit_insn (genfun (to1, from1));
                    662: #ifdef HAVE_POST_INCREMENT
                    663:       if (data->explicit_inc_to > 0)
                    664:        emit_insn (gen_add2_insn (data->to,
                    665:                                  gen_rtx (CONST_INT, VOIDmode, size)));
                    666:       if (data->explicit_inc_from > 0)
                    667:        emit_insn (gen_add2_insn (data->from,
                    668:                                  gen_rtx (CONST_INT, VOIDmode, size)));
                    669: #endif
                    670: 
                    671:       if (! data->reverse) data->offset += size;
                    672:       data->len -= size;
                    673:     }
                    674: }
                    675: 
                    676: /* Emit code to move a block Y to a block X.
                    677:    This may be done with string-move instructions,
                    678:    with multiple scalar move instructions, or with a library call.
                    679: 
                    680:    Both X and Y must be MEM rtx's (perhaps inside VOLATILE)
                    681:    with mode BLKmode.
                    682:    SIZE is an rtx that says how long they are.
                    683:    ALIGN is the maximum alignment we can assume they have,
                    684:    measured in bytes.  */
                    685: 
                    686: static void
                    687: emit_block_move (x, y, size, align)
                    688:      rtx x, y;
                    689:      rtx size;
                    690:      int align;
                    691: {
                    692: 
                    693:   register int max_step;
                    694:   rtx xinner, yinner;
                    695:   int xvolatile = 0, yvolatile = 0;
                    696: 
                    697:   if (GET_MODE (x) != BLKmode)
                    698:     abort ();
                    699: 
                    700:   if (GET_MODE (y) != BLKmode)
                    701:     abort ();
                    702: 
                    703:   x = protect_from_queue (x, 1);
                    704:   y = protect_from_queue (y, 0);
                    705: 
                    706:   xinner = x, yinner = y;
                    707: 
                    708:   if (GET_CODE (x) == VOLATILE)
                    709:     xvolatile = 1, xinner = XEXP (x, 0);
                    710:   if (GET_CODE (y) == VOLATILE)
                    711:     yvolatile = 1, yinner = XEXP (y, 0);
                    712: 
                    713:   if (GET_CODE (xinner) != MEM)
                    714:     abort ();
                    715:   if (GET_CODE (yinner) != MEM)
                    716:     abort ();
                    717:   if (size == 0)
                    718:     abort ();
                    719: 
                    720:   if (GET_CODE (size) == CONST_INT
                    721:       && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)
                    722:          < MOVE_RATIO))
                    723:     move_by_pieces (XEXP (xinner, 0), XEXP (yinner, 0),
                    724:                    INTVAL (size), align,
                    725:                    xvolatile, yvolatile);
                    726:   else
                    727:     {
                    728: #ifdef HAVE_movstrsi
                    729:       if (HAVE_movstrsi)
                    730:        {
                    731:          emit_insn (gen_movstrsi (x, y, size));
                    732:          return;
                    733:        }
                    734: #endif
                    735: #ifdef HAVE_movstrhi
                    736:       if (HAVE_movstrhi
                    737:          && GET_CODE (size) == CONST_INT
                    738:          && ((unsigned) INTVAL (size)
                    739:              < (1 << (GET_MODE_SIZE (HImode) * BITS_PER_UNIT - 1))))
                    740:        {
                    741:          emit_insn (gen_movstrhi (x, y, size));
                    742:          return;
                    743:        }
                    744: #endif
                    745:       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"),
                    746:                         3, XEXP (yinner, 0), Pmode,
                    747:                         XEXP (xinner, 0), Pmode,
                    748:                         size, Pmode);
                    749:     }
                    750: }
                    751: 
                    752: /* Generate code to copy Y into X.
                    753:    Both Y and X must have the same mode, except that
                    754:    Y can be a constant with VOIDmode.
                    755:    This mode cannot be BLKmode; use emit_block_move for that.  */
                    756: 
                    757: emit_move_insn (x, y)
                    758:      rtx x, y;
                    759: {
                    760:   enum machine_mode mode = GET_MODE (x);
                    761:   x = protect_from_queue (x, 1);
                    762:   y = protect_from_queue (y, 0);
                    763: 
                    764:   if (mode == BLKmode)
                    765:     abort ();
                    766:   if (mov_optab[(int) mode].insn_code != CODE_FOR_nothing)
                    767:     emit_insn (GEN_FCN (mov_optab[(int) mode].insn_code) (x, y));
                    768:   else if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (SImode))
                    769:     {
                    770:       register int count = GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode);
                    771:       register int i;
                    772:       for (i = 0; i < count; i++)
                    773:        {
                    774:          rtx x1, y1;
                    775:          if (GET_CODE (x) == REG)
                    776:            x1 = gen_rtx (SUBREG, SImode, x, i);
                    777:          else
                    778:            x1 = gen_rtx (MEM, SImode,
                    779:                          memory_address (SImode,
                    780:                                          plus_constant (XEXP (x, 0),
                    781:                                                         i * GET_MODE_SIZE (SImode))));
                    782:          if (GET_CODE (y) == REG)
                    783:            y1 = gen_rtx (SUBREG, SImode, y, i);
                    784:          else
                    785:            y1 = gen_rtx (MEM, SImode,
                    786:                          memory_address (SImode,
                    787:                                          plus_constant (XEXP (y, 0),
                    788:                                                         i * GET_MODE_SIZE (SImode))));
                    789:          emit_insn (gen_movsi (protect_from_queue (x1, 1), protect_from_queue (y1, 0)));
                    790:        }
                    791:     }
                    792:   else
                    793:     abort ();
                    794: }
                    795: 
                    796: /* Pushing data onto the stack.  */
                    797: 
                    798: /* Push a block of length SIZE (perhaps variable)
                    799:    and return an rtx to address the beginning of the block.
                    800:    Note that it is not possible for the value returned to be a QUEUED.  */
                    801: 
                    802: static rtx
                    803: push_block (size)
                    804:      rtx size;
                    805: {
                    806:   register rtx temp;
                    807:   anti_adjust_stack (size);
                    808:        
                    809: #ifdef STACK_GROWS_DOWNWARD
                    810:   temp = gen_rtx (REG, Pmode, STACK_POINTER_REGNUM);
                    811: #else
                    812:   temp = gen_rtx (PLUS, Pmode,
                    813:                  gen_rtx (REG, Pmode, STACK_POINTER_REGNUM),
                    814:                  size);
                    815:   if (GET_CODE (size) != CONST_INT)
                    816:     temp = force_operand (temp, 0);
                    817: #endif
                    818:   return memory_address (QImode, temp);
                    819: }
                    820: 
                    821: static rtx
                    822: gen_push_operand ()
                    823: {
                    824:   return gen_rtx (
                    825: #ifdef STACK_GROWS_DOWNWARD
                    826:                  PRE_DEC,
                    827: #else
                    828:                  PRE_INC,
                    829: #endif
                    830:                  Pmode,
                    831:                  gen_rtx (REG, Pmode, STACK_POINTER_REGNUM));
                    832: }
                    833: 
                    834: /* Generate code to push X onto the stack, assuming it has mode MODE.
                    835:    MODE is redundant except when X is a CONST_INT (since they don't
                    836:    carry mode info).
                    837:    SIZE is an rtx for the size of data to be copied (in bytes),
                    838:    needed only if X is BLKmode.
                    839:    ALIGN (in bytes) is maximum alignment we can assume.  */
                    840: 
                    841: static void
                    842: emit_push_insn (x, mode, size, align)
                    843:      register rtx x;
                    844:      enum machine_mode mode;
                    845:      rtx size;
                    846:      int align;
                    847: {
                    848:   rtx xinner;
                    849: 
                    850:   xinner = x = protect_from_queue (x, 0);
                    851: 
                    852:   if (GET_CODE (x) == VOLATILE)
                    853:     xinner = XEXP (x, 0);
                    854: 
                    855:   if (mode == BLKmode)
                    856:     {
                    857:       register rtx temp;
                    858:          
                    859:       if (size == 0)
                    860:        abort ();
                    861: 
                    862:       if (GET_CODE (size) == CONST_INT
                    863:          && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)
                    864:              < MOVE_RATIO))
                    865:        move_by_pieces (gen_push_operand (),
                    866:                        XEXP (xinner, 0),
                    867:                        INTVAL (size), align,
                    868:                        0, GET_CODE (x) == VOLATILE);
                    869:       else
                    870:        {
                    871:          temp = push_block (size);
                    872: #ifdef HAVE_movstrsi
                    873:          if (HAVE_movstrsi)
                    874:            {
                    875:              emit_insn (gen_movstrsi (gen_rtx (MEM, BLKmode, temp), x, size));
                    876:              return;
                    877:            }
                    878: #endif
                    879: #ifdef HAVE_movstrhi
                    880:          if (HAVE_movstrhi
                    881:              && GET_CODE (size) == CONST_INT
                    882:              && ((unsigned) INTVAL (size)
                    883:                  < (1 << (GET_MODE_SIZE (HImode) * BITS_PER_UNIT - 1))))
                    884:            {
                    885:              emit_insn (gen_movstrhi (gen_rtx (MEM, BLKmode, temp),
                    886:                                       x, size));
                    887:              return;
                    888:            }
                    889: #endif
                    890:          /* Correct TEMP so it holds what will be a description of
                    891:             the address to copy to, valid after one arg is pushed.  */
                    892: #ifdef STACK_GROWS_DOWNWARD
                    893:          temp = plus_constant (temp, GET_MODE_SIZE (Pmode));
                    894: #else
                    895:          temp = plus_constant (temp, - GET_MODE_SIZE (Pmode));
                    896: #endif
                    897:          emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"),
                    898:                             3, XEXP (xinner, 0), Pmode,
                    899:                             temp, Pmode,
                    900:                             size, Pmode);
                    901:        }
                    902:     }
                    903:   else if (mov_optab[(int) mode].insn_code != CODE_FOR_nothing)
                    904:     {
                    905:       register rtx push = gen_rtx (MEM, mode, gen_push_operand ());
                    906:       emit_insn (GEN_FCN (mov_optab[(int) mode].insn_code) (push, x));
                    907:     }
                    908:   else
                    909:     abort ();
                    910: }
                    911: 
                    912: /* Output a library call to function FUN (a SYMBOL_REF rtx)
                    913:    with NARGS different arguments, passed as alternating rtx values
                    914:    and machine_modes to convert them to.
                    915:    The rtx values should have been passed through protect_from_queue already.  */
                    916: 
                    917: /*VARARGS2*/
                    918: void
                    919: emit_library_call (fun, nargs, a1)
                    920:      rtx fun;
                    921:      int nargs;
                    922:      struct { rtx value; enum machine_mode mode; } a1;
                    923: {
                    924:   register int args_size = 0;
                    925:   register int argnum;
                    926: #ifndef STACK_GROWS_DOWNWARD
                    927:   for (argnum = 0; argnum < nargs; argnum++)
                    928: #else
                    929:   for (argnum = nargs - 1; argnum >= 0; argnum--)
                    930: #endif
                    931:     {
                    932:       register enum machine_mode mode = (&a1)[argnum].mode;
                    933:       register rtx val = (&a1)[argnum].value;
                    934:       /* Convert the arg value to the mode the library wants.  */
                    935:       /* ??? It is wrong to do it here; must do it earlier
                    936:         where we know the signedness of the arg.  */
                    937:       if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
                    938:        {
                    939:          val = gen_reg_rtx (mode);
                    940:          convert_move (val, (&a1)[argnum].value, 0);
                    941:        }
                    942:       emit_push_insn (val, mode, 0, 0);
                    943:       args_size += GET_MODE_SIZE (mode);
                    944:       current_args_size += GET_MODE_SIZE (mode);
                    945:     }
                    946: 
                    947:   emit_queue ();
                    948:   gen_call_1 (fun, 0, args_size / GET_MODE_SIZE (SImode), args_size);
                    949: }
                    950: 
                    951: /* Expand an assignment that stores the value of FROM into TO.
                    952:    Return an rtx for the value of TO.  This may contain a QUEUED rtx.  */
                    953: 
                    954: rtx
                    955: expand_assignment (to, from)
                    956:      tree to, from;
                    957: {
                    958:   register rtx to_rtx = 0;
                    959: 
                    960:   /* Don't crash if the lhs of the assignment was erroneous.  */
                    961: 
                    962:   if (TREE_CODE (to) == ERROR_MARK)
                    963:     return expand_expr (from, 0, VOIDmode, 0);
                    964: 
                    965:   /* Assignment of a structure component needs special treatment
                    966:      if the structure component's rtx is not simply a MEM.  */
                    967: 
                    968:   if (TREE_CODE (to) == COMPONENT_REF)
                    969:     {
                    970:       register enum machine_mode mode1 = DECL_MODE (TREE_OPERAND (to, 1));
                    971:       int volstruct = 0;
                    972: 
                    973:       /* Get the structure as an rtx.  */
                    974: 
                    975:       to_rtx = expand_expr (TREE_OPERAND (to, 0), 0, VOIDmode, 0);
                    976: 
                    977:       /* If the structure is in a register or if the component
                    978:         is a bit field, we cannot use addressing to access it.
                    979:         Use bit-field techniques or SUBREG to store in it.  */
                    980: 
                    981:       if (mode1 == BImode || GET_CODE (to_rtx) == REG
                    982:          || GET_CODE (to_rtx) == SUBREG)
                    983:        {
                    984:          tree field = TREE_OPERAND (to, 1);
                    985:          int bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field);
                    986:          return store_bit_field (to_rtx, bitsize, DECL_OFFSET (field),
                    987:                                  DECL_MODE (field),
                    988:                                  expand_expr (from, 0, VOIDmode, 0));
                    989:        }
                    990: 
                    991:       /* Get the address of the structure the component is in.
                    992:         Record if structure is volatile.  */
                    993: 
                    994:       if (GET_CODE (to_rtx) == VOLATILE)
                    995:        {
                    996:          to_rtx = XEXP (to_rtx, 0);
                    997:          volstruct = 1;
                    998:        }
                    999:       if (GET_CODE (to_rtx) != MEM)
                   1000:        abort ();
                   1001:       to_rtx = XEXP (to_rtx, 0);
                   1002: 
                   1003:       /* Now build a reference to just the desired component.  */
                   1004: 
                   1005:       to_rtx = gen_rtx (MEM, mode1,
                   1006:                        memory_address (mode1,
                   1007:                                        plus_constant (to_rtx,
                   1008:                                                       (DECL_OFFSET
                   1009:                                                        (TREE_OPERAND (to, 1))
                   1010:                                                        / BITS_PER_UNIT))));
                   1011:       to_rtx->in_struct = 1;
                   1012: 
                   1013:       /* Make component volatile if structure is.  */
                   1014: 
                   1015:       if (! cse_not_expected && volstruct)
                   1016:        to_rtx = gen_rtx (VOLATILE, mode1, to_rtx);
                   1017:     }
                   1018: 
                   1019:   /* Arrays in registers also need special treatment.  */
                   1020: 
                   1021:   if (TREE_CODE (to) == ARRAY_REF)
                   1022:     {
                   1023:       /* Check to see whether the array is in a register.  */
                   1024:       tree array = TREE_OPERAND (TREE_OPERAND (to, 0), 0);
                   1025:       register tree temexp;
                   1026: 
                   1027:       /* Look through any COMPONENT_REFS to the containing struct.
                   1028:         Start by taking the array out of the ADDR_EXPR that's operand 0.  */
                   1029:       for (temexp = array;
                   1030:           TREE_CODE (temexp) == COMPONENT_REF;
                   1031:           temexp = TREE_OPERAND (temexp, 0));
                   1032: 
                   1033:       if (TREE_CODE (TREE_OPERAND (to, 1)) == INTEGER_CST
                   1034:          && TREE_CODE (temexp) == VAR_DECL
                   1035:          && DECL_RTL (temexp) != 0
                   1036:          && (GET_CODE (DECL_RTL (temexp)) == REG
                   1037:              || GET_CODE (DECL_RTL (temexp)) == SUBREG))
                   1038:        {
                   1039:          /* The array or containing struct is a variable in a register
                   1040:             and the index is constant.  */
                   1041:          int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (to)));
                   1042: 
                   1043:          to_rtx = expand_expr (array, 0, VOIDmode, 0);
                   1044:          return store_bit_field (to_rtx, bitsize,
                   1045:                                  TREE_INT_CST_LOW (TREE_OPERAND (to, 1)) * bitsize,
                   1046:                                  TYPE_MODE (TREE_TYPE (to)),
                   1047:                                  expand_expr (from, 0, VOIDmode, 0));
                   1048:        }
                   1049: 
                   1050:       /* The array is in memory.  Generate the tree for *(array+index)
                   1051:         and store into that insted.  */
                   1052: 
                   1053:       to = build_indirect_ref (build_binary_op (PLUS_EXPR,
                   1054:                                                TREE_OPERAND (to, 0),
                   1055:                                                TREE_OPERAND (to, 1)));
                   1056:     }
                   1057: 
                   1058:   /* Ordinary treatment.  Expand TO to get a REG or MEM rtx.
                   1059:      Don't re-expand if it was expanded already (in COMPONENT_REF case).  */
                   1060: 
                   1061:   if (to_rtx == 0)
                   1062:     to_rtx = expand_expr (to, 0, VOIDmode, 0);
                   1063: 
                   1064:   /* Compute FROM and store the value in the rtx we got.  */
                   1065: 
                   1066:   store_expr (from, to_rtx);
                   1067:   return to_rtx;
                   1068: }
                   1069: 
                   1070: /* Generate code for computing expression EXP,
                   1071:    and storing the value into TARGET.  Returns TARGET.
                   1072:    TARGET may contain a QUEUED rtx.  */
                   1073: 
                   1074: static rtx
                   1075: store_expr (exp, target)
                   1076:      register tree exp;
                   1077:      register rtx target;
                   1078: {
                   1079:   register rtx temp = expand_expr (exp, target, GET_MODE (target), 0);
                   1080:   if (temp != target && TREE_CODE (exp) != ERROR_MARK)
                   1081:     {
                   1082:       target = protect_from_queue (target, 1);
                   1083:       if (GET_MODE (temp) != GET_MODE (target)
                   1084:          && GET_MODE (temp) != VOIDmode)
                   1085:        convert_move (target, temp, type_unsigned_p (TREE_TYPE (exp)));
                   1086:       else if (GET_MODE (temp) == BLKmode)
                   1087:        emit_block_move (target, temp, expr_size (exp),
                   1088:                         TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
                   1089:       else
                   1090:        emit_move_insn (target, temp);
                   1091:     }
                   1092:   return target;
                   1093: }
                   1094: 
                   1095: /* Given an rtx VALUE that may contain additions and multiplications,
                   1096:    return an equivalent value that just refers to a register or memory.
                   1097:    This is done by generating instructions to perform the arithmetic
                   1098:    and returning a pseudo-register containing the value.  */
                   1099: 
                   1100: rtx
                   1101: force_operand (value, target)
                   1102:      rtx value, target;
                   1103: {
                   1104:   register struct optab *binoptab = 0;
                   1105:   register rtx op2 = XEXP (value, 1);
                   1106:   /* Use subtarget as the target for operand 0 of a binary operation.  */
                   1107:   register rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
                   1108: 
                   1109:   if (GET_CODE (value) == PLUS)
                   1110:     binoptab = add_optab;
                   1111:   else if (GET_CODE (value) == MINUS)
                   1112:     binoptab = sub_optab;
                   1113:   else if (GET_CODE (value) == MULT)
                   1114:     {
                   1115:       if (!CONSTANT_ADDRESS_P (op2)
                   1116:          && !(GET_CODE (op2) == REG && op2 != subtarget))
                   1117:        subtarget = 0;
                   1118:       return expand_mult (GET_MODE (value),
                   1119:                          force_operand (XEXP (value, 0), subtarget),
                   1120:                          force_operand (op2, 0),
                   1121:                          target, 0);
                   1122:     }
                   1123: 
                   1124:   if (binoptab)
                   1125:     {
                   1126:       if (!CONSTANT_ADDRESS_P (op2)
                   1127:          && !(GET_CODE (op2) == REG && op2 != subtarget))
                   1128:        subtarget = 0;
                   1129:       return expand_binop (GET_MODE (value), binoptab,
                   1130:                           force_operand (XEXP (value, 0), subtarget),
                   1131:                           force_operand (op2, 0),
                   1132:                           target, 0, OPTAB_LIB_WIDEN);
                   1133:       /* We give UNSIGNEP = 0 to expand_binop
                   1134:         because the only operations we are expanding here are signed ones.  */
                   1135:     }
                   1136:   return value;
                   1137: }
                   1138: 
                   1139: /* expand_expr: generate code for computing expression EXP.
                   1140:    An rtx for the computed value is returned.
                   1141: 
                   1142:    The value may be stored in TARGET if TARGET is nonzero.
                   1143:    TARGET is just a suggestion; callers must assume that
                   1144:    the rtx returned may not be the same as TARGET.
                   1145: 
                   1146:    If TMODE is not VOIDmode, it suggests generating the
                   1147:    result in mode TMODE.  But this is done only when convenient.
                   1148:    Otherwise, TMODE is ignored and the value generated in its natural mode.
                   1149:    TMODE is just a suggestion; callers must assume that
                   1150:    the rtx returned may not have mode TMODE.
                   1151: 
                   1152:    If SUM_OK is nonzero then when EXP is an addition
                   1153:    we can return an rtx of the form (MULT (REG ...) (CONST_INT ...))
                   1154:    or a nest of (PLUS ...) and (MINUS ...) where the terms are
                   1155:    products as above, or REG or MEM, or constant.
                   1156:    If SUM_OK is zero, in such cases we would output mul or add instructions
                   1157:    and then return a pseudo reg containing the sum.  */
                   1158: 
                   1159: /* Subroutine of expand_expr:
                   1160:    return the target to use when recursively expanding
                   1161:    the first operand of an arithmetic operation.  */
                   1162: 
                   1163: static rtx
                   1164: validate_subtarget (subtarget, otherop)
                   1165:      rtx subtarget;
                   1166:      tree otherop;
                   1167: {
                   1168:   if (TREE_LITERAL (otherop))
                   1169:     return subtarget;
                   1170:   if (TREE_CODE (otherop) == VAR_DECL
                   1171:       && DECL_RTL (otherop) != subtarget)
                   1172:     return subtarget;
                   1173:   return 0;
                   1174: }
                   1175: 
                   1176: rtx
                   1177: expand_expr (exp, target, tmode, sum_ok)
                   1178:      register tree exp;
                   1179:      rtx target;
                   1180:      enum machine_mode tmode;
                   1181:      int sum_ok;
                   1182: {
                   1183:   register rtx op0, op1, temp;
                   1184:   tree type = TREE_TYPE (exp);
                   1185:   register enum machine_mode mode = TYPE_MODE (type);
                   1186:   register enum tree_code code = TREE_CODE (exp);
                   1187:   struct optab *this_optab;
                   1188:   int negate_1;
                   1189:   /* Use subtarget as the target for operand 0 of a binary operation.  */
                   1190:   rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
                   1191:   static tree dbg2;
                   1192:   dbg2 = exp;
                   1193: 
                   1194:   /* If will do cse, generate all results into registers
                   1195:      since 1) that allows cse to find more things
                   1196:      and 2) otherwise cse could produce an insn the machine
                   1197:      cannot support.  */
                   1198: 
                   1199:   if (! cse_not_expected && mode != BLKmode)
                   1200:     target = subtarget;
                   1201: 
                   1202:   switch (code)
                   1203:     {
                   1204:     case FUNCTION_DECL:
                   1205:     case VAR_DECL:
                   1206:       temp = DECL_RTL (exp);
                   1207:       if (! cse_not_expected && TREE_VOLATILE (exp))
                   1208:        return gen_rtx (VOLATILE, DECL_MODE (exp), temp);
                   1209:       else
                   1210:        return temp;
                   1211: 
                   1212:     case PARM_DECL:
                   1213:     case RESULT_DECL:
                   1214:       if (DECL_RTL (exp) == 0)
                   1215:        abort ();
                   1216:       if (GET_CODE (DECL_RTL (exp)) == SYMBOL_REF)
                   1217:        abort ();
                   1218:       return DECL_RTL (exp);
                   1219: 
                   1220:     case INTEGER_CST:
                   1221:       return gen_rtx (CONST_INT, VOIDmode, TREE_INT_CST_LOW (exp));
                   1222: 
                   1223:     case CONST_DECL:
                   1224:       return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0);
                   1225: 
                   1226:     case REAL_CST:
                   1227:       if (TREE_CST_RTL (exp))
                   1228:        return TREE_CST_RTL (exp);
                   1229:       /* If optimized, generate immediate float
                   1230:         which will be turned into memory float if necessary.  */
                   1231:       if (!cse_not_expected)
                   1232:        return immed_real_const (exp);
                   1233:       output_constant_def (exp);
                   1234:       return TREE_CST_RTL (exp);
                   1235: 
                   1236:     case COMPLEX_CST:
                   1237:     case STRING_CST:
                   1238:       if (TREE_CST_RTL (exp))
                   1239:        return TREE_CST_RTL (exp);
                   1240:       output_constant_def (exp);
                   1241:       return TREE_CST_RTL (exp);
                   1242: 
                   1243:     case SAVE_EXPR:
                   1244:       if (SAVE_EXPR_RTL (exp) == 0)
                   1245:        {
                   1246:          SAVE_EXPR_RTL (exp) = gen_reg_rtx (mode);
                   1247:          store_expr (TREE_OPERAND (exp, 0), SAVE_EXPR_RTL (exp));
                   1248:        }
                   1249:       return SAVE_EXPR_RTL (exp);
                   1250: 
                   1251:     case INDIRECT_REF:
                   1252:       {
                   1253:        tree exp1 = TREE_OPERAND (exp, 0);
                   1254:        tree exp2;
                   1255: 
                   1256:        /* A SAVE_EXPR as the address in an INDIRECT_EXPR is generated
                   1257:           for  *PTR += ANYTHING  where PTR is put inside the SAVE_EXPR.
                   1258:           This code has the same general effect as simply doing
                   1259:           expand_expr on the save expr, except that the expression PTR
                   1260:           is computed for use as a memory address.  This means different
                   1261:           code, suitable for indexing, may be generated.  */
                   1262:        if (TREE_CODE (exp1) == SAVE_EXPR
                   1263:            && SAVE_EXPR_RTL (exp1) == 0
                   1264:            && TREE_CODE (exp2 = TREE_OPERAND (exp1, 0)) != ERROR_MARK
                   1265:            && TYPE_MODE (TREE_TYPE (exp1)) == Pmode
                   1266:            && TYPE_MODE (TREE_TYPE (exp2)) == Pmode)
                   1267:          {
                   1268:            temp = expand_expr (TREE_OPERAND (exp1, 0), 0, VOIDmode, 1);
                   1269:            op0 = memory_address (mode, temp);
                   1270:            op0 = copy_all_regs (op0);
                   1271:            SAVE_EXPR_RTL (exp1) = op0;
                   1272:          }
                   1273:        else
                   1274:          {
                   1275:            op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 1);
                   1276:            op0 = memory_address (mode, op0);
                   1277:          }
                   1278:       }
                   1279:       temp = gen_rtx (MEM, mode, op0);
                   1280:       if (! cse_not_expected && TREE_THIS_VOLATILE (exp))
                   1281:        return gen_rtx (VOLATILE, mode, temp);
                   1282:       else
                   1283:        return temp;
                   1284: 
                   1285:     case COMPONENT_REF:
                   1286:       {
                   1287:        register enum machine_mode mode1 = DECL_MODE (TREE_OPERAND (exp, 1));
                   1288:        int volstruct = 0;
                   1289:        tree dbg1 = TREE_OPERAND (exp, 0);  /* For debugging */
                   1290: 
                   1291:        op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   1292:        if (mode1 == BImode || GET_CODE (op0) == REG
                   1293:            || GET_CODE (op0) == SUBREG)
                   1294:          {
                   1295:            tree field = TREE_OPERAND (exp, 1);
                   1296:            int bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field);
                   1297:            return extract_bit_field (op0, bitsize, DECL_OFFSET (field),
                   1298:                                      type_unsigned_p (TREE_TYPE (field)),
                   1299:                                      target, mode, tmode);
                   1300:          }
                   1301:        if (tmode != VOIDmode)
                   1302:          mode = tmode;
                   1303:        /* Get the address of the structure the component is in.  */
                   1304:        if (GET_CODE (op0) == VOLATILE)
                   1305:          {
                   1306:            op0 = XEXP (op0, 0);
                   1307:            volstruct = 1;
                   1308:          }
                   1309:        if (GET_CODE (op0) != MEM)
                   1310:          abort ();
                   1311:        op0 = XEXP (op0, 0);
                   1312:        op0 = gen_rtx (MEM, mode1,
                   1313:                       memory_address (mode1,
                   1314:                                       plus_constant (op0,
                   1315:                                                      (DECL_OFFSET
                   1316:                                                       (TREE_OPERAND (exp, 1))
                   1317:                                                       / BITS_PER_UNIT))));
                   1318:        op0->in_struct = 1;
                   1319:        if (! cse_not_expected && volstruct)
                   1320:          op0 = gen_rtx (VOLATILE, mode1, op0);
                   1321:        if (mode == mode1 || mode == BLKmode)
                   1322:          return op0;
                   1323:        if (target == 0)
                   1324:          target = gen_reg_rtx (mode);
                   1325:        convert_move (target, op0, type_unsigned_p (TREE_TYPE (TREE_OPERAND (exp, 1))));
                   1326:        return target;
                   1327:       }
                   1328: 
                   1329:       /* ARRAY_REF is used in C for an actual array (not just a pointer)
                   1330:         indexed by a constant index.  It enables us to avoid taking the
                   1331:         address of the array, which may allow a short array (or a struct
                   1332:         or union containing one) to go in a register.  */
                   1333:     case ARRAY_REF:
                   1334:       {
                   1335:        /* Check to see whether the array is in a register.  */
                   1336:        tree array = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
                   1337:        register tree temexp;
                   1338: 
                   1339:        /* Look through any COMPONENT_REFS to the containing struct.
                   1340:           Start by taking the array out of the ADDR_EXPR that's operand 0.  */
                   1341:        for (temexp = array;
                   1342:             TREE_CODE (temexp) == COMPONENT_REF;
                   1343:             temexp = TREE_OPERAND (temexp, 0));
                   1344: 
                   1345:        if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
                   1346:            && TREE_CODE (temexp) == VAR_DECL
                   1347:            && DECL_RTL (temexp) != 0
                   1348:            && (GET_CODE (DECL_RTL (temexp)) == REG
                   1349:                || GET_CODE (DECL_RTL (temexp)) == SUBREG))
                   1350:          {
                   1351:            /* The array or containing struct is a variable in a register
                   1352:               and the index is constant.  */
                   1353:            int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (exp)));
                   1354: 
                   1355:            op0 = expand_expr (array, 0, VOIDmode, 0);
                   1356:            return extract_bit_field (op0, bitsize,
                   1357:                                      TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * bitsize,
                   1358:                                      type_unsigned_p (TREE_TYPE (exp)),
                   1359:                                      target, mode, tmode);
                   1360:          }
                   1361: 
                   1362:        /* The array is in memory.  Generate the tree for *(array+index)
                   1363:           and expand that.  */
                   1364: 
                   1365:        temexp = build_indirect_ref (build_binary_op (PLUS_EXPR,
                   1366:                                                      TREE_OPERAND (exp, 0),
                   1367:                                                      TREE_OPERAND (exp, 1)));
                   1368:        return expand_expr (temexp, 0, VOIDmode, 0);
                   1369:       }
                   1370: 
                   1371:       /* Intended for a reference to a buffer of a file-object in Pascal.
                   1372:         But it's not certain that a special tree code will really be
                   1373:         necessary for these.  INDIRECT_REF might work for them.  */
                   1374:     case BUFFER_REF:
                   1375:       abort ();
                   1376: 
                   1377:     case CALL_EXPR:
                   1378:       /* If this call was expanded already by preexpand_calls,
                   1379:         just return the result we got.  */
                   1380:       if (CALL_EXPR_RTL (exp) != 0)
                   1381:        return CALL_EXPR_RTL (exp);
                   1382:       return expand_call (exp, target);
                   1383: 
                   1384:     case NOP_EXPR:
                   1385:     case CONVERT_EXPR:
                   1386:       if (TREE_CODE (type) == VOID_TYPE)
                   1387:        {
                   1388:          expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, sum_ok);
                   1389:          return const0_rtx;
                   1390:        }
                   1391:       if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   1392:        return expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, sum_ok);
                   1393:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, mode, 0);
                   1394:       if (GET_MODE (op0) == mode)
                   1395:        return op0;
                   1396:       if (target == 0)
                   1397:        target = gen_reg_rtx (mode);
                   1398:       convert_move (target, op0, type_unsigned_p (TREE_TYPE (TREE_OPERAND (exp, 0))));
                   1399:       return target;
                   1400: 
                   1401:     case PLUS_EXPR:
                   1402:       preexpand_calls (exp);
                   1403:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
                   1404:        {
                   1405:          op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode, 1);
                   1406:          op1 = plus_constant (op1, TREE_INT_CST_LOW (TREE_OPERAND (exp, 0)));
                   1407:          if (sum_ok)
                   1408:            return op1;
                   1409:          return force_operand (op1, target);
                   1410:        }
                   1411:       negate_1 = 1;
                   1412:     plus_minus:
                   1413:       if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
                   1414:        {
                   1415:          op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 1);
                   1416:          op0 = plus_constant (op0,
                   1417:                               negate_1 * TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)));
                   1418:          if (sum_ok)
                   1419:            return op0;
                   1420:          return force_operand (op0, target);
                   1421:        }
                   1422:       this_optab = add_optab;
                   1423:       if (!sum_ok) goto binop;
                   1424:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   1425:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 1);
                   1426:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 1);
                   1427:       /* Put a sum last, to simplify what follows.  */
                   1428: #ifdef OLD_INDEXING
                   1429:       if (GET_CODE (op1) == MULT)
                   1430:        {
                   1431:          temp = op0;
                   1432:          op0 = op1;
                   1433:          op1 = temp;
                   1434:        }
                   1435: #endif
                   1436: #ifndef OLD_INDEXING
                   1437:       /* Make sure any term that's a sum with a constant comes last.  */
                   1438:       if (GET_CODE (op0) == PLUS
                   1439:          && CONSTANT_ADDRESS_P (XEXP (op0, 1)))
                   1440:        {
                   1441:          temp = op0;
                   1442:          op0 = op1;
                   1443:          op1 = temp;
                   1444:        }
                   1445:       /* If adding to a sum including a constant,
                   1446:         associate it to put the constant outside.  */
                   1447:       if (GET_CODE (op1) == PLUS
                   1448:          && CONSTANT_ADDRESS_P (XEXP (op1, 1)))
                   1449:        {
                   1450:          op0 = gen_rtx (PLUS, mode, XEXP (op1, 0), op0);
                   1451:          if (GET_CODE (XEXP (op1, 1)) == CONST_INT)
                   1452:            return plus_constant (op0, INTVAL (XEXP (op1, 1)));
                   1453:          else
                   1454:            return gen_rtx (PLUS, mode, op0, XEXP (op1, 1));
                   1455:        }
                   1456: #endif
                   1457:       return gen_rtx (PLUS, mode, op0, op1);
                   1458: 
                   1459:     case MINUS_EXPR:
                   1460:       preexpand_calls (exp);
                   1461:       if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
                   1462:        {
                   1463:          negate_1 = -1;
                   1464:          goto plus_minus;
                   1465:        }
                   1466:       this_optab = sub_optab;
                   1467:       goto binop;
                   1468: 
                   1469:     case MULT_EXPR:
                   1470:       preexpand_calls (exp);
                   1471:       /* If first operand is constant, swap them.
                   1472:         Thus the following special case checks need only
                   1473:         check the second operand.  */
                   1474:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
                   1475:        {
                   1476:          register tree t1 = TREE_OPERAND (exp, 0);
                   1477:          TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1);
                   1478:          TREE_OPERAND (exp, 1) = t1;
                   1479:        }
                   1480: 
                   1481:       /* Attempt to return something suitable for generating an
                   1482:         indexed address, for machines that support that.  */
                   1483: 
                   1484:       if (sum_ok && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST) 
                   1485:        {
                   1486:          op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   1487:          if (GET_CODE (op0) != REG)
                   1488:            {
                   1489:              temp = gen_reg_rtx (GET_MODE (op0));
                   1490:              emit_move_insn (temp, op0);
                   1491:              op0 = temp;
                   1492:            }
                   1493:          return gen_rtx (MULT, mode, op0, 
                   1494:                          gen_rtx (CONST_INT, VOIDmode,
                   1495:                                   TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))));
                   1496:        }
                   1497:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   1498:       /* Check for multiplying things that have been extended
                   1499:         from a narrower type.  If this machine supports multiplying
                   1500:         in that narrower type with a result in the desired type,
                   1501:         do it that way, and avoid the explicit type-conversion.  */
                   1502:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
                   1503:          && TREE_CODE (TREE_TYPE (exp)) == INTEGER_TYPE
                   1504:          && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
                   1505:              < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   1506:          && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
                   1507:               && int_fits_type_p (TREE_OPERAND (exp, 1),
                   1508:                                   TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))
                   1509:              ||
                   1510:              (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
                   1511:               && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
                   1512:                   ==
                   1513:                   TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))))))
                   1514:        {
                   1515:          enum machine_mode innermode
                   1516:            = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)));
                   1517:          this_optab = (type_unsigned_p (TREE_TYPE (exp))
                   1518:                        ? umul_widen_optab : smul_widen_optab);
                   1519:          if ((int) innermode + 1 == (int) mode
                   1520:              && this_optab[(int) mode].insn_code != CODE_FOR_nothing)
                   1521:            {
                   1522:              op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
                   1523:                                 0, VOIDmode, 0);
                   1524:              if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
                   1525:                op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1526:              else
                   1527:                op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
                   1528:                                   0, VOIDmode, 0);
                   1529:              goto binop2;
                   1530:            }
                   1531:        }
                   1532:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   1533:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1534:       return expand_mult (mode, op0, op1, target, type_unsigned_p (type));
                   1535: 
                   1536:     case TRUNC_DIV_EXPR:
                   1537:     case FLOOR_DIV_EXPR:
                   1538:     case CEIL_DIV_EXPR:
                   1539:     case ROUND_DIV_EXPR:
                   1540:       preexpand_calls (exp);
                   1541:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   1542:       /* Possible optimization: compute the dividend with SUM_OK
                   1543:         then if the divisor is constant can optimize the case
                   1544:         where some terms of the dividend have coeffs divisible by it.  */
                   1545:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   1546:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1547:       return expand_divmod (0, code, mode, op0, op1, target,
                   1548:                            type_unsigned_p (type));
                   1549: 
                   1550:     case RDIV_EXPR:
                   1551:       preexpand_calls (exp);
                   1552:       this_optab = flodiv_optab;
                   1553:       goto binop;
                   1554: 
                   1555:     case TRUNC_MOD_EXPR:
                   1556:     case FLOOR_MOD_EXPR:
                   1557:     case CEIL_MOD_EXPR:
                   1558:     case ROUND_MOD_EXPR:
                   1559:       preexpand_calls (exp);
                   1560:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   1561:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   1562:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1563:       return expand_divmod (1, code, mode, op0, op1, target,
                   1564:                            type_unsigned_p (type));
                   1565: #if 0
                   1566: #ifdef HAVE_divmoddisi4
                   1567:       if (GET_MODE (op0) != DImode)
                   1568:        {
                   1569:          temp = gen_reg_rtx (DImode);
                   1570:          convert_move (temp, op0, 0);
                   1571:          op0 = temp;
                   1572:          if (GET_MODE (op1) != SImode && GET_CODE (op1) != CONST_INT)
                   1573:            {
                   1574:              temp = gen_reg_rtx (SImode);
                   1575:              convert_move (temp, op1, 0);
                   1576:              op1 = temp;
                   1577:            }
                   1578:          temp = gen_reg_rtx (SImode);
                   1579:          if (target == 0)
                   1580:            target = gen_reg_rtx (SImode);
                   1581:          emit_insn (gen_divmoddisi4 (temp, protect_from_queue (op0, 0),
                   1582:                                      protect_from_queue (op1, 0),
                   1583:                                      protect_from_queue (target, 1)));
                   1584:          return target;
                   1585:        }
                   1586: #endif
                   1587: #endif
                   1588: 
                   1589:     case FIX_ROUND_EXPR:
                   1590:     case FIX_FLOOR_EXPR:
                   1591:     case FIX_CEIL_EXPR:
                   1592:       abort ();                        /* Not used for C.  */
                   1593: 
                   1594:     case FIX_TRUNC_EXPR:
                   1595:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   1596:       if (target == 0)
                   1597:        target = gen_reg_rtx (mode);
                   1598:       if (mode == HImode || mode == QImode)
                   1599:        {
                   1600:          register rtx temp = gen_reg_rtx (SImode);
                   1601:          expand_fix (temp, op0);
                   1602:          convert_move (target, temp, 0);
                   1603:        }
                   1604:       else
                   1605:        expand_fix (target, op0);
                   1606:       return target;
                   1607: 
                   1608:     case FLOAT_EXPR:
                   1609:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   1610:       if (target == 0)
                   1611:        target = gen_reg_rtx (mode);
                   1612:       if (GET_MODE (op0) == HImode
                   1613:          || GET_MODE (op0) == QImode)
                   1614:        {
                   1615:          register rtx temp = gen_reg_rtx (SImode);
                   1616:          convert_move (temp, op0, 0);
                   1617:          expand_float (target, temp);
                   1618:        }
                   1619:       else
                   1620:        expand_float (target, op0);
                   1621:       return target;
                   1622: 
                   1623:     case NEGATE_EXPR:
                   1624:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   1625:       temp = expand_unop (mode, neg_optab, op0, target, 0);
                   1626:       if (temp == 0)
                   1627:        abort ();
                   1628:       return temp;
                   1629: 
                   1630:     case ABS_EXPR:
                   1631:       /* First try to do it with a special abs instruction.
                   1632:         If that does not win, use conditional jump and negate.  */
                   1633:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   1634:       temp = expand_unop (mode, abs_optab, op0, target, 0);
                   1635:       if (temp != 0)
                   1636:        return temp;
                   1637:       temp = gen_label_rtx ();
                   1638:       if (target == 0 || GET_CODE (target) != REG)
                   1639:        target = gen_reg_rtx (GET_MODE (op0));
                   1640:       emit_move_insn (target, op0);
                   1641:       emit_tst_insn (target);
                   1642:       emit_jump_insn (gen_bge (temp));
                   1643:       op0 = expand_unop (mode, neg_optab, target, target, 0);
                   1644:       if (op0 != target)
                   1645:        emit_move_insn (target, op0);
                   1646:       emit_label (temp);
                   1647:       return target;
                   1648: 
                   1649:     case MAX_EXPR:
                   1650:     case MIN_EXPR:
                   1651:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1652:       if (target == 0 || GET_CODE (target) != REG || target == op1)
                   1653:        target = gen_reg_rtx (GET_MODE (op0));
                   1654:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   1655:       if (target != op0)
                   1656:        emit_move_insn (target, op0);
                   1657:       op0 = gen_label_rtx ();
                   1658:       if (code == MAX_EXPR)
                   1659:        temp = (type_unsigned_p (TREE_TYPE (TREE_OPERAND (exp, 1)))
                   1660:                ? compare1 (target, op1, GEU, LEU, 1)
                   1661:                : compare1 (target, op1, GE, LE, 0));
                   1662:       else
                   1663:        temp = (type_unsigned_p (TREE_TYPE (TREE_OPERAND (exp, 1)))
                   1664:                ? compare1 (target, op1, LEU, GEU, 1)
                   1665:                : compare1 (target, op1, LE, GE, 0));
                   1666:       emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
                   1667:                               gen_rtx (IF_THEN_ELSE, VOIDmode,
                   1668:                                        temp,
                   1669:                                        gen_rtx (LABEL_REF, VOIDmode, op0),
                   1670:                                        pc_rtx)));
                   1671:       emit_move_insn (target, op1);
                   1672:       emit_label (temp);
                   1673:       return target;
                   1674: 
                   1675: /* ??? Can optimize when the operand of this is a bitwise operation,
                   1676:    by using a different bitwise operation.  */
                   1677:     case BIT_NOT_EXPR:
                   1678:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   1679:       temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
                   1680:       if (temp == 0)
                   1681:        abort ();
                   1682:       return temp;
                   1683: 
                   1684: /* ??? Can optimize bitwise operations with one arg constant.
                   1685:    Pastel optimizes (a bitwise1 n) bitwise2 (a bitwise3 b)
                   1686:    and (a bitwise1 b) bitwise2 b (etc)
                   1687:    but that is probably not worth while.  */
                   1688: 
                   1689: /* AND_EXPR is for bitwise anding.
                   1690:    TRUTH_AND_EXPR is for anding two boolean values
                   1691:    when we want in all cases to compute both of them.
                   1692:    In general it is fastest to do TRUTH_AND_EXPR by
                   1693:    computing both operands as actual zero-or-1 values
                   1694:    and then bitwise anding.  In cases where there cannot
                   1695:    be any side effects, better code would be made by
                   1696:    treating TRUTH_AND_EXPR like TRUTH_ANDIF_EXPR;
                   1697:    but the question is how to recognize those cases.  */
                   1698: 
                   1699:     case TRUTH_AND_EXPR:
                   1700:     case BIT_AND_EXPR:
                   1701:       preexpand_calls (exp);
                   1702:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   1703:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   1704:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1705:       return expand_bit_and (mode, op0, op1, target);
                   1706: 
                   1707: /* See comment above about TRUTH_AND_EXPR; it applies here too.  */
                   1708:     case TRUTH_OR_EXPR:
                   1709:     case BIT_IOR_EXPR:
                   1710:       preexpand_calls (exp);
                   1711:       this_optab = ior_optab;
                   1712:       goto binop;
                   1713: 
                   1714:     case BIT_XOR_EXPR:
                   1715:       preexpand_calls (exp);
                   1716:       this_optab = xor_optab;
                   1717:       goto binop;
                   1718: 
                   1719:     case LSHIFT_EXPR:
                   1720:     case RSHIFT_EXPR:
                   1721:     case LROTATE_EXPR:
                   1722:     case RROTATE_EXPR:
                   1723:       preexpand_calls (exp);
                   1724:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   1725:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   1726:       return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
                   1727:                           type_unsigned_p (type));
                   1728: 
                   1729: /* ??? cv's were used to effect here to combine additive constants
                   1730:    and to determine the answer when only additive constants differ.
                   1731:    Also, the addition of one can be handled by changing the condition.  */
                   1732:     case LT_EXPR:
                   1733:     case LE_EXPR:
                   1734:     case GT_EXPR:
                   1735:     case GE_EXPR:
                   1736:     case EQ_EXPR:
                   1737:     case NE_EXPR:
                   1738:       preexpand_calls (exp);
                   1739:       temp = do_store_flag (exp, target);
                   1740:       if (temp != 0)
                   1741:        return temp;
                   1742:       if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1)))
                   1743:        {
                   1744:          /* For foo != 0, load foo, and if it is nonzero load 1 instead. */
                   1745:          temp = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   1746:          if (temp != subtarget)
                   1747:            temp = copy_to_reg (temp);
                   1748:          op1 = gen_label_rtx ();
                   1749:          emit_cmp_insn (temp, const0_rtx, 0, type_unsigned_p (type));
                   1750:          emit_jump_insn (gen_beq (op1));
                   1751:          emit_move_insn (temp, const1_rtx);
                   1752:          emit_label (op1);
                   1753:          return temp;
                   1754:        }
                   1755:       /* If no set-flag instruction, must generate a conditional
                   1756:         store into a temporary variable.  Drop through
                   1757:         and handle this like && and ||.  */
                   1758: 
                   1759:     case TRUTH_ANDIF_EXPR:
                   1760:     case TRUTH_ORIF_EXPR:
                   1761:       temp = gen_reg_rtx (mode);
                   1762:       emit_clr_insn (temp);
                   1763:       op1 = gen_label_rtx ();
                   1764:       jumpifnot (exp, op1);
                   1765:       emit_0_to_1_insn (temp);
                   1766:       emit_label (op1);
                   1767:       return temp;
                   1768: 
                   1769:     case TRUTH_NOT_EXPR:
                   1770:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   1771:       /* The parser is careful to generate TRUTH_NOT_EXPR
                   1772:         only with operands that are always zero or one.  */
                   1773:       temp = expand_binop (mode, xor_optab, op0,
                   1774:                           gen_rtx (CONST_INT, mode, 1),
                   1775:                           target, 1, OPTAB_LIB_WIDEN);
                   1776:       if (temp == 0)
                   1777:        abort ();
                   1778:       return temp;
                   1779: 
                   1780:     case COMPOUND_EXPR:
                   1781:       expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   1782:       emit_queue ();
                   1783:       return expand_expr (TREE_OPERAND (exp, 1), target, VOIDmode, 0);
                   1784: 
                   1785:     case COND_EXPR:
                   1786:       /* Note that COND_EXPRs whose type is a structure or union
                   1787:         are required to be constructed to contain assignments of
                   1788:         a temporary variable, so that we can evaluate them here
                   1789:         for side effect only.  If type is void, we must do likewise.  */
                   1790:       op0 = gen_label_rtx ();
                   1791:       op1 = gen_label_rtx ();
                   1792: 
                   1793:       if (mode == BLKmode || mode == VOIDmode)
                   1794:        temp = 0;
                   1795:       else if (target)
                   1796:        temp = target;
                   1797:       else
                   1798:        temp = gen_reg_rtx (mode);
                   1799: 
                   1800:       jumpifnot (TREE_OPERAND (exp, 0), op0);
                   1801:       current_args_size += 1;
                   1802:       if (temp != 0)
                   1803:        store_expr (TREE_OPERAND (exp, 1), temp);
                   1804:       else
                   1805:        expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1806:       emit_queue ();
                   1807:       emit_jump_insn (gen_jump (op1));
                   1808:       emit_barrier ();
                   1809:       emit_label (op0);
                   1810:       if (temp != 0)
                   1811:        store_expr (TREE_OPERAND (exp, 2), temp);
                   1812:       else
                   1813:        expand_expr (TREE_OPERAND (exp, 2), 0, VOIDmode, 0);
                   1814:       emit_queue ();
                   1815:       emit_label (op1);
                   1816:       current_args_size -= 1;
                   1817:       return temp;
                   1818: 
                   1819:     case MODIFY_EXPR:
                   1820:       /* If lhs is complex, expand calls in rhs before computing it.
                   1821:         That's so we don't compute a pointer and save it over a call.
                   1822:         If lhs is simple, compute it first so we can give it as a
                   1823:         target if the rhs is just a call.  This avoids an extra temp and copy
                   1824:         and that prevents a partial-subsumption which makes bad code.
                   1825:         Actually we could treat component_ref's of vars like vars.  */
                   1826:       if (TREE_CODE (TREE_OPERAND (exp, 0)) != VAR_DECL)
                   1827:        preexpand_calls (exp);
                   1828:       temp = expand_assignment (TREE_OPERAND (exp, 0),
                   1829:                                TREE_OPERAND (exp, 1));
                   1830:       return temp;
                   1831: 
                   1832:     case PREINCREMENT_EXPR:
                   1833:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   1834:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1835:       expand_binop (mode, add_optab, copy_rtx (op0), op1, copy_rtx (op0),
                   1836:                    0, OPTAB_LIB_WIDEN);
                   1837:       return op0;
                   1838: 
                   1839:     case PREDECREMENT_EXPR:
                   1840:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   1841:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1842:       expand_binop (mode, sub_optab, copy_rtx (op0), op1, copy_rtx (op0),
                   1843:                    0, OPTAB_LIB_WIDEN);
                   1844:       return op0;
                   1845: 
                   1846:     case POSTINCREMENT_EXPR:
                   1847:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   1848:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1849:       op0 = stabilize (op0);
                   1850:       return enqueue_insn (op0, gen_add2_insn (copy_rtx (op0), op1));
                   1851: 
                   1852:     case POSTDECREMENT_EXPR:
                   1853:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   1854:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1855:       op0 = stabilize (op0);
                   1856:       return enqueue_insn (op0, gen_sub2_insn (copy_rtx (op0), op1));
                   1857: 
                   1858:     case ADDR_EXPR:
                   1859:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   1860:       if (GET_CODE (op0) == VOLATILE)
                   1861:        op0 = XEXP (op0, 0);
                   1862:       if (GET_CODE (op0) != MEM)
                   1863:        abort ();
                   1864:       if (sum_ok)
                   1865:        return XEXP (op0, 0);
                   1866:       return force_operand (XEXP (op0, 0), target);
                   1867: 
                   1868:     case ENTRY_VALUE_EXPR:
                   1869:       abort ();
                   1870: 
                   1871:     case ERROR_MARK:
                   1872:       return gen_rtx (CONST_INT, (mode != VOIDmode) ? mode : SImode, 0);
                   1873: 
                   1874:     default:
                   1875:       abort ();
                   1876:     }
                   1877: 
                   1878:   /* Here to do an ordinary binary operator, generating an instruction
                   1879:      from the optab already placed in `this_optab'.  */
                   1880:  binop:
                   1881:   /* Detect things like x = y | (a == b)
                   1882:      and do them as (x = y), (a == b ? x |= 1 : 0), x.  */
                   1883:   /* First, get the comparison or conditional into the second arg.  */
                   1884:   if (comparison_code[(int) TREE_CODE (TREE_OPERAND (exp, 0))]
                   1885:       || (TREE_CODE (TREE_OPERAND (exp, 0)) == COND_EXPR
                   1886:          && (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
                   1887:              || integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 2)))))
                   1888:     {
                   1889:       if (this_optab == ior_optab || this_optab == add_optab
                   1890:          || this_optab == xor_optab)
                   1891:        {
                   1892:          tree exch = TREE_OPERAND (exp, 1);
                   1893:          TREE_OPERAND (exp, 1) = TREE_OPERAND (exp, 0);
                   1894:          TREE_OPERAND (exp, 0) = exch;
                   1895:        }
                   1896:     }
                   1897:   if (comparison_code[(int) TREE_CODE (TREE_OPERAND (exp, 1))]
                   1898:       || (TREE_CODE (TREE_OPERAND (exp, 1)) == COND_EXPR
                   1899:          && (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 1))
                   1900:              || integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 2)))))
                   1901:     {
                   1902:       if (this_optab == ior_optab || this_optab == add_optab
                   1903:          || this_optab == xor_optab || this_optab == sub_optab
                   1904:          || this_optab == lshl_optab || this_optab == ashl_optab
                   1905:          || this_optab == lshr_optab || this_optab == ashr_optab
                   1906:          || this_optab == rotl_optab || this_optab == rotr_optab)
                   1907:        {
                   1908:          tree thenexp, condexp;
                   1909:          rtx thenv = 0;
                   1910: 
                   1911:          if (target == 0) target = gen_reg_rtx (mode);
                   1912:          store_expr (TREE_OPERAND (exp, 0), target);
                   1913:          op0 = gen_label_rtx ();
                   1914: 
                   1915:          if (TREE_CODE (TREE_OPERAND (exp, 1)) != COND_EXPR)
                   1916:            {
                   1917:              do_jump (TREE_OPERAND (exp, 1), op0, 0);
                   1918:              thenv = const1_rtx;
                   1919:            }
                   1920:          else if (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 2)))
                   1921:            {
                   1922:              do_jump (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), op0, 0);
                   1923:              thenexp = TREE_OPERAND (TREE_OPERAND (exp, 1), 1);
                   1924:            }
                   1925:          else
                   1926:            {
                   1927:              do_jump (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0, op0);
                   1928:              thenexp = TREE_OPERAND (TREE_OPERAND (exp, 1), 2);
                   1929:            }
                   1930: 
                   1931:          if (thenv == 0)
                   1932:            thenv = expand_expr (thenexp, 0, VOIDmode, 0);
                   1933: 
                   1934:          if (this_optab == rotl_optab || this_optab == rotr_optab)
                   1935:            temp = expand_binop (mode, this_optab, target, thenv, target,
                   1936:                                 -1, OPTAB_LIB);
                   1937:          else if (this_optab == lshl_optab || this_optab == lshr_optab)
                   1938:            temp = expand_binop (mode, this_optab, target, thenv, target,
                   1939:                                 1, OPTAB_LIB_WIDEN);
                   1940:          else
                   1941:            temp = expand_binop (mode, this_optab, target, thenv, target,
                   1942:                                 0, OPTAB_LIB_WIDEN);
                   1943:          if (target != temp)
                   1944:            emit_move_insn (target, temp);
                   1945: 
                   1946:          emit_label (op0);
                   1947:          return target;
                   1948:        }
                   1949:     }
                   1950:   subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   1951:   op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   1952:   op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   1953:  binop2:
                   1954:   temp = expand_binop (mode, this_optab, op0, op1, target,
                   1955:                       type_unsigned_p (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
                   1956:  binop1:
                   1957:   if (temp == 0)
                   1958:     abort ();
                   1959:   return temp;
                   1960: }
                   1961: 
                   1962: /* Expand all function calls contained within EXP, innermost ones first.
                   1963:    But don't look within expressions that have sequence points.
                   1964:    For each CALL_EXPR, record the rtx for its value
                   1965:    in the CALL_EXPR_RTL field..  */
                   1966: 
                   1967: static void
                   1968: preexpand_calls (exp)
                   1969:      tree exp;
                   1970: {
                   1971:   register int nops, i;
                   1972: 
                   1973:   if (! do_preexpand_calls)
                   1974:     return;
                   1975: 
                   1976:   switch (TREE_CODE (exp))
                   1977:     {
                   1978:     case CALL_EXPR:
                   1979:       if (CALL_EXPR_RTL (exp) == 0)
                   1980:        CALL_EXPR_RTL (exp) = expand_call (exp, 0);
                   1981:       return;
                   1982: 
                   1983:     case COMPOUND_EXPR:
                   1984:     case COND_EXPR:
                   1985:     case TRUTH_ANDIF_EXPR:
                   1986:     case TRUTH_ORIF_EXPR:
                   1987:       /* If we find one of these, then we can be sure
                   1988:         the adjust will be done for it (since it makes jumps).
                   1989:         Do it now, so that if this is inside an argument
                   1990:         of a function, we don't get the stack adjustment
                   1991:         after some other args have already been pushed.  */
                   1992:       do_pending_stack_adjust ();
                   1993:       return;
                   1994: 
                   1995:     case SAVE_EXPR:
                   1996:       if (SAVE_EXPR_RTL (exp) != 0)
                   1997:        return;
                   1998:     }
                   1999: 
                   2000:   nops = tree_code_length[(int) TREE_CODE (exp)];
                   2001:   for (i = 0; i < nops; i++)
                   2002:     if (TREE_OPERAND (exp, i) != 0)
                   2003:       {
                   2004:        register int type = *tree_code_type[(int) TREE_CODE (TREE_OPERAND (exp, i))];
                   2005:        if (type == 'e' || type == 'r')
                   2006:          preexpand_calls (TREE_OPERAND (exp, i));
                   2007:       }
                   2008: }
                   2009: 
                   2010: /* Generate instructions to call function FUNEXP and pass
                   2011:    it the static chain.  NARGS is the "number of args",
                   2012:    to put in the call instruction on machines that require this.
                   2013:    Also generate the code to pop the args after returning,
                   2014:    (ARGS_SIZE is size of stuff to pop, in bytes).  */
                   2015: 
                   2016: static void
                   2017: gen_call_1 (funexp, context, nargs, args_size)
                   2018:      rtx funexp;
                   2019:      rtx context;
                   2020:      int nargs;
                   2021:      int args_size;
                   2022: {
                   2023:   funexp = protect_from_queue (funexp, 0);
                   2024:   if (context)
                   2025:     context = protect_from_queue (context, 0);
                   2026: 
                   2027:   /* Function variable in language with nested functions.  */
                   2028:   if (GET_MODE (funexp) == EPmode)
                   2029:     {
                   2030:       register rtx reg = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM);
                   2031:       emit_insn (gen_movsi (reg, gen_highpart (Pmode, funexp)));
                   2032:       emit_insn (gen_rtx (USE, VOIDmode, reg));
                   2033:       funexp = memory_address (QImode, gen_lowpart (Pmode, funexp));
                   2034:       emit_call_insn (gen_call (gen_rtx (MEM, QImode, funexp),
                   2035:                                gen_rtx (CONST_INT, VOIDmode, nargs)));
                   2036:     }
                   2037:   else
                   2038:     {
                   2039:       if (context != 0)
                   2040:        {
                   2041:          /* Unless function variable in C, or top level function constant */
                   2042:          register rtx reg = gen_rtx (REG, Pmode, STATIC_CHAIN_REGNUM);
                   2043:          emit_insn (gen_movsi (reg, lookup_static_chain (context)));
                   2044:          emit_insn (gen_rtx (USE, VOIDmode, reg));
                   2045:        }
                   2046:       emit_call_insn (gen_call (gen_rtx (MEM, QImode, 
                   2047:                                         memory_address (QImode, funexp)),
                   2048:                                gen_rtx (CONST_INT, VOIDmode, nargs)));
                   2049:     }
                   2050:   /* If returning from the subroutine does not automatically pop the args,
                   2051:      we need an instruction to pop them sooner or later.
                   2052:      Perhaps do it now; perhaps just record how much space to pop later.  */
                   2053:   current_args_size -= args_size;
                   2054: #ifndef RETURN_POPS_ARGS
                   2055:   if (args_size != 0)
                   2056:     {
                   2057:       if (TARGET_DEFER_POP && current_args_size == 0)
                   2058:        pending_stack_adjust += args_size;
                   2059:       else
                   2060:        adjust_stack (gen_rtx (CONST_INT, VOIDmode, args_size));
                   2061:     }
                   2062: #endif
                   2063: }
                   2064: 
                   2065: /* At the start of a function, record that we have no previously-pushed
                   2066:    arguments waiting to be popped.  */
                   2067: 
                   2068: clear_pending_stack_adjust ()
                   2069: {
                   2070:   pending_stack_adjust = 0;
                   2071: }
                   2072: 
                   2073: /* At start of function, initialize.  */
                   2074: clear_current_args_size ()
                   2075: {
                   2076:   current_args_size = 0;
                   2077: }
                   2078: 
                   2079: /* Pop any previously-pushed arguments that have not been popped yet.  */
                   2080: 
                   2081: do_pending_stack_adjust ()
                   2082: {
                   2083:   if (current_args_size == 0)
                   2084:     {
                   2085:       if (pending_stack_adjust != 0)
                   2086:        adjust_stack (gen_rtx (CONST_INT, VOIDmode, pending_stack_adjust));
                   2087:       pending_stack_adjust = 0;
                   2088:     }
                   2089: }
                   2090: 
                   2091: /* Generate all the code for a function call
                   2092:    and return an rtx for its value.
                   2093:    Store the value in TARGET (specified as an rtx) if convenient.
                   2094:    If the value is stored in TARGET then TARGET is returned.  */
                   2095: 
                   2096: static rtx
                   2097: expand_call (exp, target)
                   2098:      tree exp;
                   2099:      rtx target;
                   2100: {
                   2101:   tree actparms = TREE_OPERAND (exp, 1);
                   2102:   register tree p;
                   2103:   int args_size = 0;
                   2104:   register int i;
                   2105:   register tree *argvec;
                   2106:   int num_actuals;
                   2107:   rtx structure_value_addr = 0;
                   2108: 
                   2109:   /* Don't let pending stack adjusts add up to too much.
                   2110:      Also, do all pending adjustments now
                   2111:      if there is any chance this might be a call to alloca.  */
                   2112: 
                   2113:   if (pending_stack_adjust >= 32
                   2114:       || (pending_stack_adjust > 0
                   2115:          &&
                   2116:          /* Unless it's a call to a specific function that isn't alloca,
                   2117:             we must assume it might be alloca.  */
                   2118:          !(p = TREE_OPERAND (exp, 0),
                   2119:            TREE_CODE (p) == ADDR_EXPR
                   2120:            && TREE_CODE (TREE_OPERAND (p, 0)) == FUNCTION_DECL
                   2121:            && strcmp (IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (p, 0))),
                   2122:                       "alloca"))))
                   2123:     do_pending_stack_adjust ();
                   2124: 
                   2125:   if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode)
                   2126:     {
                   2127:       /* This call returns a big structure.  */
                   2128:       if (target)
                   2129:        structure_value_addr = XEXP (target, 0);
                   2130:       else
                   2131:        /* Make room on the stack to hold the value.  */
                   2132:        structure_value_addr = get_structure_value_addr (expr_size (exp));
                   2133:     }
                   2134: 
                   2135:   for (p = actparms, i = 0; p; p = TREE_CHAIN (p)) i++;
                   2136:   num_actuals = i;
                   2137:   argvec = (tree *) alloca (i * sizeof (tree));
                   2138: 
                   2139: #ifdef STACK_GROWS_DOWNWARD
                   2140:   /* In this case, must reverse order of args
                   2141:      so that we compute and pust the last arg first.  */
                   2142:   for (p = actparms, i = num_actuals - 1; p; p = TREE_CHAIN (p), i--)
                   2143:     argvec[i] = p;
                   2144: #else
                   2145:   for (p = actparms, i = 0; p; p = TREE_CHAIN (p), i++)
                   2146:     argvec[i] = p;
                   2147: #endif
                   2148:   
                   2149:   for (i = 0; i < num_actuals; i++)
                   2150:     {
                   2151:       register tree p = argvec[i];
                   2152:       register tree pval = TREE_VALUE (p);
                   2153: 
                   2154:       /* Push the next argument.  Note that it has already been converted
                   2155:         if necessary to the type that the called function expects.  */
                   2156: 
                   2157:       if (TREE_CODE (pval) == ERROR_MARK)
                   2158:        ;
                   2159:       else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode)
                   2160:        {
                   2161:          register int size, used;
                   2162: 
                   2163:          /* Argument is a scalar.
                   2164:             Push it, and if its size is less than the
                   2165:             amount of space allocated to it,
                   2166:             also bump stack pointer by the additional space.
                   2167:             Note that in C the default argument promotions
                   2168:             will prevent such mismatches.  */
                   2169: 
                   2170:          used = size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (pval)));
                   2171:          /* Compute how much space the push instruction will push.
                   2172:             On many machines, pushing a byte will advance the stack
                   2173:             pointer by a halfword.  */
                   2174:          size = PUSH_ROUNDING (size);
                   2175:          /* Compute how much space the argument should get:
                   2176:             round up to a multiple of the alignment for arguments.  */
                   2177:          used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
                   2178:                   / (PARM_BOUNDARY / BITS_PER_UNIT))
                   2179:                  * (PARM_BOUNDARY / BITS_PER_UNIT));
                   2180: 
                   2181: #ifdef STACK_GROWS_DOWNWARD
                   2182:          if (size != used)
                   2183:            anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode,
                   2184:                                        used - size));
                   2185: #endif
                   2186: 
                   2187:          emit_push_insn (expand_expr (pval, 0, VOIDmode, 0),
                   2188:                          TYPE_MODE (TREE_TYPE (pval)), 0, 0);
                   2189: 
                   2190: #ifndef STACK_GROWS_DOWNWARD
                   2191:          if (size != used)
                   2192:            anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode,
                   2193:                                        used - size));
                   2194: #endif
                   2195: 
                   2196:          /* Account for the space thus used.  */
                   2197:          args_size += used;
                   2198:          current_args_size += used;
                   2199:        }
                   2200:       else
                   2201:        {
                   2202:          register rtx tem = expand_expr (pval, 0, VOIDmode, 0);
                   2203:          register tree size = size_in_bytes (TREE_TYPE (pval));
                   2204:          register tree used;
                   2205:          register int excess;
                   2206: 
                   2207:          /* Pushing a nonscalar.  Round its size up to a multiple
                   2208:             of the allocation unit for arguments.  This part works
                   2209:             on variable-size objects since SIZE and USED are rtx's.  */
                   2210: 
                   2211:          used = convert_units (convert_units (size, BITS_PER_UNIT, PARM_BOUNDARY),
                   2212:                                PARM_BOUNDARY, BITS_PER_UNIT);
                   2213: 
                   2214:          if (!TREE_LITERAL (used))
                   2215:            abort ();
                   2216: 
                   2217:          excess = TREE_INT_CST_LOW (used) - PUSH_ROUNDING (TREE_INT_CST_LOW (size));
                   2218: 
                   2219: #ifdef STACK_GROWS_DOWNWARD
                   2220:          if (excess != 0)
                   2221:            anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, excess));
                   2222: #endif
                   2223: 
                   2224:          emit_push_insn (tem, TYPE_MODE (TREE_TYPE (pval)),
                   2225:                          expand_expr (size, 0, VOIDmode, 0),
                   2226:                          (TYPE_ALIGN (TREE_TYPE (pval))
                   2227:                           / BITS_PER_UNIT));
                   2228: 
                   2229: #ifndef STACK_GROWS_DOWNWARD
                   2230:          if (excess != 0)
                   2231:            anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, excess));
                   2232: #endif
                   2233:          args_size += TREE_INT_CST_LOW (used);
                   2234:          current_args_size += TREE_INT_CST_LOW (used);
                   2235:        }
                   2236:     }
                   2237: 
                   2238:   /* Perform postincrements before actually calling the function.  */
                   2239:   emit_queue ();
                   2240: 
                   2241:   /* Pass the function the address in which to return a structure value.  */
                   2242:   if (structure_value_addr)
                   2243:     {
                   2244:       register rtx reg = gen_rtx (REG, Pmode, STRUCT_VALUE_REGNUM);
                   2245:       emit_move_insn (reg, structure_value_addr);
                   2246:       emit_insn (gen_rtx (USE, VOIDmode, reg));
                   2247:     }
                   2248: 
                   2249:   gen_call_1 (expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0),
                   2250: /* ??? For Pascal, this must pass a context to get the static chain from
                   2251:    in certain cases.  */
                   2252:              0,
                   2253:              args_size / GET_MODE_SIZE (SImode), args_size);
                   2254: 
                   2255: /* ???  Nothing has been done here to record control flow
                   2256:    when contained functions can do nonlocal gotos.  */
                   2257: 
                   2258:   /* If value type not void, return an rtx for the value.  */
                   2259: 
                   2260:   if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode)
                   2261:     return 0;
                   2262: 
                   2263:   if (structure_value_addr)
                   2264:     {
                   2265:       if (target)
                   2266:        return target;
                   2267:       return gen_rtx (MEM, BLKmode, structure_value_addr);
                   2268:     }
                   2269:   
                   2270:   if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)))
                   2271:     {
                   2272:       copy_function_value (target);
                   2273:       return target;
                   2274:     }
                   2275:   return function_value (TYPE_MODE (TREE_TYPE (exp)));
                   2276: }
                   2277: 
                   2278: /* Expand conditional expressions.  */
                   2279: 
                   2280: /* Generate code to evaluate EXP and jump to LABEL if the value is zero.
                   2281:    LABEL is an rtx of code CODE_LABEL, in this function and all the
                   2282:    functions here.  */
                   2283: 
                   2284: jumpifnot (exp, label)
                   2285:      tree exp;
                   2286:      rtx label;
                   2287: {
                   2288:   do_jump (exp, label, 0);
                   2289: }
                   2290: 
                   2291: /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero.  */
                   2292: 
                   2293: jumpif (exp, label)
                   2294:      tree exp;
                   2295:      rtx label;
                   2296: {
                   2297:   do_jump (exp, 0, label);
                   2298: }
                   2299: 
                   2300: /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
                   2301:    the result is zero, or IF_TRUE_LABEL if the result is one.
                   2302:    Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero,
                   2303:    meaning fall through in that case.
                   2304: 
                   2305:    This function is responsible for optimizing cases such as
                   2306:    &&, || and comparison operators in EXP.  */
                   2307: 
                   2308: do_jump (exp, if_false_label, if_true_label)
                   2309:      tree exp;
                   2310:      rtx if_false_label, if_true_label;
                   2311: {
                   2312:   register enum tree_code code = TREE_CODE (exp);
                   2313:   /* Some cases need to create a label to jump to
                   2314:      in order to properly fall through.
                   2315:      These cases set DROP_THROUGH_LABEL nonzero.  */
                   2316:   rtx drop_through_label = 0;
                   2317:   rtx temp;
                   2318:   rtx comparison = 0;
                   2319: 
                   2320:   emit_queue ();
                   2321: 
                   2322:   switch (code)
                   2323:     {
                   2324:     case ERROR_MARK:
                   2325:       break;
                   2326: 
                   2327:     case INTEGER_CST:
                   2328:       temp = integer_zerop (exp) ? if_false_label : if_true_label;
                   2329:       if (temp)
                   2330:        emit_jump (temp);
                   2331:       break;
                   2332: 
                   2333:     case ADDR_EXPR:
                   2334:       /* The address of something can never be zero.  */
                   2335:       if (if_true_label)
                   2336:        emit_jump (if_true_label);
                   2337:       break;
                   2338: 
                   2339:     case NOP_EXPR:
                   2340:       do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
                   2341:       break;
                   2342: 
                   2343:     case TRUTH_NOT_EXPR:
                   2344:       do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
                   2345:       break;
                   2346: 
                   2347:     case TRUTH_ANDIF_EXPR:
                   2348:       if (if_false_label == 0)
                   2349:        if_false_label = drop_through_label = gen_label_rtx ();
                   2350:       do_jump (TREE_OPERAND (exp, 0), if_false_label, 0);
                   2351:       do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
                   2352:       break;
                   2353: 
                   2354:     case TRUTH_ORIF_EXPR:
                   2355:       if (if_true_label == 0)
                   2356:        if_true_label = drop_through_label = gen_label_rtx ();
                   2357:       do_jump (TREE_OPERAND (exp, 0), 0, if_true_label);
                   2358:       do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
                   2359:       break;
                   2360: 
                   2361:     case COMPOUND_EXPR:
                   2362:       expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   2363:       emit_queue ();
                   2364:       do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
                   2365:       break;
                   2366: 
                   2367:     case COND_EXPR:
                   2368:       {
                   2369:        register rtx label1 = gen_label_rtx ();
                   2370:        drop_through_label = gen_label_rtx ();
                   2371:        do_jump (TREE_OPERAND (exp, 0), label1, 0);
                   2372:        /* Now the THEN-expression.  */
                   2373:        do_jump (TREE_OPERAND (exp, 1),
                   2374:                 if_false_label ? if_false_label : drop_through_label,
                   2375:                 if_true_label ? if_true_label : drop_through_label);
                   2376:        emit_label (label1);
                   2377:        /* Now the ELSE-expression.  */
                   2378:        do_jump (TREE_OPERAND (exp, 2),
                   2379:                 if_false_label ? if_false_label : drop_through_label,
                   2380:                 if_true_label ? if_true_label : drop_through_label);
                   2381:       }
                   2382:       break;
                   2383: 
                   2384:     case EQ_EXPR:
                   2385:       comparison = compare (exp, EQ, EQ, EQ, EQ);
                   2386:       break;
                   2387: 
                   2388:     case NE_EXPR:
                   2389:       comparison = compare (exp, NE, NE, NE, NE);
                   2390:       break;
                   2391: 
                   2392:     case LT_EXPR:
                   2393:       comparison = compare (exp, LT, LTU, GT, GTU);
                   2394:       break;
                   2395: 
                   2396:     case LE_EXPR:
                   2397:       comparison = compare (exp, LE, LEU, GE, GEU);
                   2398:       break;
                   2399: 
                   2400:     case GT_EXPR:
                   2401:       comparison = compare (exp, GT, GTU, LT, LTU);
                   2402:       break;
                   2403: 
                   2404:     case GE_EXPR:
                   2405:       comparison = compare (exp, GE, GEU, LE, LEU);
                   2406:       break;
                   2407: 
                   2408:     default:
                   2409:       temp = expand_expr (exp, 0, VOIDmode, 0);
                   2410:       do_pending_stack_adjust ();
                   2411:       emit_cmp_insn (temp, gen_rtx (CONST_INT, GET_MODE (temp), 0),
                   2412:                     0, 0);
                   2413: 
                   2414:       if (if_true_label)
                   2415:        emit_jump_insn (gen_bne (if_true_label));
                   2416:       if (if_false_label)
                   2417:        {
                   2418:          if (if_true_label)
                   2419:            emit_jump (if_false_label);
                   2420:          else
                   2421:            emit_jump_insn (gen_beq (if_false_label));
                   2422:        }
                   2423:     }
                   2424: 
                   2425:   /* If COMPARISON is nonzero here, it is an rtx that can be substituted
                   2426:      straight into a conditional jump instruction as the jump condition.
                   2427:      Otherwise, all the work has been done already.  */
                   2428: 
                   2429:   if (comparison)
                   2430:     if (if_true_label)
                   2431:       {
                   2432:        emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
                   2433:                                 gen_rtx (IF_THEN_ELSE, VOIDmode, comparison,
                   2434:                                          gen_rtx (LABEL_REF, VOIDmode,
                   2435:                                                   if_true_label),
                   2436:                                          pc_rtx)));
                   2437:        if (if_false_label)
                   2438:          emit_jump (if_false_label);
                   2439:       }
                   2440:     else if (if_false_label)
                   2441:       {
                   2442:        emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
                   2443:                                 gen_rtx (IF_THEN_ELSE, VOIDmode, comparison,
                   2444:                                          pc_rtx,
                   2445:                                          gen_rtx (LABEL_REF, VOIDmode,
                   2446:                                                   if_false_label))));
                   2447:       }
                   2448: 
                   2449:   if (drop_through_label)
                   2450:     emit_label (drop_through_label);
                   2451: }
                   2452: 
                   2453: /* Generate code for a comparison expression EXP
                   2454:    (including code to compute the values to be compared)
                   2455:    and set (CC0) according to the result.
                   2456:    SIGNED_FORWARD should be the rtx operation for this comparison for
                   2457:    signed data; UNSIGNED_FORWARD, likewise for use if data is unsigned.
                   2458:    SIGNED_REVERSE and UNSIGNED_REVERSE are used if it is desirable
                   2459:    to interchange the operands for the compare instruction.
                   2460: 
                   2461:    We force a stack adjustment unless there are currently
                   2462:    things pushed on the stack that aren't yet used.  */
                   2463: 
                   2464: static rtx
                   2465: compare (exp, signed_forward, unsigned_forward,
                   2466:         signed_reverse, unsigned_reverse)
                   2467:      register tree exp;
                   2468:      enum rtx_code signed_forward, unsigned_forward;
                   2469:      enum rtx_code signed_reverse, unsigned_reverse;
                   2470: {
                   2471:   register rtx op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   2472:   register rtx op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   2473:   register enum machine_mode mode = GET_MODE (op0);
                   2474:   int unsignedp;
                   2475: 
                   2476:   /* If one operand is 0, make it the second one.  */
                   2477: 
                   2478:   if (op0 == const0_rtx || op0 == fconst0_rtx || op0 == dconst0_rtx)
                   2479:     {
                   2480:       rtx tem = op0;
                   2481:       op0 = op1;
                   2482:       op1 = tem;
                   2483:       signed_forward = signed_reverse;
                   2484:       unsigned_forward = unsigned_reverse;
                   2485:     }
                   2486: 
                   2487:   if (force_mem)
                   2488:     {
                   2489:       op0 = force_not_mem (op0);
                   2490:       op1 = force_not_mem (op1);
                   2491:     }
                   2492: 
                   2493:   do_pending_stack_adjust ();
                   2494: 
                   2495:   unsignedp = (type_unsigned_p (TREE_TYPE (TREE_OPERAND (exp, 0)))
                   2496:               || type_unsigned_p (TREE_TYPE (TREE_OPERAND (exp, 1))));
                   2497: 
                   2498:   emit_cmp_insn (op0, op1,
                   2499:                 (mode == BLKmode) ? expr_size (TREE_OPERAND (exp, 0)) : 0,
                   2500:                 unsignedp);
                   2501: 
                   2502:   return gen_rtx ((unsignedp ? unsigned_forward : signed_forward),
                   2503:                  VOIDmode, cc0_rtx, const0_rtx);
                   2504: }
                   2505: 
                   2506: /* Like compare but expects the values to compare as two rtx's.
                   2507:    The decision as to signed or unsigned comparison must be made by the caller.
                   2508:    BLKmode is not allowed.  */
                   2509: 
                   2510: static rtx
                   2511: compare1 (op0, op1, forward_op, reverse_op, unsignedp)
                   2512:      register rtx op0, op1;
                   2513:      enum rtx_code forward_op, reverse_op;
                   2514:      int unsignedp;
                   2515: {
                   2516:   register enum machine_mode mode = GET_MODE (op0);
                   2517: 
                   2518:   /* If one operand is 0, make it the second one.  */
                   2519: 
                   2520:   if (op0 == const0_rtx || op0 == fconst0_rtx || op0 == dconst0_rtx)
                   2521:     {
                   2522:       rtx tem = op0;
                   2523:       op0 = op1;
                   2524:       op1 = tem;
                   2525:       forward_op = reverse_op;
                   2526:     }
                   2527: 
                   2528:   if (force_mem)
                   2529:     {
                   2530:       op0 = force_not_mem (op0);
                   2531:       op1 = force_not_mem (op1);
                   2532:     }
                   2533: 
                   2534:   do_pending_stack_adjust ();
                   2535: 
                   2536:   emit_cmp_insn (op0, op1, 0, unsignedp);
                   2537: 
                   2538:   return gen_rtx (forward_op, VOIDmode, cc0_rtx, const0_rtx);
                   2539: }
                   2540: 
                   2541: /* Generate code to jump to LABEL if OP1 and OP2 are equal.  */
                   2542: 
                   2543: void
                   2544: do_jump_if_equal (op1, op2, label)
                   2545:      rtx op1, op2, label;
                   2546: {
                   2547:   emit_cmp_insn (op1, op2, 0);
                   2548:   emit_jump_insn (gen_beq (label));
                   2549: }
                   2550: 
                   2551: /* Generate code to calculate EXP using a store-flag instruction
                   2552:    and return an rtx for the result.
                   2553:    If TARGET is nonzero, store the result there if convenient.
                   2554: 
                   2555:    Return zero if there is no suitable set-flag instruction
                   2556:    available on this machine.  */
                   2557: 
                   2558: static rtx
                   2559: do_store_flag (exp, target)
                   2560:      tree exp;
                   2561:      rtx target;
                   2562: {
                   2563:   register enum tree_code code = TREE_CODE (exp);
                   2564:   register rtx comparison = 0;
                   2565: 
                   2566:   if (target == 0 || GET_MODE (target) != SImode)
                   2567:     target = gen_reg_rtx (SImode);
                   2568: 
                   2569:   switch (code)
                   2570:     {
                   2571: #ifdef HAVE_seqsi
                   2572:     case EQ_EXPR:
                   2573:       if (HAVE_seqsi)
                   2574:        comparison = compare (exp, EQ, EQ, EQ, EQ);
                   2575:       break;
                   2576: #endif
                   2577: 
                   2578: #ifdef HAVE_snesi
                   2579:     case NE_EXPR:
                   2580:       if (HAVE_snesi)
                   2581:        comparison = compare (exp, NE, NE, NE, NE);
                   2582:       break;
                   2583: #endif
                   2584: 
                   2585: #if defined (HAVE_sltsi) && defined (HAVE_sltusi) && defined (HAVE_sgtsi) && defined (HAVE_sgtusi)
                   2586:     case LT_EXPR:
                   2587:       if (HAVE_sltsi && HAVE_sltusi && HAVE_sgtsi && HAVE_sgtusi)
                   2588:        comparison = compare (exp, LT, LTU, GT, GTU);
                   2589:       break;
                   2590: 
                   2591:     case GT_EXPR:
                   2592:       if (HAVE_sltsi && HAVE_sltusi && HAVE_sgtsi && HAVE_sgtusi)
                   2593:        comparison = compare (exp, GT, GTU, LT, LTU);
                   2594:       break;
                   2595: #endif
                   2596: 
                   2597: #if defined (HAVE_slesi) && defined (HAVE_sleusi) && defined (HAVE_sgesi) && defined (HAVE_sgeusi)
                   2598:     case LE_EXPR:
                   2599:       if (HAVE_slesi && HAVE_sleusi && HAVE_sgesi && HAVE_sgeusi)
                   2600:        comparison = compare (exp, LE, LEU, GE, GEU);
                   2601:       break;
                   2602: 
                   2603:     case GE_EXPR:
                   2604:       if (HAVE_slesi && HAVE_sleusi && HAVE_sgesi && HAVE_sgeusi)
                   2605:        comparison = compare (exp, GE, GEU, LE, LEU);
                   2606:       break;
                   2607: #endif
                   2608:     }
                   2609:   if (comparison == 0)
                   2610:     return 0;
                   2611: 
                   2612:   emit_insn (gen_rtx (SET, VOIDmode, target, comparison));
                   2613:   expand_bit_and (GET_MODE (target), target, const1_rtx, target);
                   2614:   return target;
                   2615: }
                   2616: 
                   2617: /* Generate a tablejump instruction (used for switch statements).  */
                   2618: 
                   2619: #ifdef HAVE_tablejump
                   2620: 
                   2621: /* INDEX is the value being switched on, with the lowest value
                   2622:    in the table already subtracted.
                   2623:    RANGE is the length of the jump table.
                   2624:    TABLE_LABEL is a CODE_LABEL rtx for the table itself.
                   2625:    DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
                   2626:    index value is out of range.  */
                   2627: 
                   2628: void
                   2629: do_tablejump (index, range, table_label, default_label)
                   2630:      rtx index, range, table_label, default_label;
                   2631: {
                   2632:   register rtx temp;
                   2633: 
                   2634:   emit_cmp_insn (index, const0_rtx, 0);
                   2635:   emit_jump_insn (gen_blt (default_label));
                   2636:   emit_cmp_insn (range, index, 0);
                   2637:   emit_jump_insn (gen_blt (default_label));
                   2638:   index = memory_address (CASE_VECTOR_MODE,
                   2639:                          gen_rtx (PLUS, Pmode,
                   2640:                                   gen_rtx (LABEL_REF, VOIDmode, table_label),
                   2641:                                   gen_rtx (MULT, Pmode, index,
                   2642:                                            gen_rtx (CONST_INT, VOIDmode,
                   2643:                                                     GET_MODE_SIZE (CASE_VECTOR_MODE)))));
                   2644:   temp = gen_reg_rtx (CASE_VECTOR_MODE);
                   2645:   convert_move (temp, gen_rtx (MEM, CASE_VECTOR_MODE, index), 0);
                   2646: 
                   2647:   emit_jump_insn (gen_tablejump (temp));
                   2648: }
                   2649: 
                   2650: #endif /* HAVE_tablejump */}

unix.superglobalmegacorp.com

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