Annotation of gcc/expr.c, revision 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.