Annotation of gcc/expr.c, revision 1.1.1.4

1.1       root        1: /* Convert tree expression to rtl instructions, for GNU compiler.
                      2:    Copyright (C) 1988, 1992 Free Software Foundation, Inc.
                      3: 
                      4: This file is part of GNU CC.
                      5: 
                      6: GNU CC is free software; you can redistribute it and/or modify
                      7: it under the terms of the GNU General Public License as published by
                      8: the Free Software Foundation; either version 2, or (at your option)
                      9: any later version.
                     10: 
                     11: GNU CC is distributed in the hope that it will be useful,
                     12: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     14: GNU General Public License for more details.
                     15: 
                     16: You should have received a copy of the GNU General Public License
                     17: along with GNU CC; see the file COPYING.  If not, write to
                     18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     19: 
                     20: 
                     21: #include "config.h"
                     22: #include "rtl.h"
                     23: #include "tree.h"
                     24: #include "flags.h"
                     25: #include "function.h"
                     26: #include "insn-flags.h"
                     27: #include "insn-codes.h"
                     28: #include "expr.h"
                     29: #include "insn-config.h"
                     30: #include "recog.h"
                     31: #include "output.h"
                     32: #include "gvarargs.h"
                     33: #include "typeclass.h"
                     34: 
                     35: #define CEIL(x,y) (((x) + (y) - 1) / (y))
                     36: 
                     37: /* Decide whether a function's arguments should be processed
                     38:    from first to last or from last to first.  */
                     39: 
                     40: #ifdef STACK_GROWS_DOWNWARD
                     41: #ifdef PUSH_ROUNDING
                     42: #define PUSH_ARGS_REVERSED     /* If it's last to first */
                     43: #endif
                     44: #endif
                     45: 
                     46: #ifndef STACK_PUSH_CODE
                     47: #ifdef STACK_GROWS_DOWNWARD
                     48: #define STACK_PUSH_CODE PRE_DEC
                     49: #else
                     50: #define STACK_PUSH_CODE PRE_INC
                     51: #endif
                     52: #endif
                     53: 
                     54: /* Like STACK_BOUNDARY but in units of bytes, not bits.  */
                     55: #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
                     56: 
                     57: /* If this is nonzero, we do not bother generating VOLATILE
                     58:    around volatile memory references, and we are willing to
                     59:    output indirect addresses.  If cse is to follow, we reject
                     60:    indirect addresses so a useful potential cse is generated;
                     61:    if it is used only once, instruction combination will produce
                     62:    the same indirect address eventually.  */
                     63: int cse_not_expected;
                     64: 
                     65: /* Nonzero to generate code for all the subroutines within an
                     66:    expression before generating the upper levels of the expression.
                     67:    Nowadays this is never zero.  */
                     68: int do_preexpand_calls = 1;
                     69: 
                     70: /* Number of units that we should eventually pop off the stack.
                     71:    These are the arguments to function calls that have already returned.  */
                     72: int pending_stack_adjust;
                     73: 
                     74: /* Nonzero means stack pops must not be deferred, and deferred stack
                     75:    pops must not be output.  It is nonzero inside a function call,
                     76:    inside a conditional expression, inside a statement expression,
                     77:    and in other cases as well.  */
                     78: int inhibit_defer_pop;
                     79: 
                     80: /* A list of all cleanups which belong to the arguments of
                     81:    function calls being expanded by expand_call.  */
                     82: tree cleanups_this_call;
                     83: 
                     84: /* Nonzero means __builtin_saveregs has already been done in this function.
                     85:    The value is the pseudoreg containing the value __builtin_saveregs
                     86:    returned.  */
                     87: static rtx saveregs_value;
                     88: 
                     89: rtx store_expr ();
                     90: static void store_constructor ();
                     91: static rtx store_field ();
                     92: static rtx expand_builtin ();
                     93: static rtx compare ();
                     94: static rtx do_store_flag ();
                     95: static void preexpand_calls ();
                     96: static rtx expand_increment ();
                     97: static void init_queue ();
                     98: 
                     99: void do_pending_stack_adjust ();
                    100: static void do_jump_for_compare ();
                    101: static void do_jump_by_parts_equality ();
                    102: static void do_jump_by_parts_equality_rtx ();
                    103: static void do_jump_by_parts_greater ();
                    104: 
1.1.1.4 ! root      105: /* Record for each mode whether we can move a register directly to or
        !           106:    from an object of that mode in memory.  If we can't, we won't try
        !           107:    to use that mode directly when accessing a field of that mode.  */
        !           108: 
        !           109: static char direct_load[NUM_MACHINE_MODES];
        !           110: static char direct_store[NUM_MACHINE_MODES];
        !           111: 
1.1       root      112: /* MOVE_RATIO is the number of move instructions that is better than
                    113:    a block move.  */
                    114: 
                    115: #ifndef MOVE_RATIO
1.1.1.4 ! root      116: #if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi) || defined (HAVE_movstrdi) || defined (HAVE_movstrti)
1.1       root      117: #define MOVE_RATIO 2
                    118: #else
                    119: /* A value of around 6 would minimize code size; infinity would minimize
                    120:    execution time.  */
                    121: #define MOVE_RATIO 15
                    122: #endif
                    123: #endif
1.1.1.2   root      124: 
1.1.1.4 ! root      125: /* This array records the insn_code of insns to perform block moves.  */
        !           126: static enum insn_code movstr_optab[NUM_MACHINE_MODES];
        !           127: 
1.1.1.2   root      128: /* SLOW_UNALIGNED_ACCESS is non-zero if unaligned accesses are very slow. */
                    129: 
                    130: #ifndef SLOW_UNALIGNED_ACCESS
                    131: #define SLOW_UNALIGNED_ACCESS 0
                    132: #endif
1.1       root      133: 
1.1.1.4 ! root      134: /* This is run once per compilation to set up which modes can be used
        !           135:    directly in memory and to initialize the block move optab.  */
        !           136: 
        !           137: void
        !           138: init_expr_once ()
        !           139: {
        !           140:   rtx insn, pat;
        !           141:   enum machine_mode mode;
        !           142:   /* Try indexing by frame ptr and try by stack ptr.
        !           143:      It is known that on the Convex the stack ptr isn't a valid index.
        !           144:      With luck, one or the other is valid on any machine.  */
        !           145:   rtx mem = gen_rtx (MEM, VOIDmode, stack_pointer_rtx);
        !           146:   rtx mem1 = gen_rtx (MEM, VOIDmode, frame_pointer_rtx);
        !           147: 
        !           148:   start_sequence ();
        !           149:   insn = emit_insn (gen_rtx (SET, 0, 0));
        !           150:   pat = PATTERN (insn);
        !           151: 
        !           152:   for (mode = VOIDmode; (int) mode < NUM_MACHINE_MODES;
        !           153:        mode = (enum machine_mode) ((int) mode + 1))
        !           154:     {
        !           155:       int regno;
        !           156:       rtx reg;
        !           157:       int num_clobbers;
        !           158: 
        !           159:       direct_load[(int) mode] = direct_store[(int) mode] = 0;
        !           160:       PUT_MODE (mem, mode);
        !           161:       PUT_MODE (mem1, mode);
        !           162: 
        !           163:       /* See if there is some register that can be used in this mode and
        !           164:         directly loaded or stored from memory.  */
        !           165: 
        !           166:       if (mode != VOIDmode && mode != BLKmode)
        !           167:        for (regno = 0; regno < FIRST_PSEUDO_REGISTER
        !           168:             && (direct_load[(int) mode] == 0 || direct_store[(int) mode] == 0);
        !           169:             regno++)
        !           170:          {
        !           171:            if (! HARD_REGNO_MODE_OK (regno, mode))
        !           172:              continue;
        !           173: 
        !           174:            reg = gen_rtx (REG, mode, regno);
        !           175: 
        !           176:            SET_SRC (pat) = mem;
        !           177:            SET_DEST (pat) = reg;
        !           178:            if (recog (pat, insn, &num_clobbers) >= 0)
        !           179:              direct_load[(int) mode] = 1;
        !           180: 
        !           181:            SET_SRC (pat) = mem1;
        !           182:            SET_DEST (pat) = reg;
        !           183:            if (recog (pat, insn, &num_clobbers) >= 0)
        !           184:              direct_load[(int) mode] = 1;
        !           185: 
        !           186:            SET_SRC (pat) = reg;
        !           187:            SET_DEST (pat) = mem;
        !           188:            if (recog (pat, insn, &num_clobbers) >= 0)
        !           189:              direct_store[(int) mode] = 1;
        !           190: 
        !           191:            SET_SRC (pat) = reg;
        !           192:            SET_DEST (pat) = mem1;
        !           193:            if (recog (pat, insn, &num_clobbers) >= 0)
        !           194:              direct_store[(int) mode] = 1;
        !           195:          }
        !           196: 
        !           197:       movstr_optab[(int) mode] = CODE_FOR_nothing;
        !           198:     }
        !           199: 
        !           200:   end_sequence ();
        !           201: 
        !           202: #ifdef HAVE_movstrqi
        !           203:   if (HAVE_movstrqi)
        !           204:     movstr_optab[(int) QImode] = CODE_FOR_movstrqi;
        !           205: #endif
        !           206: #ifdef HAVE_movstrhi
        !           207:   if (HAVE_movstrhi)
        !           208:     movstr_optab[(int) HImode] = CODE_FOR_movstrhi;
        !           209: #endif
        !           210: #ifdef HAVE_movstrsi
        !           211:   if (HAVE_movstrsi)
        !           212:     movstr_optab[(int) SImode] = CODE_FOR_movstrsi;
        !           213: #endif
        !           214: #ifdef HAVE_movstrdi
        !           215:   if (HAVE_movstrdi)
        !           216:     movstr_optab[(int) DImode] = CODE_FOR_movstrdi;
        !           217: #endif
        !           218: #ifdef HAVE_movstrti
        !           219:   if (HAVE_movstrti)
        !           220:     movstr_optab[(int) TImode] = CODE_FOR_movstrti;
        !           221: #endif
        !           222: }
        !           223:       
1.1       root      224: /* This is run at the start of compiling a function.  */
                    225: 
                    226: void
                    227: init_expr ()
                    228: {
                    229:   init_queue ();
                    230: 
                    231:   pending_stack_adjust = 0;
                    232:   inhibit_defer_pop = 0;
                    233:   cleanups_this_call = 0;
                    234:   saveregs_value = 0;
1.1.1.2   root      235:   forced_labels = 0;
1.1       root      236: }
                    237: 
                    238: /* Save all variables describing the current status into the structure *P.
                    239:    This is used before starting a nested function.  */
                    240: 
                    241: void
                    242: save_expr_status (p)
                    243:      struct function *p;
                    244: {
                    245:   /* Instead of saving the postincrement queue, empty it.  */
                    246:   emit_queue ();
                    247: 
                    248:   p->pending_stack_adjust = pending_stack_adjust;
                    249:   p->inhibit_defer_pop = inhibit_defer_pop;
                    250:   p->cleanups_this_call = cleanups_this_call;
                    251:   p->saveregs_value = saveregs_value;
1.1.1.2   root      252:   p->forced_labels = forced_labels;
1.1       root      253: 
                    254:   pending_stack_adjust = 0;
                    255:   inhibit_defer_pop = 0;
                    256:   cleanups_this_call = 0;
                    257:   saveregs_value = 0;
1.1.1.2   root      258:   forced_labels = 0;
1.1       root      259: }
                    260: 
                    261: /* Restore all variables describing the current status from the structure *P.
                    262:    This is used after a nested function.  */
                    263: 
                    264: void
                    265: restore_expr_status (p)
                    266:      struct function *p;
                    267: {
                    268:   pending_stack_adjust = p->pending_stack_adjust;
                    269:   inhibit_defer_pop = p->inhibit_defer_pop;
                    270:   cleanups_this_call = p->cleanups_this_call;
                    271:   saveregs_value = p->saveregs_value;
1.1.1.2   root      272:   forced_labels = p->forced_labels;
1.1       root      273: }
                    274: 
                    275: /* Manage the queue of increment instructions to be output
                    276:    for POSTINCREMENT_EXPR expressions, etc.  */
                    277: 
                    278: static rtx pending_chain;
                    279: 
                    280: /* Queue up to increment (or change) VAR later.  BODY says how:
                    281:    BODY should be the same thing you would pass to emit_insn
                    282:    to increment right away.  It will go to emit_insn later on.
                    283: 
                    284:    The value is a QUEUED expression to be used in place of VAR
                    285:    where you want to guarantee the pre-incrementation value of VAR.  */
                    286: 
                    287: static rtx
                    288: enqueue_insn (var, body)
                    289:      rtx var, body;
                    290: {
                    291:   pending_chain = gen_rtx (QUEUED, GET_MODE (var),
1.1.1.4 ! root      292:                           var, NULL_RTX, NULL_RTX, body, pending_chain);
1.1       root      293:   return pending_chain;
                    294: }
                    295: 
                    296: /* Use protect_from_queue to convert a QUEUED expression
                    297:    into something that you can put immediately into an instruction.
                    298:    If the queued incrementation has not happened yet,
                    299:    protect_from_queue returns the variable itself.
                    300:    If the incrementation has happened, protect_from_queue returns a temp
                    301:    that contains a copy of the old value of the variable.
                    302: 
                    303:    Any time an rtx which might possibly be a QUEUED is to be put
                    304:    into an instruction, it must be passed through protect_from_queue first.
                    305:    QUEUED expressions are not meaningful in instructions.
                    306: 
                    307:    Do not pass a value through protect_from_queue and then hold
                    308:    on to it for a while before putting it in an instruction!
                    309:    If the queue is flushed in between, incorrect code will result.  */
                    310: 
                    311: rtx
                    312: protect_from_queue (x, modify)
                    313:      register rtx x;
                    314:      int modify;
                    315: {
                    316:   register RTX_CODE code = GET_CODE (x);
                    317: 
                    318: #if 0  /* A QUEUED can hang around after the queue is forced out.  */
                    319:   /* Shortcut for most common case.  */
                    320:   if (pending_chain == 0)
                    321:     return x;
                    322: #endif
                    323: 
                    324:   if (code != QUEUED)
                    325:     {
                    326:       /* A special hack for read access to (MEM (QUEUED ...))
                    327:         to facilitate use of autoincrement.
                    328:         Make a copy of the contents of the memory location
                    329:         rather than a copy of the address, but not
                    330:         if the value is of mode BLKmode.  */
                    331:       if (code == MEM && GET_MODE (x) != BLKmode
                    332:          && GET_CODE (XEXP (x, 0)) == QUEUED && !modify)
                    333:        {
                    334:          register rtx y = XEXP (x, 0);
                    335:          XEXP (x, 0) = QUEUED_VAR (y);
                    336:          if (QUEUED_INSN (y))
                    337:            {
                    338:              register rtx temp = gen_reg_rtx (GET_MODE (x));
                    339:              emit_insn_before (gen_move_insn (temp, x),
                    340:                                QUEUED_INSN (y));
                    341:              return temp;
                    342:            }
                    343:          return x;
                    344:        }
                    345:       /* Otherwise, recursively protect the subexpressions of all
                    346:         the kinds of rtx's that can contain a QUEUED.  */
                    347:       if (code == MEM)
                    348:        XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0);
                    349:       else if (code == PLUS || code == MULT)
                    350:        {
                    351:          XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0);
                    352:          XEXP (x, 1) = protect_from_queue (XEXP (x, 1), 0);
                    353:        }
                    354:       return x;
                    355:     }
                    356:   /* If the increment has not happened, use the variable itself.  */
                    357:   if (QUEUED_INSN (x) == 0)
                    358:     return QUEUED_VAR (x);
                    359:   /* If the increment has happened and a pre-increment copy exists,
                    360:      use that copy.  */
                    361:   if (QUEUED_COPY (x) != 0)
                    362:     return QUEUED_COPY (x);
                    363:   /* The increment has happened but we haven't set up a pre-increment copy.
                    364:      Set one up now, and use it.  */
                    365:   QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x)));
                    366:   emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)),
                    367:                    QUEUED_INSN (x));
                    368:   return QUEUED_COPY (x);
                    369: }
                    370: 
                    371: /* Return nonzero if X contains a QUEUED expression:
                    372:    if it contains anything that will be altered by a queued increment.
                    373:    We handle only combinations of MEM, PLUS, MINUS and MULT operators
                    374:    since memory addresses generally contain only those.  */
                    375: 
                    376: static int
                    377: queued_subexp_p (x)
                    378:      rtx x;
                    379: {
                    380:   register enum rtx_code code = GET_CODE (x);
                    381:   switch (code)
                    382:     {
                    383:     case QUEUED:
                    384:       return 1;
                    385:     case MEM:
                    386:       return queued_subexp_p (XEXP (x, 0));
                    387:     case MULT:
                    388:     case PLUS:
                    389:     case MINUS:
                    390:       return queued_subexp_p (XEXP (x, 0))
                    391:        || queued_subexp_p (XEXP (x, 1));
                    392:     }
                    393:   return 0;
                    394: }
                    395: 
                    396: /* Perform all the pending incrementations.  */
                    397: 
                    398: void
                    399: emit_queue ()
                    400: {
                    401:   register rtx p;
                    402:   while (p = pending_chain)
                    403:     {
                    404:       QUEUED_INSN (p) = emit_insn (QUEUED_BODY (p));
                    405:       pending_chain = QUEUED_NEXT (p);
                    406:     }
                    407: }
                    408: 
                    409: static void
                    410: init_queue ()
                    411: {
                    412:   if (pending_chain)
                    413:     abort ();
                    414: }
                    415: 
                    416: /* Copy data from FROM to TO, where the machine modes are not the same.
                    417:    Both modes may be integer, or both may be floating.
                    418:    UNSIGNEDP should be nonzero if FROM is an unsigned type.
                    419:    This causes zero-extension instead of sign-extension.  */
                    420: 
                    421: void
                    422: convert_move (to, from, unsignedp)
                    423:      register rtx to, from;
                    424:      int unsignedp;
                    425: {
                    426:   enum machine_mode to_mode = GET_MODE (to);
                    427:   enum machine_mode from_mode = GET_MODE (from);
                    428:   int to_real = GET_MODE_CLASS (to_mode) == MODE_FLOAT;
                    429:   int from_real = GET_MODE_CLASS (from_mode) == MODE_FLOAT;
                    430:   enum insn_code code;
                    431:   rtx libcall;
                    432: 
                    433:   /* rtx code for making an equivalent value.  */
                    434:   enum rtx_code equiv_code = (unsignedp ? ZERO_EXTEND : SIGN_EXTEND);
                    435: 
                    436:   to = protect_from_queue (to, 1);
                    437:   from = protect_from_queue (from, 0);
                    438: 
                    439:   if (to_real != from_real)
                    440:     abort ();
                    441: 
1.1.1.4 ! root      442:   /* If FROM is a SUBREG that indicates that we have already done at least
        !           443:      the required extension, strip it.  We don't handle such SUBREGs as
        !           444:      TO here.  */
        !           445: 
        !           446:   if (GET_CODE (from) == SUBREG && SUBREG_PROMOTED_VAR_P (from)
        !           447:       && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (from)))
        !           448:          >= GET_MODE_SIZE (to_mode))
        !           449:       && SUBREG_PROMOTED_UNSIGNED_P (from) == unsignedp)
        !           450:     from = gen_lowpart (to_mode, from), from_mode = to_mode;
        !           451: 
        !           452:   if (GET_CODE (to) == SUBREG && SUBREG_PROMOTED_VAR_P (to))
        !           453:     abort ();
        !           454: 
1.1       root      455:   if (to_mode == from_mode
                    456:       || (from_mode == VOIDmode && CONSTANT_P (from)))
                    457:     {
                    458:       emit_move_insn (to, from);
                    459:       return;
                    460:     }
                    461: 
                    462:   if (to_real)
                    463:     {
                    464: #ifdef HAVE_extendsfdf2
                    465:       if (HAVE_extendsfdf2 && from_mode == SFmode && to_mode == DFmode)
                    466:        {
                    467:          emit_unop_insn (CODE_FOR_extendsfdf2, to, from, UNKNOWN);
                    468:          return;
                    469:        }
                    470: #endif
1.1.1.4 ! root      471: #ifdef HAVE_extendsfxf2
        !           472:       if (HAVE_extendsfxf2 && from_mode == SFmode && to_mode == XFmode)
        !           473:        {
        !           474:          emit_unop_insn (CODE_FOR_extendsfxf2, to, from, UNKNOWN);
        !           475:          return;
        !           476:        }
        !           477: #endif
1.1       root      478: #ifdef HAVE_extendsftf2
                    479:       if (HAVE_extendsftf2 && from_mode == SFmode && to_mode == TFmode)
                    480:        {
                    481:          emit_unop_insn (CODE_FOR_extendsftf2, to, from, UNKNOWN);
                    482:          return;
                    483:        }
                    484: #endif
1.1.1.4 ! root      485: #ifdef HAVE_extenddfxf2
        !           486:       if (HAVE_extenddfxf2 && from_mode == DFmode && to_mode == XFmode)
        !           487:        {
        !           488:          emit_unop_insn (CODE_FOR_extenddfxf2, to, from, UNKNOWN);
        !           489:          return;
        !           490:        }
        !           491: #endif
1.1       root      492: #ifdef HAVE_extenddftf2
                    493:       if (HAVE_extenddftf2 && from_mode == DFmode && to_mode == TFmode)
                    494:        {
                    495:          emit_unop_insn (CODE_FOR_extenddftf2, to, from, UNKNOWN);
                    496:          return;
                    497:        }
                    498: #endif
                    499: #ifdef HAVE_truncdfsf2
                    500:       if (HAVE_truncdfsf2 && from_mode == DFmode && to_mode == SFmode)
                    501:        {
                    502:          emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN);
                    503:          return;
                    504:        }
                    505: #endif
1.1.1.4 ! root      506: #ifdef HAVE_truncxfsf2
        !           507:       if (HAVE_truncxfsf2 && from_mode == XFmode && to_mode == SFmode)
        !           508:        {
        !           509:          emit_unop_insn (CODE_FOR_truncxfsf2, to, from, UNKNOWN);
        !           510:          return;
        !           511:        }
        !           512: #endif
1.1       root      513: #ifdef HAVE_trunctfsf2
                    514:       if (HAVE_trunctfsf2 && from_mode == TFmode && to_mode == SFmode)
                    515:        {
                    516:          emit_unop_insn (CODE_FOR_trunctfsf2, to, from, UNKNOWN);
                    517:          return;
                    518:        }
                    519: #endif
1.1.1.4 ! root      520: #ifdef HAVE_truncxfdf2
        !           521:       if (HAVE_truncxfdf2 && from_mode == XFmode && to_mode == DFmode)
        !           522:        {
        !           523:          emit_unop_insn (CODE_FOR_truncxfdf2, to, from, UNKNOWN);
        !           524:          return;
        !           525:        }
        !           526: #endif
1.1       root      527: #ifdef HAVE_trunctfdf2
                    528:       if (HAVE_trunctfdf2 && from_mode == TFmode && to_mode == DFmode)
                    529:        {
                    530:          emit_unop_insn (CODE_FOR_trunctfdf2, to, from, UNKNOWN);
                    531:          return;
                    532:        }
                    533: #endif
                    534: 
1.1.1.4 ! root      535:       libcall = (rtx) 0;
        !           536:       switch (from_mode)
        !           537:        {
        !           538:        case SFmode:
        !           539:          switch (to_mode)
        !           540:            {
        !           541:            case DFmode:
        !           542:              libcall = extendsfdf2_libfunc;
        !           543:              break;
        !           544: 
        !           545:            case XFmode:
        !           546:              libcall = extendsfxf2_libfunc;
        !           547:              break;
        !           548: 
        !           549:            case TFmode:
        !           550:              libcall = extendsftf2_libfunc;
        !           551:              break;
        !           552:            }
        !           553:          break;
        !           554: 
        !           555:        case DFmode:
        !           556:          switch (to_mode)
        !           557:            {
        !           558:            case SFmode:
        !           559:              libcall = truncdfsf2_libfunc;
        !           560:              break;
        !           561: 
        !           562:            case XFmode:
        !           563:              libcall = extenddfxf2_libfunc;
        !           564:              break;
        !           565: 
        !           566:            case TFmode:
        !           567:              libcall = extenddftf2_libfunc;
        !           568:              break;
        !           569:            }
        !           570:          break;
        !           571: 
        !           572:        case XFmode:
        !           573:          switch (to_mode)
        !           574:            {
        !           575:            case SFmode:
        !           576:              libcall = truncxfsf2_libfunc;
        !           577:              break;
        !           578: 
        !           579:            case DFmode:
        !           580:              libcall = truncxfdf2_libfunc;
        !           581:              break;
        !           582:            }
        !           583:          break;
        !           584: 
        !           585:        case TFmode:
        !           586:          switch (to_mode)
        !           587:            {
        !           588:            case SFmode:
        !           589:              libcall = trunctfsf2_libfunc;
        !           590:              break;
        !           591: 
        !           592:            case DFmode:
        !           593:              libcall = trunctfdf2_libfunc;
        !           594:              break;
        !           595:            }
        !           596:          break;
        !           597:        }
        !           598: 
        !           599:       if (libcall == (rtx) 0)
        !           600:        /* This conversion is not implemented yet.  */
1.1       root      601:        abort ();
                    602: 
1.1.1.2   root      603:       emit_library_call (libcall, 1, to_mode, 1, from, from_mode);
1.1       root      604:       emit_move_insn (to, hard_libcall_value (to_mode));
                    605:       return;
                    606:     }
                    607: 
                    608:   /* Now both modes are integers.  */
                    609: 
                    610:   /* Handle expanding beyond a word.  */
                    611:   if (GET_MODE_BITSIZE (from_mode) < GET_MODE_BITSIZE (to_mode)
                    612:       && GET_MODE_BITSIZE (to_mode) > BITS_PER_WORD)
                    613:     {
                    614:       rtx insns;
                    615:       rtx lowpart;
                    616:       rtx fill_value;
                    617:       rtx lowfrom;
                    618:       int i;
                    619:       enum machine_mode lowpart_mode;
                    620:       int nwords = CEIL (GET_MODE_SIZE (to_mode), UNITS_PER_WORD);
                    621: 
                    622:       /* Try converting directly if the insn is supported.  */
                    623:       if ((code = can_extend_p (to_mode, from_mode, unsignedp))
                    624:          != CODE_FOR_nothing)
                    625:        {
1.1.1.4 ! root      626:          /* If FROM is a SUBREG, put it into a register.  Do this
        !           627:             so that we always generate the same set of insns for
        !           628:             better cse'ing; if an intermediate assignment occurred,
        !           629:             we won't be doing the operation directly on the SUBREG.  */
        !           630:          if (optimize > 0 && GET_CODE (from) == SUBREG)
        !           631:            from = force_reg (from_mode, from);
1.1       root      632:          emit_unop_insn (code, to, from, equiv_code);
                    633:          return;
                    634:        }
                    635:       /* Next, try converting via full word.  */
                    636:       else if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD
                    637:               && ((code = can_extend_p (to_mode, word_mode, unsignedp))
                    638:                   != CODE_FOR_nothing))
                    639:        {
                    640:          convert_move (gen_lowpart (word_mode, to), from, unsignedp);
                    641:          emit_unop_insn (code, to,
                    642:                          gen_lowpart (word_mode, to), equiv_code);
                    643:          return;
                    644:        }
                    645: 
                    646:       /* No special multiword conversion insn; do it by hand.  */
                    647:       start_sequence ();
                    648: 
                    649:       /* Get a copy of FROM widened to a word, if necessary.  */
                    650:       if (GET_MODE_BITSIZE (from_mode) < BITS_PER_WORD)
                    651:        lowpart_mode = word_mode;
                    652:       else
                    653:        lowpart_mode = from_mode;
                    654: 
                    655:       lowfrom = convert_to_mode (lowpart_mode, from, unsignedp);
                    656: 
                    657:       lowpart = gen_lowpart (lowpart_mode, to);
                    658:       emit_move_insn (lowpart, lowfrom);
                    659: 
                    660:       /* Compute the value to put in each remaining word.  */
                    661:       if (unsignedp)
                    662:        fill_value = const0_rtx;
                    663:       else
                    664:        {
                    665: #ifdef HAVE_slt
                    666:          if (HAVE_slt
                    667:              && insn_operand_mode[(int) CODE_FOR_slt][0] == word_mode
                    668:              && STORE_FLAG_VALUE == -1)
                    669:            {
1.1.1.4 ! root      670:              emit_cmp_insn (lowfrom, const0_rtx, NE, NULL_RTX,
        !           671:                             lowpart_mode, 0, 0);
1.1       root      672:              fill_value = gen_reg_rtx (word_mode);
                    673:              emit_insn (gen_slt (fill_value));
                    674:            }
                    675:          else
                    676: #endif
                    677:            {
                    678:              fill_value
                    679:                = expand_shift (RSHIFT_EXPR, lowpart_mode, lowfrom,
                    680:                                size_int (GET_MODE_BITSIZE (lowpart_mode) - 1),
1.1.1.4 ! root      681:                                NULL_RTX, 0);
1.1       root      682:              fill_value = convert_to_mode (word_mode, fill_value, 1);
                    683:            }
                    684:        }
                    685: 
                    686:       /* Fill the remaining words.  */
                    687:       for (i = GET_MODE_SIZE (lowpart_mode) / UNITS_PER_WORD; i < nwords; i++)
                    688:        {
                    689:          int index = (WORDS_BIG_ENDIAN ? nwords - i - 1 : i);
                    690:          rtx subword = operand_subword (to, index, 1, to_mode);
                    691: 
                    692:          if (subword == 0)
                    693:            abort ();
                    694: 
                    695:          if (fill_value != subword)
                    696:            emit_move_insn (subword, fill_value);
                    697:        }
                    698: 
                    699:       insns = get_insns ();
                    700:       end_sequence ();
                    701: 
1.1.1.4 ! root      702:       emit_no_conflict_block (insns, to, from, NULL_RTX,
1.1       root      703:                              gen_rtx (equiv_code, to_mode, from));
                    704:       return;
                    705:     }
                    706: 
                    707:   if (GET_MODE_BITSIZE (from_mode) > BITS_PER_WORD)
                    708:     {
                    709:       convert_move (to, gen_lowpart (word_mode, from), 0);
                    710:       return;
                    711:     }
                    712: 
                    713:   /* Handle pointer conversion */                      /* SPEE 900220 */
                    714:   if (to_mode == PSImode)
                    715:     {
                    716:       if (from_mode != SImode)
                    717:        from = convert_to_mode (SImode, from, unsignedp);
                    718: 
                    719: #ifdef HAVE_truncsipsi
                    720:       if (HAVE_truncsipsi)
                    721:        {
                    722:          emit_unop_insn (CODE_FOR_truncsipsi, to, from, UNKNOWN);
                    723:          return;
                    724:        }
                    725: #endif /* HAVE_truncsipsi */
                    726:       abort ();
                    727:     }
                    728: 
                    729:   if (from_mode == PSImode)
                    730:     {
                    731:       if (to_mode != SImode)
                    732:        {
                    733:          from = convert_to_mode (SImode, from, unsignedp);
                    734:          from_mode = SImode;
                    735:        }
                    736:       else
                    737:        {
                    738: #ifdef HAVE_extendpsisi
                    739:          if (HAVE_extendpsisi)
                    740:            {
                    741:              emit_unop_insn (CODE_FOR_extendpsisi, to, from, UNKNOWN);
                    742:              return;
                    743:            }
                    744: #endif /* HAVE_extendpsisi */
                    745:          abort ();
                    746:        }
                    747:     }
                    748: 
                    749:   /* Now follow all the conversions between integers
                    750:      no more than a word long.  */
                    751: 
                    752:   /* For truncation, usually we can just refer to FROM in a narrower mode.  */
                    753:   if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)
                    754:       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
                    755:                                GET_MODE_BITSIZE (from_mode))
                    756:       && ((GET_CODE (from) == MEM
                    757:           && ! MEM_VOLATILE_P (from)
1.1.1.4 ! root      758:           && direct_load[(int) to_mode]
1.1       root      759:           && ! mode_dependent_address_p (XEXP (from, 0)))
                    760:          || GET_CODE (from) == REG
                    761:          || GET_CODE (from) == SUBREG))
                    762:     {
                    763:       emit_move_insn (to, gen_lowpart (to_mode, from));
                    764:       return;
                    765:     }
                    766: 
                    767:   /* For truncation, usually we can just refer to FROM in a narrower mode.  */
                    768:   if (GET_MODE_BITSIZE (to_mode) > GET_MODE_BITSIZE (from_mode))
                    769:     {
                    770:       /* Convert directly if that works.  */
                    771:       if ((code = can_extend_p (to_mode, from_mode, unsignedp))
                    772:          != CODE_FOR_nothing)
                    773:        {
1.1.1.4 ! root      774:          /* If FROM is a SUBREG, put it into a register.  Do this
        !           775:             so that we always generate the same set of insns for
        !           776:             better cse'ing; if an intermediate assignment occurred,
        !           777:             we won't be doing the operation directly on the SUBREG.  */
        !           778:          if (optimize > 0 && GET_CODE (from) == SUBREG)
        !           779:            from = force_reg (from_mode, from);
1.1       root      780:          emit_unop_insn (code, to, from, equiv_code);
                    781:          return;
                    782:        }
                    783:       else
                    784:        {
                    785:          enum machine_mode intermediate;
                    786: 
                    787:          /* Search for a mode to convert via.  */
                    788:          for (intermediate = from_mode; intermediate != VOIDmode;
                    789:               intermediate = GET_MODE_WIDER_MODE (intermediate))
                    790:            if ((can_extend_p (to_mode, intermediate, unsignedp)
                    791:                 != CODE_FOR_nothing)
                    792:                && (can_extend_p (intermediate, from_mode, unsignedp)
                    793:                    != CODE_FOR_nothing))
                    794:              {
                    795:                convert_move (to, convert_to_mode (intermediate, from,
                    796:                                                   unsignedp), unsignedp);
                    797:                return;
                    798:              }
                    799: 
                    800:          /* No suitable intermediate mode.  */
                    801:          abort ();
                    802:        }
                    803:     }
                    804: 
                    805:   /* Support special truncate insns for certain modes.  */ 
                    806: 
                    807:   if (from_mode == DImode && to_mode == SImode)
                    808:     {
                    809: #ifdef HAVE_truncdisi2
                    810:       if (HAVE_truncdisi2)
                    811:        {
                    812:          emit_unop_insn (CODE_FOR_truncdisi2, to, from, UNKNOWN);
                    813:          return;
                    814:        }
                    815: #endif
                    816:       convert_move (to, force_reg (from_mode, from), unsignedp);
                    817:       return;
                    818:     }
                    819: 
                    820:   if (from_mode == DImode && to_mode == HImode)
                    821:     {
                    822: #ifdef HAVE_truncdihi2
                    823:       if (HAVE_truncdihi2)
                    824:        {
                    825:          emit_unop_insn (CODE_FOR_truncdihi2, to, from, UNKNOWN);
                    826:          return;
                    827:        }
                    828: #endif
                    829:       convert_move (to, force_reg (from_mode, from), unsignedp);
                    830:       return;
                    831:     }
                    832: 
                    833:   if (from_mode == DImode && to_mode == QImode)
                    834:     {
                    835: #ifdef HAVE_truncdiqi2
                    836:       if (HAVE_truncdiqi2)
                    837:        {
                    838:          emit_unop_insn (CODE_FOR_truncdiqi2, to, from, UNKNOWN);
                    839:          return;
                    840:        }
                    841: #endif
                    842:       convert_move (to, force_reg (from_mode, from), unsignedp);
                    843:       return;
                    844:     }
                    845: 
                    846:   if (from_mode == SImode && to_mode == HImode)
                    847:     {
                    848: #ifdef HAVE_truncsihi2
                    849:       if (HAVE_truncsihi2)
                    850:        {
                    851:          emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN);
                    852:          return;
                    853:        }
                    854: #endif
                    855:       convert_move (to, force_reg (from_mode, from), unsignedp);
                    856:       return;
                    857:     }
                    858: 
                    859:   if (from_mode == SImode && to_mode == QImode)
                    860:     {
                    861: #ifdef HAVE_truncsiqi2
                    862:       if (HAVE_truncsiqi2)
                    863:        {
                    864:          emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN);
                    865:          return;
                    866:        }
                    867: #endif
                    868:       convert_move (to, force_reg (from_mode, from), unsignedp);
                    869:       return;
                    870:     }
                    871: 
                    872:   if (from_mode == HImode && to_mode == QImode)
                    873:     {
                    874: #ifdef HAVE_trunchiqi2
                    875:       if (HAVE_trunchiqi2)
                    876:        {
                    877:          emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN);
                    878:          return;
                    879:        }
                    880: #endif
                    881:       convert_move (to, force_reg (from_mode, from), unsignedp);
                    882:       return;
                    883:     }
                    884: 
                    885:   /* Handle truncation of volatile memrefs, and so on;
                    886:      the things that couldn't be truncated directly,
                    887:      and for which there was no special instruction.  */
                    888:   if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode))
                    889:     {
                    890:       rtx temp = force_reg (to_mode, gen_lowpart (to_mode, from));
                    891:       emit_move_insn (to, temp);
                    892:       return;
                    893:     }
                    894: 
                    895:   /* Mode combination is not recognized.  */
                    896:   abort ();
                    897: }
                    898: 
                    899: /* Return an rtx for a value that would result
                    900:    from converting X to mode MODE.
                    901:    Both X and MODE may be floating, or both integer.
                    902:    UNSIGNEDP is nonzero if X is an unsigned value.
                    903:    This can be done by referring to a part of X in place
1.1.1.4 ! root      904:    or by copying to a new temporary with conversion.
        !           905: 
        !           906:    This function *must not* call protect_from_queue
        !           907:    except when putting X into an insn (in which case convert_move does it).  */
1.1       root      908: 
                    909: rtx
                    910: convert_to_mode (mode, x, unsignedp)
                    911:      enum machine_mode mode;
                    912:      rtx x;
                    913:      int unsignedp;
                    914: {
                    915:   register rtx temp;
1.1.1.4 ! root      916:  
        !           917:   /* If FROM is a SUBREG that indicates that we have already done at least
        !           918:      the required extension, strip it.  */
1.1       root      919: 
1.1.1.4 ! root      920:   if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)
        !           921:       && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) >= GET_MODE_SIZE (mode)
        !           922:       && SUBREG_PROMOTED_UNSIGNED_P (x) == unsignedp)
        !           923:     x = gen_lowpart (mode, x);
1.1       root      924: 
                    925:   if (mode == GET_MODE (x))
                    926:     return x;
                    927: 
                    928:   /* There is one case that we must handle specially: If we are converting
1.1.1.4 ! root      929:      a CONST_INT into a mode whose size is twice HOST_BITS_PER_WIDE_INT and
1.1       root      930:      we are to interpret the constant as unsigned, gen_lowpart will do
                    931:      the wrong if the constant appears negative.  What we want to do is
                    932:      make the high-order word of the constant zero, not all ones.  */
                    933: 
                    934:   if (unsignedp && GET_MODE_CLASS (mode) == MODE_INT
1.1.1.4 ! root      935:       && GET_MODE_BITSIZE (mode) == 2 * HOST_BITS_PER_WIDE_INT
1.1       root      936:       && GET_CODE (x) == CONST_INT && INTVAL (x) < 0)
1.1.1.4 ! root      937:     return immed_double_const (INTVAL (x), (HOST_WIDE_INT) 0, mode);
1.1       root      938: 
                    939:   /* We can do this with a gen_lowpart if both desired and current modes
                    940:      are integer, and this is either a constant integer, a register, or a
                    941:      non-volatile MEM.  Except for the constant case, we must be narrowing
                    942:      the operand.  */
                    943: 
                    944:   if (GET_CODE (x) == CONST_INT
                    945:       || (GET_MODE_CLASS (mode) == MODE_INT
                    946:          && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
                    947:          && (GET_CODE (x) == CONST_DOUBLE
                    948:              || (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (x))
                    949:                  && ((GET_CODE (x) == MEM && ! MEM_VOLATILE_P (x))
1.1.1.4 ! root      950:                      && direct_load[(int) mode]
1.1       root      951:                      || GET_CODE (x) == REG)))))
                    952:     return gen_lowpart (mode, x);
                    953: 
                    954:   temp = gen_reg_rtx (mode);
                    955:   convert_move (temp, x, unsignedp);
                    956:   return temp;
                    957: }
                    958: 
                    959: /* Generate several move instructions to copy LEN bytes
                    960:    from block FROM to block TO.  (These are MEM rtx's with BLKmode).
                    961:    The caller must pass FROM and TO
                    962:     through protect_from_queue before calling.
                    963:    ALIGN (in bytes) is maximum alignment we can assume.  */
                    964: 
                    965: struct move_by_pieces
                    966: {
                    967:   rtx to;
                    968:   rtx to_addr;
                    969:   int autinc_to;
                    970:   int explicit_inc_to;
                    971:   rtx from;
                    972:   rtx from_addr;
                    973:   int autinc_from;
                    974:   int explicit_inc_from;
                    975:   int len;
                    976:   int offset;
                    977:   int reverse;
                    978: };
                    979: 
                    980: static void move_by_pieces_1 ();
                    981: static int move_by_pieces_ninsns ();
                    982: 
                    983: static void
                    984: move_by_pieces (to, from, len, align)
                    985:      rtx to, from;
                    986:      int len, align;
                    987: {
                    988:   struct move_by_pieces data;
                    989:   rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0);
1.1.1.2   root      990:   int max_size = MOVE_MAX + 1;
1.1       root      991: 
                    992:   data.offset = 0;
                    993:   data.to_addr = to_addr;
                    994:   data.from_addr = from_addr;
                    995:   data.to = to;
                    996:   data.from = from;
                    997:   data.autinc_to
                    998:     = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
                    999:        || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
                   1000:   data.autinc_from
                   1001:     = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
                   1002:        || GET_CODE (from_addr) == POST_INC
                   1003:        || GET_CODE (from_addr) == POST_DEC);
                   1004: 
                   1005:   data.explicit_inc_from = 0;
                   1006:   data.explicit_inc_to = 0;
                   1007:   data.reverse
                   1008:     = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
                   1009:   if (data.reverse) data.offset = len;
                   1010:   data.len = len;
                   1011: 
                   1012:   /* If copying requires more than two move insns,
                   1013:      copy addresses to registers (to make displacements shorter)
                   1014:      and use post-increment if available.  */
                   1015:   if (!(data.autinc_from && data.autinc_to)
                   1016:       && move_by_pieces_ninsns (len, align) > 2)
                   1017:     {
                   1018: #ifdef HAVE_PRE_DECREMENT
                   1019:       if (data.reverse && ! data.autinc_from)
                   1020:        {
                   1021:          data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
                   1022:          data.autinc_from = 1;
                   1023:          data.explicit_inc_from = -1;
                   1024:        }
                   1025: #endif
                   1026: #ifdef HAVE_POST_INCREMENT
                   1027:       if (! data.autinc_from)
                   1028:        {
                   1029:          data.from_addr = copy_addr_to_reg (from_addr);
                   1030:          data.autinc_from = 1;
                   1031:          data.explicit_inc_from = 1;
                   1032:        }
                   1033: #endif
                   1034:       if (!data.autinc_from && CONSTANT_P (from_addr))
                   1035:        data.from_addr = copy_addr_to_reg (from_addr);
                   1036: #ifdef HAVE_PRE_DECREMENT
                   1037:       if (data.reverse && ! data.autinc_to)
                   1038:        {
                   1039:          data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
                   1040:          data.autinc_to = 1;
                   1041:          data.explicit_inc_to = -1;
                   1042:        }
                   1043: #endif
                   1044: #ifdef HAVE_POST_INCREMENT
                   1045:       if (! data.reverse && ! data.autinc_to)
                   1046:        {
                   1047:          data.to_addr = copy_addr_to_reg (to_addr);
                   1048:          data.autinc_to = 1;
                   1049:          data.explicit_inc_to = 1;
                   1050:        }
                   1051: #endif
                   1052:       if (!data.autinc_to && CONSTANT_P (to_addr))
                   1053:        data.to_addr = copy_addr_to_reg (to_addr);
                   1054:     }
                   1055: 
1.1.1.2   root     1056:   if (! (STRICT_ALIGNMENT || SLOW_UNALIGNED_ACCESS)
                   1057:       || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
1.1       root     1058:     align = MOVE_MAX;
                   1059: 
                   1060:   /* First move what we can in the largest integer mode, then go to
                   1061:      successively smaller modes.  */
                   1062: 
                   1063:   while (max_size > 1)
                   1064:     {
                   1065:       enum machine_mode mode = VOIDmode, tmode;
                   1066:       enum insn_code icode;
                   1067: 
1.1.1.3   root     1068:       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
                   1069:           tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
                   1070:        if (GET_MODE_SIZE (tmode) < max_size)
1.1       root     1071:          mode = tmode;
                   1072: 
                   1073:       if (mode == VOIDmode)
                   1074:        break;
                   1075: 
                   1076:       icode = mov_optab->handlers[(int) mode].insn_code;
                   1077:       if (icode != CODE_FOR_nothing
                   1078:          && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT,
                   1079:                           GET_MODE_SIZE (mode)))
                   1080:        move_by_pieces_1 (GEN_FCN (icode), mode, &data);
                   1081: 
                   1082:       max_size = GET_MODE_SIZE (mode);
                   1083:     }
                   1084: 
                   1085:   /* The code above should have handled everything.  */
                   1086:   if (data.len != 0)
                   1087:     abort ();
                   1088: }
                   1089: 
                   1090: /* Return number of insns required to move L bytes by pieces.
                   1091:    ALIGN (in bytes) is maximum alignment we can assume.  */
                   1092: 
                   1093: static int
                   1094: move_by_pieces_ninsns (l, align)
                   1095:      unsigned int l;
                   1096:      int align;
                   1097: {
                   1098:   register int n_insns = 0;
1.1.1.2   root     1099:   int max_size = MOVE_MAX + 1;
1.1       root     1100: 
1.1.1.2   root     1101:   if (! (STRICT_ALIGNMENT || SLOW_UNALIGNED_ACCESS)
                   1102:       || align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
1.1       root     1103:     align = MOVE_MAX;
                   1104: 
                   1105:   while (max_size > 1)
                   1106:     {
                   1107:       enum machine_mode mode = VOIDmode, tmode;
                   1108:       enum insn_code icode;
                   1109: 
1.1.1.3   root     1110:       for (tmode = GET_CLASS_NARROWEST_MODE (MODE_INT);
                   1111:           tmode != VOIDmode; tmode = GET_MODE_WIDER_MODE (tmode))
                   1112:        if (GET_MODE_SIZE (tmode) < max_size)
1.1       root     1113:          mode = tmode;
                   1114: 
                   1115:       if (mode == VOIDmode)
                   1116:        break;
                   1117: 
                   1118:       icode = mov_optab->handlers[(int) mode].insn_code;
                   1119:       if (icode != CODE_FOR_nothing
                   1120:          && align >= MIN (BIGGEST_ALIGNMENT / BITS_PER_UNIT,
                   1121:                           GET_MODE_SIZE (mode)))
                   1122:        n_insns += l / GET_MODE_SIZE (mode), l %= GET_MODE_SIZE (mode);
                   1123: 
                   1124:       max_size = GET_MODE_SIZE (mode);
                   1125:     }
                   1126: 
                   1127:   return n_insns;
                   1128: }
                   1129: 
                   1130: /* Subroutine of move_by_pieces.  Move as many bytes as appropriate
                   1131:    with move instructions for mode MODE.  GENFUN is the gen_... function
                   1132:    to make a move insn for that mode.  DATA has all the other info.  */
                   1133: 
                   1134: static void
                   1135: move_by_pieces_1 (genfun, mode, data)
                   1136:      rtx (*genfun) ();
                   1137:      enum machine_mode mode;
                   1138:      struct move_by_pieces *data;
                   1139: {
                   1140:   register int size = GET_MODE_SIZE (mode);
                   1141:   register rtx to1, from1;
                   1142: 
                   1143:   while (data->len >= size)
                   1144:     {
                   1145:       if (data->reverse) data->offset -= size;
                   1146: 
                   1147:       to1 = (data->autinc_to
                   1148:             ? gen_rtx (MEM, mode, data->to_addr)
                   1149:             : change_address (data->to, mode,
                   1150:                               plus_constant (data->to_addr, data->offset)));
                   1151:       from1 =
                   1152:        (data->autinc_from
                   1153:         ? gen_rtx (MEM, mode, data->from_addr)
                   1154:         : change_address (data->from, mode,
                   1155:                           plus_constant (data->from_addr, data->offset)));
                   1156: 
                   1157: #ifdef HAVE_PRE_DECREMENT
                   1158:       if (data->explicit_inc_to < 0)
1.1.1.4 ! root     1159:        emit_insn (gen_add2_insn (data->to_addr, GEN_INT (-size)));
1.1       root     1160:       if (data->explicit_inc_from < 0)
1.1.1.4 ! root     1161:        emit_insn (gen_add2_insn (data->from_addr, GEN_INT (-size)));
1.1       root     1162: #endif
                   1163: 
                   1164:       emit_insn ((*genfun) (to1, from1));
                   1165: #ifdef HAVE_POST_INCREMENT
                   1166:       if (data->explicit_inc_to > 0)
1.1.1.4 ! root     1167:        emit_insn (gen_add2_insn (data->to_addr, GEN_INT (size)));
1.1       root     1168:       if (data->explicit_inc_from > 0)
1.1.1.4 ! root     1169:        emit_insn (gen_add2_insn (data->from_addr, GEN_INT (size)));
1.1       root     1170: #endif
                   1171: 
                   1172:       if (! data->reverse) data->offset += size;
                   1173: 
                   1174:       data->len -= size;
                   1175:     }
                   1176: }
                   1177: 
                   1178: /* Emit code to move a block Y to a block X.
                   1179:    This may be done with string-move instructions,
                   1180:    with multiple scalar move instructions, or with a library call.
                   1181: 
                   1182:    Both X and Y must be MEM rtx's (perhaps inside VOLATILE)
                   1183:    with mode BLKmode.
                   1184:    SIZE is an rtx that says how long they are.
                   1185:    ALIGN is the maximum alignment we can assume they have,
                   1186:    measured in bytes.  */
                   1187: 
                   1188: void
                   1189: emit_block_move (x, y, size, align)
                   1190:      rtx x, y;
                   1191:      rtx size;
                   1192:      int align;
                   1193: {
                   1194:   if (GET_MODE (x) != BLKmode)
                   1195:     abort ();
                   1196: 
                   1197:   if (GET_MODE (y) != BLKmode)
                   1198:     abort ();
                   1199: 
                   1200:   x = protect_from_queue (x, 1);
                   1201:   y = protect_from_queue (y, 0);
1.1.1.4 ! root     1202:   size = protect_from_queue (size, 0);
1.1       root     1203: 
                   1204:   if (GET_CODE (x) != MEM)
                   1205:     abort ();
                   1206:   if (GET_CODE (y) != MEM)
                   1207:     abort ();
                   1208:   if (size == 0)
                   1209:     abort ();
                   1210: 
                   1211:   if (GET_CODE (size) == CONST_INT
1.1.1.4 ! root     1212:       && (move_by_pieces_ninsns (INTVAL (size), align) < MOVE_RATIO))
1.1       root     1213:     move_by_pieces (x, y, INTVAL (size), align);
                   1214:   else
                   1215:     {
                   1216:       /* Try the most limited insn first, because there's no point
                   1217:         including more than one in the machine description unless
                   1218:         the more limited one has some advantage.  */
1.1.1.4 ! root     1219: 
        !          1220:       rtx opalign = GEN_INT (align);
        !          1221:       enum machine_mode mode;
        !          1222: 
        !          1223:       for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
        !          1224:           mode = GET_MODE_WIDER_MODE (mode))
1.1       root     1225:        {
1.1.1.4 ! root     1226:          enum insn_code code = movstr_optab[(int) mode];
        !          1227: 
        !          1228:          if (code != CODE_FOR_nothing
        !          1229:              /* We don't need MODE to be narrower than BITS_PER_HOST_WIDE_INT
        !          1230:                 here because if SIZE is less than the mode mask, as it is
        !          1231:                 returned by the macro, it will definately be less than the
        !          1232:                 actual mode mask.  */
        !          1233:              && (unsigned) INTVAL (size) <= GET_MODE_MASK (mode)
        !          1234:              && (insn_operand_predicate[(int) code][0] == 0
        !          1235:                  || (*insn_operand_predicate[(int) code][0]) (x, BLKmode))
        !          1236:              && (insn_operand_predicate[(int) code][1] == 0
        !          1237:                  || (*insn_operand_predicate[(int) code][1]) (y, BLKmode))
        !          1238:              && (insn_operand_predicate[(int) code][3] == 0
        !          1239:                  || (*insn_operand_predicate[(int) code][3]) (opalign,
        !          1240:                                                               VOIDmode)))
1.1       root     1241:            {
1.1.1.4 ! root     1242:              rtx op2;
        !          1243:              rtx last = get_last_insn ();
        !          1244:              rtx pat;
        !          1245: 
        !          1246:              op2 = convert_to_mode (mode, size, 1);
        !          1247:              if (insn_operand_predicate[(int) code][2] != 0
        !          1248:                  && ! (*insn_operand_predicate[(int) code][2]) (op2, mode))
        !          1249:                op2 = copy_to_mode_reg (mode, op2);
        !          1250: 
        !          1251:              pat = GEN_FCN ((int) code) (x, y, op2, opalign);
        !          1252:              if (pat)
        !          1253:                {
        !          1254:                  emit_insn (pat);
        !          1255:                  return;
        !          1256:                }
        !          1257:              else
        !          1258:                delete_insns_since (last);
1.1       root     1259:            }
                   1260:        }
                   1261: 
                   1262: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.4 ! root     1263:       emit_library_call (memcpy_libfunc, 0,
1.1       root     1264:                         VOIDmode, 3, XEXP (x, 0), Pmode,
                   1265:                         XEXP (y, 0), Pmode,
1.1.1.4 ! root     1266:                         convert_to_mode (Pmode, size, 1), Pmode);
1.1       root     1267: #else
1.1.1.4 ! root     1268:       emit_library_call (bcopy_libfunc, 0,
1.1       root     1269:                         VOIDmode, 3, XEXP (y, 0), Pmode,
                   1270:                         XEXP (x, 0), Pmode,
1.1.1.4 ! root     1271:                         convert_to_mode (Pmode, size, 1), Pmode);
1.1       root     1272: #endif
                   1273:     }
                   1274: }
                   1275: 
                   1276: /* Copy all or part of a value X into registers starting at REGNO.
                   1277:    The number of registers to be filled is NREGS.  */
                   1278: 
                   1279: void
                   1280: move_block_to_reg (regno, x, nregs, mode)
                   1281:      int regno;
                   1282:      rtx x;
                   1283:      int nregs;
                   1284:      enum machine_mode mode;
                   1285: {
                   1286:   int i;
                   1287:   rtx pat, last;
                   1288: 
                   1289:   if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
                   1290:     x = validize_mem (force_const_mem (mode, x));
                   1291: 
                   1292:   /* See if the machine can do this with a load multiple insn.  */
                   1293: #ifdef HAVE_load_multiple
                   1294:   last = get_last_insn ();
                   1295:   pat = gen_load_multiple (gen_rtx (REG, word_mode, regno), x,
1.1.1.4 ! root     1296:                           GEN_INT (nregs));
1.1       root     1297:   if (pat)
                   1298:     {
                   1299:       emit_insn (pat);
                   1300:       return;
                   1301:     }
                   1302:   else
                   1303:     delete_insns_since (last);
                   1304: #endif
                   1305: 
                   1306:   for (i = 0; i < nregs; i++)
                   1307:     emit_move_insn (gen_rtx (REG, word_mode, regno + i),
                   1308:                    operand_subword_force (x, i, mode));
                   1309: }
                   1310: 
                   1311: /* Copy all or part of a BLKmode value X out of registers starting at REGNO.
                   1312:    The number of registers to be filled is NREGS.  */
                   1313: 
                   1314: void
                   1315: move_block_from_reg (regno, x, nregs)
                   1316:      int regno;
                   1317:      rtx x;
                   1318:      int nregs;
                   1319: {
                   1320:   int i;
                   1321:   rtx pat, last;
                   1322: 
                   1323:   /* See if the machine can do this with a store multiple insn.  */
                   1324: #ifdef HAVE_store_multiple
                   1325:   last = get_last_insn ();
                   1326:   pat = gen_store_multiple (x, gen_rtx (REG, word_mode, regno),
1.1.1.4 ! root     1327:                            GEN_INT (nregs));
1.1       root     1328:   if (pat)
                   1329:     {
                   1330:       emit_insn (pat);
                   1331:       return;
                   1332:     }
                   1333:   else
                   1334:     delete_insns_since (last);
                   1335: #endif
                   1336: 
                   1337:   for (i = 0; i < nregs; i++)
                   1338:     {
                   1339:       rtx tem = operand_subword (x, i, 1, BLKmode);
                   1340: 
                   1341:       if (tem == 0)
                   1342:        abort ();
                   1343: 
                   1344:       emit_move_insn (tem, gen_rtx (REG, word_mode, regno + i));
                   1345:     }
                   1346: }
                   1347: 
                   1348: /* Mark NREGS consecutive regs, starting at REGNO, as being live now.  */
                   1349: 
                   1350: void
                   1351: use_regs (regno, nregs)
                   1352:      int regno;
                   1353:      int nregs;
                   1354: {
                   1355:   int i;
                   1356: 
                   1357:   for (i = 0; i < nregs; i++)
                   1358:     emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, word_mode, regno + i)));
                   1359: }
1.1.1.4 ! root     1360: 
        !          1361: /* Mark the instructions since PREV as a libcall block.
        !          1362:    Add REG_LIBCALL to PREV and add a REG_RETVAL to the most recent insn.  */
        !          1363: 
        !          1364: static rtx
        !          1365: group_insns (prev)
        !          1366:      rtx prev;
        !          1367: {
        !          1368:   rtx insn_first;
        !          1369:   rtx insn_last;
        !          1370: 
        !          1371:   /* Find the instructions to mark */
        !          1372:   if (prev)
        !          1373:     insn_first = NEXT_INSN (prev);
        !          1374:   else
        !          1375:     insn_first = get_insns ();
        !          1376: 
        !          1377:   insn_last = get_last_insn ();
        !          1378: 
        !          1379:   REG_NOTES (insn_last) = gen_rtx (INSN_LIST, REG_RETVAL, insn_first,
        !          1380:                                   REG_NOTES (insn_last));
        !          1381: 
        !          1382:   REG_NOTES (insn_first) = gen_rtx (INSN_LIST, REG_LIBCALL, insn_last,
        !          1383:                                    REG_NOTES (insn_first));
        !          1384: }
1.1       root     1385: 
                   1386: /* Write zeros through the storage of OBJECT.
                   1387:    If OBJECT has BLKmode, SIZE is its length in bytes.  */
                   1388: 
                   1389: void
                   1390: clear_storage (object, size)
                   1391:      rtx object;
                   1392:      int size;
                   1393: {
                   1394:   if (GET_MODE (object) == BLKmode)
                   1395:     {
                   1396: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.4 ! root     1397:       emit_library_call (memset_libfunc, 0,
1.1       root     1398:                         VOIDmode, 3,
                   1399:                         XEXP (object, 0), Pmode, const0_rtx, Pmode,
1.1.1.4 ! root     1400:                         GEN_INT (size), Pmode);
1.1       root     1401: #else
1.1.1.4 ! root     1402:       emit_library_call (bzero_libfunc, 0,
1.1       root     1403:                         VOIDmode, 2,
                   1404:                         XEXP (object, 0), Pmode,
1.1.1.4 ! root     1405:                         GEN_INT (size), Pmode);
1.1       root     1406: #endif
                   1407:     }
                   1408:   else
                   1409:     emit_move_insn (object, const0_rtx);
                   1410: }
                   1411: 
                   1412: /* Generate code to copy Y into X.
                   1413:    Both Y and X must have the same mode, except that
                   1414:    Y can be a constant with VOIDmode.
                   1415:    This mode cannot be BLKmode; use emit_block_move for that.
                   1416: 
                   1417:    Return the last instruction emitted.  */
                   1418: 
                   1419: rtx
                   1420: emit_move_insn (x, y)
                   1421:      rtx x, y;
                   1422: {
                   1423:   enum machine_mode mode = GET_MODE (x);
1.1.1.4 ! root     1424:   enum machine_mode submode;
        !          1425:   enum mode_class class = GET_MODE_CLASS (mode);
1.1       root     1426:   int i;
                   1427: 
                   1428:   x = protect_from_queue (x, 1);
                   1429:   y = protect_from_queue (y, 0);
                   1430: 
                   1431:   if (mode == BLKmode || (GET_MODE (y) != mode && GET_MODE (y) != VOIDmode))
                   1432:     abort ();
                   1433: 
                   1434:   if (CONSTANT_P (y) && ! LEGITIMATE_CONSTANT_P (y))
                   1435:     y = force_const_mem (mode, y);
                   1436: 
                   1437:   /* If X or Y are memory references, verify that their addresses are valid
                   1438:      for the machine.  */
                   1439:   if (GET_CODE (x) == MEM
                   1440:       && ((! memory_address_p (GET_MODE (x), XEXP (x, 0))
                   1441:           && ! push_operand (x, GET_MODE (x)))
                   1442:          || (flag_force_addr
                   1443:              && CONSTANT_ADDRESS_P (XEXP (x, 0)))))
                   1444:     x = change_address (x, VOIDmode, XEXP (x, 0));
                   1445: 
                   1446:   if (GET_CODE (y) == MEM
                   1447:       && (! memory_address_p (GET_MODE (y), XEXP (y, 0))
                   1448:          || (flag_force_addr
                   1449:              && CONSTANT_ADDRESS_P (XEXP (y, 0)))))
                   1450:     y = change_address (y, VOIDmode, XEXP (y, 0));
                   1451: 
                   1452:   if (mode == BLKmode)
                   1453:     abort ();
                   1454: 
1.1.1.4 ! root     1455:   if (class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
        !          1456:     submode = mode_for_size (GET_MODE_UNIT_SIZE (mode) * BITS_PER_UNIT,
        !          1457:                             (class == MODE_COMPLEX_INT
        !          1458:                              ? MODE_INT : MODE_FLOAT),
        !          1459:                             0);
        !          1460: 
1.1       root     1461:   if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                   1462:     return
                   1463:       emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
                   1464: 
1.1.1.4 ! root     1465:   /* Expand complex moves by moving real part and imag part, if posible.  */
        !          1466:   else if ((class == MODE_COMPLEX_FLOAT || class == MODE_COMPLEX_INT)
        !          1467:           && submode != BLKmode
        !          1468:           && (mov_optab->handlers[(int) submode].insn_code
        !          1469:               != CODE_FOR_nothing))
        !          1470:     {
        !          1471:       /* Don't split destination if it is a stack push.  */
        !          1472:       int stack = push_operand (x, GET_MODE (x));
        !          1473:       rtx prev = get_last_insn ();
        !          1474: 
        !          1475:       /* Tell flow that the whole of the destination is being set.  */
        !          1476:       if (GET_CODE (x) == REG)
        !          1477:        emit_insn (gen_rtx (CLOBBER, VOIDmode, x));
        !          1478: 
        !          1479:       /* If this is a stack, push the highpart first, so it
        !          1480:         will be in the argument order.
        !          1481: 
        !          1482:         In that case, change_address is used only to convert
        !          1483:         the mode, not to change the address.  */
        !          1484:       emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
        !          1485:                 ((stack ? change_address (x, submode, (rtx) 0)
        !          1486:                   : gen_highpart (submode, x)),
        !          1487:                  gen_highpart (submode, y)));
        !          1488:       emit_insn (GEN_FCN (mov_optab->handlers[(int) submode].insn_code)
        !          1489:                 ((stack ? change_address (x, submode, (rtx) 0)
        !          1490:                   : gen_lowpart (submode, x)),
        !          1491:                  gen_lowpart (submode, y)));
        !          1492: 
        !          1493:       group_insns (prev);
        !          1494: 
        !          1495:       return get_last_insn ();
        !          1496:     }
        !          1497: 
1.1       root     1498:   /* This will handle any multi-word mode that lacks a move_insn pattern.
                   1499:      However, you will get better code if you define such patterns,
                   1500:      even if they must turn into multiple assembler instructions.  */
1.1.1.4 ! root     1501:   else if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
1.1       root     1502:     {
                   1503:       rtx last_insn = 0;
1.1.1.4 ! root     1504:       rtx prev_insn = get_last_insn ();
1.1       root     1505: 
                   1506:       for (i = 0;
                   1507:           i < (GET_MODE_SIZE (mode)  + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD;
                   1508:           i++)
                   1509:        {
                   1510:          rtx xpart = operand_subword (x, i, 1, mode);
                   1511:          rtx ypart = operand_subword (y, i, 1, mode);
                   1512: 
                   1513:          /* If we can't get a part of Y, put Y into memory if it is a
                   1514:             constant.  Otherwise, force it into a register.  If we still
                   1515:             can't get a part of Y, abort.  */
                   1516:          if (ypart == 0 && CONSTANT_P (y))
                   1517:            {
                   1518:              y = force_const_mem (mode, y);
                   1519:              ypart = operand_subword (y, i, 1, mode);
                   1520:            }
                   1521:          else if (ypart == 0)
                   1522:            ypart = operand_subword_force (y, i, mode);
                   1523: 
                   1524:          if (xpart == 0 || ypart == 0)
                   1525:            abort ();
                   1526: 
                   1527:          last_insn = emit_move_insn (xpart, ypart);
                   1528:        }
1.1.1.4 ! root     1529:       /* Mark these insns as a libcall block.  */
        !          1530:       group_insns (prev_insn);
        !          1531: 
1.1       root     1532:       return last_insn;
                   1533:     }
                   1534:   else
                   1535:     abort ();
                   1536: }
                   1537: 
                   1538: /* Pushing data onto the stack.  */
                   1539: 
                   1540: /* Push a block of length SIZE (perhaps variable)
                   1541:    and return an rtx to address the beginning of the block.
                   1542:    Note that it is not possible for the value returned to be a QUEUED.
                   1543:    The value may be virtual_outgoing_args_rtx.
                   1544: 
                   1545:    EXTRA is the number of bytes of padding to push in addition to SIZE.
                   1546:    BELOW nonzero means this padding comes at low addresses;
                   1547:    otherwise, the padding comes at high addresses.  */
                   1548: 
                   1549: rtx
                   1550: push_block (size, extra, below)
                   1551:      rtx size;
                   1552:      int extra, below;
                   1553: {
                   1554:   register rtx temp;
                   1555:   if (CONSTANT_P (size))
                   1556:     anti_adjust_stack (plus_constant (size, extra));
                   1557:   else if (GET_CODE (size) == REG && extra == 0)
                   1558:     anti_adjust_stack (size);
                   1559:   else
                   1560:     {
                   1561:       rtx temp = copy_to_mode_reg (Pmode, size);
                   1562:       if (extra != 0)
1.1.1.4 ! root     1563:        temp = expand_binop (Pmode, add_optab, temp, GEN_INT (extra),
1.1       root     1564:                             temp, 0, OPTAB_LIB_WIDEN);
                   1565:       anti_adjust_stack (temp);
                   1566:     }
                   1567: 
                   1568: #ifdef STACK_GROWS_DOWNWARD
                   1569:   temp = virtual_outgoing_args_rtx;
                   1570:   if (extra != 0 && below)
                   1571:     temp = plus_constant (temp, extra);
                   1572: #else
                   1573:   if (GET_CODE (size) == CONST_INT)
                   1574:     temp = plus_constant (virtual_outgoing_args_rtx,
                   1575:                          - INTVAL (size) - (below ? 0 : extra));
                   1576:   else if (extra != 0 && !below)
                   1577:     temp = gen_rtx (PLUS, Pmode, virtual_outgoing_args_rtx,
                   1578:                    negate_rtx (Pmode, plus_constant (size, extra)));
                   1579:   else
                   1580:     temp = gen_rtx (PLUS, Pmode, virtual_outgoing_args_rtx,
                   1581:                    negate_rtx (Pmode, size));
                   1582: #endif
                   1583: 
                   1584:   return memory_address (GET_CLASS_NARROWEST_MODE (MODE_INT), temp);
                   1585: }
                   1586: 
1.1.1.4 ! root     1587: rtx
1.1       root     1588: gen_push_operand ()
                   1589: {
                   1590:   return gen_rtx (STACK_PUSH_CODE, Pmode, stack_pointer_rtx);
                   1591: }
                   1592: 
                   1593: /* Generate code to push X onto the stack, assuming it has mode MODE and
                   1594:    type TYPE.
                   1595:    MODE is redundant except when X is a CONST_INT (since they don't
                   1596:    carry mode info).
                   1597:    SIZE is an rtx for the size of data to be copied (in bytes),
                   1598:    needed only if X is BLKmode.
                   1599: 
                   1600:    ALIGN (in bytes) is maximum alignment we can assume.
                   1601: 
                   1602:    If PARTIAL is nonzero, then copy that many of the first words
                   1603:    of X into registers starting with REG, and push the rest of X.
                   1604:    The amount of space pushed is decreased by PARTIAL words,
                   1605:    rounded *down* to a multiple of PARM_BOUNDARY.
                   1606:    REG must be a hard register in this case.
                   1607: 
                   1608:    EXTRA is the amount in bytes of extra space to leave next to this arg.
1.1.1.3   root     1609:    This is ignored if an argument block has already been allocated.
1.1       root     1610: 
                   1611:    On a machine that lacks real push insns, ARGS_ADDR is the address of
                   1612:    the bottom of the argument block for this call.  We use indexing off there
                   1613:    to store the arg.  On machines with push insns, ARGS_ADDR is 0 when a
                   1614:    argument block has not been preallocated.
                   1615: 
                   1616:    ARGS_SO_FAR is the size of args previously pushed for this call.  */
                   1617: 
                   1618: void
                   1619: emit_push_insn (x, mode, type, size, align, partial, reg, extra,
                   1620:                args_addr, args_so_far)
                   1621:      register rtx x;
                   1622:      enum machine_mode mode;
                   1623:      tree type;
                   1624:      rtx size;
                   1625:      int align;
                   1626:      int partial;
                   1627:      rtx reg;
                   1628:      int extra;
                   1629:      rtx args_addr;
                   1630:      rtx args_so_far;
                   1631: {
                   1632:   rtx xinner;
                   1633:   enum direction stack_direction
                   1634: #ifdef STACK_GROWS_DOWNWARD
                   1635:     = downward;
                   1636: #else
                   1637:     = upward;
                   1638: #endif
                   1639: 
                   1640:   /* Decide where to pad the argument: `downward' for below,
                   1641:      `upward' for above, or `none' for don't pad it.
                   1642:      Default is below for small data on big-endian machines; else above.  */
                   1643:   enum direction where_pad = FUNCTION_ARG_PADDING (mode, type);
                   1644: 
                   1645:   /* Invert direction if stack is post-update.  */
                   1646:   if (STACK_PUSH_CODE == POST_INC || STACK_PUSH_CODE == POST_DEC)
                   1647:     if (where_pad != none)
                   1648:       where_pad = (where_pad == downward ? upward : downward);
                   1649: 
                   1650:   xinner = x = protect_from_queue (x, 0);
                   1651: 
                   1652:   if (mode == BLKmode)
                   1653:     {
                   1654:       /* Copy a block into the stack, entirely or partially.  */
                   1655: 
                   1656:       register rtx temp;
                   1657:       int used = partial * UNITS_PER_WORD;
                   1658:       int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);
                   1659:       int skip;
                   1660:       
                   1661:       if (size == 0)
                   1662:        abort ();
                   1663: 
                   1664:       used -= offset;
                   1665: 
                   1666:       /* USED is now the # of bytes we need not copy to the stack
                   1667:         because registers will take care of them.  */
                   1668: 
                   1669:       if (partial != 0)
                   1670:        xinner = change_address (xinner, BLKmode,
                   1671:                                 plus_constant (XEXP (xinner, 0), used));
                   1672: 
                   1673:       /* If the partial register-part of the arg counts in its stack size,
                   1674:         skip the part of stack space corresponding to the registers.
                   1675:         Otherwise, start copying to the beginning of the stack space,
                   1676:         by setting SKIP to 0.  */
                   1677: #ifndef REG_PARM_STACK_SPACE
                   1678:       skip = 0;
                   1679: #else
                   1680:       skip = used;
                   1681: #endif
                   1682: 
                   1683: #ifdef PUSH_ROUNDING
                   1684:       /* Do it with several push insns if that doesn't take lots of insns
                   1685:         and if there is no difficulty with push insns that skip bytes
                   1686:         on the stack for alignment purposes.  */
                   1687:       if (args_addr == 0
                   1688:          && GET_CODE (size) == CONST_INT
                   1689:          && skip == 0
                   1690:          && (move_by_pieces_ninsns ((unsigned) INTVAL (size) - used, align)
                   1691:              < MOVE_RATIO)
                   1692:          /* Here we avoid the case of a structure whose weak alignment
                   1693:             forces many pushes of a small amount of data,
                   1694:             and such small pushes do rounding that causes trouble.  */
1.1.1.2   root     1695:          && ((! STRICT_ALIGNMENT && ! SLOW_UNALIGNED_ACCESS)
                   1696:              || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT
1.1       root     1697:              || PUSH_ROUNDING (align) == align)
                   1698:          && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
                   1699:        {
                   1700:          /* Push padding now if padding above and stack grows down,
                   1701:             or if padding below and stack grows up.
                   1702:             But if space already allocated, this has already been done.  */
                   1703:          if (extra && args_addr == 0
                   1704:              && where_pad != none && where_pad != stack_direction)
1.1.1.4 ! root     1705:            anti_adjust_stack (GEN_INT (extra));
1.1       root     1706: 
                   1707:          move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner,
                   1708:                          INTVAL (size) - used, align);
                   1709:        }
                   1710:       else
                   1711: #endif /* PUSH_ROUNDING */
                   1712:        {
                   1713:          /* Otherwise make space on the stack and copy the data
                   1714:             to the address of that space.  */
                   1715: 
                   1716:          /* Deduct words put into registers from the size we must copy.  */
                   1717:          if (partial != 0)
                   1718:            {
                   1719:              if (GET_CODE (size) == CONST_INT)
1.1.1.4 ! root     1720:                size = GEN_INT (INTVAL (size) - used);
1.1       root     1721:              else
                   1722:                size = expand_binop (GET_MODE (size), sub_optab, size,
1.1.1.4 ! root     1723:                                     GEN_INT (used), NULL_RTX, 0,
        !          1724:                                     OPTAB_LIB_WIDEN);
1.1       root     1725:            }
                   1726: 
                   1727:          /* Get the address of the stack space.
                   1728:             In this case, we do not deal with EXTRA separately.
                   1729:             A single stack adjust will do.  */
                   1730:          if (! args_addr)
                   1731:            {
                   1732:              temp = push_block (size, extra, where_pad == downward);
                   1733:              extra = 0;
                   1734:            }
                   1735:          else if (GET_CODE (args_so_far) == CONST_INT)
                   1736:            temp = memory_address (BLKmode,
                   1737:                                   plus_constant (args_addr,
                   1738:                                                  skip + INTVAL (args_so_far)));
                   1739:          else
                   1740:            temp = memory_address (BLKmode,
                   1741:                                   plus_constant (gen_rtx (PLUS, Pmode,
                   1742:                                                           args_addr, args_so_far),
                   1743:                                                  skip));
                   1744: 
                   1745:          /* TEMP is the address of the block.  Copy the data there.  */
                   1746:          if (GET_CODE (size) == CONST_INT
                   1747:              && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)
                   1748:                  < MOVE_RATIO))
                   1749:            {
                   1750:              move_by_pieces (gen_rtx (MEM, BLKmode, temp), xinner,
                   1751:                              INTVAL (size), align);
                   1752:              goto ret;
                   1753:            }
                   1754:          /* Try the most limited insn first, because there's no point
                   1755:             including more than one in the machine description unless
                   1756:             the more limited one has some advantage.  */
                   1757: #ifdef HAVE_movstrqi
                   1758:          if (HAVE_movstrqi
                   1759:              && GET_CODE (size) == CONST_INT
                   1760:              && ((unsigned) INTVAL (size)
                   1761:                  < (1 << (GET_MODE_BITSIZE (QImode) - 1))))
                   1762:            {
                   1763:              emit_insn (gen_movstrqi (gen_rtx (MEM, BLKmode, temp),
1.1.1.4 ! root     1764:                                       xinner, size, GEN_INT (align)));
1.1       root     1765:              goto ret;
                   1766:            }
                   1767: #endif
                   1768: #ifdef HAVE_movstrhi
                   1769:          if (HAVE_movstrhi
                   1770:              && GET_CODE (size) == CONST_INT
                   1771:              && ((unsigned) INTVAL (size)
                   1772:                  < (1 << (GET_MODE_BITSIZE (HImode) - 1))))
                   1773:            {
                   1774:              emit_insn (gen_movstrhi (gen_rtx (MEM, BLKmode, temp),
1.1.1.4 ! root     1775:                                       xinner, size, GEN_INT (align)));
1.1       root     1776:              goto ret;
                   1777:            }
                   1778: #endif
                   1779: #ifdef HAVE_movstrsi
                   1780:          if (HAVE_movstrsi)
                   1781:            {
                   1782:              emit_insn (gen_movstrsi (gen_rtx (MEM, BLKmode, temp),
1.1.1.4 ! root     1783:                                       xinner, size, GEN_INT (align)));
1.1       root     1784:              goto ret;
                   1785:            }
                   1786: #endif
                   1787: #ifdef HAVE_movstrdi
                   1788:          if (HAVE_movstrdi)
                   1789:            {
                   1790:              emit_insn (gen_movstrdi (gen_rtx (MEM, BLKmode, temp),
1.1.1.4 ! root     1791:                                       xinner, size, GEN_INT (align)));
1.1       root     1792:              goto ret;
                   1793:            }
                   1794: #endif
                   1795: 
                   1796: #ifndef ACCUMULATE_OUTGOING_ARGS
                   1797:          /* If the source is referenced relative to the stack pointer,
                   1798:             copy it to another register to stabilize it.  We do not need
                   1799:             to do this if we know that we won't be changing sp.  */
                   1800: 
                   1801:          if (reg_mentioned_p (virtual_stack_dynamic_rtx, temp)
                   1802:              || reg_mentioned_p (virtual_outgoing_args_rtx, temp))
                   1803:            temp = copy_to_reg (temp);
                   1804: #endif
                   1805: 
                   1806:          /* Make inhibit_defer_pop nonzero around the library call
                   1807:             to force it to pop the bcopy-arguments right away.  */
                   1808:          NO_DEFER_POP;
                   1809: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.4 ! root     1810:          emit_library_call (memcpy_libfunc, 0,
1.1       root     1811:                             VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode,
                   1812:                             size, Pmode);
                   1813: #else
1.1.1.4 ! root     1814:          emit_library_call (bcopy_libfunc, 0,
1.1       root     1815:                             VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode,
                   1816:                             size, Pmode);
                   1817: #endif
                   1818:          OK_DEFER_POP;
                   1819:        }
                   1820:     }
                   1821:   else if (partial > 0)
                   1822:     {
                   1823:       /* Scalar partly in registers.  */
                   1824: 
                   1825:       int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
                   1826:       int i;
                   1827:       int not_stack;
                   1828:       /* # words of start of argument
                   1829:         that we must make space for but need not store.  */
                   1830:       int offset = partial % (PARM_BOUNDARY / BITS_PER_WORD);
                   1831:       int args_offset = INTVAL (args_so_far);
                   1832:       int skip;
                   1833: 
                   1834:       /* Push padding now if padding above and stack grows down,
                   1835:         or if padding below and stack grows up.
                   1836:         But if space already allocated, this has already been done.  */
                   1837:       if (extra && args_addr == 0
                   1838:          && where_pad != none && where_pad != stack_direction)
1.1.1.4 ! root     1839:        anti_adjust_stack (GEN_INT (extra));
1.1       root     1840: 
                   1841:       /* If we make space by pushing it, we might as well push
                   1842:         the real data.  Otherwise, we can leave OFFSET nonzero
                   1843:         and leave the space uninitialized.  */
                   1844:       if (args_addr == 0)
                   1845:        offset = 0;
                   1846: 
                   1847:       /* Now NOT_STACK gets the number of words that we don't need to
                   1848:         allocate on the stack.  */
                   1849:       not_stack = partial - offset;
                   1850: 
                   1851:       /* If the partial register-part of the arg counts in its stack size,
                   1852:         skip the part of stack space corresponding to the registers.
                   1853:         Otherwise, start copying to the beginning of the stack space,
                   1854:         by setting SKIP to 0.  */
                   1855: #ifndef REG_PARM_STACK_SPACE
                   1856:       skip = 0;
                   1857: #else
                   1858:       skip = not_stack;
                   1859: #endif
                   1860: 
                   1861:       if (CONSTANT_P (x) && ! LEGITIMATE_CONSTANT_P (x))
                   1862:        x = validize_mem (force_const_mem (mode, x));
                   1863: 
                   1864:       /* If X is a hard register in a non-integer mode, copy it into a pseudo;
                   1865:         SUBREGs of such registers are not allowed.  */
                   1866:       if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER
                   1867:           && GET_MODE_CLASS (GET_MODE (x)) != MODE_INT))
                   1868:        x = copy_to_reg (x);
                   1869: 
                   1870:       /* Loop over all the words allocated on the stack for this arg.  */
                   1871:       /* We can do it by words, because any scalar bigger than a word
                   1872:         has a size a multiple of a word.  */
                   1873: #ifndef PUSH_ARGS_REVERSED
                   1874:       for (i = not_stack; i < size; i++)
                   1875: #else
                   1876:       for (i = size - 1; i >= not_stack; i--)
                   1877: #endif
                   1878:        if (i >= not_stack + offset)
                   1879:          emit_push_insn (operand_subword_force (x, i, mode),
1.1.1.4 ! root     1880:                          word_mode, NULL_TREE, NULL_RTX, align, 0, NULL_RTX,
        !          1881:                          0, args_addr,
        !          1882:                          GEN_INT (args_offset + ((i - not_stack + skip)
1.1       root     1883:                                                  * UNITS_PER_WORD)));
                   1884:     }
                   1885:   else
                   1886:     {
                   1887:       rtx addr;
                   1888: 
                   1889:       /* Push padding now if padding above and stack grows down,
                   1890:         or if padding below and stack grows up.
                   1891:         But if space already allocated, this has already been done.  */
                   1892:       if (extra && args_addr == 0
                   1893:          && where_pad != none && where_pad != stack_direction)
1.1.1.4 ! root     1894:        anti_adjust_stack (GEN_INT (extra));
1.1       root     1895: 
                   1896: #ifdef PUSH_ROUNDING
                   1897:       if (args_addr == 0)
                   1898:        addr = gen_push_operand ();
                   1899:       else
                   1900: #endif
                   1901:        if (GET_CODE (args_so_far) == CONST_INT)
                   1902:          addr
                   1903:            = memory_address (mode,
                   1904:                              plus_constant (args_addr, INTVAL (args_so_far)));
                   1905:       else
                   1906:        addr = memory_address (mode, gen_rtx (PLUS, Pmode, args_addr,
                   1907:                                              args_so_far));
                   1908: 
                   1909:       emit_move_insn (gen_rtx (MEM, mode, addr), x);
                   1910:     }
                   1911: 
                   1912:  ret:
                   1913:   /* If part should go in registers, copy that part
                   1914:      into the appropriate registers.  Do this now, at the end,
                   1915:      since mem-to-mem copies above may do function calls.  */
                   1916:   if (partial > 0)
                   1917:     move_block_to_reg (REGNO (reg), x, partial, mode);
                   1918: 
                   1919:   if (extra && args_addr == 0 && where_pad == stack_direction)
1.1.1.4 ! root     1920:     anti_adjust_stack (GEN_INT (extra));
1.1       root     1921: }
                   1922: 
                   1923: /* Output a library call to function FUN (a SYMBOL_REF rtx)
                   1924:    (emitting the queue unless NO_QUEUE is nonzero),
                   1925:    for a value of mode OUTMODE,
                   1926:    with NARGS different arguments, passed as alternating rtx values
                   1927:    and machine_modes to convert them to.
                   1928:    The rtx values should have been passed through protect_from_queue already.
                   1929: 
                   1930:    NO_QUEUE will be true if and only if the library call is a `const' call
                   1931:    which will be enclosed in REG_LIBCALL/REG_RETVAL notes; it is equivalent
1.1.1.4 ! root     1932:    to the variable is_const in expand_call.
        !          1933: 
        !          1934:    NO_QUEUE must be true for const calls, because if it isn't, then
        !          1935:    any pending increment will be emitted between REG_LIBCALL/REG_RETVAL notes,
        !          1936:    and will be lost if the libcall sequence is optimized away.
        !          1937: 
        !          1938:    NO_QUEUE must be false for non-const calls, because if it isn't, the
        !          1939:    call insn will have its CONST_CALL_P bit set, and it will be incorrectly
        !          1940:    optimized.  For instance, the instruction scheduler may incorrectly
        !          1941:    move memory references across the non-const call.  */
1.1       root     1942: 
                   1943: void
                   1944: emit_library_call (va_alist)
                   1945:      va_dcl
                   1946: {
                   1947:   va_list p;
                   1948:   struct args_size args_size;
                   1949:   register int argnum;
                   1950:   enum machine_mode outmode;
                   1951:   int nargs;
                   1952:   rtx fun;
                   1953:   rtx orgfun;
                   1954:   int inc;
                   1955:   int count;
                   1956:   rtx argblock = 0;
                   1957:   CUMULATIVE_ARGS args_so_far;
                   1958:   struct arg { rtx value; enum machine_mode mode; rtx reg; int partial;
                   1959:               struct args_size offset; struct args_size size; };
                   1960:   struct arg *argvec;
                   1961:   int old_inhibit_defer_pop = inhibit_defer_pop;
                   1962:   int no_queue = 0;
                   1963:   rtx use_insns;
                   1964: 
                   1965:   va_start (p);
                   1966:   orgfun = fun = va_arg (p, rtx);
                   1967:   no_queue = va_arg (p, int);
                   1968:   outmode = va_arg (p, enum machine_mode);
                   1969:   nargs = va_arg (p, int);
                   1970: 
                   1971:   /* Copy all the libcall-arguments out of the varargs data
                   1972:      and into a vector ARGVEC.
                   1973: 
                   1974:      Compute how to pass each argument.  We only support a very small subset
                   1975:      of the full argument passing conventions to limit complexity here since
                   1976:      library functions shouldn't have many args.  */
                   1977: 
                   1978:   argvec = (struct arg *) alloca (nargs * sizeof (struct arg));
                   1979: 
                   1980:   INIT_CUMULATIVE_ARGS (args_so_far, (tree)0, fun);
                   1981: 
                   1982:   args_size.constant = 0;
                   1983:   args_size.var = 0;
                   1984: 
                   1985:   for (count = 0; count < nargs; count++)
                   1986:     {
                   1987:       rtx val = va_arg (p, rtx);
                   1988:       enum machine_mode mode = va_arg (p, enum machine_mode);
                   1989: 
                   1990:       /* We cannot convert the arg value to the mode the library wants here;
                   1991:         must do it earlier where we know the signedness of the arg.  */
                   1992:       if (mode == BLKmode
                   1993:          || (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode))
                   1994:        abort ();
                   1995: 
                   1996:       /* On some machines, there's no way to pass a float to a library fcn.
                   1997:         Pass it as a double instead.  */
                   1998: #ifdef LIBGCC_NEEDS_DOUBLE
                   1999:       if (LIBGCC_NEEDS_DOUBLE && mode == SFmode)
1.1.1.4 ! root     2000:        val = convert_to_mode (DFmode, val, 0), mode = DFmode;
1.1       root     2001: #endif
                   2002: 
1.1.1.4 ! root     2003:       /* There's no need to call protect_from_queue, because
        !          2004:         either emit_move_insn or emit_push_insn will do that.  */
        !          2005: 
1.1       root     2006:       /* Make sure it is a reasonable operand for a move or push insn.  */
                   2007:       if (GET_CODE (val) != REG && GET_CODE (val) != MEM
                   2008:          && ! (CONSTANT_P (val) && LEGITIMATE_CONSTANT_P (val)))
1.1.1.4 ! root     2009:        val = force_operand (val, NULL_RTX);
1.1       root     2010: 
                   2011:       argvec[count].value = val;
                   2012:       argvec[count].mode = mode;
                   2013: 
                   2014: #ifdef FUNCTION_ARG_PASS_BY_REFERENCE
1.1.1.4 ! root     2015:       if (FUNCTION_ARG_PASS_BY_REFERENCE (args_so_far, mode, NULL_TREE, 1))
1.1       root     2016:        abort ();
                   2017: #endif
                   2018: 
1.1.1.4 ! root     2019:       argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1);
1.1       root     2020:       if (argvec[count].reg && GET_CODE (argvec[count].reg) == EXPR_LIST)
                   2021:        abort ();
                   2022: #ifdef FUNCTION_ARG_PARTIAL_NREGS
                   2023:       argvec[count].partial
1.1.1.4 ! root     2024:        = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, NULL_TREE, 1);
1.1       root     2025: #else
                   2026:       argvec[count].partial = 0;
                   2027: #endif
                   2028: 
1.1.1.4 ! root     2029:       locate_and_pad_parm (mode, NULL_TREE,
1.1       root     2030:                           argvec[count].reg && argvec[count].partial == 0,
1.1.1.4 ! root     2031:                           NULL_TREE, &args_size, &argvec[count].offset,
1.1       root     2032:                           &argvec[count].size);
                   2033: 
                   2034:       if (argvec[count].size.var)
                   2035:        abort ();
                   2036: 
                   2037: #ifndef REG_PARM_STACK_SPACE
                   2038:       if (argvec[count].partial)
                   2039:        argvec[count].size.constant -= argvec[count].partial * UNITS_PER_WORD;
                   2040: #endif
                   2041: 
                   2042:       if (argvec[count].reg == 0 || argvec[count].partial != 0
                   2043: #ifdef REG_PARM_STACK_SPACE
                   2044:          || 1
                   2045: #endif
                   2046:          )
                   2047:        args_size.constant += argvec[count].size.constant;
                   2048: 
                   2049: #ifdef ACCUMULATE_OUTGOING_ARGS
                   2050:       /* If this arg is actually passed on the stack, it might be
                   2051:         clobbering something we already put there (this library call might
                   2052:         be inside the evaluation of an argument to a function whose call
                   2053:         requires the stack).  This will only occur when the library call
                   2054:         has sufficient args to run out of argument registers.  Abort in
                   2055:         this case; if this ever occurs, code must be added to save and
                   2056:         restore the arg slot.  */
                   2057: 
                   2058:       if (argvec[count].reg == 0 || argvec[count].partial != 0)
                   2059:        abort ();
                   2060: #endif
                   2061: 
                   2062:       FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree)0, 1);
                   2063:     }
                   2064:   va_end (p);
                   2065: 
                   2066:   /* If this machine requires an external definition for library
                   2067:      functions, write one out.  */
                   2068:   assemble_external_libcall (fun);
                   2069: 
                   2070: #ifdef STACK_BOUNDARY
                   2071:   args_size.constant = (((args_size.constant + (STACK_BYTES - 1))
                   2072:                         / STACK_BYTES) * STACK_BYTES);
                   2073: #endif
                   2074: 
                   2075: #ifdef REG_PARM_STACK_SPACE
                   2076:   args_size.constant = MAX (args_size.constant,
                   2077:                            REG_PARM_STACK_SPACE ((tree) 0));
                   2078: #endif
                   2079: 
                   2080: #ifdef ACCUMULATE_OUTGOING_ARGS
                   2081:   if (args_size.constant > current_function_outgoing_args_size)
                   2082:     current_function_outgoing_args_size = args_size.constant;
                   2083:   args_size.constant = 0;
                   2084: #endif
                   2085: 
                   2086: #ifndef PUSH_ROUNDING
1.1.1.4 ! root     2087:   argblock = push_block (GEN_INT (args_size.constant), 0, 0);
1.1       root     2088: #endif
                   2089: 
                   2090: #ifdef PUSH_ARGS_REVERSED
                   2091:   inc = -1;
                   2092:   argnum = nargs - 1;
                   2093: #else
                   2094:   inc = 1;
                   2095:   argnum = 0;
                   2096: #endif
                   2097: 
                   2098:   /* Push the args that need to be pushed.  */
                   2099: 
                   2100:   for (count = 0; count < nargs; count++, argnum += inc)
                   2101:     {
                   2102:       register enum machine_mode mode = argvec[argnum].mode;
                   2103:       register rtx val = argvec[argnum].value;
                   2104:       rtx reg = argvec[argnum].reg;
                   2105:       int partial = argvec[argnum].partial;
                   2106: 
                   2107:       if (! (reg != 0 && partial == 0))
1.1.1.4 ! root     2108:        emit_push_insn (val, mode, NULL_TREE, NULL_RTX, 0, partial, reg, 0,
        !          2109:                        argblock, GEN_INT (argvec[count].offset.constant));
1.1       root     2110:       NO_DEFER_POP;
                   2111:     }
                   2112: 
                   2113: #ifdef PUSH_ARGS_REVERSED
                   2114:   argnum = nargs - 1;
                   2115: #else
                   2116:   argnum = 0;
                   2117: #endif
                   2118: 
                   2119:   /* Now load any reg parms into their regs.  */
                   2120: 
                   2121:   for (count = 0; count < nargs; count++, argnum += inc)
                   2122:     {
                   2123:       register enum machine_mode mode = argvec[argnum].mode;
                   2124:       register rtx val = argvec[argnum].value;
                   2125:       rtx reg = argvec[argnum].reg;
                   2126:       int partial = argvec[argnum].partial;
                   2127: 
                   2128:       if (reg != 0 && partial == 0)
                   2129:        emit_move_insn (reg, val);
                   2130:       NO_DEFER_POP;
                   2131:     }
                   2132: 
                   2133:   /* For version 1.37, try deleting this entirely.  */
                   2134:   if (! no_queue)
                   2135:     emit_queue ();
                   2136: 
                   2137:   /* Any regs containing parms remain in use through the call.  */
                   2138:   start_sequence ();
                   2139:   for (count = 0; count < nargs; count++)
                   2140:     if (argvec[count].reg != 0)
                   2141:       emit_insn (gen_rtx (USE, VOIDmode, argvec[count].reg));
                   2142: 
                   2143:   use_insns = get_insns ();
                   2144:   end_sequence ();
                   2145: 
1.1.1.4 ! root     2146:   fun = prepare_call_address (fun, NULL_TREE, &use_insns);
1.1       root     2147: 
                   2148:   /* Don't allow popping to be deferred, since then
                   2149:      cse'ing of library calls could delete a call and leave the pop.  */
                   2150:   NO_DEFER_POP;
                   2151: 
                   2152:   /* We pass the old value of inhibit_defer_pop + 1 to emit_call_1, which
                   2153:      will set inhibit_defer_pop to that value.  */
                   2154: 
                   2155:   emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), args_size.constant, 0,
                   2156:               FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
1.1.1.4 ! root     2157:               outmode != VOIDmode ? hard_libcall_value (outmode) : NULL_RTX,
1.1       root     2158:               old_inhibit_defer_pop + 1, use_insns, no_queue);
                   2159: 
                   2160:   /* Now restore inhibit_defer_pop to its actual original value.  */
                   2161:   OK_DEFER_POP;
                   2162: }
                   2163: 
                   2164: /* Expand an assignment that stores the value of FROM into TO.
                   2165:    If WANT_VALUE is nonzero, return an rtx for the value of TO.
                   2166:    (This may contain a QUEUED rtx.)
                   2167:    Otherwise, the returned value is not meaningful.
                   2168: 
                   2169:    SUGGEST_REG is no longer actually used.
                   2170:    It used to mean, copy the value through a register
                   2171:    and return that register, if that is possible.
                   2172:    But now we do this if WANT_VALUE.
                   2173: 
                   2174:    If the value stored is a constant, we return the constant.  */
                   2175: 
                   2176: rtx
                   2177: expand_assignment (to, from, want_value, suggest_reg)
                   2178:      tree to, from;
                   2179:      int want_value;
                   2180:      int suggest_reg;
                   2181: {
                   2182:   register rtx to_rtx = 0;
                   2183:   rtx result;
                   2184: 
                   2185:   /* Don't crash if the lhs of the assignment was erroneous.  */
                   2186: 
                   2187:   if (TREE_CODE (to) == ERROR_MARK)
1.1.1.4 ! root     2188:     return expand_expr (from, NULL_RTX, VOIDmode, 0);
1.1       root     2189: 
                   2190:   /* Assignment of a structure component needs special treatment
                   2191:      if the structure component's rtx is not simply a MEM.
                   2192:      Assignment of an array element at a constant index
                   2193:      has the same problem.  */
                   2194: 
                   2195:   if (TREE_CODE (to) == COMPONENT_REF
                   2196:       || TREE_CODE (to) == BIT_FIELD_REF
                   2197:       || (TREE_CODE (to) == ARRAY_REF
                   2198:          && TREE_CODE (TREE_OPERAND (to, 1)) == INTEGER_CST
                   2199:          && TREE_CODE (TYPE_SIZE (TREE_TYPE (to))) == INTEGER_CST))
                   2200:     {
                   2201:       enum machine_mode mode1;
                   2202:       int bitsize;
                   2203:       int bitpos;
1.1.1.3   root     2204:       tree offset;
1.1       root     2205:       int unsignedp;
                   2206:       int volatilep = 0;
1.1.1.3   root     2207:       tree tem = get_inner_reference (to, &bitsize, &bitpos, &offset,
1.1       root     2208:                                      &mode1, &unsignedp, &volatilep);
                   2209: 
                   2210:       /* If we are going to use store_bit_field and extract_bit_field,
                   2211:         make sure to_rtx will be safe for multiple use.  */
                   2212: 
                   2213:       if (mode1 == VOIDmode && want_value)
                   2214:        tem = stabilize_reference (tem);
                   2215: 
1.1.1.4 ! root     2216:       to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, 0);
1.1.1.3   root     2217:       if (offset != 0)
                   2218:        {
1.1.1.4 ! root     2219:          rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
1.1.1.3   root     2220: 
                   2221:          if (GET_CODE (to_rtx) != MEM)
                   2222:            abort ();
                   2223:          to_rtx = change_address (to_rtx, VOIDmode,
                   2224:                                   gen_rtx (PLUS, Pmode, XEXP (to_rtx, 0),
                   2225:                                            force_reg (Pmode, offset_rtx)));
                   2226:        }
1.1       root     2227:       if (volatilep)
                   2228:        {
                   2229:          if (GET_CODE (to_rtx) == MEM)
                   2230:            MEM_VOLATILE_P (to_rtx) = 1;
                   2231: #if 0  /* This was turned off because, when a field is volatile
                   2232:          in an object which is not volatile, the object may be in a register,
                   2233:          and then we would abort over here.  */
                   2234:          else
                   2235:            abort ();
                   2236: #endif
                   2237:        }
                   2238: 
                   2239:       result = store_field (to_rtx, bitsize, bitpos, mode1, from,
                   2240:                            (want_value
                   2241:                             /* Spurious cast makes HPUX compiler happy.  */
                   2242:                             ? (enum machine_mode) TYPE_MODE (TREE_TYPE (to))
                   2243:                             : VOIDmode),
                   2244:                            unsignedp,
                   2245:                            /* Required alignment of containing datum.  */
                   2246:                            TYPE_ALIGN (TREE_TYPE (tem)) / BITS_PER_UNIT,
                   2247:                            int_size_in_bytes (TREE_TYPE (tem)));
                   2248:       preserve_temp_slots (result);
                   2249:       free_temp_slots ();
                   2250: 
                   2251:       return result;
                   2252:     }
                   2253: 
                   2254:   /* Ordinary treatment.  Expand TO to get a REG or MEM rtx.
                   2255:      Don't re-expand if it was expanded already (in COMPONENT_REF case).  */
                   2256: 
                   2257:   if (to_rtx == 0)
1.1.1.4 ! root     2258:     to_rtx = expand_expr (to, NULL_RTX, VOIDmode, 0);
1.1       root     2259: 
                   2260:   /* In case we are returning the contents of an object which overlaps
                   2261:      the place the value is being stored, use a safe function when copying
                   2262:      a value through a pointer into a structure value return block.  */
                   2263:   if (TREE_CODE (to) == RESULT_DECL && TREE_CODE (from) == INDIRECT_REF
                   2264:       && current_function_returns_struct
                   2265:       && !current_function_returns_pcc_struct)
                   2266:     {
1.1.1.4 ! root     2267:       rtx from_rtx = expand_expr (from, NULL_RTX, VOIDmode, 0);
1.1       root     2268:       rtx size = expr_size (from);
                   2269: 
                   2270: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.4 ! root     2271:       emit_library_call (memcpy_libfunc, 0,
1.1       root     2272:                         VOIDmode, 3, XEXP (to_rtx, 0), Pmode,
                   2273:                         XEXP (from_rtx, 0), Pmode,
                   2274:                         size, Pmode);
                   2275: #else
1.1.1.4 ! root     2276:       emit_library_call (bcopy_libfunc, 0,
1.1       root     2277:                         VOIDmode, 3, XEXP (from_rtx, 0), Pmode,
                   2278:                         XEXP (to_rtx, 0), Pmode,
                   2279:                         size, Pmode);
                   2280: #endif
                   2281: 
                   2282:       preserve_temp_slots (to_rtx);
                   2283:       free_temp_slots ();
                   2284:       return to_rtx;
                   2285:     }
                   2286: 
                   2287:   /* Compute FROM and store the value in the rtx we got.  */
                   2288: 
                   2289:   result = store_expr (from, to_rtx, want_value);
                   2290:   preserve_temp_slots (result);
                   2291:   free_temp_slots ();
                   2292:   return result;
                   2293: }
                   2294: 
                   2295: /* Generate code for computing expression EXP,
                   2296:    and storing the value into TARGET.
                   2297:    Returns TARGET or an equivalent value.
                   2298:    TARGET may contain a QUEUED rtx.
                   2299: 
                   2300:    If SUGGEST_REG is nonzero, copy the value through a register
                   2301:    and return that register, if that is possible.
                   2302: 
                   2303:    If the value stored is a constant, we return the constant.  */
                   2304: 
                   2305: rtx
                   2306: store_expr (exp, target, suggest_reg)
                   2307:      register tree exp;
                   2308:      register rtx target;
                   2309:      int suggest_reg;
                   2310: {
                   2311:   register rtx temp;
                   2312:   int dont_return_target = 0;
                   2313: 
                   2314:   if (TREE_CODE (exp) == COMPOUND_EXPR)
                   2315:     {
                   2316:       /* Perform first part of compound expression, then assign from second
                   2317:         part.  */
                   2318:       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
                   2319:       emit_queue ();
                   2320:       return store_expr (TREE_OPERAND (exp, 1), target, suggest_reg);
                   2321:     }
                   2322:   else if (TREE_CODE (exp) == COND_EXPR && GET_MODE (target) == BLKmode)
                   2323:     {
                   2324:       /* For conditional expression, get safe form of the target.  Then
                   2325:         test the condition, doing the appropriate assignment on either
                   2326:         side.  This avoids the creation of unnecessary temporaries.
                   2327:         For non-BLKmode, it is more efficient not to do this.  */
                   2328: 
                   2329:       rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
                   2330: 
                   2331:       emit_queue ();
                   2332:       target = protect_from_queue (target, 1);
                   2333: 
                   2334:       NO_DEFER_POP;
                   2335:       jumpifnot (TREE_OPERAND (exp, 0), lab1);
                   2336:       store_expr (TREE_OPERAND (exp, 1), target, suggest_reg);
                   2337:       emit_queue ();
                   2338:       emit_jump_insn (gen_jump (lab2));
                   2339:       emit_barrier ();
                   2340:       emit_label (lab1);
                   2341:       store_expr (TREE_OPERAND (exp, 2), target, suggest_reg);
                   2342:       emit_queue ();
                   2343:       emit_label (lab2);
                   2344:       OK_DEFER_POP;
                   2345:       return target;
                   2346:     }
                   2347:   else if (suggest_reg && GET_CODE (target) == MEM
                   2348:           && GET_MODE (target) != BLKmode)
                   2349:     /* If target is in memory and caller wants value in a register instead,
                   2350:        arrange that.  Pass TARGET as target for expand_expr so that,
                   2351:        if EXP is another assignment, SUGGEST_REG will be nonzero for it.
                   2352:        We know expand_expr will not use the target in that case.  */
                   2353:     {
1.1.1.4 ! root     2354:       temp = expand_expr (exp, cse_not_expected ? NULL_RTX : target,
1.1       root     2355:                          GET_MODE (target), 0);
                   2356:       if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
                   2357:        temp = copy_to_reg (temp);
                   2358:       dont_return_target = 1;
                   2359:     }
                   2360:   else if (queued_subexp_p (target))
                   2361:     /* If target contains a postincrement, it is not safe
                   2362:        to use as the returned value.  It would access the wrong
                   2363:        place by the time the queued increment gets output.
                   2364:        So copy the value through a temporary and use that temp
                   2365:        as the result.  */
                   2366:     {
                   2367:       if (GET_MODE (target) != BLKmode && GET_MODE (target) != VOIDmode)
                   2368:        {
                   2369:          /* Expand EXP into a new pseudo.  */
                   2370:          temp = gen_reg_rtx (GET_MODE (target));
                   2371:          temp = expand_expr (exp, temp, GET_MODE (target), 0);
                   2372:        }
                   2373:       else
1.1.1.4 ! root     2374:        temp = expand_expr (exp, NULL_RTX, GET_MODE (target), 0);
1.1       root     2375:       dont_return_target = 1;
                   2376:     }
1.1.1.4 ! root     2377:   else if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target))
        !          2378:     /* If this is an scalar in a register that is stored in a wider mode
        !          2379:        than the declared mode, compute the result into its declared mode
        !          2380:        and then convert to the wider mode.  Our value is the computed
        !          2381:        expression.  */
        !          2382:     {
        !          2383:       temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
        !          2384:       convert_move (SUBREG_REG (target), temp,
        !          2385:                    SUBREG_PROMOTED_UNSIGNED_P (target));
        !          2386:       return temp;
        !          2387:     }
1.1       root     2388:   else
                   2389:     {
                   2390:       temp = expand_expr (exp, target, GET_MODE (target), 0);
                   2391:       /* DO return TARGET if it's a specified hardware register.
                   2392:         expand_return relies on this.  */
                   2393:       if (!(target && GET_CODE (target) == REG
                   2394:            && REGNO (target) < FIRST_PSEUDO_REGISTER)
                   2395:          && CONSTANT_P (temp))
                   2396:        dont_return_target = 1;
                   2397:     }
                   2398: 
                   2399:   /* If value was not generated in the target, store it there.
                   2400:      Convert the value to TARGET's type first if nec.  */
                   2401: 
                   2402:   if (temp != target && TREE_CODE (exp) != ERROR_MARK)
                   2403:     {
                   2404:       target = protect_from_queue (target, 1);
                   2405:       if (GET_MODE (temp) != GET_MODE (target)
                   2406:          && GET_MODE (temp) != VOIDmode)
                   2407:        {
                   2408:          int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
                   2409:          if (dont_return_target)
                   2410:            {
                   2411:              /* In this case, we will return TEMP,
                   2412:                 so make sure it has the proper mode.
                   2413:                 But don't forget to store the value into TARGET.  */
                   2414:              temp = convert_to_mode (GET_MODE (target), temp, unsignedp);
                   2415:              emit_move_insn (target, temp);
                   2416:            }
                   2417:          else
                   2418:            convert_move (target, temp, unsignedp);
                   2419:        }
                   2420: 
                   2421:       else if (GET_MODE (temp) == BLKmode && TREE_CODE (exp) == STRING_CST)
                   2422:        {
                   2423:          /* Handle copying a string constant into an array.
                   2424:             The string constant may be shorter than the array.
                   2425:             So copy just the string's actual length, and clear the rest.  */
                   2426:          rtx size;
                   2427: 
1.1.1.2   root     2428:          /* Get the size of the data type of the string,
                   2429:             which is actually the size of the target.  */
                   2430:          size = expr_size (exp);
                   2431:          if (GET_CODE (size) == CONST_INT
                   2432:              && INTVAL (size) < TREE_STRING_LENGTH (exp))
                   2433:            emit_block_move (target, temp, size,
                   2434:                             TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
                   2435:          else
1.1       root     2436:            {
1.1.1.2   root     2437:              /* Compute the size of the data to copy from the string.  */
                   2438:              tree copy_size
                   2439:                = fold (build (MIN_EXPR, sizetype,
                   2440:                               size_binop (CEIL_DIV_EXPR,
                   2441:                                           TYPE_SIZE (TREE_TYPE (exp)),
                   2442:                                           size_int (BITS_PER_UNIT)),
                   2443:                               convert (sizetype,
                   2444:                                        build_int_2 (TREE_STRING_LENGTH (exp), 0))));
1.1.1.4 ! root     2445:              rtx copy_size_rtx = expand_expr (copy_size, NULL_RTX,
        !          2446:                                               VOIDmode, 0);
1.1.1.2   root     2447:              rtx label = 0;
                   2448: 
                   2449:              /* Copy that much.  */
                   2450:              emit_block_move (target, temp, copy_size_rtx,
                   2451:                               TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
                   2452: 
                   2453:              /* Figure out how much is left in TARGET
                   2454:                 that we have to clear.  */
                   2455:              if (GET_CODE (copy_size_rtx) == CONST_INT)
                   2456:                {
                   2457:                  temp = plus_constant (XEXP (target, 0),
                   2458:                                        TREE_STRING_LENGTH (exp));
                   2459:                  size = plus_constant (size,
                   2460:                                        - TREE_STRING_LENGTH (exp));
                   2461:                }
                   2462:              else
                   2463:                {
                   2464:                  enum machine_mode size_mode = Pmode;
                   2465: 
                   2466:                  temp = force_reg (Pmode, XEXP (target, 0));
                   2467:                  temp = expand_binop (size_mode, add_optab, temp,
1.1.1.4 ! root     2468:                                       copy_size_rtx, NULL_RTX, 0,
        !          2469:                                       OPTAB_LIB_WIDEN);
1.1.1.2   root     2470: 
                   2471:                  size = expand_binop (size_mode, sub_optab, size,
1.1.1.4 ! root     2472:                                       copy_size_rtx, NULL_RTX, 0,
        !          2473:                                       OPTAB_LIB_WIDEN);
1.1.1.2   root     2474: 
1.1.1.4 ! root     2475:                  emit_cmp_insn (size, const0_rtx, LT, NULL_RTX,
1.1.1.2   root     2476:                                 GET_MODE (size), 0, 0);
                   2477:                  label = gen_label_rtx ();
                   2478:                  emit_jump_insn (gen_blt (label));
                   2479:                }
                   2480: 
                   2481:              if (size != const0_rtx)
                   2482:                {
1.1       root     2483: #ifdef TARGET_MEM_FUNCTIONS
1.1.1.4 ! root     2484:                  emit_library_call (memset_libfunc, 0, VOIDmode, 3,
1.1.1.2   root     2485:                                     temp, Pmode, const0_rtx, Pmode, size, Pmode);
1.1       root     2486: #else
1.1.1.4 ! root     2487:                  emit_library_call (bzero_libfunc, 0, VOIDmode, 2,
1.1.1.2   root     2488:                                     temp, Pmode, size, Pmode);
1.1       root     2489: #endif
1.1.1.2   root     2490:                }
                   2491:              if (label)
                   2492:                emit_label (label);
1.1       root     2493:            }
                   2494:        }
                   2495:       else if (GET_MODE (temp) == BLKmode)
                   2496:        emit_block_move (target, temp, expr_size (exp),
                   2497:                         TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
                   2498:       else
                   2499:        emit_move_insn (target, temp);
                   2500:     }
                   2501:   if (dont_return_target)
                   2502:     return temp;
                   2503:   return target;
                   2504: }
                   2505: 
                   2506: /* Store the value of constructor EXP into the rtx TARGET.
                   2507:    TARGET is either a REG or a MEM.  */
                   2508: 
                   2509: static void
                   2510: store_constructor (exp, target)
                   2511:      tree exp;
                   2512:      rtx target;
                   2513: {
1.1.1.3   root     2514:   tree type = TREE_TYPE (exp);
                   2515: 
1.1       root     2516:   /* We know our target cannot conflict, since safe_from_p has been called.  */
                   2517: #if 0
                   2518:   /* Don't try copying piece by piece into a hard register
                   2519:      since that is vulnerable to being clobbered by EXP.
                   2520:      Instead, construct in a pseudo register and then copy it all.  */
                   2521:   if (GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER)
                   2522:     {
                   2523:       rtx temp = gen_reg_rtx (GET_MODE (target));
                   2524:       store_constructor (exp, temp);
                   2525:       emit_move_insn (target, temp);
                   2526:       return;
                   2527:     }
                   2528: #endif
                   2529: 
1.1.1.3   root     2530:   if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
1.1       root     2531:     {
                   2532:       register tree elt;
                   2533: 
1.1.1.3   root     2534:       /* Inform later passes that the whole union value is dead.  */
                   2535:       if (TREE_CODE (type) == UNION_TYPE)
1.1       root     2536:        emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
1.1.1.3   root     2537: 
                   2538:       /* If we are building a static constructor into a register,
                   2539:         set the initial value as zero so we can fold the value into
                   2540:         a constant.  */
                   2541:       else if (GET_CODE (target) == REG && TREE_STATIC (exp))
                   2542:        emit_move_insn (target, const0_rtx);
                   2543: 
1.1       root     2544:       /* If the constructor has fewer fields than the structure,
                   2545:         clear the whole structure first.  */
                   2546:       else if (list_length (CONSTRUCTOR_ELTS (exp))
1.1.1.3   root     2547:               != list_length (TYPE_FIELDS (type)))
                   2548:        clear_storage (target, int_size_in_bytes (type));
1.1       root     2549:       else
                   2550:        /* Inform later passes that the old value is dead.  */
                   2551:        emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
                   2552: 
                   2553:       /* Store each element of the constructor into
                   2554:         the corresponding field of TARGET.  */
                   2555: 
                   2556:       for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
                   2557:        {
                   2558:          register tree field = TREE_PURPOSE (elt);
                   2559:          register enum machine_mode mode;
                   2560:          int bitsize;
                   2561:          int bitpos;
                   2562:          int unsignedp;
                   2563: 
1.1.1.4 ! root     2564:          /* Just ignore missing fields.
        !          2565:             We cleared the whole structure, above,
        !          2566:             if any fields are missing.  */
        !          2567:          if (field == 0)
        !          2568:            continue;
        !          2569: 
1.1       root     2570:          bitsize = TREE_INT_CST_LOW (DECL_SIZE (field));
                   2571:          unsignedp = TREE_UNSIGNED (field);
                   2572:          mode = DECL_MODE (field);
                   2573:          if (DECL_BIT_FIELD (field))
                   2574:            mode = VOIDmode;
                   2575: 
                   2576:          if (TREE_CODE (DECL_FIELD_BITPOS (field)) != INTEGER_CST)
                   2577:            /* ??? This case remains to be written.  */
                   2578:            abort ();
                   2579: 
                   2580:          bitpos = TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field));
                   2581: 
                   2582:          store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt),
                   2583:                       /* The alignment of TARGET is
                   2584:                          at least what its type requires.  */
                   2585:                       VOIDmode, 0,
1.1.1.3   root     2586:                       TYPE_ALIGN (type) / BITS_PER_UNIT,
                   2587:                       int_size_in_bytes (type));
1.1       root     2588:        }
                   2589:     }
1.1.1.3   root     2590:   else if (TREE_CODE (type) == ARRAY_TYPE)
1.1       root     2591:     {
                   2592:       register tree elt;
                   2593:       register int i;
1.1.1.3   root     2594:       tree domain = TYPE_DOMAIN (type);
1.1.1.4 ! root     2595:       HOST_WIDE_INT minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain));
        !          2596:       HOST_WIDE_INT maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain));
1.1.1.3   root     2597:       tree elttype = TREE_TYPE (type);
1.1       root     2598: 
                   2599:       /* If the constructor has fewer fields than the structure,
1.1.1.3   root     2600:         clear the whole structure first.  Similarly if this this is
                   2601:         static constructor of a non-BLKmode object.  */
1.1       root     2602: 
1.1.1.3   root     2603:       if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1
                   2604:          || (GET_CODE (target) == REG && TREE_STATIC (exp)))
1.1       root     2605:        clear_storage (target, maxelt - minelt + 1);
                   2606:       else
                   2607:        /* Inform later passes that the old value is dead.  */
                   2608:        emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
                   2609: 
                   2610:       /* Store each element of the constructor into
                   2611:         the corresponding element of TARGET, determined
                   2612:         by counting the elements.  */
                   2613:       for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
                   2614:           elt;
                   2615:           elt = TREE_CHAIN (elt), i++)
                   2616:        {
                   2617:          register enum machine_mode mode;
                   2618:          int bitsize;
                   2619:          int bitpos;
                   2620:          int unsignedp;
                   2621: 
                   2622:          mode = TYPE_MODE (elttype);
                   2623:          bitsize = GET_MODE_BITSIZE (mode);
                   2624:          unsignedp = TREE_UNSIGNED (elttype);
                   2625: 
                   2626:          bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype)));
                   2627: 
                   2628:          store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt),
                   2629:                       /* The alignment of TARGET is
                   2630:                          at least what its type requires.  */
                   2631:                       VOIDmode, 0,
1.1.1.3   root     2632:                       TYPE_ALIGN (type) / BITS_PER_UNIT,
                   2633:                       int_size_in_bytes (type));
1.1       root     2634:        }
                   2635:     }
                   2636: 
                   2637:   else
                   2638:     abort ();
                   2639: }
                   2640: 
                   2641: /* Store the value of EXP (an expression tree)
                   2642:    into a subfield of TARGET which has mode MODE and occupies
                   2643:    BITSIZE bits, starting BITPOS bits from the start of TARGET.
                   2644:    If MODE is VOIDmode, it means that we are storing into a bit-field.
                   2645: 
                   2646:    If VALUE_MODE is VOIDmode, return nothing in particular.
                   2647:    UNSIGNEDP is not used in this case.
                   2648: 
                   2649:    Otherwise, return an rtx for the value stored.  This rtx
                   2650:    has mode VALUE_MODE if that is convenient to do.
                   2651:    In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
                   2652: 
                   2653:    ALIGN is the alignment that TARGET is known to have, measured in bytes.
                   2654:    TOTAL_SIZE is the size in bytes of the structure, or -1 if varying.  */
                   2655: 
                   2656: static rtx
                   2657: store_field (target, bitsize, bitpos, mode, exp, value_mode,
                   2658:             unsignedp, align, total_size)
                   2659:      rtx target;
                   2660:      int bitsize, bitpos;
                   2661:      enum machine_mode mode;
                   2662:      tree exp;
                   2663:      enum machine_mode value_mode;
                   2664:      int unsignedp;
                   2665:      int align;
                   2666:      int total_size;
                   2667: {
1.1.1.4 ! root     2668:   HOST_WIDE_INT width_mask = 0;
1.1       root     2669: 
1.1.1.4 ! root     2670:   if (bitsize < HOST_BITS_PER_WIDE_INT)
        !          2671:     width_mask = ((HOST_WIDE_INT) 1 << bitsize) - 1;
1.1       root     2672: 
                   2673:   /* If we are storing into an unaligned field of an aligned union that is
                   2674:      in a register, we may have the mode of TARGET being an integer mode but
                   2675:      MODE == BLKmode.  In that case, get an aligned object whose size and
                   2676:      alignment are the same as TARGET and store TARGET into it (we can avoid
                   2677:      the store if the field being stored is the entire width of TARGET).  Then
                   2678:      call ourselves recursively to store the field into a BLKmode version of
                   2679:      that object.  Finally, load from the object into TARGET.  This is not
                   2680:      very efficient in general, but should only be slightly more expensive
                   2681:      than the otherwise-required unaligned accesses.  Perhaps this can be
                   2682:      cleaned up later.  */
                   2683: 
                   2684:   if (mode == BLKmode
                   2685:       && (GET_CODE (target) == REG || GET_CODE (target) == SUBREG))
                   2686:     {
                   2687:       rtx object = assign_stack_temp (GET_MODE (target),
                   2688:                                      GET_MODE_SIZE (GET_MODE (target)), 0);
                   2689:       rtx blk_object = copy_rtx (object);
                   2690: 
                   2691:       PUT_MODE (blk_object, BLKmode);
                   2692: 
                   2693:       if (bitsize != GET_MODE_BITSIZE (GET_MODE (target)))
                   2694:        emit_move_insn (object, target);
                   2695: 
                   2696:       store_field (blk_object, bitsize, bitpos, mode, exp, VOIDmode, 0,
                   2697:                   align, total_size);
                   2698: 
                   2699:       emit_move_insn (target, object);
                   2700: 
                   2701:       return target;
                   2702:     }
                   2703: 
                   2704:   /* If the structure is in a register or if the component
                   2705:      is a bit field, we cannot use addressing to access it.
                   2706:      Use bit-field techniques or SUBREG to store in it.  */
                   2707: 
1.1.1.4 ! root     2708:   if (mode == VOIDmode
        !          2709:       || (mode != BLKmode && ! direct_store[(int) mode])
        !          2710:       || GET_CODE (target) == REG
1.1       root     2711:       || GET_CODE (target) == SUBREG)
                   2712:     {
1.1.1.4 ! root     2713:       rtx temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
1.1       root     2714:       /* Store the value in the bitfield.  */
                   2715:       store_bit_field (target, bitsize, bitpos, mode, temp, align, total_size);
                   2716:       if (value_mode != VOIDmode)
                   2717:        {
                   2718:          /* The caller wants an rtx for the value.  */
                   2719:          /* If possible, avoid refetching from the bitfield itself.  */
                   2720:          if (width_mask != 0
                   2721:              && ! (GET_CODE (target) == MEM && MEM_VOLATILE_P (target)))
1.1.1.4 ! root     2722:            {
        !          2723:              tree count;
        !          2724:              enum machine_mode tmode;
        !          2725: 
        !          2726:              if (unsignedp)
        !          2727:                return expand_and (temp, GEN_INT (width_mask), NULL_RTX);
        !          2728:              tmode = GET_MODE (temp);
        !          2729:              if (tmode == VOIDmode)
        !          2730:                tmode = value_mode;
        !          2731:              count = build_int_2 (GET_MODE_BITSIZE (tmode) - bitsize, 0);
        !          2732:              temp = expand_shift (LSHIFT_EXPR, tmode, temp, count, 0, 0);
        !          2733:              return expand_shift (RSHIFT_EXPR, tmode, temp, count, 0, 0);
        !          2734:            }
1.1       root     2735:          return extract_bit_field (target, bitsize, bitpos, unsignedp,
1.1.1.4 ! root     2736:                                    NULL_RTX, value_mode, 0, align,
        !          2737:                                    total_size);
1.1       root     2738:        }
                   2739:       return const0_rtx;
                   2740:     }
                   2741:   else
                   2742:     {
                   2743:       rtx addr = XEXP (target, 0);
                   2744:       rtx to_rtx;
                   2745: 
                   2746:       /* If a value is wanted, it must be the lhs;
                   2747:         so make the address stable for multiple use.  */
                   2748: 
                   2749:       if (value_mode != VOIDmode && GET_CODE (addr) != REG
                   2750:          && ! CONSTANT_ADDRESS_P (addr)
                   2751:          /* A frame-pointer reference is already stable.  */
                   2752:          && ! (GET_CODE (addr) == PLUS
                   2753:                && GET_CODE (XEXP (addr, 1)) == CONST_INT
                   2754:                && (XEXP (addr, 0) == virtual_incoming_args_rtx
                   2755:                    || XEXP (addr, 0) == virtual_stack_vars_rtx)))
                   2756:        addr = copy_to_reg (addr);
                   2757: 
                   2758:       /* Now build a reference to just the desired component.  */
                   2759: 
                   2760:       to_rtx = change_address (target, mode,
                   2761:                               plus_constant (addr, (bitpos / BITS_PER_UNIT)));
                   2762:       MEM_IN_STRUCT_P (to_rtx) = 1;
                   2763: 
                   2764:       return store_expr (exp, to_rtx, value_mode != VOIDmode);
                   2765:     }
                   2766: }
                   2767: 
                   2768: /* Given an expression EXP that may be a COMPONENT_REF, a BIT_FIELD_REF,
                   2769:    or an ARRAY_REF, look for nested COMPONENT_REFs, BIT_FIELD_REFs, or
                   2770:    ARRAY_REFs at constant positions and find the ultimate containing object,
                   2771:    which we return.
                   2772: 
                   2773:    We set *PBITSIZE to the size in bits that we want, *PBITPOS to the
                   2774:    bit position, and *PUNSIGNEDP to the signedness of the field.
1.1.1.3   root     2775:    If the position of the field is variable, we store a tree
                   2776:    giving the variable offset (in units) in *POFFSET.
                   2777:    This offset is in addition to the bit position.
                   2778:    If the position is not variable, we store 0 in *POFFSET.
1.1       root     2779: 
                   2780:    If any of the extraction expressions is volatile,
                   2781:    we store 1 in *PVOLATILEP.  Otherwise we don't change that.
                   2782: 
                   2783:    If the field is a bit-field, *PMODE is set to VOIDmode.  Otherwise, it
                   2784:    is a mode that can be used to access the field.  In that case, *PBITSIZE
1.1.1.3   root     2785:    is redundant.
                   2786: 
                   2787:    If the field describes a variable-sized object, *PMODE is set to
                   2788:    VOIDmode and *PBITSIZE is set to -1.  An access cannot be made in
                   2789:    this case, but the address of the object can be found.  */
1.1       root     2790: 
                   2791: tree
1.1.1.3   root     2792: get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode, punsignedp, pvolatilep)
1.1       root     2793:      tree exp;
                   2794:      int *pbitsize;
                   2795:      int *pbitpos;
1.1.1.3   root     2796:      tree *poffset;
1.1       root     2797:      enum machine_mode *pmode;
                   2798:      int *punsignedp;
                   2799:      int *pvolatilep;
                   2800: {
                   2801:   tree size_tree = 0;
                   2802:   enum machine_mode mode = VOIDmode;
1.1.1.3   root     2803:   tree offset = 0;
1.1       root     2804: 
                   2805:   if (TREE_CODE (exp) == COMPONENT_REF)
                   2806:     {
                   2807:       size_tree = DECL_SIZE (TREE_OPERAND (exp, 1));
                   2808:       if (! DECL_BIT_FIELD (TREE_OPERAND (exp, 1)))
                   2809:        mode = DECL_MODE (TREE_OPERAND (exp, 1));
                   2810:       *punsignedp = TREE_UNSIGNED (TREE_OPERAND (exp, 1));
                   2811:     }
                   2812:   else if (TREE_CODE (exp) == BIT_FIELD_REF)
                   2813:     {
                   2814:       size_tree = TREE_OPERAND (exp, 1);
                   2815:       *punsignedp = TREE_UNSIGNED (exp);
                   2816:     }
                   2817:   else
                   2818:     {
                   2819:       mode = TYPE_MODE (TREE_TYPE (exp));
                   2820:       *pbitsize = GET_MODE_BITSIZE (mode);
                   2821:       *punsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
                   2822:     }
                   2823:       
                   2824:   if (size_tree)
                   2825:     {
                   2826:       if (TREE_CODE (size_tree) != INTEGER_CST)
1.1.1.3   root     2827:        mode = BLKmode, *pbitsize = -1;
                   2828:       else
                   2829:        *pbitsize = TREE_INT_CST_LOW (size_tree);
1.1       root     2830:     }
                   2831: 
                   2832:   /* Compute cumulative bit-offset for nested component-refs and array-refs,
                   2833:      and find the ultimate containing object.  */
                   2834: 
                   2835:   *pbitpos = 0;
                   2836: 
                   2837:   while (1)
                   2838:     {
1.1.1.4 ! root     2839:       if (TREE_CODE (exp) == INDIRECT_REF && flag_volatile)
        !          2840:        *pvolatilep = 1;
        !          2841: 
1.1.1.3   root     2842:       if (TREE_CODE (exp) == COMPONENT_REF || TREE_CODE (exp) == BIT_FIELD_REF)
1.1       root     2843:        {
1.1.1.3   root     2844:          tree pos = (TREE_CODE (exp) == COMPONENT_REF
                   2845:                      ? DECL_FIELD_BITPOS (TREE_OPERAND (exp, 1))
                   2846:                      : TREE_OPERAND (exp, 2));
1.1       root     2847: 
1.1.1.3   root     2848:          if (TREE_CODE (pos) == PLUS_EXPR)
                   2849:            {
                   2850:              tree constant, var;
                   2851:              if (TREE_CODE (TREE_OPERAND (pos, 0)) == INTEGER_CST)
                   2852:                {
                   2853:                  constant = TREE_OPERAND (pos, 0);
                   2854:                  var = TREE_OPERAND (pos, 1);
                   2855:                }
                   2856:              else if (TREE_CODE (TREE_OPERAND (pos, 1)) == INTEGER_CST)
                   2857:                {
                   2858:                  constant = TREE_OPERAND (pos, 1);
                   2859:                  var = TREE_OPERAND (pos, 0);
                   2860:                }
                   2861:              else
                   2862:                abort ();
                   2863:              *pbitpos += TREE_INT_CST_LOW (constant);
                   2864:              if (offset)
                   2865:                offset = size_binop (PLUS_EXPR, offset,
                   2866:                                     size_binop (FLOOR_DIV_EXPR, var,
                   2867:                                                 size_int (BITS_PER_UNIT)));
                   2868:              else
                   2869:                offset = size_binop (FLOOR_DIV_EXPR, var,
                   2870:                                     size_int (BITS_PER_UNIT));
                   2871:            }
                   2872:          else if (TREE_CODE (pos) == INTEGER_CST)
                   2873:            *pbitpos += TREE_INT_CST_LOW (pos);
                   2874:          else
                   2875:            {
                   2876:              /* Assume here that the offset is a multiple of a unit.
                   2877:                 If not, there should be an explicitly added constant.  */
                   2878:              if (offset)
                   2879:                offset = size_binop (PLUS_EXPR, offset,
                   2880:                                     size_binop (FLOOR_DIV_EXPR, pos,
                   2881:                                                 size_int (BITS_PER_UNIT)));
                   2882:              else
                   2883:                offset = size_binop (FLOOR_DIV_EXPR, pos,
                   2884:                                     size_int (BITS_PER_UNIT));
                   2885:            }
1.1       root     2886:        }
                   2887: 
                   2888:       else if (TREE_CODE (exp) == ARRAY_REF
                   2889:               && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
                   2890:               && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST)
                   2891:        {
                   2892:          *pbitpos += (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))
                   2893:                       * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))));
                   2894:        }
                   2895:       else if (TREE_CODE (exp) != NON_LVALUE_EXPR
                   2896:               && ! ((TREE_CODE (exp) == NOP_EXPR
                   2897:                      || TREE_CODE (exp) == CONVERT_EXPR)
                   2898:                     && (TYPE_MODE (TREE_TYPE (exp))
                   2899:                         == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))))
                   2900:        break;
1.1.1.3   root     2901: 
                   2902:       /* If any reference in the chain is volatile, the effect is volatile.  */
                   2903:       if (TREE_THIS_VOLATILE (exp))
                   2904:        *pvolatilep = 1;
1.1       root     2905:       exp = TREE_OPERAND (exp, 0);
                   2906:     }
                   2907: 
                   2908:   /* If this was a bit-field, see if there is a mode that allows direct
                   2909:      access in case EXP is in memory.  */
                   2910:   if (mode == VOIDmode && *pbitpos % *pbitsize == 0)
                   2911:     {
                   2912:       mode = mode_for_size (*pbitsize, MODE_INT, 0);
                   2913:       if (mode == BLKmode)
                   2914:        mode = VOIDmode;
                   2915:     }
                   2916: 
                   2917:   *pmode = mode;
1.1.1.3   root     2918:   *poffset = offset;
                   2919: #if 0
                   2920:   /* We aren't finished fixing the callers to really handle nonzero offset.  */
                   2921:   if (offset != 0)
                   2922:     abort ();
                   2923: #endif
1.1       root     2924: 
                   2925:   return exp;
                   2926: }
                   2927: 
                   2928: /* Given an rtx VALUE that may contain additions and multiplications,
                   2929:    return an equivalent value that just refers to a register or memory.
                   2930:    This is done by generating instructions to perform the arithmetic
1.1.1.4 ! root     2931:    and returning a pseudo-register containing the value.
        !          2932: 
        !          2933:    The returned value may be a REG, SUBREG, MEM or constant.  */
1.1       root     2934: 
                   2935: rtx
                   2936: force_operand (value, target)
                   2937:      rtx value, target;
                   2938: {
                   2939:   register optab binoptab = 0;
                   2940:   /* Use a temporary to force order of execution of calls to
                   2941:      `force_operand'.  */
                   2942:   rtx tmp;
                   2943:   register rtx op2;
                   2944:   /* Use subtarget as the target for operand 0 of a binary operation.  */
                   2945:   register rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
                   2946: 
                   2947:   if (GET_CODE (value) == PLUS)
                   2948:     binoptab = add_optab;
                   2949:   else if (GET_CODE (value) == MINUS)
                   2950:     binoptab = sub_optab;
                   2951:   else if (GET_CODE (value) == MULT)
                   2952:     {
                   2953:       op2 = XEXP (value, 1);
                   2954:       if (!CONSTANT_P (op2)
                   2955:          && !(GET_CODE (op2) == REG && op2 != subtarget))
                   2956:        subtarget = 0;
                   2957:       tmp = force_operand (XEXP (value, 0), subtarget);
                   2958:       return expand_mult (GET_MODE (value), tmp,
1.1.1.4 ! root     2959:                          force_operand (op2, NULL_RTX),
1.1       root     2960:                          target, 0);
                   2961:     }
                   2962: 
                   2963:   if (binoptab)
                   2964:     {
                   2965:       op2 = XEXP (value, 1);
                   2966:       if (!CONSTANT_P (op2)
                   2967:          && !(GET_CODE (op2) == REG && op2 != subtarget))
                   2968:        subtarget = 0;
                   2969:       if (binoptab == sub_optab && GET_CODE (op2) == CONST_INT)
                   2970:        {
                   2971:          binoptab = add_optab;
                   2972:          op2 = negate_rtx (GET_MODE (value), op2);
                   2973:        }
                   2974: 
                   2975:       /* Check for an addition with OP2 a constant integer and our first
                   2976:         operand a PLUS of a virtual register and something else.  In that
                   2977:         case, we want to emit the sum of the virtual register and the
                   2978:         constant first and then add the other value.  This allows virtual
                   2979:         register instantiation to simply modify the constant rather than
                   2980:         creating another one around this addition.  */
                   2981:       if (binoptab == add_optab && GET_CODE (op2) == CONST_INT
                   2982:          && GET_CODE (XEXP (value, 0)) == PLUS
                   2983:          && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
                   2984:          && REGNO (XEXP (XEXP (value, 0), 0)) >= FIRST_VIRTUAL_REGISTER
                   2985:          && REGNO (XEXP (XEXP (value, 0), 0)) <= LAST_VIRTUAL_REGISTER)
                   2986:        {
                   2987:          rtx temp = expand_binop (GET_MODE (value), binoptab,
                   2988:                                   XEXP (XEXP (value, 0), 0), op2,
                   2989:                                   subtarget, 0, OPTAB_LIB_WIDEN);
                   2990:          return expand_binop (GET_MODE (value), binoptab, temp,
                   2991:                               force_operand (XEXP (XEXP (value, 0), 1), 0),
                   2992:                               target, 0, OPTAB_LIB_WIDEN);
                   2993:        }
                   2994:                                   
                   2995:       tmp = force_operand (XEXP (value, 0), subtarget);
                   2996:       return expand_binop (GET_MODE (value), binoptab, tmp,
1.1.1.4 ! root     2997:                           force_operand (op2, NULL_RTX),
1.1       root     2998:                           target, 0, OPTAB_LIB_WIDEN);
                   2999:       /* We give UNSIGNEP = 0 to expand_binop
                   3000:         because the only operations we are expanding here are signed ones.  */
                   3001:     }
                   3002:   return value;
                   3003: }
                   3004: 
                   3005: /* Subroutine of expand_expr:
                   3006:    save the non-copied parts (LIST) of an expr (LHS), and return a list
                   3007:    which can restore these values to their previous values,
                   3008:    should something modify their storage.  */
                   3009: 
                   3010: static tree
                   3011: save_noncopied_parts (lhs, list)
                   3012:      tree lhs;
                   3013:      tree list;
                   3014: {
                   3015:   tree tail;
                   3016:   tree parts = 0;
                   3017: 
                   3018:   for (tail = list; tail; tail = TREE_CHAIN (tail))
                   3019:     if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
                   3020:       parts = chainon (parts, save_noncopied_parts (lhs, TREE_VALUE (tail)));
                   3021:     else
                   3022:       {
                   3023:        tree part = TREE_VALUE (tail);
                   3024:        tree part_type = TREE_TYPE (part);
1.1.1.4 ! root     3025:        tree to_be_saved = build (COMPONENT_REF, part_type, lhs, part);
1.1       root     3026:        rtx target = assign_stack_temp (TYPE_MODE (part_type),
                   3027:                                        int_size_in_bytes (part_type), 0);
                   3028:        if (! memory_address_p (TYPE_MODE (part_type), XEXP (target, 0)))
1.1.1.4 ! root     3029:          target = change_address (target, TYPE_MODE (part_type), NULL_RTX);
1.1       root     3030:        parts = tree_cons (to_be_saved,
1.1.1.4 ! root     3031:                           build (RTL_EXPR, part_type, NULL_TREE,
        !          3032:                                  (tree) target),
1.1       root     3033:                           parts);
                   3034:        store_expr (TREE_PURPOSE (parts), RTL_EXPR_RTL (TREE_VALUE (parts)), 0);
                   3035:       }
                   3036:   return parts;
                   3037: }
                   3038: 
                   3039: /* Subroutine of expand_expr:
                   3040:    record the non-copied parts (LIST) of an expr (LHS), and return a list
                   3041:    which specifies the initial values of these parts.  */
                   3042: 
                   3043: static tree
                   3044: init_noncopied_parts (lhs, list)
                   3045:      tree lhs;
                   3046:      tree list;
                   3047: {
                   3048:   tree tail;
                   3049:   tree parts = 0;
                   3050: 
                   3051:   for (tail = list; tail; tail = TREE_CHAIN (tail))
                   3052:     if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
                   3053:       parts = chainon (parts, init_noncopied_parts (lhs, TREE_VALUE (tail)));
                   3054:     else
                   3055:       {
                   3056:        tree part = TREE_VALUE (tail);
                   3057:        tree part_type = TREE_TYPE (part);
1.1.1.4 ! root     3058:        tree to_be_initialized = build (COMPONENT_REF, part_type, lhs, part);
1.1       root     3059:        parts = tree_cons (TREE_PURPOSE (tail), to_be_initialized, parts);
                   3060:       }
                   3061:   return parts;
                   3062: }
                   3063: 
                   3064: /* Subroutine of expand_expr: return nonzero iff there is no way that
                   3065:    EXP can reference X, which is being modified.  */
                   3066: 
                   3067: static int
                   3068: safe_from_p (x, exp)
                   3069:      rtx x;
                   3070:      tree exp;
                   3071: {
                   3072:   rtx exp_rtl = 0;
                   3073:   int i, nops;
                   3074: 
                   3075:   if (x == 0)
                   3076:     return 1;
                   3077: 
                   3078:   /* If this is a subreg of a hard register, declare it unsafe, otherwise,
                   3079:      find the underlying pseudo.  */
                   3080:   if (GET_CODE (x) == SUBREG)
                   3081:     {
                   3082:       x = SUBREG_REG (x);
                   3083:       if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
                   3084:        return 0;
                   3085:     }
                   3086: 
                   3087:   /* If X is a location in the outgoing argument area, it is always safe.  */
                   3088:   if (GET_CODE (x) == MEM
                   3089:       && (XEXP (x, 0) == virtual_outgoing_args_rtx
                   3090:          || (GET_CODE (XEXP (x, 0)) == PLUS
                   3091:              && XEXP (XEXP (x, 0), 0) == virtual_outgoing_args_rtx)))
                   3092:     return 1;
                   3093: 
                   3094:   switch (TREE_CODE_CLASS (TREE_CODE (exp)))
                   3095:     {
                   3096:     case 'd':
                   3097:       exp_rtl = DECL_RTL (exp);
                   3098:       break;
                   3099: 
                   3100:     case 'c':
                   3101:       return 1;
                   3102: 
                   3103:     case 'x':
                   3104:       if (TREE_CODE (exp) == TREE_LIST)
1.1.1.4 ! root     3105:        return ((TREE_VALUE (exp) == 0
        !          3106:                 || safe_from_p (x, TREE_VALUE (exp)))
1.1       root     3107:                && (TREE_CHAIN (exp) == 0
                   3108:                    || safe_from_p (x, TREE_CHAIN (exp))));
                   3109:       else
                   3110:        return 0;
                   3111: 
                   3112:     case '1':
                   3113:       return safe_from_p (x, TREE_OPERAND (exp, 0));
                   3114: 
                   3115:     case '2':
                   3116:     case '<':
                   3117:       return (safe_from_p (x, TREE_OPERAND (exp, 0))
                   3118:              && safe_from_p (x, TREE_OPERAND (exp, 1)));
                   3119: 
                   3120:     case 'e':
                   3121:     case 'r':
                   3122:       /* Now do code-specific tests.  EXP_RTL is set to any rtx we find in
                   3123:         the expression.  If it is set, we conflict iff we are that rtx or
                   3124:         both are in memory.  Otherwise, we check all operands of the
                   3125:         expression recursively.  */
                   3126: 
                   3127:       switch (TREE_CODE (exp))
                   3128:        {
                   3129:        case ADDR_EXPR:
                   3130:          return staticp (TREE_OPERAND (exp, 0));
                   3131: 
                   3132:        case INDIRECT_REF:
                   3133:          if (GET_CODE (x) == MEM)
                   3134:            return 0;
                   3135:          break;
                   3136: 
                   3137:        case CALL_EXPR:
                   3138:          exp_rtl = CALL_EXPR_RTL (exp);
                   3139:          if (exp_rtl == 0)
                   3140:            {
                   3141:              /* Assume that the call will clobber all hard registers and
                   3142:                 all of memory.  */
                   3143:              if ((GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
                   3144:                  || GET_CODE (x) == MEM)
                   3145:                return 0;
                   3146:            }
                   3147: 
                   3148:          break;
                   3149: 
                   3150:        case RTL_EXPR:
                   3151:          exp_rtl = RTL_EXPR_RTL (exp);
                   3152:          if (exp_rtl == 0)
                   3153:            /* We don't know what this can modify.  */
                   3154:            return 0;
                   3155: 
                   3156:          break;
                   3157: 
                   3158:        case WITH_CLEANUP_EXPR:
                   3159:          exp_rtl = RTL_EXPR_RTL (exp);
                   3160:          break;
                   3161: 
                   3162:        case SAVE_EXPR:
                   3163:          exp_rtl = SAVE_EXPR_RTL (exp);
                   3164:          break;
                   3165: 
1.1.1.3   root     3166:        case BIND_EXPR:
                   3167:          /* The only operand we look at is operand 1.  The rest aren't
                   3168:             part of the expression.  */
                   3169:          return safe_from_p (x, TREE_OPERAND (exp, 1));
                   3170: 
1.1       root     3171:        case METHOD_CALL_EXPR:
                   3172:          /* This takes a rtx argument, but shouldn't appear here. */
                   3173:          abort ();
                   3174:        }
                   3175: 
                   3176:       /* If we have an rtx, we do not need to scan our operands.  */
                   3177:       if (exp_rtl)
                   3178:        break;
                   3179: 
                   3180:       nops = tree_code_length[(int) TREE_CODE (exp)];
                   3181:       for (i = 0; i < nops; i++)
                   3182:        if (TREE_OPERAND (exp, i) != 0
                   3183:            && ! safe_from_p (x, TREE_OPERAND (exp, i)))
                   3184:          return 0;
                   3185:     }
                   3186: 
                   3187:   /* If we have an rtl, find any enclosed object.  Then see if we conflict
                   3188:      with it.  */
                   3189:   if (exp_rtl)
                   3190:     {
                   3191:       if (GET_CODE (exp_rtl) == SUBREG)
                   3192:        {
                   3193:          exp_rtl = SUBREG_REG (exp_rtl);
                   3194:          if (GET_CODE (exp_rtl) == REG
                   3195:              && REGNO (exp_rtl) < FIRST_PSEUDO_REGISTER)
                   3196:            return 0;
                   3197:        }
                   3198: 
                   3199:       /* If the rtl is X, then it is not safe.  Otherwise, it is unless both
                   3200:         are memory and EXP is not readonly.  */
                   3201:       return ! (rtx_equal_p (x, exp_rtl)
                   3202:                || (GET_CODE (x) == MEM && GET_CODE (exp_rtl) == MEM
                   3203:                    && ! TREE_READONLY (exp)));
                   3204:     }
                   3205: 
                   3206:   /* If we reach here, it is safe.  */
                   3207:   return 1;
                   3208: }
                   3209: 
                   3210: /* Subroutine of expand_expr: return nonzero iff EXP is an
                   3211:    expression whose type is statically determinable.  */
                   3212: 
                   3213: static int
                   3214: fixed_type_p (exp)
                   3215:      tree exp;
                   3216: {
                   3217:   if (TREE_CODE (exp) == PARM_DECL
                   3218:       || TREE_CODE (exp) == VAR_DECL
                   3219:       || TREE_CODE (exp) == CALL_EXPR || TREE_CODE (exp) == TARGET_EXPR
                   3220:       || TREE_CODE (exp) == COMPONENT_REF
                   3221:       || TREE_CODE (exp) == ARRAY_REF)
                   3222:     return 1;
                   3223:   return 0;
                   3224: }
                   3225: 
                   3226: /* expand_expr: generate code for computing expression EXP.
                   3227:    An rtx for the computed value is returned.  The value is never null.
                   3228:    In the case of a void EXP, const0_rtx is returned.
                   3229: 
                   3230:    The value may be stored in TARGET if TARGET is nonzero.
                   3231:    TARGET is just a suggestion; callers must assume that
                   3232:    the rtx returned may not be the same as TARGET.
                   3233: 
                   3234:    If TARGET is CONST0_RTX, it means that the value will be ignored.
                   3235: 
                   3236:    If TMODE is not VOIDmode, it suggests generating the
                   3237:    result in mode TMODE.  But this is done only when convenient.
                   3238:    Otherwise, TMODE is ignored and the value generated in its natural mode.
                   3239:    TMODE is just a suggestion; callers must assume that
                   3240:    the rtx returned may not have mode TMODE.
                   3241: 
                   3242:    EXPAND_CONST_ADDRESS says that it is okay to return a MEM
                   3243:    with a constant address even if that address is not normally legitimate.
                   3244:    EXPAND_INITIALIZER and EXPAND_SUM also have this effect.
                   3245: 
                   3246:    If MODIFIER is EXPAND_SUM then when EXP is an addition
                   3247:    we can return an rtx of the form (MULT (REG ...) (CONST_INT ...))
                   3248:    or a nest of (PLUS ...) and (MINUS ...) where the terms are
                   3249:    products as above, or REG or MEM, or constant.
                   3250:    Ordinarily in such cases we would output mul or add instructions
                   3251:    and then return a pseudo reg containing the sum.
                   3252: 
                   3253:    EXPAND_INITIALIZER is much like EXPAND_SUM except that
                   3254:    it also marks a label as absolutely required (it can't be dead).
1.1.1.4 ! root     3255:    It also makes a ZERO_EXTEND or SIGN_EXTEND instead of emitting extend insns.
1.1.1.3   root     3256:    This is used for outputting expressions used in initializers.  */
1.1       root     3257: 
                   3258: rtx
                   3259: expand_expr (exp, target, tmode, modifier)
                   3260:      register tree exp;
                   3261:      rtx target;
                   3262:      enum machine_mode tmode;
                   3263:      enum expand_modifier modifier;
                   3264: {
                   3265:   register rtx op0, op1, temp;
                   3266:   tree type = TREE_TYPE (exp);
                   3267:   int unsignedp = TREE_UNSIGNED (type);
                   3268:   register enum machine_mode mode = TYPE_MODE (type);
                   3269:   register enum tree_code code = TREE_CODE (exp);
                   3270:   optab this_optab;
                   3271:   /* Use subtarget as the target for operand 0 of a binary operation.  */
                   3272:   rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
                   3273:   rtx original_target = target;
                   3274:   int ignore = target == const0_rtx;
                   3275:   tree context;
                   3276: 
                   3277:   /* Don't use hard regs as subtargets, because the combiner
                   3278:      can only handle pseudo regs.  */
                   3279:   if (subtarget && REGNO (subtarget) < FIRST_PSEUDO_REGISTER)
                   3280:     subtarget = 0;
                   3281:   /* Avoid subtargets inside loops,
                   3282:      since they hide some invariant expressions.  */
                   3283:   if (preserve_subexpressions_p ())
                   3284:     subtarget = 0;
                   3285: 
                   3286:   if (ignore) target = 0, original_target = 0;
                   3287: 
                   3288:   /* If will do cse, generate all results into pseudo registers
                   3289:      since 1) that allows cse to find more things
                   3290:      and 2) otherwise cse could produce an insn the machine
                   3291:      cannot support.  */
                   3292: 
                   3293:   if (! cse_not_expected && mode != BLKmode && target
                   3294:       && (GET_CODE (target) != REG || REGNO (target) < FIRST_PSEUDO_REGISTER))
                   3295:     target = subtarget;
                   3296: 
                   3297:   /* Ensure we reference a volatile object even if value is ignored.  */
                   3298:   if (ignore && TREE_THIS_VOLATILE (exp)
                   3299:       && mode != VOIDmode && mode != BLKmode)
                   3300:     {
                   3301:       target = gen_reg_rtx (mode);
                   3302:       temp = expand_expr (exp, target, VOIDmode, modifier);
                   3303:       if (temp != target)
                   3304:        emit_move_insn (target, temp);
                   3305:       return target;
                   3306:     }
                   3307: 
                   3308:   switch (code)
                   3309:     {
                   3310:     case LABEL_DECL:
1.1.1.3   root     3311:       {
                   3312:        tree function = decl_function_context (exp);
                   3313:        /* Handle using a label in a containing function.  */
                   3314:        if (function != current_function_decl && function != 0)
                   3315:          {
                   3316:            struct function *p = find_function_data (function);
                   3317:            /* Allocate in the memory associated with the function
                   3318:               that the label is in.  */
                   3319:            push_obstacks (p->function_obstack,
                   3320:                           p->function_maybepermanent_obstack);
                   3321: 
                   3322:            p->forced_labels = gen_rtx (EXPR_LIST, VOIDmode,
                   3323:                                        label_rtx (exp), p->forced_labels);
                   3324:            pop_obstacks ();
                   3325:          }
                   3326:        else if (modifier == EXPAND_INITIALIZER)
                   3327:          forced_labels = gen_rtx (EXPR_LIST, VOIDmode,
                   3328:                                   label_rtx (exp), forced_labels);
1.1.1.4 ! root     3329:        temp = gen_rtx (MEM, FUNCTION_MODE,
1.1.1.3   root     3330:                        gen_rtx (LABEL_REF, Pmode, label_rtx (exp)));
1.1.1.4 ! root     3331:        if (function != current_function_decl && function != 0)
        !          3332:          LABEL_REF_NONLOCAL_P (XEXP (temp, 0)) = 1;
        !          3333:        return temp;
1.1.1.3   root     3334:       }
1.1       root     3335: 
                   3336:     case PARM_DECL:
                   3337:       if (DECL_RTL (exp) == 0)
                   3338:        {
                   3339:          error_with_decl (exp, "prior parameter's size depends on `%s'");
1.1.1.3   root     3340:          return CONST0_RTX (mode);
1.1       root     3341:        }
                   3342: 
                   3343:     case FUNCTION_DECL:
                   3344:     case VAR_DECL:
                   3345:     case RESULT_DECL:
                   3346:       if (DECL_RTL (exp) == 0)
                   3347:        abort ();
                   3348:       /* Ensure variable marked as used
                   3349:         even if it doesn't go through a parser.  */
                   3350:       TREE_USED (exp) = 1;
                   3351:       /* Handle variables inherited from containing functions.  */
                   3352:       context = decl_function_context (exp);
                   3353: 
                   3354:       /* We treat inline_function_decl as an alias for the current function
                   3355:         because that is the inline function whose vars, types, etc.
                   3356:         are being merged into the current function.
                   3357:         See expand_inline_function.  */
                   3358:       if (context != 0 && context != current_function_decl
                   3359:          && context != inline_function_decl
                   3360:          /* If var is static, we don't need a static chain to access it.  */
                   3361:          && ! (GET_CODE (DECL_RTL (exp)) == MEM
                   3362:                && CONSTANT_P (XEXP (DECL_RTL (exp), 0))))
                   3363:        {
                   3364:          rtx addr;
                   3365: 
                   3366:          /* Mark as non-local and addressable.  */
1.1.1.4 ! root     3367:          DECL_NONLOCAL (exp) = 1;
1.1       root     3368:          mark_addressable (exp);
                   3369:          if (GET_CODE (DECL_RTL (exp)) != MEM)
                   3370:            abort ();
                   3371:          addr = XEXP (DECL_RTL (exp), 0);
                   3372:          if (GET_CODE (addr) == MEM)
                   3373:            addr = gen_rtx (MEM, Pmode, fix_lexical_addr (XEXP (addr, 0), exp));
                   3374:          else
                   3375:            addr = fix_lexical_addr (addr, exp);
                   3376:          return change_address (DECL_RTL (exp), mode, addr);
                   3377:        }
1.1.1.3   root     3378: 
1.1       root     3379:       /* This is the case of an array whose size is to be determined
                   3380:         from its initializer, while the initializer is still being parsed.
                   3381:         See expand_decl.  */
                   3382:       if (GET_CODE (DECL_RTL (exp)) == MEM
                   3383:          && GET_CODE (XEXP (DECL_RTL (exp), 0)) == REG)
                   3384:        return change_address (DECL_RTL (exp), GET_MODE (DECL_RTL (exp)),
                   3385:                               XEXP (DECL_RTL (exp), 0));
                   3386:       if (GET_CODE (DECL_RTL (exp)) == MEM
                   3387:          && modifier != EXPAND_CONST_ADDRESS
                   3388:          && modifier != EXPAND_SUM
                   3389:          && modifier != EXPAND_INITIALIZER)
                   3390:        {
                   3391:          /* DECL_RTL probably contains a constant address.
                   3392:             On RISC machines where a constant address isn't valid,
                   3393:             make some insns to get that address into a register.  */
                   3394:          if (!memory_address_p (DECL_MODE (exp), XEXP (DECL_RTL (exp), 0))
                   3395:              || (flag_force_addr
                   3396:                  && CONSTANT_ADDRESS_P (XEXP (DECL_RTL (exp), 0))))
                   3397:            return change_address (DECL_RTL (exp), VOIDmode,
                   3398:                                   copy_rtx (XEXP (DECL_RTL (exp), 0)));
                   3399:        }
1.1.1.4 ! root     3400: 
        !          3401:       /* If the mode of DECL_RTL does not match that of the decl, it
        !          3402:         must be a promoted value.  We return a SUBREG of the wanted mode,
        !          3403:         but mark it so that we know that it was already extended.  */
        !          3404: 
        !          3405:       if (GET_CODE (DECL_RTL (exp)) == REG
        !          3406:          && GET_MODE (DECL_RTL (exp)) != mode)
        !          3407:        {
        !          3408:          enum machine_mode decl_mode = DECL_MODE (exp);
        !          3409: 
        !          3410:          /* Get the signedness used for this variable.  Ensure we get the
        !          3411:             same mode we got when the variable was declared.  */
        !          3412: 
        !          3413:          PROMOTE_MODE (decl_mode, unsignedp, type);
        !          3414: 
        !          3415:          if (decl_mode != GET_MODE (DECL_RTL (exp)))
        !          3416:            abort ();
        !          3417: 
        !          3418:          temp = gen_rtx (SUBREG, mode, DECL_RTL (exp), 0);
        !          3419:          SUBREG_PROMOTED_VAR_P (temp) = 1;
        !          3420:          SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
        !          3421:          return temp;
        !          3422:        }
        !          3423: 
1.1       root     3424:       return DECL_RTL (exp);
                   3425: 
                   3426:     case INTEGER_CST:
                   3427:       return immed_double_const (TREE_INT_CST_LOW (exp),
                   3428:                                 TREE_INT_CST_HIGH (exp),
                   3429:                                 mode);
                   3430: 
                   3431:     case CONST_DECL:
                   3432:       return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0);
                   3433: 
                   3434:     case REAL_CST:
                   3435:       /* If optimized, generate immediate CONST_DOUBLE
                   3436:         which will be turned into memory by reload if necessary. 
                   3437:      
                   3438:         We used to force a register so that loop.c could see it.  But
                   3439:         this does not allow gen_* patterns to perform optimizations with
                   3440:         the constants.  It also produces two insns in cases like "x = 1.0;".
                   3441:         On most machines, floating-point constants are not permitted in
                   3442:         many insns, so we'd end up copying it to a register in any case.
                   3443: 
                   3444:         Now, we do the copying in expand_binop, if appropriate.  */
                   3445:       return immed_real_const (exp);
                   3446: 
                   3447:     case COMPLEX_CST:
                   3448:     case STRING_CST:
                   3449:       if (! TREE_CST_RTL (exp))
                   3450:        output_constant_def (exp);
                   3451: 
                   3452:       /* TREE_CST_RTL probably contains a constant address.
                   3453:         On RISC machines where a constant address isn't valid,
                   3454:         make some insns to get that address into a register.  */
                   3455:       if (GET_CODE (TREE_CST_RTL (exp)) == MEM
                   3456:          && modifier != EXPAND_CONST_ADDRESS
                   3457:          && modifier != EXPAND_INITIALIZER
                   3458:          && modifier != EXPAND_SUM
                   3459:          && !memory_address_p (mode, XEXP (TREE_CST_RTL (exp), 0)))
                   3460:        return change_address (TREE_CST_RTL (exp), VOIDmode,
                   3461:                               copy_rtx (XEXP (TREE_CST_RTL (exp), 0)));
                   3462:       return TREE_CST_RTL (exp);
                   3463: 
                   3464:     case SAVE_EXPR:
                   3465:       context = decl_function_context (exp);
                   3466:       /* We treat inline_function_decl as an alias for the current function
                   3467:         because that is the inline function whose vars, types, etc.
                   3468:         are being merged into the current function.
                   3469:         See expand_inline_function.  */
                   3470:       if (context == current_function_decl || context == inline_function_decl)
                   3471:        context = 0;
                   3472: 
                   3473:       /* If this is non-local, handle it.  */
                   3474:       if (context)
                   3475:        {
                   3476:          temp = SAVE_EXPR_RTL (exp);
                   3477:          if (temp && GET_CODE (temp) == REG)
                   3478:            {
                   3479:              put_var_into_stack (exp);
                   3480:              temp = SAVE_EXPR_RTL (exp);
                   3481:            }
                   3482:          if (temp == 0 || GET_CODE (temp) != MEM)
                   3483:            abort ();
                   3484:          return change_address (temp, mode,
                   3485:                                 fix_lexical_addr (XEXP (temp, 0), exp));
                   3486:        }
                   3487:       if (SAVE_EXPR_RTL (exp) == 0)
                   3488:        {
                   3489:          if (mode == BLKmode)
                   3490:            temp
                   3491:              = assign_stack_temp (mode,
                   3492:                                   int_size_in_bytes (TREE_TYPE (exp)), 0);
                   3493:          else
1.1.1.4 ! root     3494:            {
        !          3495:              enum machine_mode var_mode = mode;
        !          3496: 
        !          3497:              if (TREE_CODE (type) == INTEGER_TYPE
        !          3498:                  || TREE_CODE (type) == ENUMERAL_TYPE
        !          3499:                  || TREE_CODE (type) == BOOLEAN_TYPE
        !          3500:                  || TREE_CODE (type) == CHAR_TYPE
        !          3501:                  || TREE_CODE (type) == REAL_TYPE
        !          3502:                  || TREE_CODE (type) == POINTER_TYPE
        !          3503:                  || TREE_CODE (type) == OFFSET_TYPE)
        !          3504:                {
        !          3505:                  PROMOTE_MODE (var_mode, unsignedp, type);
        !          3506:                }
        !          3507: 
        !          3508:              temp = gen_reg_rtx (var_mode);
        !          3509:            }
        !          3510: 
1.1       root     3511:          SAVE_EXPR_RTL (exp) = temp;
                   3512:          store_expr (TREE_OPERAND (exp, 0), temp, 0);
                   3513:          if (!optimize && GET_CODE (temp) == REG)
                   3514:            save_expr_regs = gen_rtx (EXPR_LIST, VOIDmode, temp,
                   3515:                                      save_expr_regs);
                   3516:        }
1.1.1.4 ! root     3517: 
        !          3518:       /* If the mode of SAVE_EXPR_RTL does not match that of the expression, it
        !          3519:         must be a promoted value.  We return a SUBREG of the wanted mode,
        !          3520:         but mark it so that we know that it was already extended.  Note
        !          3521:         that `unsignedp' was modified above in this case.  */
        !          3522: 
        !          3523:       if (GET_CODE (SAVE_EXPR_RTL (exp)) == REG
        !          3524:          && GET_MODE (SAVE_EXPR_RTL (exp)) != mode)
        !          3525:        {
        !          3526:          temp = gen_rtx (SUBREG, mode, SAVE_EXPR_RTL (exp), 0);
        !          3527:          SUBREG_PROMOTED_VAR_P (temp) = 1;
        !          3528:          SUBREG_PROMOTED_UNSIGNED_P (temp) = unsignedp;
        !          3529:          return temp;
        !          3530:        }
        !          3531: 
1.1       root     3532:       return SAVE_EXPR_RTL (exp);
                   3533: 
                   3534:     case EXIT_EXPR:
                   3535:       /* Exit the current loop if the body-expression is true.  */
                   3536:       {
                   3537:        rtx label = gen_label_rtx ();
1.1.1.4 ! root     3538:        do_jump (TREE_OPERAND (exp, 0), label, NULL_RTX);
        !          3539:        expand_exit_loop (NULL_PTR);
1.1       root     3540:        emit_label (label);
                   3541:       }
                   3542:       return const0_rtx;
                   3543: 
                   3544:     case LOOP_EXPR:
                   3545:       expand_start_loop (1);
                   3546:       expand_expr_stmt (TREE_OPERAND (exp, 0));
                   3547:       expand_end_loop ();
                   3548: 
                   3549:       return const0_rtx;
                   3550: 
                   3551:     case BIND_EXPR:
                   3552:       {
                   3553:        tree vars = TREE_OPERAND (exp, 0);
                   3554:        int vars_need_expansion = 0;
                   3555: 
                   3556:        /* Need to open a binding contour here because
                   3557:           if there are any cleanups they most be contained here.  */
                   3558:        expand_start_bindings (0);
                   3559: 
1.1.1.4 ! root     3560:        /* Mark the corresponding BLOCK for output in its proper place.  */
        !          3561:        if (TREE_OPERAND (exp, 2) != 0
        !          3562:            && ! TREE_USED (TREE_OPERAND (exp, 2)))
        !          3563:          insert_block (TREE_OPERAND (exp, 2));
1.1       root     3564: 
                   3565:        /* If VARS have not yet been expanded, expand them now.  */
                   3566:        while (vars)
                   3567:          {
                   3568:            if (DECL_RTL (vars) == 0)
                   3569:              {
                   3570:                vars_need_expansion = 1;
                   3571:                expand_decl (vars);
                   3572:              }
                   3573:            expand_decl_init (vars);
                   3574:            vars = TREE_CHAIN (vars);
                   3575:          }
                   3576: 
                   3577:        temp = expand_expr (TREE_OPERAND (exp, 1), target, tmode, modifier);
                   3578: 
                   3579:        expand_end_bindings (TREE_OPERAND (exp, 0), 0, 0);
                   3580: 
                   3581:        return temp;
                   3582:       }
                   3583: 
                   3584:     case RTL_EXPR:
                   3585:       if (RTL_EXPR_SEQUENCE (exp) == const0_rtx)
                   3586:        abort ();
                   3587:       emit_insns (RTL_EXPR_SEQUENCE (exp));
                   3588:       RTL_EXPR_SEQUENCE (exp) = const0_rtx;
                   3589:       return RTL_EXPR_RTL (exp);
                   3590: 
                   3591:     case CONSTRUCTOR:
1.1.1.3   root     3592:       /* All elts simple constants => refer to a constant in memory.  But
                   3593:         if this is a non-BLKmode mode, let it store a field at a time
                   3594:         since that should make a CONST_INT or CONST_DOUBLE when we
                   3595:         fold.  */
                   3596:       if (TREE_STATIC (exp) && (mode == BLKmode || TREE_ADDRESSABLE (exp)))
1.1       root     3597:        {
                   3598:          rtx constructor = output_constant_def (exp);
1.1.1.3   root     3599:          if (modifier != EXPAND_CONST_ADDRESS
                   3600:              && modifier != EXPAND_INITIALIZER
                   3601:              && modifier != EXPAND_SUM
                   3602:              && !memory_address_p (GET_MODE (constructor),
                   3603:                                    XEXP (constructor, 0)))
1.1       root     3604:            constructor = change_address (constructor, VOIDmode,
                   3605:                                          XEXP (constructor, 0));
                   3606:          return constructor;
                   3607:        }
                   3608: 
                   3609:       if (ignore)
                   3610:        {
                   3611:          tree elt;
                   3612:          for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
                   3613:            expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0);
                   3614:          return const0_rtx;
                   3615:        }
                   3616:       else
                   3617:        {
                   3618:          if (target == 0 || ! safe_from_p (target, exp))
                   3619:            {
                   3620:              if (mode != BLKmode && ! TREE_ADDRESSABLE (exp))
                   3621:                target = gen_reg_rtx (mode);
                   3622:              else
                   3623:                {
                   3624:                  rtx safe_target = assign_stack_temp (mode, int_size_in_bytes (type), 0);
                   3625:                  if (target)
                   3626:                    MEM_IN_STRUCT_P (safe_target) = MEM_IN_STRUCT_P (target);
                   3627:                  target = safe_target;
                   3628:                }
                   3629:            }
                   3630:          store_constructor (exp, target);
                   3631:          return target;
                   3632:        }
                   3633: 
                   3634:     case INDIRECT_REF:
                   3635:       {
                   3636:        tree exp1 = TREE_OPERAND (exp, 0);
                   3637:        tree exp2;
                   3638: 
                   3639:        /* A SAVE_EXPR as the address in an INDIRECT_EXPR is generated
                   3640:           for  *PTR += ANYTHING  where PTR is put inside the SAVE_EXPR.
                   3641:           This code has the same general effect as simply doing
                   3642:           expand_expr on the save expr, except that the expression PTR
                   3643:           is computed for use as a memory address.  This means different
                   3644:           code, suitable for indexing, may be generated.  */
                   3645:        if (TREE_CODE (exp1) == SAVE_EXPR
                   3646:            && SAVE_EXPR_RTL (exp1) == 0
                   3647:            && TREE_CODE (exp2 = TREE_OPERAND (exp1, 0)) != ERROR_MARK
                   3648:            && TYPE_MODE (TREE_TYPE (exp1)) == Pmode
                   3649:            && TYPE_MODE (TREE_TYPE (exp2)) == Pmode)
                   3650:          {
1.1.1.4 ! root     3651:            temp = expand_expr (TREE_OPERAND (exp1, 0), NULL_RTX,
        !          3652:                                VOIDmode, EXPAND_SUM);
1.1       root     3653:            op0 = memory_address (mode, temp);
                   3654:            op0 = copy_all_regs (op0);
                   3655:            SAVE_EXPR_RTL (exp1) = op0;
                   3656:          }
                   3657:        else
                   3658:          {
1.1.1.4 ! root     3659:            op0 = expand_expr (exp1, NULL_RTX, VOIDmode, EXPAND_SUM);
1.1       root     3660:            op0 = memory_address (mode, op0);
                   3661:          }
1.1.1.3   root     3662: 
                   3663:        temp = gen_rtx (MEM, mode, op0);
                   3664:        /* If address was computed by addition,
                   3665:           mark this as an element of an aggregate.  */
                   3666:        if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
                   3667:            || (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR
                   3668:                && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == PLUS_EXPR)
                   3669:            || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
                   3670:            || TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
                   3671:            || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE
                   3672:            || (TREE_CODE (exp1) == ADDR_EXPR
                   3673:                && (exp2 = TREE_OPERAND (exp1, 0))
                   3674:                && (TREE_CODE (TREE_TYPE (exp2)) == ARRAY_TYPE
                   3675:                    || TREE_CODE (TREE_TYPE (exp2)) == RECORD_TYPE
                   3676:                    || TREE_CODE (TREE_TYPE (exp2)) == UNION_TYPE)))
                   3677:          MEM_IN_STRUCT_P (temp) = 1;
                   3678:        MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) || flag_volatile;
1.1       root     3679: #if 0 /* It is incorrectto set RTX_UNCHANGING_P here, because the fact that
                   3680:         a location is accessed through a pointer to const does not mean
                   3681:         that the value there can never change.  */
1.1.1.3   root     3682:        RTX_UNCHANGING_P (temp) = TREE_READONLY (exp);
1.1       root     3683: #endif
1.1.1.3   root     3684:        return temp;
                   3685:       }
1.1       root     3686: 
                   3687:     case ARRAY_REF:
                   3688:       if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
                   3689:          || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
                   3690:        {
                   3691:          /* Nonconstant array index or nonconstant element size.
                   3692:             Generate the tree for *(&array+index) and expand that,
                   3693:             except do it in a language-independent way
                   3694:             and don't complain about non-lvalue arrays.
                   3695:             `mark_addressable' should already have been called
                   3696:             for any array for which this case will be reached.  */
                   3697: 
                   3698:          /* Don't forget the const or volatile flag from the array element. */
                   3699:          tree variant_type = build_type_variant (type,
                   3700:                                                  TREE_READONLY (exp),
                   3701:                                                  TREE_THIS_VOLATILE (exp));
                   3702:          tree array_adr = build1 (ADDR_EXPR, build_pointer_type (variant_type),
                   3703:                                   TREE_OPERAND (exp, 0));
                   3704:          tree index = TREE_OPERAND (exp, 1);
                   3705:          tree elt;
                   3706: 
                   3707:          /* Convert the integer argument to a type the same size as a pointer
                   3708:             so the multiply won't overflow spuriously.  */
                   3709:          if (TYPE_PRECISION (TREE_TYPE (index)) != POINTER_SIZE)
                   3710:            index = convert (type_for_size (POINTER_SIZE, 0), index);
                   3711: 
                   3712:          /* Don't think the address has side effects
                   3713:             just because the array does.
                   3714:             (In some cases the address might have side effects,
                   3715:             and we fail to record that fact here.  However, it should not
                   3716:             matter, since expand_expr should not care.)  */
                   3717:          TREE_SIDE_EFFECTS (array_adr) = 0;
                   3718: 
                   3719:          elt = build1 (INDIRECT_REF, type,
                   3720:                        fold (build (PLUS_EXPR, TYPE_POINTER_TO (variant_type),
                   3721:                                     array_adr,
                   3722:                                     fold (build (MULT_EXPR,
                   3723:                                                  TYPE_POINTER_TO (variant_type),
                   3724:                                                  index, size_in_bytes (type))))));
                   3725: 
                   3726:          /* Volatility, etc., of new expression is same as old expression.  */
                   3727:          TREE_SIDE_EFFECTS (elt) = TREE_SIDE_EFFECTS (exp);
                   3728:          TREE_THIS_VOLATILE (elt) = TREE_THIS_VOLATILE (exp);
                   3729:          TREE_READONLY (elt) = TREE_READONLY (exp);
                   3730: 
                   3731:          return expand_expr (elt, target, tmode, modifier);
                   3732:        }
                   3733: 
                   3734:       /* Fold an expression like: "foo"[2].
                   3735:         This is not done in fold so it won't happen inside &.  */
                   3736:       {
                   3737:        int i;
                   3738:        tree arg0 = TREE_OPERAND (exp, 0);
                   3739:        tree arg1 = TREE_OPERAND (exp, 1);
                   3740: 
                   3741:        if (TREE_CODE (arg0) == STRING_CST
                   3742:            && TREE_CODE (arg1) == INTEGER_CST
                   3743:            && !TREE_INT_CST_HIGH (arg1)
                   3744:            && (i = TREE_INT_CST_LOW (arg1)) < TREE_STRING_LENGTH (arg0))
                   3745:          {
                   3746:            if (TREE_TYPE (TREE_TYPE (arg0)) == integer_type_node)
                   3747:              {
                   3748:                exp = build_int_2 (((int *)TREE_STRING_POINTER (arg0))[i], 0);
                   3749:                TREE_TYPE (exp) = integer_type_node;
                   3750:                return expand_expr (exp, target, tmode, modifier);
                   3751:              }
                   3752:            if (TREE_TYPE (TREE_TYPE (arg0)) == char_type_node)
                   3753:              {
                   3754:                exp = build_int_2 (TREE_STRING_POINTER (arg0)[i], 0);
                   3755:                TREE_TYPE (exp) = integer_type_node;
                   3756:                return expand_expr (convert (TREE_TYPE (TREE_TYPE (arg0)), exp), target, tmode, modifier);
                   3757:              }
                   3758:          }
                   3759:       }
                   3760: 
                   3761:       /* If this is a constant index into a constant array,
1.1.1.3   root     3762:         just get the value from the array.  Handle both the cases when
                   3763:         we have an explicit constructor and when our operand is a variable
                   3764:         that was declared const.  */
                   3765: 
                   3766:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
                   3767:          && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)))
1.1       root     3768:        {
                   3769:          tree index = fold (TREE_OPERAND (exp, 1));
1.1.1.3   root     3770:          if (TREE_CODE (index) == INTEGER_CST
                   3771:              && TREE_INT_CST_HIGH (index) == 0)
1.1       root     3772:            {
                   3773:              int i = TREE_INT_CST_LOW (index);
1.1.1.3   root     3774:              tree elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
1.1       root     3775: 
1.1.1.3   root     3776:              while (elem && i--)
                   3777:                elem = TREE_CHAIN (elem);
                   3778:              if (elem)
                   3779:                return expand_expr (fold (TREE_VALUE (elem)), target,
                   3780:                                    tmode, modifier);
                   3781:            }
                   3782:        }
                   3783:          
                   3784:       else if (TREE_READONLY (TREE_OPERAND (exp, 0))
                   3785:               && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
                   3786:               && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == ARRAY_TYPE
                   3787:               && TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL
                   3788:               && DECL_INITIAL (TREE_OPERAND (exp, 0))
                   3789:               && optimize >= 1
                   3790:               && (TREE_CODE (DECL_INITIAL (TREE_OPERAND (exp, 0)))
                   3791:                   != ERROR_MARK))
                   3792:        {
                   3793:          tree index = fold (TREE_OPERAND (exp, 1));
                   3794:          if (TREE_CODE (index) == INTEGER_CST
                   3795:              && TREE_INT_CST_HIGH (index) == 0)
                   3796:            {
                   3797:              int i = TREE_INT_CST_LOW (index);
                   3798:              tree init = DECL_INITIAL (TREE_OPERAND (exp, 0));
                   3799: 
                   3800:              if (TREE_CODE (init) == CONSTRUCTOR)
                   3801:                {
                   3802:                  tree elem = CONSTRUCTOR_ELTS (init);
                   3803: 
                   3804:                  while (elem && i--)
                   3805:                    elem = TREE_CHAIN (elem);
                   3806:                  if (elem)
                   3807:                    return expand_expr (fold (TREE_VALUE (elem)), target,
                   3808:                                        tmode, modifier);
                   3809:                }
                   3810:              else if (TREE_CODE (init) == STRING_CST
                   3811:                       && i < TREE_STRING_LENGTH (init))
                   3812:                {
1.1.1.4 ! root     3813:                  temp = GEN_INT (TREE_STRING_POINTER (init)[i]);
1.1.1.3   root     3814:                  return convert_to_mode (mode, temp, 0);
                   3815:                }
1.1       root     3816:            }
                   3817:        }
                   3818:       /* Treat array-ref with constant index as a component-ref.  */
                   3819: 
                   3820:     case COMPONENT_REF:
                   3821:     case BIT_FIELD_REF:
1.1.1.3   root     3822:       /* If the operand is a CONSTRUCTOR, we can just extract the
                   3823:         appropriate field if it is present.  */
                   3824:       if (code != ARRAY_REF
                   3825:          && TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR)
                   3826:        {
                   3827:          tree elt;
                   3828: 
                   3829:          for (elt = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0)); elt;
                   3830:               elt = TREE_CHAIN (elt))
                   3831:            if (TREE_PURPOSE (elt) == TREE_OPERAND (exp, 1))
                   3832:              return expand_expr (TREE_VALUE (elt), target, tmode, modifier);
                   3833:        }
                   3834: 
1.1       root     3835:       {
                   3836:        enum machine_mode mode1;
                   3837:        int bitsize;
                   3838:        int bitpos;
1.1.1.3   root     3839:        tree offset;
1.1       root     3840:        int volatilep = 0;
1.1.1.3   root     3841:        tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset,
1.1       root     3842:                                        &mode1, &unsignedp, &volatilep);
                   3843: 
                   3844:        /* In some cases, we will be offsetting OP0's address by a constant.
                   3845:           So get it as a sum, if possible.  If we will be using it
                   3846:           directly in an insn, we validate it.  */
1.1.1.4 ! root     3847:        op0 = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_SUM);
1.1       root     3848: 
1.1.1.3   root     3849:        /* If this is a constant, put it into a register if it is a
                   3850:           legimate constant and memory if it isn't.  */
                   3851:        if (CONSTANT_P (op0))
                   3852:          {
                   3853:            enum machine_mode mode = TYPE_MODE (TREE_TYPE (tem));
                   3854:            if (LEGITIMATE_CONSTANT_P (op0))
                   3855:              op0 = force_reg (mode, op0);
                   3856:            else
                   3857:              op0 = validize_mem (force_const_mem (mode, op0));
                   3858:          }
                   3859: 
                   3860:        if (offset != 0)
                   3861:          {
1.1.1.4 ! root     3862:            rtx offset_rtx = expand_expr (offset, NULL_RTX, VOIDmode, 0);
1.1.1.3   root     3863: 
                   3864:            if (GET_CODE (op0) != MEM)
                   3865:              abort ();
                   3866:            op0 = change_address (op0, VOIDmode,
                   3867:                                  gen_rtx (PLUS, Pmode, XEXP (op0, 0),
                   3868:                                           force_reg (Pmode, offset_rtx)));
                   3869:          }
                   3870: 
1.1       root     3871:        /* Don't forget about volatility even if this is a bitfield.  */
                   3872:        if (GET_CODE (op0) == MEM && volatilep && ! MEM_VOLATILE_P (op0))
                   3873:          {
                   3874:            op0 = copy_rtx (op0);
                   3875:            MEM_VOLATILE_P (op0) = 1;
                   3876:          }
                   3877: 
                   3878:        if (mode1 == VOIDmode
1.1.1.4 ! root     3879:            || (mode1 != BLKmode && ! direct_load[(int) mode1]
        !          3880:                && modifier != EXPAND_CONST_ADDRESS
        !          3881:                && modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
1.1       root     3882:            || GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG)
                   3883:          {
                   3884:            /* In cases where an aligned union has an unaligned object
                   3885:               as a field, we might be extracting a BLKmode value from
                   3886:               an integer-mode (e.g., SImode) object.  Handle this case
                   3887:               by doing the extract into an object as wide as the field
                   3888:               (which we know to be the width of a basic mode), then
                   3889:               storing into memory, and changing the mode to BLKmode.  */
                   3890:            enum machine_mode ext_mode = mode;
                   3891: 
                   3892:            if (ext_mode == BLKmode)
                   3893:              ext_mode = mode_for_size (bitsize, MODE_INT, 1);
                   3894: 
                   3895:            if (ext_mode == BLKmode)
                   3896:              abort ();
                   3897: 
                   3898:            op0 = extract_bit_field (validize_mem (op0), bitsize, bitpos,
                   3899:                                     unsignedp, target, ext_mode, ext_mode,
                   3900:                                     TYPE_ALIGN (TREE_TYPE (tem)) / BITS_PER_UNIT,
                   3901:                                     int_size_in_bytes (TREE_TYPE (tem)));
                   3902:            if (mode == BLKmode)
                   3903:              {
                   3904:                rtx new = assign_stack_temp (ext_mode,
                   3905:                                             bitsize / BITS_PER_UNIT, 0);
                   3906: 
                   3907:                emit_move_insn (new, op0);
                   3908:                op0 = copy_rtx (new);
                   3909:                PUT_MODE (op0, BLKmode);
                   3910:              }
                   3911: 
                   3912:            return op0;
                   3913:          }
                   3914: 
                   3915:        /* Get a reference to just this component.  */
                   3916:        if (modifier == EXPAND_CONST_ADDRESS
                   3917:            || modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
                   3918:          op0 = gen_rtx (MEM, mode1, plus_constant (XEXP (op0, 0),
                   3919:                                                    (bitpos / BITS_PER_UNIT)));
                   3920:        else
                   3921:          op0 = change_address (op0, mode1,
                   3922:                                plus_constant (XEXP (op0, 0),
                   3923:                                               (bitpos / BITS_PER_UNIT)));
                   3924:        MEM_IN_STRUCT_P (op0) = 1;
                   3925:        MEM_VOLATILE_P (op0) |= volatilep;
                   3926:        if (mode == mode1 || mode1 == BLKmode || mode1 == tmode)
                   3927:          return op0;
                   3928:        if (target == 0)
                   3929:          target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
                   3930:        convert_move (target, op0, unsignedp);
                   3931:        return target;
                   3932:       }
                   3933: 
                   3934:     case OFFSET_REF:
                   3935:       {
                   3936:        tree base = build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 0), 0);
                   3937:        tree addr = build (PLUS_EXPR, type, base, TREE_OPERAND (exp, 1));
1.1.1.4 ! root     3938:        op0 = expand_expr (addr, NULL_RTX, VOIDmode, EXPAND_SUM);
1.1       root     3939:        temp = gen_rtx (MEM, mode, memory_address (mode, op0));
                   3940:        MEM_IN_STRUCT_P (temp) = 1;
                   3941:        MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) || flag_volatile;
                   3942: #if 0 /* It is incorrectto set RTX_UNCHANGING_P here, because the fact that
                   3943:         a location is accessed through a pointer to const does not mean
                   3944:         that the value there can never change.  */
                   3945:        RTX_UNCHANGING_P (temp) = TREE_READONLY (exp);
                   3946: #endif
                   3947:        return temp;
                   3948:       }
                   3949: 
                   3950:       /* Intended for a reference to a buffer of a file-object in Pascal.
                   3951:         But it's not certain that a special tree code will really be
                   3952:         necessary for these.  INDIRECT_REF might work for them.  */
                   3953:     case BUFFER_REF:
                   3954:       abort ();
                   3955: 
1.1.1.4 ! root     3956:     /* IN_EXPR: Inlined pascal set IN expression.
        !          3957: 
        !          3958:        Algorithm:
        !          3959:          rlo       = set_low - (set_low%bits_per_word);
        !          3960:         the_word  = set [ (index - rlo)/bits_per_word ];
        !          3961:         bit_index = index % bits_per_word;
        !          3962:         bitmask   = 1 << bit_index;
        !          3963:         return !!(the_word & bitmask);  */
        !          3964:     case IN_EXPR:
        !          3965:       preexpand_calls (exp);
        !          3966:       {
        !          3967:        tree set = TREE_OPERAND (exp, 0);
        !          3968:        tree index = TREE_OPERAND (exp, 1);
        !          3969:        tree set_type = TREE_TYPE (set);
        !          3970: 
        !          3971:        tree set_low_bound = TYPE_MIN_VALUE (TYPE_DOMAIN (set_type));
        !          3972:        tree set_high_bound = TYPE_MAX_VALUE (TYPE_DOMAIN (set_type));
        !          3973: 
        !          3974:        rtx index_val;
        !          3975:        rtx lo_r;
        !          3976:        rtx hi_r;
        !          3977:        rtx rlow;
        !          3978:        rtx diff, quo, rem, addr, bit, result;
        !          3979:        rtx setval, setaddr;
        !          3980:        enum machine_mode index_mode = TYPE_MODE (TREE_TYPE (index));
        !          3981: 
        !          3982:        if (target == 0)
        !          3983:          target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
        !          3984: 
        !          3985:        /* If domain is empty, answer is no.  */
        !          3986:        if (tree_int_cst_lt (set_high_bound, set_low_bound))
        !          3987:          return const0_rtx;
        !          3988: 
        !          3989:        index_val = expand_expr (index, 0, VOIDmode, 0);
        !          3990:        lo_r = expand_expr (set_low_bound, 0, VOIDmode, 0);
        !          3991:        hi_r = expand_expr (set_high_bound, 0, VOIDmode, 0);
        !          3992:        setval = expand_expr (set, 0, VOIDmode, 0);
        !          3993:        setaddr = XEXP (setval, 0); 
        !          3994: 
        !          3995:        /* Compare index against bounds, if they are constant.  */
        !          3996:        if (GET_CODE (index_val) == CONST_INT
        !          3997:            && GET_CODE (lo_r) == CONST_INT)
        !          3998:          {
        !          3999:            if (INTVAL (index_val) < INTVAL (lo_r))
        !          4000:              return const0_rtx;
        !          4001:          }
        !          4002: 
        !          4003:        if (GET_CODE (index_val) == CONST_INT
        !          4004:            && GET_CODE (hi_r) == CONST_INT)
        !          4005:          {
        !          4006:            if (INTVAL (hi_r) < INTVAL (index_val))
        !          4007:              return const0_rtx;
        !          4008:          }
        !          4009: 
        !          4010:        /* If we get here, we have to generate the code for both cases
        !          4011:           (in range and out of range).  */
        !          4012: 
        !          4013:        op0 = gen_label_rtx ();
        !          4014:        op1 = gen_label_rtx ();
        !          4015: 
        !          4016:        if (! (GET_CODE (index_val) == CONST_INT
        !          4017:               && GET_CODE (lo_r) == CONST_INT))
        !          4018:          {
        !          4019:            emit_cmp_insn (index_val, lo_r, LT, 0, GET_MODE (index_val), 0, 0);
        !          4020:            emit_jump_insn (gen_blt (op1));
        !          4021:          }
        !          4022: 
        !          4023:        if (! (GET_CODE (index_val) == CONST_INT
        !          4024:               && GET_CODE (hi_r) == CONST_INT))
        !          4025:          {
        !          4026:            emit_cmp_insn (index_val, hi_r, GT, 0, GET_MODE (index_val), 0, 0);
        !          4027:            emit_jump_insn (gen_bgt (op1));
        !          4028:          }
        !          4029: 
        !          4030:        /* Calculate the element number of bit zero in the first word
        !          4031:           of the set.  */
        !          4032:        if (GET_CODE (lo_r) == CONST_INT)
        !          4033:          rlow = gen_rtx (CONST_INT, VOIDmode,
        !          4034:                          INTVAL (lo_r) & ~ (1 << BITS_PER_UNIT));
        !          4035:        else
        !          4036:          rlow = expand_binop (index_mode, and_optab,
        !          4037:                               lo_r, gen_rtx (CONST_INT, VOIDmode,
        !          4038:                                              ~ (1 << BITS_PER_UNIT)),
        !          4039:                               0, 0, OPTAB_LIB_WIDEN);
        !          4040: 
        !          4041:        diff = expand_binop (index_mode, sub_optab,
        !          4042:                             index_val, rlow, 0, 0, OPTAB_LIB_WIDEN);
        !          4043: 
        !          4044:        quo = expand_divmod (0, TRUNC_DIV_EXPR, index_mode, diff,
        !          4045:                             gen_rtx (CONST_INT, VOIDmode, BITS_PER_UNIT),
        !          4046:                             0, 0);
        !          4047:        rem = expand_divmod (1, TRUNC_MOD_EXPR, index_mode, index_val,
        !          4048:                             gen_rtx (CONST_INT, VOIDmode, BITS_PER_UNIT),
        !          4049:                             0, 0);
        !          4050:        addr = memory_address (byte_mode,
        !          4051:                               expand_binop (index_mode, add_optab,
        !          4052:                                             diff, setaddr));
        !          4053:        /* Extract the bit we want to examine */
        !          4054:        bit = expand_shift (RSHIFT_EXPR, byte_mode,
        !          4055:                            gen_rtx (MEM, byte_mode, addr), rem, 0, 1);
        !          4056:        result = expand_binop (SImode, and_optab, bit, const1_rtx, target,
        !          4057:                               1, OPTAB_LIB_WIDEN);
        !          4058:        emit_move_insn (target, result);
        !          4059: 
        !          4060:        /* Output the code to handle the out-of-range case.  */
        !          4061:        emit_jump (op0);
        !          4062:        emit_label (op1);
        !          4063:        emit_move_insn (target, const0_rtx);
        !          4064:        emit_label (op0);
        !          4065:        return target;
        !          4066:       }
        !          4067: 
1.1       root     4068:     case WITH_CLEANUP_EXPR:
                   4069:       if (RTL_EXPR_RTL (exp) == 0)
                   4070:        {
                   4071:          RTL_EXPR_RTL (exp)
                   4072:            = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
1.1.1.4 ! root     4073:          cleanups_this_call
        !          4074:            = tree_cons (NULL_TREE, TREE_OPERAND (exp, 2), cleanups_this_call);
1.1       root     4075:          /* That's it for this cleanup.  */
                   4076:          TREE_OPERAND (exp, 2) = 0;
                   4077:        }
                   4078:       return RTL_EXPR_RTL (exp);
                   4079: 
                   4080:     case CALL_EXPR:
                   4081:       /* Check for a built-in function.  */
                   4082:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
                   4083:          && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == FUNCTION_DECL
                   4084:          && DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
                   4085:        return expand_builtin (exp, target, subtarget, tmode, ignore);
                   4086:       /* If this call was expanded already by preexpand_calls,
                   4087:         just return the result we got.  */
                   4088:       if (CALL_EXPR_RTL (exp) != 0)
                   4089:        return CALL_EXPR_RTL (exp);
1.1.1.3   root     4090:       return expand_call (exp, target, ignore);
1.1       root     4091: 
                   4092:     case NON_LVALUE_EXPR:
                   4093:     case NOP_EXPR:
                   4094:     case CONVERT_EXPR:
                   4095:     case REFERENCE_EXPR:
                   4096:       if (TREE_CODE (type) == VOID_TYPE || ignore)
                   4097:        {
                   4098:          expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
                   4099:          return const0_rtx;
                   4100:        }
                   4101:       if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   4102:        return expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, modifier);
                   4103:       if (TREE_CODE (type) == UNION_TYPE)
                   4104:        {
                   4105:          tree valtype = TREE_TYPE (TREE_OPERAND (exp, 0));
                   4106:          if (target == 0)
                   4107:            {
                   4108:              if (mode == BLKmode)
                   4109:                {
                   4110:                  if (TYPE_SIZE (type) == 0
                   4111:                      || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
                   4112:                    abort ();
                   4113:                  target = assign_stack_temp (BLKmode,
                   4114:                                              (TREE_INT_CST_LOW (TYPE_SIZE (type))
                   4115:                                               + BITS_PER_UNIT - 1)
                   4116:                                              / BITS_PER_UNIT, 0);
                   4117:                }
                   4118:              else
                   4119:                target = gen_reg_rtx (mode);
                   4120:            }
                   4121:          if (GET_CODE (target) == MEM)
                   4122:            /* Store data into beginning of memory target.  */
                   4123:            store_expr (TREE_OPERAND (exp, 0),
                   4124:                        change_address (target, TYPE_MODE (valtype), 0), 0);
1.1.1.4 ! root     4125: 
1.1       root     4126:          else if (GET_CODE (target) == REG)
                   4127:            /* Store this field into a union of the proper type.  */
                   4128:            store_field (target, GET_MODE_BITSIZE (TYPE_MODE (valtype)), 0,
                   4129:                         TYPE_MODE (valtype), TREE_OPERAND (exp, 0),
                   4130:                         VOIDmode, 0, 1,
                   4131:                         int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp, 0))));
                   4132:          else
                   4133:            abort ();
                   4134: 
                   4135:          /* Return the entire union.  */
                   4136:          return target;
                   4137:        }
1.1.1.4 ! root     4138:       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, 0);
1.1       root     4139:       if (GET_MODE (op0) == mode || GET_MODE (op0) == VOIDmode)
                   4140:        return op0;
1.1.1.4 ! root     4141:       if (modifier == EXPAND_INITIALIZER)
        !          4142:        return gen_rtx (unsignedp ? ZERO_EXTEND : SIGN_EXTEND, mode, op0);
1.1       root     4143:       if (flag_force_mem && GET_CODE (op0) == MEM)
                   4144:        op0 = copy_to_reg (op0);
                   4145: 
                   4146:       if (target == 0)
                   4147:        return convert_to_mode (mode, op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
                   4148:       else
                   4149:        convert_move (target, op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
                   4150:       return target;
                   4151: 
                   4152:     case PLUS_EXPR:
                   4153:       /* We come here from MINUS_EXPR when the second operand is a constant. */
                   4154:     plus_expr:
                   4155:       this_optab = add_optab;
                   4156: 
                   4157:       /* If we are adding a constant, an RTL_EXPR that is sp, fp, or ap, and
                   4158:         something else, make sure we add the register to the constant and
                   4159:         then to the other thing.  This case can occur during strength
                   4160:         reduction and doing it this way will produce better code if the
                   4161:         frame pointer or argument pointer is eliminated.
                   4162: 
                   4163:         fold-const.c will ensure that the constant is always in the inner
                   4164:         PLUS_EXPR, so the only case we need to do anything about is if
                   4165:         sp, ap, or fp is our second argument, in which case we must swap
                   4166:         the innermost first argument and our second argument.  */
                   4167: 
                   4168:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
                   4169:          && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 1)) == INTEGER_CST
                   4170:          && TREE_CODE (TREE_OPERAND (exp, 1)) == RTL_EXPR
                   4171:          && (RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == frame_pointer_rtx
                   4172:              || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == stack_pointer_rtx
                   4173:              || RTL_EXPR_RTL (TREE_OPERAND (exp, 1)) == arg_pointer_rtx))
                   4174:        {
                   4175:          tree t = TREE_OPERAND (exp, 1);
                   4176: 
                   4177:          TREE_OPERAND (exp, 1) = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
                   4178:          TREE_OPERAND (TREE_OPERAND (exp, 0), 0) = t;
                   4179:        }
                   4180: 
                   4181:       /* If the result is to be Pmode and we are adding an integer to
                   4182:         something, we might be forming a constant.  So try to use
                   4183:         plus_constant.  If it produces a sum and we can't accept it,
                   4184:         use force_operand.  This allows P = &ARR[const] to generate
                   4185:         efficient code on machines where a SYMBOL_REF is not a valid
                   4186:         address.
                   4187: 
                   4188:         If this is an EXPAND_SUM call, always return the sum.  */
                   4189:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
1.1.1.4 ! root     4190:          && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
1.1       root     4191:          && (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER
                   4192:              || mode == Pmode))
                   4193:        {
                   4194:          op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode,
                   4195:                             EXPAND_SUM);
                   4196:          op1 = plus_constant (op1, TREE_INT_CST_LOW (TREE_OPERAND (exp, 0)));
                   4197:          if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                   4198:            op1 = force_operand (op1, target);
                   4199:          return op1;
                   4200:        }
                   4201: 
                   4202:       else if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
                   4203:               && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT
                   4204:               && (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER
                   4205:                   || mode == Pmode))
                   4206:        {
                   4207:          op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode,
                   4208:                             EXPAND_SUM);
                   4209:          op0 = plus_constant (op0, TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)));
                   4210:          if (modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                   4211:            op0 = force_operand (op0, target);
                   4212:          return op0;
                   4213:        }
                   4214: 
                   4215:       /* No sense saving up arithmetic to be done
                   4216:         if it's all in the wrong mode to form part of an address.
                   4217:         And force_operand won't know whether to sign-extend or
                   4218:         zero-extend.  */
                   4219:       if ((modifier != EXPAND_SUM && modifier != EXPAND_INITIALIZER)
                   4220:          || mode != Pmode) goto binop;
                   4221: 
                   4222:       preexpand_calls (exp);
                   4223:       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   4224:        subtarget = 0;
                   4225: 
                   4226:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, modifier);
1.1.1.4 ! root     4227:       op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, modifier);
1.1.1.2   root     4228: 
1.1       root     4229:       /* Make sure any term that's a sum with a constant comes last.  */
                   4230:       if (GET_CODE (op0) == PLUS
                   4231:          && CONSTANT_P (XEXP (op0, 1)))
                   4232:        {
                   4233:          temp = op0;
                   4234:          op0 = op1;
                   4235:          op1 = temp;
                   4236:        }
                   4237:       /* If adding to a sum including a constant,
                   4238:         associate it to put the constant outside.  */
                   4239:       if (GET_CODE (op1) == PLUS
                   4240:          && CONSTANT_P (XEXP (op1, 1)))
                   4241:        {
1.1.1.2   root     4242:          rtx constant_term = const0_rtx;
                   4243: 
                   4244:          temp = simplify_binary_operation (PLUS, mode, XEXP (op1, 0), op0);
                   4245:          if (temp != 0)
                   4246:            op0 = temp;
1.1.1.3   root     4247:          /* Ensure that MULT comes first if there is one.  */
                   4248:          else if (GET_CODE (op0) == MULT)
                   4249:            op0 = gen_rtx (PLUS, mode, op0, XEXP (op1, 0));
1.1.1.2   root     4250:          else
                   4251:            op0 = gen_rtx (PLUS, mode, XEXP (op1, 0), op0);
1.1       root     4252: 
                   4253:          /* Let's also eliminate constants from op0 if possible.  */
1.1.1.2   root     4254:          op0 = eliminate_constant_term (op0, &constant_term);
                   4255: 
                   4256:          /* CONSTANT_TERM and XEXP (op1, 1) are known to be constant, so
                   4257:             their sum should be a constant.  Form it into OP1, since the 
                   4258:             result we want will then be OP0 + OP1.  */
                   4259: 
                   4260:          temp = simplify_binary_operation (PLUS, mode, constant_term,
                   4261:                                            XEXP (op1, 1));
                   4262:          if (temp != 0)
                   4263:            op1 = temp;
1.1       root     4264:          else
1.1.1.2   root     4265:            op1 = gen_rtx (PLUS, mode, constant_term, XEXP (op1, 1));
1.1       root     4266:        }
1.1.1.2   root     4267: 
                   4268:       /* Put a constant term last and put a multiplication first.  */
                   4269:       if (CONSTANT_P (op0) || GET_CODE (op1) == MULT)
                   4270:        temp = op1, op1 = op0, op0 = temp;
                   4271: 
                   4272:       temp = simplify_binary_operation (PLUS, mode, op0, op1);
                   4273:       return temp ? temp : gen_rtx (PLUS, mode, op0, op1);
1.1       root     4274: 
                   4275:     case MINUS_EXPR:
                   4276:       /* Handle difference of two symbolic constants,
                   4277:         for the sake of an initializer.  */
                   4278:       if ((modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
                   4279:          && really_constant_p (TREE_OPERAND (exp, 0))
                   4280:          && really_constant_p (TREE_OPERAND (exp, 1)))
                   4281:        {
1.1.1.4 ! root     4282:          rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX,
        !          4283:                                 VOIDmode, modifier);
        !          4284:          rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
        !          4285:                                 VOIDmode, modifier);
1.1       root     4286:          return gen_rtx (MINUS, mode, op0, op1);
                   4287:        }
                   4288:       /* Convert A - const to A + (-const).  */
                   4289:       if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
                   4290:        {
                   4291:          exp = build (PLUS_EXPR, type, TREE_OPERAND (exp, 0),
                   4292:                       fold (build1 (NEGATE_EXPR, type,
                   4293:                                     TREE_OPERAND (exp, 1))));
                   4294:          goto plus_expr;
                   4295:        }
                   4296:       this_optab = sub_optab;
                   4297:       goto binop;
                   4298: 
                   4299:     case MULT_EXPR:
                   4300:       preexpand_calls (exp);
                   4301:       /* If first operand is constant, swap them.
                   4302:         Thus the following special case checks need only
                   4303:         check the second operand.  */
                   4304:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
                   4305:        {
                   4306:          register tree t1 = TREE_OPERAND (exp, 0);
                   4307:          TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1);
                   4308:          TREE_OPERAND (exp, 1) = t1;
                   4309:        }
                   4310: 
                   4311:       /* Attempt to return something suitable for generating an
                   4312:         indexed address, for machines that support that.  */
                   4313: 
                   4314:       if (modifier == EXPAND_SUM && mode == Pmode
                   4315:          && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
1.1.1.4 ! root     4316:          && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
1.1       root     4317:        {
                   4318:          op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM);
                   4319: 
                   4320:          /* Apply distributive law if OP0 is x+c.  */
                   4321:          if (GET_CODE (op0) == PLUS
                   4322:              && GET_CODE (XEXP (op0, 1)) == CONST_INT)
                   4323:            return gen_rtx (PLUS, mode,
                   4324:                            gen_rtx (MULT, mode, XEXP (op0, 0),
1.1.1.4 ! root     4325:                                     GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))),
        !          4326:                            GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))
        !          4327:                                     * INTVAL (XEXP (op0, 1))));
1.1       root     4328: 
                   4329:          if (GET_CODE (op0) != REG)
1.1.1.4 ! root     4330:            op0 = force_operand (op0, NULL_RTX);
1.1       root     4331:          if (GET_CODE (op0) != REG)
                   4332:            op0 = copy_to_mode_reg (mode, op0);
                   4333: 
                   4334:          return gen_rtx (MULT, mode, op0,
1.1.1.4 ! root     4335:                          GEN_INT (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))));
1.1       root     4336:        }
                   4337: 
                   4338:       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   4339:        subtarget = 0;
                   4340: 
                   4341:       /* Check for multiplying things that have been extended
                   4342:         from a narrower type.  If this machine supports multiplying
                   4343:         in that narrower type with a result in the desired type,
                   4344:         do it that way, and avoid the explicit type-conversion.  */
                   4345:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
                   4346:          && TREE_CODE (type) == INTEGER_TYPE
                   4347:          && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
                   4348:              < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   4349:          && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
                   4350:               && int_fits_type_p (TREE_OPERAND (exp, 1),
                   4351:                                   TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
                   4352:               /* Don't use a widening multiply if a shift will do.  */
                   4353:               && ((GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1))))
1.1.1.4 ! root     4354:                    > HOST_BITS_PER_WIDE_INT)
1.1       root     4355:                   || exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0))
                   4356:              ||
                   4357:              (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
                   4358:               && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
                   4359:                   ==
                   4360:                   TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))
                   4361:               /* If both operands are extended, they must either both
                   4362:                  be zero-extended or both be sign-extended.  */
                   4363:               && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
                   4364:                   ==
                   4365:                   TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))))))
                   4366:        {
                   4367:          enum machine_mode innermode
                   4368:            = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)));
                   4369:          this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
                   4370:                        ? umul_widen_optab : smul_widen_optab);
                   4371:          if (mode == GET_MODE_WIDER_MODE (innermode)
                   4372:              && this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
                   4373:            {
                   4374:              op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
1.1.1.4 ! root     4375:                                 NULL_RTX, VOIDmode, 0);
1.1       root     4376:              if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
1.1.1.4 ! root     4377:                op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX,
        !          4378:                                   VOIDmode, 0);
1.1       root     4379:              else
                   4380:                op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
1.1.1.4 ! root     4381:                                   NULL_RTX, VOIDmode, 0);
1.1       root     4382:              goto binop2;
                   4383:            }
                   4384:        }
                   4385:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1.1.4 ! root     4386:       op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     4387:       return expand_mult (mode, op0, op1, target, unsignedp);
                   4388: 
                   4389:     case TRUNC_DIV_EXPR:
                   4390:     case FLOOR_DIV_EXPR:
                   4391:     case CEIL_DIV_EXPR:
                   4392:     case ROUND_DIV_EXPR:
                   4393:     case EXACT_DIV_EXPR:
                   4394:       preexpand_calls (exp);
                   4395:       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   4396:        subtarget = 0;
                   4397:       /* Possible optimization: compute the dividend with EXPAND_SUM
                   4398:         then if the divisor is constant can optimize the case
                   4399:         where some terms of the dividend have coeffs divisible by it.  */
                   4400:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1.1.4 ! root     4401:       op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     4402:       return expand_divmod (0, code, mode, op0, op1, target, unsignedp);
                   4403: 
                   4404:     case RDIV_EXPR:
                   4405:       this_optab = flodiv_optab;
                   4406:       goto binop;
                   4407: 
                   4408:     case TRUNC_MOD_EXPR:
                   4409:     case FLOOR_MOD_EXPR:
                   4410:     case CEIL_MOD_EXPR:
                   4411:     case ROUND_MOD_EXPR:
                   4412:       preexpand_calls (exp);
                   4413:       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   4414:        subtarget = 0;
                   4415:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1.1.4 ! root     4416:       op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     4417:       return expand_divmod (1, code, mode, op0, op1, target, unsignedp);
                   4418: 
                   4419:     case FIX_ROUND_EXPR:
                   4420:     case FIX_FLOOR_EXPR:
                   4421:     case FIX_CEIL_EXPR:
                   4422:       abort ();                        /* Not used for C.  */
                   4423: 
                   4424:     case FIX_TRUNC_EXPR:
1.1.1.4 ! root     4425:       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
1.1       root     4426:       if (target == 0)
                   4427:        target = gen_reg_rtx (mode);
                   4428:       expand_fix (target, op0, unsignedp);
                   4429:       return target;
                   4430: 
                   4431:     case FLOAT_EXPR:
1.1.1.4 ! root     4432:       op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
1.1       root     4433:       if (target == 0)
                   4434:        target = gen_reg_rtx (mode);
                   4435:       /* expand_float can't figure out what to do if FROM has VOIDmode.
                   4436:         So give it the correct mode.  With -O, cse will optimize this.  */
                   4437:       if (GET_MODE (op0) == VOIDmode)
                   4438:        op0 = copy_to_mode_reg (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))),
                   4439:                                op0);
                   4440:       expand_float (target, op0,
                   4441:                    TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
                   4442:       return target;
                   4443: 
                   4444:     case NEGATE_EXPR:
                   4445:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   4446:       temp = expand_unop (mode, neg_optab, op0, target, 0);
                   4447:       if (temp == 0)
                   4448:        abort ();
                   4449:       return temp;
                   4450: 
                   4451:     case ABS_EXPR:
                   4452:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   4453: 
1.1.1.4 ! root     4454:       /* Handle complex values specially.  */
        !          4455:       {
        !          4456:        enum machine_mode opmode
        !          4457:          = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
        !          4458: 
        !          4459:        if (GET_MODE_CLASS (opmode) == MODE_COMPLEX_INT
        !          4460:            || GET_MODE_CLASS (opmode) == MODE_COMPLEX_FLOAT)
        !          4461:          return expand_complex_abs (opmode, op0, target, unsignedp);
        !          4462:       }
        !          4463: 
1.1       root     4464:       /* Unsigned abs is simply the operand.  Testing here means we don't
                   4465:         risk generating incorrect code below.  */
                   4466:       if (TREE_UNSIGNED (type))
                   4467:        return op0;
                   4468: 
                   4469:       /* First try to do it with a special abs instruction.  */
                   4470:       temp = expand_unop (mode, abs_optab, op0, target, 0);
                   4471:       if (temp != 0)
                   4472:        return temp;
                   4473: 
                   4474:       /* If this machine has expensive jumps, we can do integer absolute
                   4475:         value of X as (((signed) x >> (W-1)) ^ x) - ((signed) x >> (W-1)),
                   4476:         where W is the width of MODE.  */
                   4477: 
                   4478:       if (GET_MODE_CLASS (mode) == MODE_INT && BRANCH_COST >= 2)
                   4479:        {
                   4480:          rtx extended = expand_shift (RSHIFT_EXPR, mode, op0,
                   4481:                                       size_int (GET_MODE_BITSIZE (mode) - 1),
1.1.1.4 ! root     4482:                                       NULL_RTX, 0);
1.1       root     4483: 
                   4484:          temp = expand_binop (mode, xor_optab, extended, op0, target, 0,
                   4485:                               OPTAB_LIB_WIDEN);
                   4486:          if (temp != 0)
                   4487:            temp = expand_binop (mode, sub_optab, temp, extended, target, 0,
                   4488:                                 OPTAB_LIB_WIDEN);
                   4489: 
                   4490:          if (temp != 0)
                   4491:            return temp;
                   4492:        }
                   4493: 
                   4494:       /* If that does not win, use conditional jump and negate.  */
                   4495:       target = original_target;
                   4496:       temp = gen_label_rtx ();
                   4497:       if (target == 0 || ! safe_from_p (target, TREE_OPERAND (exp, 0))
                   4498:          || (GET_CODE (target) == REG
                   4499:              && REGNO (target) < FIRST_PSEUDO_REGISTER))
                   4500:        target = gen_reg_rtx (mode);
                   4501:       emit_move_insn (target, op0);
                   4502:       emit_cmp_insn (target,
                   4503:                     expand_expr (convert (type, integer_zero_node),
1.1.1.4 ! root     4504:                                  NULL_RTX, VOIDmode, 0),
        !          4505:                     GE, NULL_RTX, mode, 0, 0);
1.1       root     4506:       NO_DEFER_POP;
                   4507:       emit_jump_insn (gen_bge (temp));
                   4508:       op0 = expand_unop (mode, neg_optab, target, target, 0);
                   4509:       if (op0 != target)
                   4510:        emit_move_insn (target, op0);
                   4511:       emit_label (temp);
                   4512:       OK_DEFER_POP;
                   4513:       return target;
                   4514: 
                   4515:     case MAX_EXPR:
                   4516:     case MIN_EXPR:
                   4517:       target = original_target;
                   4518:       if (target == 0 || ! safe_from_p (target, TREE_OPERAND (exp, 1))
                   4519:          || (GET_CODE (target) == REG
                   4520:              && REGNO (target) < FIRST_PSEUDO_REGISTER))
                   4521:        target = gen_reg_rtx (mode);
1.1.1.4 ! root     4522:       op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     4523:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   4524: 
                   4525:       /* First try to do it with a special MIN or MAX instruction.
                   4526:         If that does not win, use a conditional jump to select the proper
                   4527:         value.  */
                   4528:       this_optab = (TREE_UNSIGNED (type)
                   4529:                    ? (code == MIN_EXPR ? umin_optab : umax_optab)
                   4530:                    : (code == MIN_EXPR ? smin_optab : smax_optab));
                   4531: 
                   4532:       temp = expand_binop (mode, this_optab, op0, op1, target, unsignedp,
                   4533:                           OPTAB_WIDEN);
                   4534:       if (temp != 0)
                   4535:        return temp;
                   4536: 
                   4537:       if (target != op0)
                   4538:        emit_move_insn (target, op0);
                   4539:       op0 = gen_label_rtx ();
                   4540:       if (code == MAX_EXPR)
                   4541:        temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))
1.1.1.4 ! root     4542:                ? compare_from_rtx (target, op1, GEU, 1, mode, NULL_RTX, 0)
        !          4543:                : compare_from_rtx (target, op1, GE, 0, mode, NULL_RTX, 0));
1.1       root     4544:       else
                   4545:        temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))
1.1.1.4 ! root     4546:                ? compare_from_rtx (target, op1, LEU, 1, mode, NULL_RTX, 0)
        !          4547:                : compare_from_rtx (target, op1, LE, 0, mode, NULL_RTX, 0));
1.1       root     4548:       if (temp == const0_rtx)
                   4549:        emit_move_insn (target, op1);
                   4550:       else if (temp != const_true_rtx)
                   4551:        {
                   4552:          if (bcc_gen_fctn[(int) GET_CODE (temp)] != 0)
                   4553:            emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (temp)]) (op0));
                   4554:          else
                   4555:            abort ();
                   4556:          emit_move_insn (target, op1);
                   4557:        }
                   4558:       emit_label (op0);
                   4559:       return target;
                   4560: 
                   4561: /* ??? Can optimize when the operand of this is a bitwise operation,
                   4562:    by using a different bitwise operation.  */
                   4563:     case BIT_NOT_EXPR:
                   4564:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   4565:       temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
                   4566:       if (temp == 0)
                   4567:        abort ();
                   4568:       return temp;
                   4569: 
                   4570:     case FFS_EXPR:
                   4571:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   4572:       temp = expand_unop (mode, ffs_optab, op0, target, 1);
                   4573:       if (temp == 0)
                   4574:        abort ();
                   4575:       return temp;
                   4576: 
                   4577: /* ??? Can optimize bitwise operations with one arg constant.
                   4578:    Can optimize (a bitwise1 n) bitwise2 (a bitwise3 b)
                   4579:    and (a bitwise1 b) bitwise2 b (etc)
                   4580:    but that is probably not worth while.  */
                   4581: 
                   4582: /* BIT_AND_EXPR is for bitwise anding.
                   4583:    TRUTH_AND_EXPR is for anding two boolean values
                   4584:    when we want in all cases to compute both of them.
                   4585:    In general it is fastest to do TRUTH_AND_EXPR by
                   4586:    computing both operands as actual zero-or-1 values
                   4587:    and then bitwise anding.  In cases where there cannot
                   4588:    be any side effects, better code would be made by
                   4589:    treating TRUTH_AND_EXPR like TRUTH_ANDIF_EXPR;
                   4590:    but the question is how to recognize those cases.  */
                   4591: 
                   4592:     case TRUTH_AND_EXPR:
                   4593:     case BIT_AND_EXPR:
                   4594:       this_optab = and_optab;
                   4595:       goto binop;
                   4596: 
                   4597: /* See comment above about TRUTH_AND_EXPR; it applies here too.  */
                   4598:     case TRUTH_OR_EXPR:
                   4599:     case BIT_IOR_EXPR:
                   4600:       this_optab = ior_optab;
                   4601:       goto binop;
                   4602: 
                   4603:     case BIT_XOR_EXPR:
                   4604:       this_optab = xor_optab;
                   4605:       goto binop;
                   4606: 
                   4607:     case LSHIFT_EXPR:
                   4608:     case RSHIFT_EXPR:
                   4609:     case LROTATE_EXPR:
                   4610:     case RROTATE_EXPR:
                   4611:       preexpand_calls (exp);
                   4612:       if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   4613:        subtarget = 0;
                   4614:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   4615:       return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
                   4616:                           unsignedp);
                   4617: 
                   4618: /* Could determine the answer when only additive constants differ.
                   4619:    Also, the addition of one can be handled by changing the condition.  */
                   4620:     case LT_EXPR:
                   4621:     case LE_EXPR:
                   4622:     case GT_EXPR:
                   4623:     case GE_EXPR:
                   4624:     case EQ_EXPR:
                   4625:     case NE_EXPR:
                   4626:       preexpand_calls (exp);
                   4627:       temp = do_store_flag (exp, target, tmode != VOIDmode ? tmode : mode, 0);
                   4628:       if (temp != 0)
                   4629:        return temp;
                   4630:       /* For foo != 0, load foo, and if it is nonzero load 1 instead. */
                   4631:       if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1))
                   4632:          && original_target
                   4633:          && GET_CODE (original_target) == REG
                   4634:          && (GET_MODE (original_target)
                   4635:              == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   4636:        {
                   4637:          temp = expand_expr (TREE_OPERAND (exp, 0), original_target, VOIDmode, 0);
                   4638:          if (temp != original_target)
                   4639:            temp = copy_to_reg (temp);
                   4640:          op1 = gen_label_rtx ();
1.1.1.4 ! root     4641:          emit_cmp_insn (temp, const0_rtx, EQ, NULL_RTX,
1.1       root     4642:                         GET_MODE (temp), unsignedp, 0);
                   4643:          emit_jump_insn (gen_beq (op1));
                   4644:          emit_move_insn (temp, const1_rtx);
                   4645:          emit_label (op1);
                   4646:          return temp;
                   4647:        }
                   4648:       /* If no set-flag instruction, must generate a conditional
                   4649:         store into a temporary variable.  Drop through
                   4650:         and handle this like && and ||.  */
                   4651: 
                   4652:     case TRUTH_ANDIF_EXPR:
                   4653:     case TRUTH_ORIF_EXPR:
                   4654:       if (target == 0 || ! safe_from_p (target, exp)
                   4655:          /* Make sure we don't have a hard reg (such as function's return
                   4656:             value) live across basic blocks, if not optimizing.  */
                   4657:          || (!optimize && GET_CODE (target) == REG
                   4658:              && REGNO (target) < FIRST_PSEUDO_REGISTER))
                   4659:        target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
                   4660:       emit_clr_insn (target);
                   4661:       op1 = gen_label_rtx ();
                   4662:       jumpifnot (exp, op1);
                   4663:       emit_0_to_1_insn (target);
                   4664:       emit_label (op1);
                   4665:       return target;
                   4666: 
                   4667:     case TRUTH_NOT_EXPR:
                   4668:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   4669:       /* The parser is careful to generate TRUTH_NOT_EXPR
                   4670:         only with operands that are always zero or one.  */
1.1.1.4 ! root     4671:       temp = expand_binop (mode, xor_optab, op0, const1_rtx,
1.1       root     4672:                           target, 1, OPTAB_LIB_WIDEN);
                   4673:       if (temp == 0)
                   4674:        abort ();
                   4675:       return temp;
                   4676: 
                   4677:     case COMPOUND_EXPR:
                   4678:       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
                   4679:       emit_queue ();
                   4680:       return expand_expr (TREE_OPERAND (exp, 1),
                   4681:                          (ignore ? const0_rtx : target),
                   4682:                          VOIDmode, 0);
                   4683: 
                   4684:     case COND_EXPR:
                   4685:       {
                   4686:        /* Note that COND_EXPRs whose type is a structure or union
                   4687:           are required to be constructed to contain assignments of
                   4688:           a temporary variable, so that we can evaluate them here
                   4689:           for side effect only.  If type is void, we must do likewise.  */
                   4690: 
                   4691:        /* If an arm of the branch requires a cleanup,
                   4692:           only that cleanup is performed.  */
                   4693: 
                   4694:        tree singleton = 0;
                   4695:        tree binary_op = 0, unary_op = 0;
                   4696:        tree old_cleanups = cleanups_this_call;
                   4697:        cleanups_this_call = 0;
                   4698: 
                   4699:        /* If this is (A ? 1 : 0) and A is a condition, just evaluate it and
                   4700:           convert it to our mode, if necessary.  */
                   4701:        if (integer_onep (TREE_OPERAND (exp, 1))
                   4702:            && integer_zerop (TREE_OPERAND (exp, 2))
                   4703:            && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
                   4704:          {
                   4705:            op0 = expand_expr (TREE_OPERAND (exp, 0), target, mode, modifier);
                   4706:            if (GET_MODE (op0) == mode)
                   4707:              return op0;
                   4708:            if (target == 0)
                   4709:              target = gen_reg_rtx (mode);
                   4710:            convert_move (target, op0, unsignedp);
                   4711:            return target;
                   4712:          }
                   4713: 
                   4714:        /* If we are not to produce a result, we have no target.  Otherwise,
                   4715:           if a target was specified use it; it will not be used as an
                   4716:           intermediate target unless it is safe.  If no target, use a 
                   4717:           temporary.  */
                   4718: 
                   4719:        if (mode == VOIDmode || ignore)
                   4720:          temp = 0;
                   4721:        else if (original_target
                   4722:                 && safe_from_p (original_target, TREE_OPERAND (exp, 0)))
                   4723:          temp = original_target;
                   4724:        else if (mode == BLKmode)
                   4725:          {
                   4726:            if (TYPE_SIZE (type) == 0
                   4727:                || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
                   4728:              abort ();
                   4729:            temp = assign_stack_temp (BLKmode,
                   4730:                                      (TREE_INT_CST_LOW (TYPE_SIZE (type))
                   4731:                                       + BITS_PER_UNIT - 1)
                   4732:                                      / BITS_PER_UNIT, 0);
                   4733:          }
                   4734:        else
                   4735:          temp = gen_reg_rtx (mode);
                   4736: 
                   4737:        /* Check for X ? A + B : A.  If we have this, we can copy
                   4738:           A to the output and conditionally add B.  Similarly for unary
                   4739:           operations.  Don't do this if X has side-effects because
                   4740:           those side effects might affect A or B and the "?" operation is
                   4741:           a sequence point in ANSI.  (We test for side effects later.)  */
                   4742: 
                   4743:        if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '2'
                   4744:            && operand_equal_p (TREE_OPERAND (exp, 2),
                   4745:                                TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0))
                   4746:          singleton = TREE_OPERAND (exp, 2), binary_op = TREE_OPERAND (exp, 1);
                   4747:        else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '2'
                   4748:                 && operand_equal_p (TREE_OPERAND (exp, 1),
                   4749:                                     TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0))
                   4750:          singleton = TREE_OPERAND (exp, 1), binary_op = TREE_OPERAND (exp, 2);
                   4751:        else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 1))) == '1'
                   4752:                 && operand_equal_p (TREE_OPERAND (exp, 2),
                   4753:                                     TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0))
                   4754:          singleton = TREE_OPERAND (exp, 2), unary_op = TREE_OPERAND (exp, 1);
                   4755:        else if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 2))) == '1'
                   4756:                 && operand_equal_p (TREE_OPERAND (exp, 1),
                   4757:                                     TREE_OPERAND (TREE_OPERAND (exp, 2), 0), 0))
                   4758:          singleton = TREE_OPERAND (exp, 1), unary_op = TREE_OPERAND (exp, 2);
                   4759: 
                   4760:        /* If we had X ? A + 1 : A and we can do the test of X as a store-flag
                   4761:           operation, do this as A + (X != 0).  Similarly for other simple
                   4762:           binary operators.  */
                   4763:        if (singleton && binary_op
                   4764:            && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
                   4765:            && (TREE_CODE (binary_op) == PLUS_EXPR
                   4766:                || TREE_CODE (binary_op) == MINUS_EXPR
                   4767:                || TREE_CODE (binary_op) == BIT_IOR_EXPR
                   4768:                || TREE_CODE (binary_op) == BIT_XOR_EXPR
                   4769:                || TREE_CODE (binary_op) == BIT_AND_EXPR)
                   4770:            && integer_onep (TREE_OPERAND (binary_op, 1))
                   4771:            && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<')
                   4772:          {
                   4773:            rtx result;
                   4774:            optab boptab = (TREE_CODE (binary_op) == PLUS_EXPR ? add_optab
                   4775:                            : TREE_CODE (binary_op) == MINUS_EXPR ? sub_optab
                   4776:                            : TREE_CODE (binary_op) == BIT_IOR_EXPR ? ior_optab
                   4777:                            : TREE_CODE (binary_op) == BIT_XOR_EXPR ? xor_optab
                   4778:                            : and_optab);
                   4779: 
                   4780:            /* If we had X ? A : A + 1, do this as A + (X == 0).
                   4781: 
                   4782:               We have to invert the truth value here and then put it
                   4783:               back later if do_store_flag fails.  We cannot simply copy
                   4784:               TREE_OPERAND (exp, 0) to another variable and modify that
                   4785:               because invert_truthvalue can modify the tree pointed to
                   4786:               by its argument.  */
                   4787:            if (singleton == TREE_OPERAND (exp, 1))
                   4788:              TREE_OPERAND (exp, 0)
                   4789:                = invert_truthvalue (TREE_OPERAND (exp, 0));
                   4790: 
                   4791:            result = do_store_flag (TREE_OPERAND (exp, 0),
1.1.1.4 ! root     4792:                                    (safe_from_p (temp, singleton)
        !          4793:                                     ? temp : NULL_RTX),
1.1       root     4794:                                    mode, BRANCH_COST <= 1);
                   4795: 
                   4796:            if (result)
                   4797:              {
1.1.1.4 ! root     4798:                op1 = expand_expr (singleton, NULL_RTX, VOIDmode, 0);
1.1       root     4799:                return expand_binop (mode, boptab, op1, result, temp,
                   4800:                                     unsignedp, OPTAB_LIB_WIDEN);
                   4801:              }
                   4802:            else if (singleton == TREE_OPERAND (exp, 1))
                   4803:              TREE_OPERAND (exp, 0)
                   4804:                = invert_truthvalue (TREE_OPERAND (exp, 0));
                   4805:          }
                   4806:            
                   4807:        NO_DEFER_POP;
                   4808:        op0 = gen_label_rtx ();
                   4809: 
                   4810:        if (singleton && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)))
                   4811:          {
                   4812:            if (temp != 0)
                   4813:              {
                   4814:                /* If the target conflicts with the other operand of the
                   4815:                   binary op, we can't use it.  Also, we can't use the target
                   4816:                   if it is a hard register, because evaluating the condition
                   4817:                   might clobber it.  */
                   4818:                if ((binary_op
                   4819:                     && ! safe_from_p (temp, TREE_OPERAND (binary_op, 1)))
                   4820:                    || (GET_CODE (temp) == REG
                   4821:                        && REGNO (temp) < FIRST_PSEUDO_REGISTER))
                   4822:                  temp = gen_reg_rtx (mode);
                   4823:                store_expr (singleton, temp, 0);
                   4824:              }
                   4825:            else
1.1.1.4 ! root     4826:              expand_expr (singleton,
        !          4827:                           ignore ? const1_rtx : NULL_RTX, VOIDmode, 0);
1.1       root     4828:            if (cleanups_this_call)
                   4829:              {
                   4830:                sorry ("aggregate value in COND_EXPR");
                   4831:                cleanups_this_call = 0;
                   4832:              }
                   4833:            if (singleton == TREE_OPERAND (exp, 1))
                   4834:              jumpif (TREE_OPERAND (exp, 0), op0);
                   4835:            else
                   4836:              jumpifnot (TREE_OPERAND (exp, 0), op0);
                   4837: 
                   4838:            if (binary_op && temp == 0)
                   4839:              /* Just touch the other operand.  */
                   4840:              expand_expr (TREE_OPERAND (binary_op, 1),
1.1.1.4 ! root     4841:                           ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
1.1       root     4842:            else if (binary_op)
                   4843:              store_expr (build (TREE_CODE (binary_op), type,
                   4844:                                 make_tree (type, temp),
                   4845:                                 TREE_OPERAND (binary_op, 1)),
                   4846:                          temp, 0);
                   4847:            else
                   4848:              store_expr (build1 (TREE_CODE (unary_op), type,
                   4849:                                  make_tree (type, temp)),
                   4850:                          temp, 0);
                   4851:            op1 = op0;
                   4852:          }
                   4853: #if 0
                   4854:        /* This is now done in jump.c and is better done there because it
                   4855:           produces shorter register lifetimes.  */
                   4856:           
                   4857:        /* Check for both possibilities either constants or variables
                   4858:           in registers (but not the same as the target!).  If so, can
                   4859:           save branches by assigning one, branching, and assigning the
                   4860:           other.  */
                   4861:        else if (temp && GET_MODE (temp) != BLKmode
                   4862:                 && (TREE_CONSTANT (TREE_OPERAND (exp, 1))
                   4863:                     || ((TREE_CODE (TREE_OPERAND (exp, 1)) == PARM_DECL
                   4864:                          || TREE_CODE (TREE_OPERAND (exp, 1)) == VAR_DECL)
                   4865:                         && DECL_RTL (TREE_OPERAND (exp, 1))
                   4866:                         && GET_CODE (DECL_RTL (TREE_OPERAND (exp, 1))) == REG
                   4867:                         && DECL_RTL (TREE_OPERAND (exp, 1)) != temp))
                   4868:                 && (TREE_CONSTANT (TREE_OPERAND (exp, 2))
                   4869:                     || ((TREE_CODE (TREE_OPERAND (exp, 2)) == PARM_DECL
                   4870:                          || TREE_CODE (TREE_OPERAND (exp, 2)) == VAR_DECL)
                   4871:                         && DECL_RTL (TREE_OPERAND (exp, 2))
                   4872:                         && GET_CODE (DECL_RTL (TREE_OPERAND (exp, 2))) == REG
                   4873:                         && DECL_RTL (TREE_OPERAND (exp, 2)) != temp)))
                   4874:          {
                   4875:            if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
                   4876:              temp = gen_reg_rtx (mode);
                   4877:            store_expr (TREE_OPERAND (exp, 2), temp, 0);
                   4878:            jumpifnot (TREE_OPERAND (exp, 0), op0);
                   4879:            store_expr (TREE_OPERAND (exp, 1), temp, 0);
                   4880:            op1 = op0;
                   4881:          }
                   4882: #endif
                   4883:        /* Check for A op 0 ? A : FOO and A op 0 ? FOO : A where OP is any
                   4884:           comparison operator.  If we have one of these cases, set the
                   4885:           output to A, branch on A (cse will merge these two references),
                   4886:           then set the output to FOO.  */
                   4887:        else if (temp
                   4888:                 && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<'
                   4889:                 && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
                   4890:                 && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
                   4891:                                     TREE_OPERAND (exp, 1), 0)
                   4892:                 && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
                   4893:                 && safe_from_p (temp, TREE_OPERAND (exp, 2)))
                   4894:          {
                   4895:            if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
                   4896:              temp = gen_reg_rtx (mode);
                   4897:            store_expr (TREE_OPERAND (exp, 1), temp, 0);
                   4898:            jumpif (TREE_OPERAND (exp, 0), op0);
                   4899:            store_expr (TREE_OPERAND (exp, 2), temp, 0);
                   4900:            op1 = op0;
                   4901:          }
                   4902:        else if (temp
                   4903:                 && TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == '<'
                   4904:                 && integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
                   4905:                 && operand_equal_p (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
                   4906:                                     TREE_OPERAND (exp, 2), 0)
                   4907:                 && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
                   4908:                 && safe_from_p (temp, TREE_OPERAND (exp, 1)))
                   4909:          {
                   4910:            if (GET_CODE (temp) == REG && REGNO (temp) < FIRST_PSEUDO_REGISTER)
                   4911:              temp = gen_reg_rtx (mode);
                   4912:            store_expr (TREE_OPERAND (exp, 2), temp, 0);
                   4913:            jumpifnot (TREE_OPERAND (exp, 0), op0);
                   4914:            store_expr (TREE_OPERAND (exp, 1), temp, 0);
                   4915:            op1 = op0;
                   4916:          }
                   4917:        else
                   4918:          {
                   4919:            op1 = gen_label_rtx ();
                   4920:            jumpifnot (TREE_OPERAND (exp, 0), op0);
                   4921:            if (temp != 0)
                   4922:              store_expr (TREE_OPERAND (exp, 1), temp, 0);
                   4923:            else
1.1.1.4 ! root     4924:              expand_expr (TREE_OPERAND (exp, 1),
        !          4925:                           ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
1.1       root     4926:            if (cleanups_this_call)
                   4927:              {
                   4928:                sorry ("aggregate value in COND_EXPR");
                   4929:                cleanups_this_call = 0;
                   4930:              }
                   4931: 
                   4932:            emit_queue ();
                   4933:            emit_jump_insn (gen_jump (op1));
                   4934:            emit_barrier ();
                   4935:            emit_label (op0);
                   4936:            if (temp != 0)
                   4937:              store_expr (TREE_OPERAND (exp, 2), temp, 0);
                   4938:            else
1.1.1.4 ! root     4939:              expand_expr (TREE_OPERAND (exp, 2),
        !          4940:                           ignore ? const0_rtx : NULL_RTX, VOIDmode, 0);
1.1       root     4941:          }
                   4942: 
                   4943:        if (cleanups_this_call)
                   4944:          {
                   4945:            sorry ("aggregate value in COND_EXPR");
                   4946:            cleanups_this_call = 0;
                   4947:          }
                   4948: 
                   4949:        emit_queue ();
                   4950:        emit_label (op1);
                   4951:        OK_DEFER_POP;
                   4952:        cleanups_this_call = old_cleanups;
                   4953:        return temp;
                   4954:       }
                   4955: 
                   4956:     case TARGET_EXPR:
                   4957:       {
                   4958:        /* Something needs to be initialized, but we didn't know
                   4959:           where that thing was when building the tree.  For example,
                   4960:           it could be the return value of a function, or a parameter
                   4961:           to a function which lays down in the stack, or a temporary
                   4962:           variable which must be passed by reference.
                   4963: 
                   4964:           We guarantee that the expression will either be constructed
                   4965:           or copied into our original target.  */
                   4966: 
                   4967:        tree slot = TREE_OPERAND (exp, 0);
1.1.1.4 ! root     4968:        tree exp1;
1.1       root     4969: 
                   4970:        if (TREE_CODE (slot) != VAR_DECL)
                   4971:          abort ();
                   4972: 
                   4973:        if (target == 0)
                   4974:          {
                   4975:            if (DECL_RTL (slot) != 0)
1.1.1.4 ! root     4976:              {
        !          4977:                target = DECL_RTL (slot);
        !          4978:                /* If we have already expanded the slot, so don't do
        !          4979:                   it again.  (mrs)  */
        !          4980:                if (TREE_OPERAND (exp, 1) == NULL_TREE)
        !          4981:                  return target;
        !          4982:              }
1.1       root     4983:            else
                   4984:              {
                   4985:                target = assign_stack_temp (mode, int_size_in_bytes (type), 0);
                   4986:                /* All temp slots at this level must not conflict.  */
                   4987:                preserve_temp_slots (target);
                   4988:                DECL_RTL (slot) = target;
                   4989:              }
                   4990: 
                   4991: #if 0
1.1.1.4 ! root     4992:            /* I bet this needs to be done, and I bet that it needs to
        !          4993:               be above, inside the else clause.  The reason is
        !          4994:               simple, how else is it going to get cleaned up? (mrs)
        !          4995: 
        !          4996:               The reason is probably did not work before, and was
        !          4997:               commented out is because this was re-expanding already
        !          4998:               expanded target_exprs (target == 0 and DECL_RTL (slot)
        !          4999:               != 0) also cleaning them up many times as well.  :-( */
        !          5000: 
1.1       root     5001:            /* Since SLOT is not known to the called function
                   5002:               to belong to its stack frame, we must build an explicit
                   5003:               cleanup.  This case occurs when we must build up a reference
                   5004:               to pass the reference as an argument.  In this case,
                   5005:               it is very likely that such a reference need not be
                   5006:               built here.  */
                   5007: 
                   5008:            if (TREE_OPERAND (exp, 2) == 0)
                   5009:              TREE_OPERAND (exp, 2) = maybe_build_cleanup (slot);
                   5010:            if (TREE_OPERAND (exp, 2))
1.1.1.4 ! root     5011:              cleanups_this_call = tree_cons (NULL_TREE, TREE_OPERAND (exp, 2),
        !          5012:                                              cleanups_this_call);
1.1       root     5013: #endif
                   5014:          }
                   5015:        else
                   5016:          {
                   5017:            /* This case does occur, when expanding a parameter which
                   5018:               needs to be constructed on the stack.  The target
                   5019:               is the actual stack address that we want to initialize.
                   5020:               The function we call will perform the cleanup in this case.  */
                   5021: 
                   5022:            DECL_RTL (slot) = target;
                   5023:          }
                   5024: 
1.1.1.4 ! root     5025:        exp1 = TREE_OPERAND (exp, 1);
        !          5026:        /* Mark it as expanded.  */
        !          5027:        TREE_OPERAND (exp, 1) = NULL_TREE;
        !          5028: 
        !          5029:        return expand_expr (exp1, target, tmode, modifier);
1.1       root     5030:       }
                   5031: 
                   5032:     case INIT_EXPR:
                   5033:       {
                   5034:        tree lhs = TREE_OPERAND (exp, 0);
                   5035:        tree rhs = TREE_OPERAND (exp, 1);
                   5036:        tree noncopied_parts = 0;
                   5037:        tree lhs_type = TREE_TYPE (lhs);
                   5038: 
                   5039:        temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
                   5040:        if (TYPE_NONCOPIED_PARTS (lhs_type) != 0 && !fixed_type_p (rhs))
                   5041:          noncopied_parts = init_noncopied_parts (stabilize_reference (lhs),
                   5042:                                                  TYPE_NONCOPIED_PARTS (lhs_type));
                   5043:        while (noncopied_parts != 0)
                   5044:          {
                   5045:            expand_assignment (TREE_VALUE (noncopied_parts),
                   5046:                               TREE_PURPOSE (noncopied_parts), 0, 0);
                   5047:            noncopied_parts = TREE_CHAIN (noncopied_parts);
                   5048:          }
                   5049:        return temp;
                   5050:       }
                   5051: 
                   5052:     case MODIFY_EXPR:
                   5053:       {
                   5054:        /* If lhs is complex, expand calls in rhs before computing it.
                   5055:           That's so we don't compute a pointer and save it over a call.
                   5056:           If lhs is simple, compute it first so we can give it as a
                   5057:           target if the rhs is just a call.  This avoids an extra temp and copy
                   5058:           and that prevents a partial-subsumption which makes bad code.
                   5059:           Actually we could treat component_ref's of vars like vars.  */
                   5060: 
                   5061:        tree lhs = TREE_OPERAND (exp, 0);
                   5062:        tree rhs = TREE_OPERAND (exp, 1);
                   5063:        tree noncopied_parts = 0;
                   5064:        tree lhs_type = TREE_TYPE (lhs);
                   5065: 
                   5066:        temp = 0;
                   5067: 
                   5068:        if (TREE_CODE (lhs) != VAR_DECL
                   5069:            && TREE_CODE (lhs) != RESULT_DECL
                   5070:            && TREE_CODE (lhs) != PARM_DECL)
                   5071:          preexpand_calls (exp);
                   5072: 
                   5073:        /* Check for |= or &= of a bitfield of size one into another bitfield
                   5074:           of size 1.  In this case, (unless we need the result of the
                   5075:           assignment) we can do this more efficiently with a
                   5076:           test followed by an assignment, if necessary.
                   5077: 
                   5078:           ??? At this point, we can't get a BIT_FIELD_REF here.  But if
                   5079:           things change so we do, this code should be enhanced to
                   5080:           support it.  */
                   5081:        if (ignore
                   5082:            && TREE_CODE (lhs) == COMPONENT_REF
                   5083:            && (TREE_CODE (rhs) == BIT_IOR_EXPR
                   5084:                || TREE_CODE (rhs) == BIT_AND_EXPR)
                   5085:            && TREE_OPERAND (rhs, 0) == lhs
                   5086:            && TREE_CODE (TREE_OPERAND (rhs, 1)) == COMPONENT_REF
                   5087:            && TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (lhs, 1))) == 1
                   5088:            && TREE_INT_CST_LOW (DECL_SIZE (TREE_OPERAND (TREE_OPERAND (rhs, 1), 1))) == 1)
                   5089:          {
                   5090:            rtx label = gen_label_rtx ();
                   5091: 
                   5092:            do_jump (TREE_OPERAND (rhs, 1),
                   5093:                     TREE_CODE (rhs) == BIT_IOR_EXPR ? label : 0,
                   5094:                     TREE_CODE (rhs) == BIT_AND_EXPR ? label : 0);
                   5095:            expand_assignment (lhs, convert (TREE_TYPE (rhs),
                   5096:                                             (TREE_CODE (rhs) == BIT_IOR_EXPR
                   5097:                                              ? integer_one_node
                   5098:                                              : integer_zero_node)),
                   5099:                               0, 0);
1.1.1.3   root     5100:            do_pending_stack_adjust ();
1.1       root     5101:            emit_label (label);
                   5102:            return const0_rtx;
                   5103:          }
                   5104: 
                   5105:        if (TYPE_NONCOPIED_PARTS (lhs_type) != 0
                   5106:            && ! (fixed_type_p (lhs) && fixed_type_p (rhs)))
                   5107:          noncopied_parts = save_noncopied_parts (stabilize_reference (lhs),
                   5108:                                                  TYPE_NONCOPIED_PARTS (lhs_type));
                   5109: 
                   5110:        temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
                   5111:        while (noncopied_parts != 0)
                   5112:          {
                   5113:            expand_assignment (TREE_PURPOSE (noncopied_parts),
                   5114:                               TREE_VALUE (noncopied_parts), 0, 0);
                   5115:            noncopied_parts = TREE_CHAIN (noncopied_parts);
                   5116:          }
                   5117:        return temp;
                   5118:       }
                   5119: 
                   5120:     case PREINCREMENT_EXPR:
                   5121:     case PREDECREMENT_EXPR:
                   5122:       return expand_increment (exp, 0);
                   5123: 
                   5124:     case POSTINCREMENT_EXPR:
                   5125:     case POSTDECREMENT_EXPR:
                   5126:       /* Faster to treat as pre-increment if result is not used.  */
                   5127:       return expand_increment (exp, ! ignore);
                   5128: 
                   5129:     case ADDR_EXPR:
                   5130:       /* Are we taking the address of a nested function?  */
                   5131:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == FUNCTION_DECL
                   5132:          && decl_function_context (TREE_OPERAND (exp, 0)) != 0)
                   5133:        {
                   5134:          op0 = trampoline_address (TREE_OPERAND (exp, 0));
                   5135:          op0 = force_operand (op0, target);
                   5136:        }
                   5137:       else
                   5138:        {
1.1.1.4 ! root     5139:          op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode,
1.1       root     5140:                             (modifier == EXPAND_INITIALIZER
                   5141:                              ? modifier : EXPAND_CONST_ADDRESS));
                   5142:          if (GET_CODE (op0) != MEM)
                   5143:            abort ();
                   5144:   
                   5145:          if (modifier == EXPAND_SUM || modifier == EXPAND_INITIALIZER)
                   5146:            return XEXP (op0, 0);
                   5147:          op0 = force_operand (XEXP (op0, 0), target);
                   5148:        }
                   5149:       if (flag_force_addr && GET_CODE (op0) != REG)
                   5150:        return force_reg (Pmode, op0);
                   5151:       return op0;
                   5152: 
                   5153:     case ENTRY_VALUE_EXPR:
                   5154:       abort ();
                   5155: 
1.1.1.4 ! root     5156:     /* COMPLEX type for Extended Pascal & Fortran  */
        !          5157:     case COMPLEX_EXPR:
        !          5158:       {
        !          5159:        enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
        !          5160: 
        !          5161:        rtx prev;
        !          5162: 
        !          5163:        /* Get the rtx code of the operands.  */
        !          5164:        op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
        !          5165:        op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
        !          5166: 
        !          5167:        if (! target)
        !          5168:          target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
        !          5169: 
        !          5170:        prev = get_last_insn ();
        !          5171: 
        !          5172:        /* Tell flow that the whole of the destination is being set.  */
        !          5173:        if (GET_CODE (target) == REG)
        !          5174:          emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
        !          5175: 
        !          5176:        /* Move the real (op0) and imaginary (op1) parts to their location.  */
        !          5177:        emit_move_insn (gen_realpart (mode, target), op0);
        !          5178:        emit_move_insn (gen_imagpart (mode, target), op1);
        !          5179: 
        !          5180:        /* Complex construction should appear as a single unit.  */
        !          5181:        group_insns (prev);
        !          5182: 
        !          5183:        return target;
        !          5184:       }
        !          5185: 
        !          5186:     case REALPART_EXPR:
        !          5187:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
        !          5188:       return gen_realpart (mode, op0);
        !          5189:       
        !          5190:     case IMAGPART_EXPR:
        !          5191:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
        !          5192:       return gen_imagpart (mode, op0);
        !          5193: 
        !          5194:     case CONJ_EXPR:
        !          5195:       {
        !          5196:        enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
        !          5197:        rtx imag_t;
        !          5198:        rtx prev;
        !          5199:        
        !          5200:        op0  = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
        !          5201: 
        !          5202:        if (! target)
        !          5203:          target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
        !          5204:                                                                    
        !          5205:        prev = get_last_insn ();
        !          5206: 
        !          5207:        /* Tell flow that the whole of the destination is being set.  */
        !          5208:        if (GET_CODE (target) == REG)
        !          5209:          emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
        !          5210: 
        !          5211:        /* Store the realpart and the negated imagpart to target.  */
        !          5212:        emit_move_insn (gen_realpart (mode, target), gen_realpart (mode, op0));
        !          5213: 
        !          5214:        imag_t = gen_imagpart (mode, target);
        !          5215:        temp   = expand_unop (mode, neg_optab,
        !          5216:                              gen_imagpart (mode, op0), imag_t, 0);
        !          5217:        if (temp != imag_t)
        !          5218:          emit_move_insn (imag_t, temp);
        !          5219: 
        !          5220:        /* Conjugate should appear as a single unit */
        !          5221:        group_insns (prev);
        !          5222: 
        !          5223:        return target;
        !          5224:       }
        !          5225: 
1.1       root     5226:     case ERROR_MARK:
                   5227:       return const0_rtx;
                   5228: 
                   5229:     default:
                   5230:       return (*lang_expand_expr) (exp, target, tmode, modifier);
                   5231:     }
                   5232: 
                   5233:   /* Here to do an ordinary binary operator, generating an instruction
                   5234:      from the optab already placed in `this_optab'.  */
                   5235:  binop:
                   5236:   preexpand_calls (exp);
                   5237:   if (! safe_from_p (subtarget, TREE_OPERAND (exp, 1)))
                   5238:     subtarget = 0;
                   5239:   op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1.1.4 ! root     5240:   op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     5241:  binop2:
                   5242:   temp = expand_binop (mode, this_optab, op0, op1, target,
                   5243:                       unsignedp, OPTAB_LIB_WIDEN);
                   5244:   if (temp == 0)
                   5245:     abort ();
                   5246:   return temp;
                   5247: }
                   5248: 
1.1.1.2   root     5249: /* Return the alignment in bits of EXP, a pointer valued expression.
                   5250:    But don't return more than MAX_ALIGN no matter what.
1.1       root     5251:    The alignment returned is, by default, the alignment of the thing that
                   5252:    EXP points to (if it is not a POINTER_TYPE, 0 is returned).
                   5253: 
                   5254:    Otherwise, look at the expression to see if we can do better, i.e., if the
                   5255:    expression is actually pointing at an object whose alignment is tighter.  */
                   5256: 
                   5257: static int
                   5258: get_pointer_alignment (exp, max_align)
                   5259:      tree exp;
                   5260:      unsigned max_align;
                   5261: {
                   5262:   unsigned align, inner;
                   5263: 
                   5264:   if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
                   5265:     return 0;
                   5266: 
                   5267:   align = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
                   5268:   align = MIN (align, max_align);
                   5269: 
                   5270:   while (1)
                   5271:     {
                   5272:       switch (TREE_CODE (exp))
                   5273:        {
                   5274:        case NOP_EXPR:
                   5275:        case CONVERT_EXPR:
                   5276:        case NON_LVALUE_EXPR:
                   5277:          exp = TREE_OPERAND (exp, 0);
                   5278:          if (TREE_CODE (TREE_TYPE (exp)) != POINTER_TYPE)
                   5279:            return align;
                   5280:          inner = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (exp)));
                   5281:          inner = MIN (inner, max_align);
                   5282:          align = MAX (align, inner);
                   5283:          break;
                   5284: 
                   5285:        case PLUS_EXPR:
                   5286:          /* If sum of pointer + int, restrict our maximum alignment to that
                   5287:             imposed by the integer.  If not, we can't do any better than
                   5288:             ALIGN.  */
                   5289:          if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST)
                   5290:            return align;
                   5291: 
1.1.1.2   root     5292:          while (((TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)) * BITS_PER_UNIT)
                   5293:                  & (max_align - 1))
                   5294:                 != 0)
1.1       root     5295:            max_align >>= 1;
                   5296: 
                   5297:          exp = TREE_OPERAND (exp, 0);
                   5298:          break;
                   5299: 
                   5300:        case ADDR_EXPR:
                   5301:          /* See what we are pointing at and look at its alignment.  */
                   5302:          exp = TREE_OPERAND (exp, 0);
1.1.1.3   root     5303:          if (TREE_CODE (exp) == FUNCTION_DECL)
                   5304:            align = MAX (align, FUNCTION_BOUNDARY);
                   5305:          else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'd')
1.1       root     5306:            align = MAX (align, DECL_ALIGN (exp));
                   5307: #ifdef CONSTANT_ALIGNMENT
                   5308:          else if (TREE_CODE_CLASS (TREE_CODE (exp)) == 'c')
                   5309:            align = CONSTANT_ALIGNMENT (exp, align);
                   5310: #endif
                   5311:          return MIN (align, max_align);
                   5312: 
                   5313:        default:
                   5314:          return align;
                   5315:        }
                   5316:     }
                   5317: }
                   5318: 
                   5319: /* Return the tree node and offset if a given argument corresponds to
                   5320:    a string constant.  */
                   5321: 
                   5322: static tree
                   5323: string_constant (arg, ptr_offset)
                   5324:      tree arg;
                   5325:      tree *ptr_offset;
                   5326: {
                   5327:   STRIP_NOPS (arg);
                   5328: 
                   5329:   if (TREE_CODE (arg) == ADDR_EXPR
                   5330:       && TREE_CODE (TREE_OPERAND (arg, 0)) == STRING_CST)
                   5331:     {
                   5332:       *ptr_offset = integer_zero_node;
                   5333:       return TREE_OPERAND (arg, 0);
                   5334:     }
                   5335:   else if (TREE_CODE (arg) == PLUS_EXPR)
                   5336:     {
                   5337:       tree arg0 = TREE_OPERAND (arg, 0);
                   5338:       tree arg1 = TREE_OPERAND (arg, 1);
                   5339: 
                   5340:       STRIP_NOPS (arg0);
                   5341:       STRIP_NOPS (arg1);
                   5342: 
                   5343:       if (TREE_CODE (arg0) == ADDR_EXPR
                   5344:          && TREE_CODE (TREE_OPERAND (arg0, 0)) == STRING_CST)
                   5345:        {
                   5346:          *ptr_offset = arg1;
                   5347:          return TREE_OPERAND (arg0, 0);
                   5348:        }
                   5349:       else if (TREE_CODE (arg1) == ADDR_EXPR
                   5350:               && TREE_CODE (TREE_OPERAND (arg1, 0)) == STRING_CST)
                   5351:        {
                   5352:          *ptr_offset = arg0;
                   5353:          return TREE_OPERAND (arg1, 0);
                   5354:        }
                   5355:     }
                   5356: 
                   5357:   return 0;
                   5358: }
                   5359: 
                   5360: /* Compute the length of a C string.  TREE_STRING_LENGTH is not the right
                   5361:    way, because it could contain a zero byte in the middle.
                   5362:    TREE_STRING_LENGTH is the size of the character array, not the string.
                   5363: 
                   5364:    Unfortunately, string_constant can't access the values of const char
                   5365:    arrays with initializers, so neither can we do so here.  */
                   5366: 
                   5367: static tree
                   5368: c_strlen (src)
                   5369:      tree src;
                   5370: {
                   5371:   tree offset_node;
                   5372:   int offset, max;
                   5373:   char *ptr;
                   5374: 
                   5375:   src = string_constant (src, &offset_node);
                   5376:   if (src == 0)
                   5377:     return 0;
                   5378:   max = TREE_STRING_LENGTH (src);
                   5379:   ptr = TREE_STRING_POINTER (src);
                   5380:   if (offset_node && TREE_CODE (offset_node) != INTEGER_CST)
                   5381:     {
                   5382:       /* If the string has an internal zero byte (e.g., "foo\0bar"), we can't
                   5383:         compute the offset to the following null if we don't know where to
                   5384:         start searching for it.  */
                   5385:       int i;
                   5386:       for (i = 0; i < max; i++)
                   5387:        if (ptr[i] == 0)
                   5388:          return 0;
                   5389:       /* We don't know the starting offset, but we do know that the string
                   5390:         has no internal zero bytes.  We can assume that the offset falls
                   5391:         within the bounds of the string; otherwise, the programmer deserves
                   5392:         what he gets.  Subtract the offset from the length of the string,
                   5393:         and return that.  */
                   5394:       /* This would perhaps not be valid if we were dealing with named
                   5395:          arrays in addition to literal string constants.  */
                   5396:       return size_binop (MINUS_EXPR, size_int (max), offset_node);
                   5397:     }
                   5398: 
                   5399:   /* We have a known offset into the string.  Start searching there for
                   5400:      a null character.  */
                   5401:   if (offset_node == 0)
                   5402:     offset = 0;
                   5403:   else
                   5404:     {
                   5405:       /* Did we get a long long offset?  If so, punt.  */
                   5406:       if (TREE_INT_CST_HIGH (offset_node) != 0)
                   5407:        return 0;
                   5408:       offset = TREE_INT_CST_LOW (offset_node);
                   5409:     }
                   5410:   /* If the offset is known to be out of bounds, warn, and call strlen at
                   5411:      runtime.  */
                   5412:   if (offset < 0 || offset > max)
                   5413:     {
                   5414:       warning ("offset outside bounds of constant string");
                   5415:       return 0;
                   5416:     }
                   5417:   /* Use strlen to search for the first zero byte.  Since any strings
                   5418:      constructed with build_string will have nulls appended, we win even
                   5419:      if we get handed something like (char[4])"abcd".
                   5420: 
                   5421:      Since OFFSET is our starting index into the string, no further
                   5422:      calculation is needed.  */
                   5423:   return size_int (strlen (ptr + offset));
                   5424: }
                   5425: 
                   5426: /* Expand an expression EXP that calls a built-in function,
                   5427:    with result going to TARGET if that's convenient
                   5428:    (and in mode MODE if that's convenient).
                   5429:    SUBTARGET may be used as the target for computing one of EXP's operands.
                   5430:    IGNORE is nonzero if the value is to be ignored.  */
                   5431: 
                   5432: static rtx
                   5433: expand_builtin (exp, target, subtarget, mode, ignore)
                   5434:      tree exp;
                   5435:      rtx target;
                   5436:      rtx subtarget;
                   5437:      enum machine_mode mode;
                   5438:      int ignore;
                   5439: {
                   5440:   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
                   5441:   tree arglist = TREE_OPERAND (exp, 1);
                   5442:   rtx op0;
1.1.1.4 ! root     5443:   rtx lab1, insns;
1.1       root     5444:   enum machine_mode value_mode = TYPE_MODE (TREE_TYPE (exp));
1.1.1.4 ! root     5445:   optab builtin_optab;
1.1       root     5446: 
                   5447:   switch (DECL_FUNCTION_CODE (fndecl))
                   5448:     {
                   5449:     case BUILT_IN_ABS:
                   5450:     case BUILT_IN_LABS:
                   5451:     case BUILT_IN_FABS:
                   5452:       /* build_function_call changes these into ABS_EXPR.  */
                   5453:       abort ();
                   5454: 
1.1.1.4 ! root     5455:     case BUILT_IN_SIN:
        !          5456:     case BUILT_IN_COS:
1.1.1.2   root     5457:     case BUILT_IN_FSQRT:
                   5458:       /* If not optimizing, call the library function.  */
1.1.1.3   root     5459:       if (! optimize)
1.1.1.2   root     5460:        break;
                   5461: 
                   5462:       if (arglist == 0
1.1.1.3   root     5463:          /* Arg could be wrong type if user redeclared this fcn wrong.  */
1.1.1.2   root     5464:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
1.1.1.3   root     5465:        return CONST0_RTX (TYPE_MODE (TREE_TYPE (exp)));
1.1.1.2   root     5466: 
1.1.1.3   root     5467:       /* Stabilize and compute the argument.  */
                   5468:       if (TREE_CODE (TREE_VALUE (arglist)) != VAR_DECL
                   5469:          && TREE_CODE (TREE_VALUE (arglist)) != PARM_DECL)
                   5470:        {
                   5471:          exp = copy_node (exp);
                   5472:          arglist = copy_node (arglist);
                   5473:          TREE_OPERAND (exp, 1) = arglist;
                   5474:          TREE_VALUE (arglist) = save_expr (TREE_VALUE (arglist));
                   5475:        }
1.1.1.2   root     5476:       op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
1.1.1.3   root     5477: 
                   5478:       /* Make a suitable register to place result in.  */
                   5479:       target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
                   5480: 
1.1.1.4 ! root     5481:       emit_queue ();
1.1.1.3   root     5482:       start_sequence ();
                   5483: 
1.1.1.4 ! root     5484:       switch (DECL_FUNCTION_CODE (fndecl))
        !          5485:        {
        !          5486:        case BUILT_IN_SIN:
        !          5487:          builtin_optab = sin_optab; break;
        !          5488:        case BUILT_IN_COS:
        !          5489:          builtin_optab = cos_optab; break;
        !          5490:        case BUILT_IN_FSQRT:
        !          5491:          builtin_optab = sqrt_optab; break;
        !          5492:        default:
        !          5493:          abort ();
1.1.1.3   root     5494:        }
                   5495: 
1.1.1.4 ! root     5496:       /* Compute into TARGET.
1.1.1.2   root     5497:         Set TARGET to wherever the result comes back.  */
                   5498:       target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
1.1.1.4 ! root     5499:                            builtin_optab, op0, target, 0);
1.1.1.3   root     5500: 
                   5501:       /* If we were unable to expand via the builtin, stop the
                   5502:         sequence (without outputting the insns) and break, causing
                   5503:         a call the the library function.  */
1.1.1.2   root     5504:       if (target == 0)
1.1.1.3   root     5505:        {
                   5506:          end_sequence ();
                   5507:          break;
                   5508:         }
1.1.1.2   root     5509: 
1.1.1.4 ! root     5510:       /* Check the results by default.  But if flag_fast_math is turned on,
        !          5511:         then assume sqrt will always be called with valid arguments.  */
        !          5512: 
        !          5513:       if (! flag_fast_math)
        !          5514:        {
        !          5515:          /* Don't define the builtin FP instructions
        !          5516:             if your machine is not IEEE.  */
        !          5517:          if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT)
        !          5518:            abort ();
        !          5519: 
        !          5520:          lab1 = gen_label_rtx ();
        !          5521: 
        !          5522:          /* Test the result; if it is NaN, set errno=EDOM because
        !          5523:             the argument was not in the domain.  */
        !          5524:          emit_cmp_insn (target, target, EQ, 0, GET_MODE (target), 0, 0);
        !          5525:          emit_jump_insn (gen_beq (lab1));
        !          5526: 
        !          5527: #if TARGET_EDOM
        !          5528:          {
        !          5529: #ifdef GEN_ERRNO_RTX
        !          5530:            rtx errno_rtx = GEN_ERRNO_RTX;
        !          5531: #else
        !          5532:            rtx errno_rtx
        !          5533:              = gen_rtx (MEM, word_mode, gen_rtx (SYMBOL_REF, Pmode, "*errno"));
        !          5534: #endif
        !          5535: 
        !          5536:            emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
        !          5537:          }
        !          5538: #else
        !          5539:          /* We can't set errno=EDOM directly; let the library call do it.
        !          5540:             Pop the arguments right away in case the call gets deleted. */
        !          5541:          NO_DEFER_POP;
        !          5542:          expand_call (exp, target, 0);
        !          5543:          OK_DEFER_POP;
        !          5544: #endif
        !          5545: 
        !          5546:          emit_label (lab1);
        !          5547:        }
1.1.1.2   root     5548: 
1.1.1.3   root     5549:       /* Output the entire sequence. */
                   5550:       insns = get_insns ();
                   5551:       end_sequence ();
                   5552:       emit_insns (insns);
                   5553:  
                   5554:       return target;
                   5555: 
1.1       root     5556:     case BUILT_IN_SAVEREGS:
                   5557:       /* Don't do __builtin_saveregs more than once in a function.
                   5558:         Save the result of the first call and reuse it.  */
                   5559:       if (saveregs_value != 0)
                   5560:        return saveregs_value;
                   5561:       {
                   5562:        /* When this function is called, it means that registers must be
                   5563:           saved on entry to this function.  So we migrate the
                   5564:           call to the first insn of this function.  */
                   5565:        rtx temp;
                   5566:        rtx seq;
                   5567:        rtx valreg, saved_valreg;
                   5568: 
                   5569:        /* Now really call the function.  `expand_call' does not call
                   5570:           expand_builtin, so there is no danger of infinite recursion here.  */
                   5571:        start_sequence ();
                   5572: 
                   5573: #ifdef EXPAND_BUILTIN_SAVEREGS
                   5574:        /* Do whatever the machine needs done in this case.  */
                   5575:        temp = EXPAND_BUILTIN_SAVEREGS (arglist);
                   5576: #else
                   5577:        /* The register where the function returns its value
                   5578:           is likely to have something else in it, such as an argument.
                   5579:           So preserve that register around the call.  */
                   5580:        if (value_mode != VOIDmode)
                   5581:          {
                   5582:            valreg = hard_libcall_value (value_mode);
                   5583:            saved_valreg = gen_reg_rtx (value_mode);
                   5584:            emit_move_insn (saved_valreg, valreg);
                   5585:          }
                   5586: 
                   5587:        /* Generate the call, putting the value in a pseudo.  */
                   5588:        temp = expand_call (exp, target, ignore);
                   5589: 
                   5590:        if (value_mode != VOIDmode)
                   5591:          emit_move_insn (valreg, saved_valreg);
                   5592: #endif
                   5593: 
                   5594:        seq = get_insns ();
                   5595:        end_sequence ();
                   5596: 
                   5597:        saveregs_value = temp;
                   5598: 
                   5599:        /* This won't work inside a SEQUENCE--it really has to be
                   5600:           at the start of the function.  */
                   5601:        if (in_sequence_p ())
                   5602:          {
                   5603:            /* Better to do this than to crash.  */
                   5604:            error ("`va_start' used within `({...})'");
                   5605:            return temp;
                   5606:          }
                   5607: 
                   5608:        /* Put the sequence after the NOTE that starts the function.  */
                   5609:        emit_insns_before (seq, NEXT_INSN (get_insns ()));
                   5610:        return temp;
                   5611:       }
                   5612: 
                   5613:       /* __builtin_args_info (N) returns word N of the arg space info
                   5614:         for the current function.  The number and meanings of words
                   5615:         is controlled by the definition of CUMULATIVE_ARGS.  */
                   5616:     case BUILT_IN_ARGS_INFO:
                   5617:       {
                   5618:        int nwords = sizeof (CUMULATIVE_ARGS) / sizeof (int);
                   5619:        int i;
                   5620:        int *word_ptr = (int *) &current_function_args_info;
                   5621:        tree type, elts, result;
                   5622: 
                   5623:        if (sizeof (CUMULATIVE_ARGS) % sizeof (int) != 0)
                   5624:          fatal ("CUMULATIVE_ARGS type defined badly; see %s, line %d",
                   5625:                 __FILE__, __LINE__);
                   5626: 
                   5627:        if (arglist != 0)
                   5628:          {
                   5629:            tree arg = TREE_VALUE (arglist);
                   5630:            if (TREE_CODE (arg) != INTEGER_CST)
                   5631:              error ("argument of __builtin_args_info must be constant");
                   5632:            else
                   5633:              {
                   5634:                int wordnum = TREE_INT_CST_LOW (arg);
                   5635: 
                   5636:                if (wordnum < 0 || wordnum >= nwords)
                   5637:                  error ("argument of __builtin_args_info out of range");
                   5638:                else
1.1.1.4 ! root     5639:                  return GEN_INT (word_ptr[wordnum]);
1.1       root     5640:              }
                   5641:          }
                   5642:        else
                   5643:          error ("missing argument in __builtin_args_info");
                   5644: 
                   5645:        return const0_rtx;
                   5646: 
                   5647: #if 0
                   5648:        for (i = 0; i < nwords; i++)
                   5649:          elts = tree_cons (NULL_TREE, build_int_2 (word_ptr[i], 0));
                   5650: 
                   5651:        type = build_array_type (integer_type_node,
                   5652:                                 build_index_type (build_int_2 (nwords, 0)));
                   5653:        result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (elts));
                   5654:        TREE_CONSTANT (result) = 1;
                   5655:        TREE_STATIC (result) = 1;
                   5656:        result = build (INDIRECT_REF, build_pointer_type (type), result);
                   5657:        TREE_CONSTANT (result) = 1;
1.1.1.4 ! root     5658:        return expand_expr (result, NULL_RTX, VOIDmode, 0);
1.1       root     5659: #endif
                   5660:       }
                   5661: 
                   5662:       /* Return the address of the first anonymous stack arg.  */
                   5663:     case BUILT_IN_NEXT_ARG:
                   5664:       {
                   5665:        tree fntype = TREE_TYPE (current_function_decl);
                   5666:        if (!(TYPE_ARG_TYPES (fntype) != 0
                   5667:              && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
                   5668:                  != void_type_node)))
                   5669:          {
                   5670:            error ("`va_start' used in function with fixed args");
                   5671:            return const0_rtx;
                   5672:          }
                   5673:       }
                   5674: 
                   5675:       return expand_binop (Pmode, add_optab,
                   5676:                           current_function_internal_arg_pointer,
                   5677:                           current_function_arg_offset_rtx,
1.1.1.4 ! root     5678:                           NULL_RTX, 0, OPTAB_LIB_WIDEN);
1.1       root     5679: 
                   5680:     case BUILT_IN_CLASSIFY_TYPE:
                   5681:       if (arglist != 0)
                   5682:        {
                   5683:          tree type = TREE_TYPE (TREE_VALUE (arglist));
                   5684:          enum tree_code code = TREE_CODE (type);
                   5685:          if (code == VOID_TYPE)
1.1.1.4 ! root     5686:            return GEN_INT (void_type_class);
1.1       root     5687:          if (code == INTEGER_TYPE)
1.1.1.4 ! root     5688:            return GEN_INT (integer_type_class);
1.1       root     5689:          if (code == CHAR_TYPE)
1.1.1.4 ! root     5690:            return GEN_INT (char_type_class);
1.1       root     5691:          if (code == ENUMERAL_TYPE)
1.1.1.4 ! root     5692:            return GEN_INT (enumeral_type_class);
1.1       root     5693:          if (code == BOOLEAN_TYPE)
1.1.1.4 ! root     5694:            return GEN_INT (boolean_type_class);
1.1       root     5695:          if (code == POINTER_TYPE)
1.1.1.4 ! root     5696:            return GEN_INT (pointer_type_class);
1.1       root     5697:          if (code == REFERENCE_TYPE)
1.1.1.4 ! root     5698:            return GEN_INT (reference_type_class);
1.1       root     5699:          if (code == OFFSET_TYPE)
1.1.1.4 ! root     5700:            return GEN_INT (offset_type_class);
1.1       root     5701:          if (code == REAL_TYPE)
1.1.1.4 ! root     5702:            return GEN_INT (real_type_class);
1.1       root     5703:          if (code == COMPLEX_TYPE)
1.1.1.4 ! root     5704:            return GEN_INT (complex_type_class);
1.1       root     5705:          if (code == FUNCTION_TYPE)
1.1.1.4 ! root     5706:            return GEN_INT (function_type_class);
1.1       root     5707:          if (code == METHOD_TYPE)
1.1.1.4 ! root     5708:            return GEN_INT (method_type_class);
1.1       root     5709:          if (code == RECORD_TYPE)
1.1.1.4 ! root     5710:            return GEN_INT (record_type_class);
1.1       root     5711:          if (code == UNION_TYPE)
1.1.1.4 ! root     5712:            return GEN_INT (union_type_class);
1.1       root     5713:          if (code == ARRAY_TYPE)
1.1.1.4 ! root     5714:            return GEN_INT (array_type_class);
1.1       root     5715:          if (code == STRING_TYPE)
1.1.1.4 ! root     5716:            return GEN_INT (string_type_class);
1.1       root     5717:          if (code == SET_TYPE)
1.1.1.4 ! root     5718:            return GEN_INT (set_type_class);
1.1       root     5719:          if (code == FILE_TYPE)
1.1.1.4 ! root     5720:            return GEN_INT (file_type_class);
1.1       root     5721:          if (code == LANG_TYPE)
1.1.1.4 ! root     5722:            return GEN_INT (lang_type_class);
1.1       root     5723:        }
1.1.1.4 ! root     5724:       return GEN_INT (no_type_class);
1.1       root     5725: 
                   5726:     case BUILT_IN_CONSTANT_P:
                   5727:       if (arglist == 0)
                   5728:        return const0_rtx;
                   5729:       else
1.1.1.4 ! root     5730:        return (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (arglist))) == 'c'
1.1       root     5731:                ? const1_rtx : const0_rtx);
                   5732: 
                   5733:     case BUILT_IN_FRAME_ADDRESS:
                   5734:       /* The argument must be a nonnegative integer constant.
                   5735:         It counts the number of frames to scan up the stack.
                   5736:         The value is the address of that frame.  */
                   5737:     case BUILT_IN_RETURN_ADDRESS:
                   5738:       /* The argument must be a nonnegative integer constant.
                   5739:         It counts the number of frames to scan up the stack.
                   5740:         The value is the return address saved in that frame.  */
                   5741:       if (arglist == 0)
                   5742:        /* Warning about missing arg was already issued.  */
                   5743:        return const0_rtx;
                   5744:       else if (TREE_CODE (TREE_VALUE (arglist)) != INTEGER_CST)
                   5745:        {
                   5746:          error ("invalid arg to __builtin_return_address");
                   5747:          return const0_rtx;
                   5748:        }
                   5749:       else if (tree_int_cst_lt (TREE_VALUE (arglist), integer_zero_node))
                   5750:        {
                   5751:          error ("invalid arg to __builtin_return_address");
                   5752:          return const0_rtx;
                   5753:        }
                   5754:       else
                   5755:        {
                   5756:          int count = TREE_INT_CST_LOW (TREE_VALUE (arglist)); 
                   5757:          rtx tem = frame_pointer_rtx;
                   5758:          int i;
                   5759: 
                   5760:          /* Scan back COUNT frames to the specified frame.  */
                   5761:          for (i = 0; i < count; i++)
                   5762:            {
                   5763:              /* Assume the dynamic chain pointer is in the word that
                   5764:                 the frame address points to, unless otherwise specified.  */
                   5765: #ifdef DYNAMIC_CHAIN_ADDRESS
                   5766:              tem = DYNAMIC_CHAIN_ADDRESS (tem);
                   5767: #endif
                   5768:              tem = memory_address (Pmode, tem);
                   5769:              tem = copy_to_reg (gen_rtx (MEM, Pmode, tem));
                   5770:            }
                   5771: 
                   5772:          /* For __builtin_frame_address, return what we've got.  */
                   5773:          if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FRAME_ADDRESS)
                   5774:            return tem;
                   5775: 
                   5776:          /* For __builtin_return_address,
                   5777:             Get the return address from that frame.  */
                   5778: #ifdef RETURN_ADDR_RTX
                   5779:          return RETURN_ADDR_RTX (count, tem);
                   5780: #else
                   5781:          tem = memory_address (Pmode,
                   5782:                                plus_constant (tem, GET_MODE_SIZE (Pmode)));
                   5783:          return copy_to_reg (gen_rtx (MEM, Pmode, tem));
                   5784: #endif
                   5785:        }
                   5786: 
                   5787:     case BUILT_IN_ALLOCA:
                   5788:       if (arglist == 0
                   5789:          /* Arg could be non-integer if user redeclared this fcn wrong.  */
                   5790:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
                   5791:        return const0_rtx;
                   5792:       current_function_calls_alloca = 1;
                   5793:       /* Compute the argument.  */
1.1.1.4 ! root     5794:       op0 = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0);
1.1       root     5795: 
                   5796:       /* Allocate the desired space.  */
1.1.1.3   root     5797:       target = allocate_dynamic_stack_space (op0, target, BITS_PER_UNIT);
1.1       root     5798: 
                   5799:       /* Record the new stack level for nonlocal gotos.  */
1.1.1.3   root     5800:       if (nonlocal_goto_handler_slot != 0)
1.1.1.4 ! root     5801:        emit_stack_save (SAVE_NONLOCAL, &nonlocal_goto_stack_level, NULL_RTX);
1.1       root     5802:       return target;
                   5803: 
                   5804:     case BUILT_IN_FFS:
                   5805:       /* If not optimizing, call the library function.  */
                   5806:       if (!optimize)
                   5807:        break;
                   5808: 
                   5809:       if (arglist == 0
                   5810:          /* Arg could be non-integer if user redeclared this fcn wrong.  */
                   5811:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
                   5812:        return const0_rtx;
                   5813: 
                   5814:       /* Compute the argument.  */
                   5815:       op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
                   5816:       /* Compute ffs, into TARGET if possible.
                   5817:         Set TARGET to wherever the result comes back.  */
                   5818:       target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
                   5819:                            ffs_optab, op0, target, 1);
                   5820:       if (target == 0)
                   5821:        abort ();
                   5822:       return target;
                   5823: 
                   5824:     case BUILT_IN_STRLEN:
                   5825:       /* If not optimizing, call the library function.  */
                   5826:       if (!optimize)
                   5827:        break;
                   5828: 
                   5829:       if (arglist == 0
                   5830:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   5831:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
                   5832:        return const0_rtx;
                   5833:       else
                   5834:        {
1.1.1.3   root     5835:          tree src = TREE_VALUE (arglist);
                   5836:          tree len = c_strlen (src);
1.1       root     5837: 
1.1.1.3   root     5838:          int align
                   5839:            = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
                   5840: 
                   5841:          rtx result, src_rtx, char_rtx;
                   5842:          enum machine_mode insn_mode = value_mode, char_mode;
                   5843:          enum insn_code icode;
                   5844: 
                   5845:          /* If the length is known, just return it. */
                   5846:          if (len != 0)
                   5847:            return expand_expr (len, target, mode, 0);
                   5848: 
                   5849:          /* If SRC is not a pointer type, don't do this operation inline. */
                   5850:          if (align == 0)
1.1       root     5851:            break;
1.1.1.3   root     5852: 
                   5853:          /* Call a function if we can't compute strlen in the right mode. */
                   5854: 
                   5855:          while (insn_mode != VOIDmode)
                   5856:            {
                   5857:              icode = strlen_optab->handlers[(int) insn_mode].insn_code;
                   5858:              if (icode != CODE_FOR_nothing)
                   5859:                break;
                   5860: 
                   5861:              insn_mode = GET_MODE_WIDER_MODE (insn_mode);
                   5862:            }
                   5863:          if (insn_mode == VOIDmode)
                   5864:            break;
                   5865: 
                   5866:          /* Make a place to write the result of the instruction.  */
                   5867:          result = target;
                   5868:          if (! (result != 0
                   5869:                 && GET_CODE (result) == REG
                   5870:                 && GET_MODE (result) == insn_mode
                   5871:                 && REGNO (result) >= FIRST_PSEUDO_REGISTER))
                   5872:            result = gen_reg_rtx (insn_mode);
                   5873: 
                   5874:          /* Make sure the operands are acceptable to the predicates.  */
                   5875: 
                   5876:          if (! (*insn_operand_predicate[(int)icode][0]) (result, insn_mode))
                   5877:            result = gen_reg_rtx (insn_mode);
                   5878: 
                   5879:          src_rtx = memory_address (BLKmode,
1.1.1.4 ! root     5880:                                    expand_expr (src, NULL_RTX, Pmode,
1.1.1.3   root     5881:                                                 EXPAND_NORMAL));
                   5882:          if (! (*insn_operand_predicate[(int)icode][1]) (src_rtx, Pmode))
                   5883:            src_rtx = copy_to_mode_reg (Pmode, src_rtx);
                   5884: 
                   5885:          char_rtx = const0_rtx;
                   5886:          char_mode = insn_operand_mode[(int)icode][2];
                   5887:          if (! (*insn_operand_predicate[(int)icode][2]) (char_rtx, char_mode))
                   5888:            char_rtx = copy_to_mode_reg (char_mode, char_rtx);
                   5889: 
                   5890:          emit_insn (GEN_FCN (icode) (result,
                   5891:                                      gen_rtx (MEM, BLKmode, src_rtx),
1.1.1.4 ! root     5892:                                      char_rtx, GEN_INT (align)));
1.1.1.3   root     5893: 
                   5894:          /* Return the value in the proper mode for this function.  */
                   5895:          if (GET_MODE (result) == value_mode)
                   5896:            return result;
                   5897:          else if (target != 0)
                   5898:            {
                   5899:              convert_move (target, result, 0);
                   5900:              return target;
                   5901:            }
                   5902:          else
                   5903:            return convert_to_mode (value_mode, result, 0);
1.1       root     5904:        }
                   5905: 
                   5906:     case BUILT_IN_STRCPY:
                   5907:       /* If not optimizing, call the library function.  */
                   5908:       if (!optimize)
                   5909:        break;
                   5910: 
                   5911:       if (arglist == 0
                   5912:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   5913:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
                   5914:          || TREE_CHAIN (arglist) == 0
                   5915:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE)
                   5916:        return const0_rtx;
                   5917:       else
                   5918:        {
                   5919:          tree len = c_strlen (TREE_VALUE (TREE_CHAIN (arglist)));
                   5920: 
                   5921:          if (len == 0)
                   5922:            break;
                   5923: 
                   5924:          len = size_binop (PLUS_EXPR, len, integer_one_node);
                   5925: 
1.1.1.4 ! root     5926:          chainon (arglist, build_tree_list (NULL_TREE, len));
1.1       root     5927:        }
                   5928: 
                   5929:       /* Drops in.  */
                   5930:     case BUILT_IN_MEMCPY:
                   5931:       /* If not optimizing, call the library function.  */
                   5932:       if (!optimize)
                   5933:        break;
                   5934: 
                   5935:       if (arglist == 0
                   5936:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   5937:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
                   5938:          || TREE_CHAIN (arglist) == 0
                   5939:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
                   5940:          || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
                   5941:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
                   5942:        return const0_rtx;
                   5943:       else
                   5944:        {
                   5945:          tree dest = TREE_VALUE (arglist);
                   5946:          tree src = TREE_VALUE (TREE_CHAIN (arglist));
                   5947:          tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
                   5948: 
                   5949:          int src_align
                   5950:            = get_pointer_alignment (src, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
                   5951:          int dest_align
                   5952:            = get_pointer_alignment (dest, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
                   5953:          rtx dest_rtx;
                   5954: 
                   5955:          /* If either SRC or DEST is not a pointer type, don't do
                   5956:             this operation in-line.  */
                   5957:          if (src_align == 0 || dest_align == 0)
                   5958:            {
                   5959:              if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRCPY)
                   5960:                TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
                   5961:              break;
                   5962:            }
                   5963: 
1.1.1.4 ! root     5964:          dest_rtx = expand_expr (dest, NULL_RTX, Pmode, EXPAND_NORMAL);
1.1       root     5965: 
                   5966:          /* Copy word part most expediently.  */
                   5967:          emit_block_move (gen_rtx (MEM, BLKmode,
                   5968:                                    memory_address (BLKmode, dest_rtx)),
                   5969:                           gen_rtx (MEM, BLKmode,
                   5970:                                    memory_address (BLKmode,
1.1.1.4 ! root     5971:                                                    expand_expr (src, NULL_RTX,
        !          5972:                                                                 Pmode,
1.1       root     5973:                                                                 EXPAND_NORMAL))),
1.1.1.4 ! root     5974:                           expand_expr (len, NULL_RTX, VOIDmode, 0),
1.1       root     5975:                           MIN (src_align, dest_align));
                   5976:          return dest_rtx;
                   5977:        }
                   5978: 
                   5979: /* These comparison functions need an instruction that returns an actual
                   5980:    index.  An ordinary compare that just sets the condition codes
                   5981:    is not enough.  */
                   5982: #ifdef HAVE_cmpstrsi
                   5983:     case BUILT_IN_STRCMP:
                   5984:       /* If not optimizing, call the library function.  */
                   5985:       if (!optimize)
                   5986:        break;
                   5987: 
                   5988:       if (arglist == 0
                   5989:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   5990:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
                   5991:          || TREE_CHAIN (arglist) == 0
                   5992:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE)
                   5993:        return const0_rtx;
                   5994:       else if (!HAVE_cmpstrsi)
                   5995:        break;
                   5996:       {
                   5997:        tree arg1 = TREE_VALUE (arglist);
                   5998:        tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
                   5999:        tree offset;
                   6000:        tree len, len2;
                   6001: 
                   6002:        len = c_strlen (arg1);
                   6003:        if (len)
                   6004:          len = size_binop (PLUS_EXPR, integer_one_node, len);
                   6005:        len2 = c_strlen (arg2);
                   6006:        if (len2)
                   6007:          len2 = size_binop (PLUS_EXPR, integer_one_node, len2);
                   6008: 
                   6009:        /* If we don't have a constant length for the first, use the length
                   6010:           of the second, if we know it.  We don't require a constant for
                   6011:           this case; some cost analysis could be done if both are available
                   6012:           but neither is constant.  For now, assume they're equally cheap.
                   6013: 
                   6014:           If both strings have constant lengths, use the smaller.  This
                   6015:           could arise if optimization results in strcpy being called with
                   6016:           two fixed strings, or if the code was machine-generated.  We should
                   6017:           add some code to the `memcmp' handler below to deal with such
                   6018:           situations, someday.  */
                   6019:        if (!len || TREE_CODE (len) != INTEGER_CST)
                   6020:          {
                   6021:            if (len2)
                   6022:              len = len2;
                   6023:            else if (len == 0)
                   6024:              break;
                   6025:          }
                   6026:        else if (len2 && TREE_CODE (len2) == INTEGER_CST)
                   6027:          {
                   6028:            if (tree_int_cst_lt (len2, len))
                   6029:              len = len2;
                   6030:          }
                   6031: 
1.1.1.4 ! root     6032:        chainon (arglist, build_tree_list (NULL_TREE, len));
1.1       root     6033:       }
                   6034: 
                   6035:       /* Drops in.  */
                   6036:     case BUILT_IN_MEMCMP:
                   6037:       /* If not optimizing, call the library function.  */
                   6038:       if (!optimize)
                   6039:        break;
                   6040: 
                   6041:       if (arglist == 0
                   6042:          /* Arg could be non-pointer if user redeclared this fcn wrong.  */
                   6043:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE
                   6044:          || TREE_CHAIN (arglist) == 0
                   6045:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (arglist)))) != POINTER_TYPE
                   6046:          || TREE_CHAIN (TREE_CHAIN (arglist)) == 0
                   6047:          || TREE_CODE (TREE_TYPE (TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))))) != INTEGER_TYPE)
                   6048:        return const0_rtx;
                   6049:       else if (!HAVE_cmpstrsi)
                   6050:        break;
                   6051:       {
                   6052:        tree arg1 = TREE_VALUE (arglist);
                   6053:        tree arg2 = TREE_VALUE (TREE_CHAIN (arglist));
                   6054:        tree len = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
                   6055:        rtx result;
                   6056: 
                   6057:        int arg1_align
                   6058:          = get_pointer_alignment (arg1, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
                   6059:        int arg2_align
                   6060:          = get_pointer_alignment (arg2, BIGGEST_ALIGNMENT) / BITS_PER_UNIT;
                   6061:        enum machine_mode insn_mode
                   6062:          = insn_operand_mode[(int) CODE_FOR_cmpstrsi][0];
                   6063: 
                   6064:        /* If we don't have POINTER_TYPE, call the function.  */
                   6065:        if (arg1_align == 0 || arg2_align == 0)
                   6066:          {
                   6067:            if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRCMP)
                   6068:              TREE_CHAIN (TREE_CHAIN (arglist)) = 0;
                   6069:            break;
                   6070:          }
                   6071: 
                   6072:        /* Make a place to write the result of the instruction.  */
                   6073:        result = target;
                   6074:        if (! (result != 0
                   6075:               && GET_CODE (result) == REG && GET_MODE (result) == insn_mode
                   6076:               && REGNO (result) >= FIRST_PSEUDO_REGISTER))
                   6077:          result = gen_reg_rtx (insn_mode);
                   6078: 
                   6079:        emit_insn (gen_cmpstrsi (result,
                   6080:                                 gen_rtx (MEM, BLKmode,
1.1.1.4 ! root     6081:                                          expand_expr (arg1, NULL_RTX, Pmode,
        !          6082:                                                       EXPAND_NORMAL)),
1.1       root     6083:                                 gen_rtx (MEM, BLKmode,
1.1.1.4 ! root     6084:                                          expand_expr (arg2, NULL_RTX, Pmode,
        !          6085:                                                       EXPAND_NORMAL)),
        !          6086:                                 expand_expr (len, NULL_RTX, VOIDmode, 0),
        !          6087:                                 GEN_INT (MIN (arg1_align, arg2_align))));
1.1       root     6088: 
                   6089:        /* Return the value in the proper mode for this function.  */
                   6090:        mode = TYPE_MODE (TREE_TYPE (exp));
                   6091:        if (GET_MODE (result) == mode)
                   6092:          return result;
                   6093:        else if (target != 0)
                   6094:          {
                   6095:            convert_move (target, result, 0);
                   6096:            return target;
                   6097:          }
                   6098:        else
                   6099:          return convert_to_mode (mode, result, 0);
                   6100:       }        
                   6101: #else
                   6102:     case BUILT_IN_STRCMP:
                   6103:     case BUILT_IN_MEMCMP:
                   6104:       break;
                   6105: #endif
                   6106: 
                   6107:     default:                   /* just do library call, if unknown builtin */
                   6108:       error ("built-in function %s not currently supported",
                   6109:             IDENTIFIER_POINTER (DECL_NAME (fndecl)));
                   6110:     }
                   6111: 
                   6112:   /* The switch statement above can drop through to cause the function
                   6113:      to be called normally.  */
                   6114: 
                   6115:   return expand_call (exp, target, ignore);
                   6116: }
                   6117: 
                   6118: /* Expand code for a post- or pre- increment or decrement
                   6119:    and return the RTX for the result.
                   6120:    POST is 1 for postinc/decrements and 0 for preinc/decrements.  */
                   6121: 
                   6122: static rtx
                   6123: expand_increment (exp, post)
                   6124:      register tree exp;
                   6125:      int post;
                   6126: {
                   6127:   register rtx op0, op1;
                   6128:   register rtx temp, value;
                   6129:   register tree incremented = TREE_OPERAND (exp, 0);
                   6130:   optab this_optab = add_optab;
                   6131:   int icode;
                   6132:   enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
                   6133:   int op0_is_copy = 0;
                   6134: 
                   6135:   /* Stabilize any component ref that might need to be
                   6136:      evaluated more than once below.  */
                   6137:   if (TREE_CODE (incremented) == BIT_FIELD_REF
                   6138:       || (TREE_CODE (incremented) == COMPONENT_REF
                   6139:          && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF
                   6140:              || DECL_BIT_FIELD (TREE_OPERAND (incremented, 1)))))
                   6141:     incremented = stabilize_reference (incremented);
                   6142: 
                   6143:   /* Compute the operands as RTX.
                   6144:      Note whether OP0 is the actual lvalue or a copy of it:
1.1.1.3   root     6145:      I believe it is a copy iff it is a register or subreg
1.1.1.4 ! root     6146:      and insns were generated in computing it.   */
        !          6147: 
1.1       root     6148:   temp = get_last_insn ();
1.1.1.4 ! root     6149:   op0 = expand_expr (incremented, NULL_RTX, VOIDmode, 0);
        !          6150: 
        !          6151:   /* If OP0 is a SUBREG made for a promoted variable, we cannot increment
        !          6152:      in place but intead must do sign- or zero-extension during assignment,
        !          6153:      so we copy it into a new register and let the code below use it as
        !          6154:      a copy.
        !          6155: 
        !          6156:      Note that we can safely modify this SUBREG since it is know not to be
        !          6157:      shared (it was made by the expand_expr call above).  */
        !          6158: 
        !          6159:   if (GET_CODE (op0) == SUBREG && SUBREG_PROMOTED_VAR_P (op0))
        !          6160:     SUBREG_REG (op0) = copy_to_reg (SUBREG_REG (op0));
        !          6161: 
1.1.1.3   root     6162:   op0_is_copy = ((GET_CODE (op0) == SUBREG || GET_CODE (op0) == REG)
                   6163:                 && temp != get_last_insn ());
1.1.1.4 ! root     6164:   op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     6165: 
                   6166:   /* Decide whether incrementing or decrementing.  */
                   6167:   if (TREE_CODE (exp) == POSTDECREMENT_EXPR
                   6168:       || TREE_CODE (exp) == PREDECREMENT_EXPR)
                   6169:     this_optab = sub_optab;
                   6170: 
                   6171:   /* If OP0 is not the actual lvalue, but rather a copy in a register,
                   6172:      then we cannot just increment OP0.  We must
                   6173:      therefore contrive to increment the original value.
                   6174:      Then we can return OP0 since it is a copy of the old value.  */
                   6175:   if (op0_is_copy)
                   6176:     {
                   6177:       /* This is the easiest way to increment the value wherever it is.
                   6178:         Problems with multiple evaluation of INCREMENTED
                   6179:         are prevented because either (1) it is a component_ref,
                   6180:         in which case it was stabilized above, or (2) it is an array_ref
                   6181:         with constant index in an array in a register, which is
                   6182:         safe to reevaluate.  */
                   6183:       tree newexp = build ((this_optab == add_optab
                   6184:                            ? PLUS_EXPR : MINUS_EXPR),
                   6185:                           TREE_TYPE (exp),
                   6186:                           incremented,
                   6187:                           TREE_OPERAND (exp, 1));
                   6188:       temp = expand_assignment (incremented, newexp, ! post, 0);
                   6189:       return post ? op0 : temp;
                   6190:     }
                   6191: 
                   6192:   /* Convert decrement by a constant into a negative increment.  */
                   6193:   if (this_optab == sub_optab
                   6194:       && GET_CODE (op1) == CONST_INT)
                   6195:     {
1.1.1.4 ! root     6196:       op1 = GEN_INT (- INTVAL (op1));
1.1       root     6197:       this_optab = add_optab;
                   6198:     }
                   6199: 
                   6200:   if (post)
                   6201:     {
                   6202:       /* We have a true reference to the value in OP0.
                   6203:         If there is an insn to add or subtract in this mode, queue it.  */
                   6204: 
                   6205: #if 0  /* Turned off to avoid making extra insn for indexed memref.  */
                   6206:       op0 = stabilize (op0);
                   6207: #endif
                   6208: 
                   6209:       icode = (int) this_optab->handlers[(int) mode].insn_code;
                   6210:       if (icode != (int) CODE_FOR_nothing
                   6211:          /* Make sure that OP0 is valid for operands 0 and 1
                   6212:             of the insn we want to queue.  */
                   6213:          && (*insn_operand_predicate[icode][0]) (op0, mode)
                   6214:          && (*insn_operand_predicate[icode][1]) (op0, mode))
                   6215:        {
                   6216:          if (! (*insn_operand_predicate[icode][2]) (op1, mode))
                   6217:            op1 = force_reg (mode, op1);
                   6218: 
                   6219:          return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1));
                   6220:        }
                   6221:     }
                   6222: 
                   6223:   /* Preincrement, or we can't increment with one simple insn.  */
                   6224:   if (post)
                   6225:     /* Save a copy of the value before inc or dec, to return it later.  */
                   6226:     temp = value = copy_to_reg (op0);
                   6227:   else
                   6228:     /* Arrange to return the incremented value.  */
                   6229:     /* Copy the rtx because expand_binop will protect from the queue,
                   6230:        and the results of that would be invalid for us to return
                   6231:        if our caller does emit_queue before using our result.  */
                   6232:     temp = copy_rtx (value = op0);
                   6233: 
                   6234:   /* Increment however we can.  */
                   6235:   op1 = expand_binop (mode, this_optab, value, op1, op0,
                   6236:                      TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
                   6237:   /* Make sure the value is stored into OP0.  */
                   6238:   if (op1 != op0)
                   6239:     emit_move_insn (op0, op1);
                   6240: 
                   6241:   return temp;
                   6242: }
                   6243: 
                   6244: /* Expand all function calls contained within EXP, innermost ones first.
                   6245:    But don't look within expressions that have sequence points.
                   6246:    For each CALL_EXPR, record the rtx for its value
                   6247:    in the CALL_EXPR_RTL field.  */
                   6248: 
                   6249: static void
                   6250: preexpand_calls (exp)
                   6251:      tree exp;
                   6252: {
                   6253:   register int nops, i;
                   6254:   int type = TREE_CODE_CLASS (TREE_CODE (exp));
                   6255: 
                   6256:   if (! do_preexpand_calls)
                   6257:     return;
                   6258: 
                   6259:   /* Only expressions and references can contain calls.  */
                   6260: 
                   6261:   if (type != 'e' && type != '<' && type != '1' && type != '2' && type != 'r')
                   6262:     return;
                   6263: 
                   6264:   switch (TREE_CODE (exp))
                   6265:     {
                   6266:     case CALL_EXPR:
                   6267:       /* Do nothing if already expanded.  */
                   6268:       if (CALL_EXPR_RTL (exp) != 0)
                   6269:        return;
                   6270: 
                   6271:       /* Do nothing to built-in functions.  */
                   6272:       if (TREE_CODE (TREE_OPERAND (exp, 0)) != ADDR_EXPR
                   6273:          || TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) != FUNCTION_DECL
                   6274:          || ! DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
1.1.1.4 ! root     6275:        CALL_EXPR_RTL (exp) = expand_call (exp, NULL_RTX, 0);
1.1       root     6276:       return;
                   6277: 
                   6278:     case COMPOUND_EXPR:
                   6279:     case COND_EXPR:
                   6280:     case TRUTH_ANDIF_EXPR:
                   6281:     case TRUTH_ORIF_EXPR:
                   6282:       /* If we find one of these, then we can be sure
                   6283:         the adjust will be done for it (since it makes jumps).
                   6284:         Do it now, so that if this is inside an argument
                   6285:         of a function, we don't get the stack adjustment
                   6286:         after some other args have already been pushed.  */
                   6287:       do_pending_stack_adjust ();
                   6288:       return;
                   6289: 
                   6290:     case BLOCK:
                   6291:     case RTL_EXPR:
                   6292:     case WITH_CLEANUP_EXPR:
                   6293:       return;
                   6294: 
                   6295:     case SAVE_EXPR:
                   6296:       if (SAVE_EXPR_RTL (exp) != 0)
                   6297:        return;
                   6298:     }
                   6299: 
                   6300:   nops = tree_code_length[(int) TREE_CODE (exp)];
                   6301:   for (i = 0; i < nops; i++)
                   6302:     if (TREE_OPERAND (exp, i) != 0)
                   6303:       {
                   6304:        type = TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, i)));
                   6305:        if (type == 'e' || type == '<' || type == '1' || type == '2'
                   6306:            || type == 'r')
                   6307:          preexpand_calls (TREE_OPERAND (exp, i));
                   6308:       }
                   6309: }
                   6310: 
                   6311: /* At the start of a function, record that we have no previously-pushed
                   6312:    arguments waiting to be popped.  */
                   6313: 
                   6314: void
                   6315: init_pending_stack_adjust ()
                   6316: {
                   6317:   pending_stack_adjust = 0;
                   6318: }
                   6319: 
                   6320: /* When exiting from function, if safe, clear out any pending stack adjust
                   6321:    so the adjustment won't get done.  */
                   6322: 
                   6323: void
                   6324: clear_pending_stack_adjust ()
                   6325: {
                   6326: #ifdef EXIT_IGNORE_STACK
1.1.1.2   root     6327:   if (! flag_omit_frame_pointer && EXIT_IGNORE_STACK
1.1.1.4 ! root     6328:       && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)
1.1       root     6329:       && ! flag_inline_functions)
                   6330:     pending_stack_adjust = 0;
                   6331: #endif
                   6332: }
                   6333: 
                   6334: /* Pop any previously-pushed arguments that have not been popped yet.  */
                   6335: 
                   6336: void
                   6337: do_pending_stack_adjust ()
                   6338: {
                   6339:   if (inhibit_defer_pop == 0)
                   6340:     {
                   6341:       if (pending_stack_adjust != 0)
1.1.1.4 ! root     6342:        adjust_stack (GEN_INT (pending_stack_adjust));
1.1       root     6343:       pending_stack_adjust = 0;
                   6344:     }
                   6345: }
                   6346: 
                   6347: /* Expand all cleanups up to OLD_CLEANUPS.
                   6348:    Needed here, and also for language-dependent calls.  */
                   6349: 
                   6350: void
                   6351: expand_cleanups_to (old_cleanups)
                   6352:      tree old_cleanups;
                   6353: {
                   6354:   while (cleanups_this_call != old_cleanups)
                   6355:     {
1.1.1.4 ! root     6356:       expand_expr (TREE_VALUE (cleanups_this_call), NULL_RTX, VOIDmode, 0);
1.1       root     6357:       cleanups_this_call = TREE_CHAIN (cleanups_this_call);
                   6358:     }
                   6359: }
                   6360: 
                   6361: /* Expand conditional expressions.  */
                   6362: 
                   6363: /* Generate code to evaluate EXP and jump to LABEL if the value is zero.
                   6364:    LABEL is an rtx of code CODE_LABEL, in this function and all the
                   6365:    functions here.  */
                   6366: 
                   6367: void
                   6368: jumpifnot (exp, label)
                   6369:      tree exp;
                   6370:      rtx label;
                   6371: {
1.1.1.4 ! root     6372:   do_jump (exp, label, NULL_RTX);
1.1       root     6373: }
                   6374: 
                   6375: /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero.  */
                   6376: 
                   6377: void
                   6378: jumpif (exp, label)
                   6379:      tree exp;
                   6380:      rtx label;
                   6381: {
1.1.1.4 ! root     6382:   do_jump (exp, NULL_RTX, label);
1.1       root     6383: }
                   6384: 
                   6385: /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
                   6386:    the result is zero, or IF_TRUE_LABEL if the result is one.
                   6387:    Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero,
                   6388:    meaning fall through in that case.
                   6389: 
1.1.1.3   root     6390:    do_jump always does any pending stack adjust except when it does not
                   6391:    actually perform a jump.  An example where there is no jump
                   6392:    is when EXP is `(foo (), 0)' and IF_FALSE_LABEL is null.
                   6393: 
1.1       root     6394:    This function is responsible for optimizing cases such as
                   6395:    &&, || and comparison operators in EXP.  */
                   6396: 
                   6397: void
                   6398: do_jump (exp, if_false_label, if_true_label)
                   6399:      tree exp;
                   6400:      rtx if_false_label, if_true_label;
                   6401: {
                   6402:   register enum tree_code code = TREE_CODE (exp);
                   6403:   /* Some cases need to create a label to jump to
                   6404:      in order to properly fall through.
                   6405:      These cases set DROP_THROUGH_LABEL nonzero.  */
                   6406:   rtx drop_through_label = 0;
                   6407:   rtx temp;
                   6408:   rtx comparison = 0;
                   6409:   int i;
                   6410:   tree type;
                   6411: 
                   6412:   emit_queue ();
                   6413: 
                   6414:   switch (code)
                   6415:     {
                   6416:     case ERROR_MARK:
                   6417:       break;
                   6418: 
                   6419:     case INTEGER_CST:
                   6420:       temp = integer_zerop (exp) ? if_false_label : if_true_label;
                   6421:       if (temp)
                   6422:        emit_jump (temp);
                   6423:       break;
                   6424: 
                   6425: #if 0
                   6426:       /* This is not true with #pragma weak  */
                   6427:     case ADDR_EXPR:
                   6428:       /* The address of something can never be zero.  */
                   6429:       if (if_true_label)
                   6430:        emit_jump (if_true_label);
                   6431:       break;
                   6432: #endif
                   6433: 
                   6434:     case NOP_EXPR:
                   6435:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
                   6436:          || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
                   6437:          || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF)
                   6438:        goto normal;
                   6439:     case CONVERT_EXPR:
                   6440:       /* If we are narrowing the operand, we have to do the compare in the
                   6441:         narrower mode.  */
                   6442:       if ((TYPE_PRECISION (TREE_TYPE (exp))
                   6443:           < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   6444:        goto normal;
                   6445:     case NON_LVALUE_EXPR:
                   6446:     case REFERENCE_EXPR:
                   6447:     case ABS_EXPR:
                   6448:     case NEGATE_EXPR:
                   6449:     case LROTATE_EXPR:
                   6450:     case RROTATE_EXPR:
                   6451:       /* These cannot change zero->non-zero or vice versa.  */
                   6452:       do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
                   6453:       break;
                   6454: 
                   6455: #if 0
                   6456:       /* This is never less insns than evaluating the PLUS_EXPR followed by
                   6457:         a test and can be longer if the test is eliminated.  */
                   6458:     case PLUS_EXPR:
                   6459:       /* Reduce to minus.  */
                   6460:       exp = build (MINUS_EXPR, TREE_TYPE (exp),
                   6461:                   TREE_OPERAND (exp, 0),
                   6462:                   fold (build1 (NEGATE_EXPR, TREE_TYPE (TREE_OPERAND (exp, 1)),
                   6463:                                 TREE_OPERAND (exp, 1))));
                   6464:       /* Process as MINUS.  */
                   6465: #endif
                   6466: 
                   6467:     case MINUS_EXPR:
                   6468:       /* Non-zero iff operands of minus differ.  */
                   6469:       comparison = compare (build (NE_EXPR, TREE_TYPE (exp),
                   6470:                                   TREE_OPERAND (exp, 0),
                   6471:                                   TREE_OPERAND (exp, 1)),
                   6472:                            NE, NE);
                   6473:       break;
                   6474: 
                   6475:     case BIT_AND_EXPR:
                   6476:       /* If we are AND'ing with a small constant, do this comparison in the
                   6477:         smallest type that fits.  If the machine doesn't have comparisons
                   6478:         that small, it will be converted back to the wider comparison.
                   6479:         This helps if we are testing the sign bit of a narrower object.
                   6480:         combine can't do this for us because it can't know whether a
                   6481:         ZERO_EXTRACT or a compare in a smaller mode exists, but we do.  */
                   6482: 
1.1.1.4 ! root     6483:       if (! SLOW_BYTE_ACCESS
        !          6484:          && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
        !          6485:          && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
1.1       root     6486:          && (i = floor_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))) >= 0
                   6487:          && (type = type_for_size (i + 1, 1)) != 0
1.1.1.4 ! root     6488:          && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
        !          6489:          && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
        !          6490:              != CODE_FOR_nothing))
1.1       root     6491:        {
                   6492:          do_jump (convert (type, exp), if_false_label, if_true_label);
                   6493:          break;
                   6494:        }
                   6495:       goto normal;
                   6496: 
                   6497:     case TRUTH_NOT_EXPR:
                   6498:       do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
                   6499:       break;
                   6500: 
                   6501:     case TRUTH_ANDIF_EXPR:
                   6502:       if (if_false_label == 0)
                   6503:        if_false_label = drop_through_label = gen_label_rtx ();
1.1.1.4 ! root     6504:       do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX);
1.1       root     6505:       do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
                   6506:       break;
                   6507: 
                   6508:     case TRUTH_ORIF_EXPR:
                   6509:       if (if_true_label == 0)
                   6510:        if_true_label = drop_through_label = gen_label_rtx ();
1.1.1.4 ! root     6511:       do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label);
1.1       root     6512:       do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
                   6513:       break;
                   6514: 
                   6515:     case COMPOUND_EXPR:
                   6516:       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
                   6517:       free_temp_slots ();
                   6518:       emit_queue ();
1.1.1.3   root     6519:       do_pending_stack_adjust ();
1.1       root     6520:       do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
                   6521:       break;
                   6522: 
                   6523:     case COMPONENT_REF:
                   6524:     case BIT_FIELD_REF:
                   6525:     case ARRAY_REF:
                   6526:       {
                   6527:        int bitsize, bitpos, unsignedp;
                   6528:        enum machine_mode mode;
                   6529:        tree type;
1.1.1.3   root     6530:        tree offset;
1.1       root     6531:        int volatilep = 0;
                   6532: 
                   6533:        /* Get description of this reference.  We don't actually care
                   6534:           about the underlying object here.  */
1.1.1.3   root     6535:        get_inner_reference (exp, &bitsize, &bitpos, &offset,
                   6536:                             &mode, &unsignedp, &volatilep);
1.1       root     6537: 
                   6538:        type = type_for_size (bitsize, unsignedp);
1.1.1.4 ! root     6539:        if (! SLOW_BYTE_ACCESS
        !          6540:            && type != 0 && bitsize >= 0
        !          6541:            && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
        !          6542:            && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
        !          6543:                != CODE_FOR_nothing))
1.1       root     6544:          {
                   6545:            do_jump (convert (type, exp), if_false_label, if_true_label);
                   6546:            break;
                   6547:          }
                   6548:        goto normal;
                   6549:       }
                   6550: 
                   6551:     case COND_EXPR:
                   6552:       /* Do (a ? 1 : 0) and (a ? 0 : 1) as special cases.  */
                   6553:       if (integer_onep (TREE_OPERAND (exp, 1))
                   6554:          && integer_zerop (TREE_OPERAND (exp, 2)))
                   6555:        do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
                   6556: 
                   6557:       else if (integer_zerop (TREE_OPERAND (exp, 1))
                   6558:               && integer_onep (TREE_OPERAND (exp, 2)))
                   6559:        do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
                   6560: 
                   6561:       else
                   6562:        {
                   6563:          register rtx label1 = gen_label_rtx ();
                   6564:          drop_through_label = gen_label_rtx ();
1.1.1.4 ! root     6565:          do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX);
1.1       root     6566:          /* Now the THEN-expression.  */
                   6567:          do_jump (TREE_OPERAND (exp, 1),
                   6568:                   if_false_label ? if_false_label : drop_through_label,
                   6569:                   if_true_label ? if_true_label : drop_through_label);
1.1.1.3   root     6570:          /* In case the do_jump just above never jumps.  */
                   6571:          do_pending_stack_adjust ();
1.1       root     6572:          emit_label (label1);
                   6573:          /* Now the ELSE-expression.  */
                   6574:          do_jump (TREE_OPERAND (exp, 2),
                   6575:                   if_false_label ? if_false_label : drop_through_label,
                   6576:                   if_true_label ? if_true_label : drop_through_label);
                   6577:        }
                   6578:       break;
                   6579: 
                   6580:     case EQ_EXPR:
                   6581:       if (integer_zerop (TREE_OPERAND (exp, 1)))
                   6582:        do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
                   6583:       else if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   6584:                == MODE_INT)
                   6585:               && 
                   6586:               !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   6587:        do_jump_by_parts_equality (exp, if_false_label, if_true_label);
                   6588:       else
                   6589:        comparison = compare (exp, EQ, EQ);
                   6590:       break;
                   6591: 
                   6592:     case NE_EXPR:
                   6593:       if (integer_zerop (TREE_OPERAND (exp, 1)))
                   6594:        do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
                   6595:       else if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   6596:                == MODE_INT)
                   6597:               && 
                   6598:               !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   6599:        do_jump_by_parts_equality (exp, if_true_label, if_false_label);
                   6600:       else
                   6601:        comparison = compare (exp, NE, NE);
                   6602:       break;
                   6603: 
                   6604:     case LT_EXPR:
                   6605:       if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   6606:           == MODE_INT)
                   6607:          && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   6608:        do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label);
                   6609:       else
                   6610:        comparison = compare (exp, LT, LTU);
                   6611:       break;
                   6612: 
                   6613:     case LE_EXPR:
                   6614:       if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   6615:           == MODE_INT)
                   6616:          && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   6617:        do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label);
                   6618:       else
                   6619:        comparison = compare (exp, LE, LEU);
                   6620:       break;
                   6621: 
                   6622:     case GT_EXPR:
                   6623:       if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   6624:           == MODE_INT)
                   6625:          && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   6626:        do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label);
                   6627:       else
                   6628:        comparison = compare (exp, GT, GTU);
                   6629:       break;
                   6630: 
                   6631:     case GE_EXPR:
                   6632:       if ((GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   6633:           == MODE_INT)
                   6634:          && !can_compare_p (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
                   6635:        do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label);
                   6636:       else
                   6637:        comparison = compare (exp, GE, GEU);
                   6638:       break;
                   6639: 
                   6640:     default:
                   6641:     normal:
1.1.1.4 ! root     6642:       temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);
1.1       root     6643: #if 0
                   6644:       /* This is not needed any more and causes poor code since it causes
                   6645:         comparisons and tests from non-SI objects to have different code
                   6646:         sequences.  */
                   6647:       /* Copy to register to avoid generating bad insns by cse
                   6648:         from (set (mem ...) (arithop))  (set (cc0) (mem ...)).  */
                   6649:       if (!cse_not_expected && GET_CODE (temp) == MEM)
                   6650:        temp = copy_to_reg (temp);
                   6651: #endif
                   6652:       do_pending_stack_adjust ();
                   6653:       if (GET_CODE (temp) == CONST_INT)
                   6654:        comparison = (temp == const0_rtx ? const0_rtx : const_true_rtx);
                   6655:       else if (GET_CODE (temp) == LABEL_REF)
                   6656:        comparison = const_true_rtx;
                   6657:       else if (GET_MODE_CLASS (GET_MODE (temp)) == MODE_INT
                   6658:               && !can_compare_p (GET_MODE (temp)))
                   6659:        /* Note swapping the labels gives us not-equal.  */
                   6660:        do_jump_by_parts_equality_rtx (temp, if_true_label, if_false_label);
                   6661:       else if (GET_MODE (temp) != VOIDmode)
                   6662:        comparison = compare_from_rtx (temp, CONST0_RTX (GET_MODE (temp)),
1.1.1.4 ! root     6663:                                       NE, TREE_UNSIGNED (TREE_TYPE (exp)),
        !          6664:                                       GET_MODE (temp), NULL_RTX, 0);
1.1       root     6665:       else
                   6666:        abort ();
                   6667:     }
                   6668: 
                   6669:   /* Do any postincrements in the expression that was tested.  */
                   6670:   emit_queue ();
                   6671: 
                   6672:   /* If COMPARISON is nonzero here, it is an rtx that can be substituted
                   6673:      straight into a conditional jump instruction as the jump condition.
                   6674:      Otherwise, all the work has been done already.  */
                   6675: 
                   6676:   if (comparison == const_true_rtx)
                   6677:     {
                   6678:       if (if_true_label)
                   6679:        emit_jump (if_true_label);
                   6680:     }
                   6681:   else if (comparison == const0_rtx)
                   6682:     {
                   6683:       if (if_false_label)
                   6684:        emit_jump (if_false_label);
                   6685:     }
                   6686:   else if (comparison)
                   6687:     do_jump_for_compare (comparison, if_false_label, if_true_label);
                   6688: 
                   6689:   free_temp_slots ();
                   6690: 
                   6691:   if (drop_through_label)
1.1.1.3   root     6692:     {
                   6693:       /* If do_jump produces code that might be jumped around,
                   6694:         do any stack adjusts from that code, before the place
                   6695:         where control merges in.  */
                   6696:       do_pending_stack_adjust ();
                   6697:       emit_label (drop_through_label);
                   6698:     }
1.1       root     6699: }
                   6700: 
                   6701: /* Given a comparison expression EXP for values too wide to be compared
                   6702:    with one insn, test the comparison and jump to the appropriate label.
                   6703:    The code of EXP is ignored; we always test GT if SWAP is 0,
                   6704:    and LT if SWAP is 1.  */
                   6705: 
                   6706: static void
                   6707: do_jump_by_parts_greater (exp, swap, if_false_label, if_true_label)
                   6708:      tree exp;
                   6709:      int swap;
                   6710:      rtx if_false_label, if_true_label;
                   6711: {
1.1.1.4 ! root     6712:   rtx op0 = expand_expr (TREE_OPERAND (exp, swap), NULL_RTX, VOIDmode, 0);
        !          6713:   rtx op1 = expand_expr (TREE_OPERAND (exp, !swap), NULL_RTX, VOIDmode, 0);
1.1       root     6714:   enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
                   6715:   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
                   6716:   rtx drop_through_label = 0;
                   6717:   int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));
                   6718:   int i;
                   6719: 
                   6720:   if (! if_true_label || ! if_false_label)
                   6721:     drop_through_label = gen_label_rtx ();
                   6722:   if (! if_true_label)
                   6723:     if_true_label = drop_through_label;
                   6724:   if (! if_false_label)
                   6725:     if_false_label = drop_through_label;
                   6726: 
                   6727:   /* Compare a word at a time, high order first.  */
                   6728:   for (i = 0; i < nwords; i++)
                   6729:     {
                   6730:       rtx comp;
                   6731:       rtx op0_word, op1_word;
                   6732: 
                   6733:       if (WORDS_BIG_ENDIAN)
                   6734:        {
                   6735:          op0_word = operand_subword_force (op0, i, mode);
                   6736:          op1_word = operand_subword_force (op1, i, mode);
                   6737:        }
                   6738:       else
                   6739:        {
                   6740:          op0_word = operand_subword_force (op0, nwords - 1 - i, mode);
                   6741:          op1_word = operand_subword_force (op1, nwords - 1 - i, mode);
                   6742:        }
                   6743: 
                   6744:       /* All but high-order word must be compared as unsigned.  */
                   6745:       comp = compare_from_rtx (op0_word, op1_word,
                   6746:                               (unsignedp || i > 0) ? GTU : GT,
1.1.1.4 ! root     6747:                               unsignedp, word_mode, NULL_RTX, 0);
1.1       root     6748:       if (comp == const_true_rtx)
                   6749:        emit_jump (if_true_label);
                   6750:       else if (comp != const0_rtx)
1.1.1.4 ! root     6751:        do_jump_for_compare (comp, NULL_RTX, if_true_label);
1.1       root     6752: 
                   6753:       /* Consider lower words only if these are equal.  */
                   6754:       comp = compare_from_rtx (op0_word, op1_word, NE, unsignedp, word_mode,
1.1.1.4 ! root     6755:                               NULL_RTX, 0);
1.1       root     6756:       if (comp == const_true_rtx)
                   6757:        emit_jump (if_false_label);
                   6758:       else if (comp != const0_rtx)
1.1.1.4 ! root     6759:        do_jump_for_compare (comp, NULL_RTX, if_false_label);
1.1       root     6760:     }
                   6761: 
                   6762:   if (if_false_label)
                   6763:     emit_jump (if_false_label);
                   6764:   if (drop_through_label)
                   6765:     emit_label (drop_through_label);
                   6766: }
                   6767: 
                   6768: /* Given an EQ_EXPR expression EXP for values too wide to be compared
                   6769:    with one insn, test the comparison and jump to the appropriate label.  */
                   6770: 
                   6771: static void
                   6772: do_jump_by_parts_equality (exp, if_false_label, if_true_label)
                   6773:      tree exp;
                   6774:      rtx if_false_label, if_true_label;
                   6775: {
1.1.1.4 ! root     6776:   rtx op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
        !          6777:   rtx op1 = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     6778:   enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
                   6779:   int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
                   6780:   int i;
                   6781:   rtx drop_through_label = 0;
                   6782: 
                   6783:   if (! if_false_label)
                   6784:     drop_through_label = if_false_label = gen_label_rtx ();
                   6785: 
                   6786:   for (i = 0; i < nwords; i++)
                   6787:     {
                   6788:       rtx comp = compare_from_rtx (operand_subword_force (op0, i, mode),
                   6789:                                   operand_subword_force (op1, i, mode),
1.1.1.4 ! root     6790:                                   EQ, TREE_UNSIGNED (TREE_TYPE (exp)),
        !          6791:                                   word_mode, NULL_RTX, 0);
1.1       root     6792:       if (comp == const_true_rtx)
                   6793:        emit_jump (if_false_label);
                   6794:       else if (comp != const0_rtx)
1.1.1.4 ! root     6795:        do_jump_for_compare (comp, if_false_label, NULL_RTX);
1.1       root     6796:     }
                   6797: 
                   6798:   if (if_true_label)
                   6799:     emit_jump (if_true_label);
                   6800:   if (drop_through_label)
                   6801:     emit_label (drop_through_label);
                   6802: }
                   6803: 
                   6804: /* Jump according to whether OP0 is 0.
                   6805:    We assume that OP0 has an integer mode that is too wide
                   6806:    for the available compare insns.  */
                   6807: 
                   6808: static void
                   6809: do_jump_by_parts_equality_rtx (op0, if_false_label, if_true_label)
                   6810:      rtx op0;
                   6811:      rtx if_false_label, if_true_label;
                   6812: {
                   6813:   int nwords = GET_MODE_SIZE (GET_MODE (op0)) / UNITS_PER_WORD;
                   6814:   int i;
                   6815:   rtx drop_through_label = 0;
                   6816: 
                   6817:   if (! if_false_label)
                   6818:     drop_through_label = if_false_label = gen_label_rtx ();
                   6819: 
                   6820:   for (i = 0; i < nwords; i++)
                   6821:     {
                   6822:       rtx comp = compare_from_rtx (operand_subword_force (op0, i,
                   6823:                                                          GET_MODE (op0)),
1.1.1.4 ! root     6824:                                   const0_rtx, EQ, 1, word_mode, NULL_RTX, 0);
1.1       root     6825:       if (comp == const_true_rtx)
                   6826:        emit_jump (if_false_label);
                   6827:       else if (comp != const0_rtx)
1.1.1.4 ! root     6828:        do_jump_for_compare (comp, if_false_label, NULL_RTX);
1.1       root     6829:     }
                   6830: 
                   6831:   if (if_true_label)
                   6832:     emit_jump (if_true_label);
                   6833:   if (drop_through_label)
                   6834:     emit_label (drop_through_label);
                   6835: }
                   6836: 
                   6837: /* Given a comparison expression in rtl form, output conditional branches to
                   6838:    IF_TRUE_LABEL, IF_FALSE_LABEL, or both.  */
                   6839: 
                   6840: static void
                   6841: do_jump_for_compare (comparison, if_false_label, if_true_label)
                   6842:      rtx comparison, if_false_label, if_true_label;
                   6843: {
                   6844:   if (if_true_label)
                   6845:     {
                   6846:       if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0)
                   6847:        emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_true_label));
                   6848:       else
                   6849:        abort ();
                   6850: 
                   6851:       if (if_false_label)
                   6852:        emit_jump (if_false_label);
                   6853:     }
                   6854:   else if (if_false_label)
                   6855:     {
                   6856:       rtx insn;
                   6857:       rtx prev = PREV_INSN (get_last_insn ());
                   6858:       rtx branch = 0;
                   6859: 
                   6860:       /* Output the branch with the opposite condition.  Then try to invert
                   6861:         what is generated.  If more than one insn is a branch, or if the
                   6862:         branch is not the last insn written, abort. If we can't invert
                   6863:         the branch, emit make a true label, redirect this jump to that,
                   6864:         emit a jump to the false label and define the true label.  */
                   6865: 
                   6866:       if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0)
                   6867:        emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_false_label));
                   6868:       else
                   6869:        abort ();
                   6870: 
                   6871:       /* Here we get the insn before what was just emitted.
                   6872:         On some machines, emitting the branch can discard
                   6873:         the previous compare insn and emit a replacement.  */
                   6874:       if (prev == 0)
                   6875:        /* If there's only one preceding insn...  */
                   6876:        insn = get_insns ();
                   6877:       else
                   6878:        insn = NEXT_INSN (prev);
                   6879: 
                   6880:       for (insn = NEXT_INSN (insn); insn; insn = NEXT_INSN (insn))
                   6881:        if (GET_CODE (insn) == JUMP_INSN)
                   6882:          {
                   6883:            if (branch)
                   6884:              abort ();
                   6885:            branch = insn;
                   6886:          }
                   6887: 
                   6888:       if (branch != get_last_insn ())
                   6889:        abort ();
                   6890: 
                   6891:       if (! invert_jump (branch, if_false_label))
                   6892:        {
                   6893:          if_true_label = gen_label_rtx ();
                   6894:          redirect_jump (branch, if_true_label);
                   6895:          emit_jump (if_false_label);
                   6896:          emit_label (if_true_label);
                   6897:        }
                   6898:     }
                   6899: }
                   6900: 
                   6901: /* Generate code for a comparison expression EXP
                   6902:    (including code to compute the values to be compared)
                   6903:    and set (CC0) according to the result.
                   6904:    SIGNED_CODE should be the rtx operation for this comparison for
                   6905:    signed data; UNSIGNED_CODE, likewise for use if data is unsigned.
                   6906: 
                   6907:    We force a stack adjustment unless there are currently
                   6908:    things pushed on the stack that aren't yet used.  */
                   6909: 
                   6910: static rtx
                   6911: compare (exp, signed_code, unsigned_code)
                   6912:      register tree exp;
                   6913:      enum rtx_code signed_code, unsigned_code;
                   6914: {
1.1.1.4 ! root     6915:   register rtx op0
        !          6916:     = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0);
        !          6917:   register rtx op1
        !          6918:     = expand_expr (TREE_OPERAND (exp, 1), NULL_RTX, VOIDmode, 0);
1.1       root     6919:   register tree type = TREE_TYPE (TREE_OPERAND (exp, 0));
                   6920:   register enum machine_mode mode = TYPE_MODE (type);
                   6921:   int unsignedp = TREE_UNSIGNED (type);
                   6922:   enum rtx_code code = unsignedp ? unsigned_code : signed_code;
                   6923: 
                   6924:   return compare_from_rtx (op0, op1, code, unsignedp, mode,
                   6925:                           ((mode == BLKmode)
1.1.1.4 ! root     6926:                            ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
1.1       root     6927:                           TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
                   6928: }
                   6929: 
                   6930: /* Like compare but expects the values to compare as two rtx's.
                   6931:    The decision as to signed or unsigned comparison must be made by the caller.
                   6932: 
                   6933:    If MODE is BLKmode, SIZE is an RTX giving the size of the objects being
                   6934:    compared.
                   6935: 
                   6936:    If ALIGN is non-zero, it is the alignment of this type; if zero, the
                   6937:    size of MODE should be used.  */
                   6938: 
                   6939: rtx
                   6940: compare_from_rtx (op0, op1, code, unsignedp, mode, size, align)
                   6941:      register rtx op0, op1;
                   6942:      enum rtx_code code;
                   6943:      int unsignedp;
                   6944:      enum machine_mode mode;
                   6945:      rtx size;
                   6946:      int align;
                   6947: {
                   6948:   /* If one operand is constant, make it the second one.  */
                   6949: 
                   6950:   if (GET_CODE (op0) == CONST_INT || GET_CODE (op0) == CONST_DOUBLE)
                   6951:     {
                   6952:       rtx tem = op0;
                   6953:       op0 = op1;
                   6954:       op1 = tem;
                   6955:       code = swap_condition (code);
                   6956:     }
                   6957: 
                   6958:   if (flag_force_mem)
                   6959:     {
                   6960:       op0 = force_not_mem (op0);
                   6961:       op1 = force_not_mem (op1);
                   6962:     }
                   6963: 
                   6964:   do_pending_stack_adjust ();
                   6965: 
                   6966:   if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT)
                   6967:     return simplify_relational_operation (code, mode, op0, op1);
                   6968: 
1.1.1.4 ! root     6969: #if 0
        !          6970:   /* There's no need to do this now that combine.c can eliminate lots of
        !          6971:      sign extensions.  This can be less efficient in certain cases on other
        !          6972:      machines.
        !          6973: 
1.1       root     6974:   /* If this is a signed equality comparison, we can do it as an
                   6975:      unsigned comparison since zero-extension is cheaper than sign
1.1.1.4 ! root     6976:      extension and comparisons with zero are done as unsigned.  This is
        !          6977:      the case even on machines that can do fast sign extension, since
        !          6978:      zero-extension is easier to combinen with other operations than
        !          6979:      sign-extension is.  If we are comparing against a constant, we must
        !          6980:      convert it to what it would look like unsigned.  */
1.1       root     6981:   if ((code == EQ || code == NE) && ! unsignedp
1.1.1.4 ! root     6982:       && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT)
1.1       root     6983:     {
                   6984:       if (GET_CODE (op1) == CONST_INT
                   6985:          && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1))
1.1.1.4 ! root     6986:        op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0)));
1.1       root     6987:       unsignedp = 1;
                   6988:     }
1.1.1.4 ! root     6989: #endif
1.1       root     6990:        
                   6991:   emit_cmp_insn (op0, op1, code, size, mode, unsignedp, align);
                   6992: 
                   6993:   return gen_rtx (code, VOIDmode, cc0_rtx, const0_rtx);
                   6994: }
                   6995: 
                   6996: /* Generate code to calculate EXP using a store-flag instruction
1.1.1.3   root     6997:    and return an rtx for the result.  EXP is either a comparison
                   6998:    or a TRUTH_NOT_EXPR whose operand is a comparison.
                   6999: 
1.1       root     7000:    If TARGET is nonzero, store the result there if convenient.
                   7001: 
                   7002:    If ONLY_CHEAP is non-zero, only do this if it is likely to be very
                   7003:    cheap.
                   7004: 
                   7005:    Return zero if there is no suitable set-flag instruction
                   7006:    available on this machine.
                   7007: 
                   7008:    Once expand_expr has been called on the arguments of the comparison,
                   7009:    we are committed to doing the store flag, since it is not safe to
                   7010:    re-evaluate the expression.  We emit the store-flag insn by calling
                   7011:    emit_store_flag, but only expand the arguments if we have a reason
                   7012:    to believe that emit_store_flag will be successful.  If we think that
                   7013:    it will, but it isn't, we have to simulate the store-flag with a
                   7014:    set/jump/set sequence.  */
                   7015: 
                   7016: static rtx
                   7017: do_store_flag (exp, target, mode, only_cheap)
                   7018:      tree exp;
                   7019:      rtx target;
                   7020:      enum machine_mode mode;
                   7021:      int only_cheap;
                   7022: {
                   7023:   enum rtx_code code;
1.1.1.3   root     7024:   tree arg0, arg1, type;
1.1       root     7025:   tree tem;
1.1.1.3   root     7026:   enum machine_mode operand_mode;
                   7027:   int invert = 0;
                   7028:   int unsignedp;
1.1       root     7029:   rtx op0, op1;
                   7030:   enum insn_code icode;
                   7031:   rtx subtarget = target;
                   7032:   rtx result, label, pattern, jump_pat;
                   7033: 
1.1.1.3   root     7034:   /* If this is a TRUTH_NOT_EXPR, set a flag indicating we must invert the
                   7035:      result at the end.  We can't simply invert the test since it would
                   7036:      have already been inverted if it were valid.  This case occurs for
                   7037:      some floating-point comparisons.  */
                   7038: 
                   7039:   if (TREE_CODE (exp) == TRUTH_NOT_EXPR)
                   7040:     invert = 1, exp = TREE_OPERAND (exp, 0);
                   7041: 
                   7042:   arg0 = TREE_OPERAND (exp, 0);
                   7043:   arg1 = TREE_OPERAND (exp, 1);
                   7044:   type = TREE_TYPE (arg0);
                   7045:   operand_mode = TYPE_MODE (type);
                   7046:   unsignedp = TREE_UNSIGNED (type);
                   7047: 
1.1       root     7048:   /* We won't bother with BLKmode store-flag operations because it would mean
                   7049:      passing a lot of information to emit_store_flag.  */
                   7050:   if (operand_mode == BLKmode)
                   7051:     return 0;
                   7052: 
1.1.1.4 ! root     7053:   STRIP_NOPS (arg0);
        !          7054:   STRIP_NOPS (arg1);
1.1       root     7055: 
                   7056:   /* Get the rtx comparison code to use.  We know that EXP is a comparison
                   7057:      operation of some type.  Some comparisons against 1 and -1 can be
                   7058:      converted to comparisons with zero.  Do so here so that the tests
1.1.1.2   root     7059:      below will be aware that we have a comparison with zero.   These
                   7060:      tests will not catch constants in the first operand, but constants
                   7061:      are rarely passed as the first operand.  */
1.1       root     7062: 
                   7063:   switch (TREE_CODE (exp))
                   7064:     {
                   7065:     case EQ_EXPR:
                   7066:       code = EQ;
                   7067:       break;
                   7068:     case NE_EXPR:
                   7069:       code = NE;
                   7070:       break;
                   7071:     case LT_EXPR:
                   7072:       if (integer_onep (arg1))
                   7073:        arg1 = integer_zero_node, code = unsignedp ? LEU : LE;
                   7074:       else
                   7075:        code = unsignedp ? LTU : LT;
                   7076:       break;
                   7077:     case LE_EXPR:
                   7078:       if (integer_all_onesp (arg1))
                   7079:        arg1 = integer_zero_node, code = unsignedp ? LTU : LT;
                   7080:       else
                   7081:        code = unsignedp ? LEU : LE;
                   7082:       break;
                   7083:     case GT_EXPR:
                   7084:       if (integer_all_onesp (arg1))
                   7085:        arg1 = integer_zero_node, code = unsignedp ? GEU : GE;
                   7086:       else
                   7087:        code = unsignedp ? GTU : GT;
                   7088:       break;
                   7089:     case GE_EXPR:
                   7090:       if (integer_onep (arg1))
                   7091:        arg1 = integer_zero_node, code = unsignedp ? GTU : GT;
                   7092:       else
                   7093:        code = unsignedp ? GEU : GE;
                   7094:       break;
                   7095:     default:
                   7096:       abort ();
                   7097:     }
                   7098: 
1.1.1.2   root     7099:   /* Put a constant second.  */
                   7100:   if (TREE_CODE (arg0) == REAL_CST || TREE_CODE (arg0) == INTEGER_CST)
                   7101:     {
                   7102:       tem = arg0; arg0 = arg1; arg1 = tem;
                   7103:       code = swap_condition (code);
                   7104:     }
                   7105: 
1.1       root     7106:   /* If this is an equality or inequality test of a single bit, we can
                   7107:      do this by shifting the bit being tested to the low-order bit and
                   7108:      masking the result with the constant 1.  If the condition was EQ,
                   7109:      we xor it with 1.  This does not require an scc insn and is faster
                   7110:      than an scc insn even if we have it.  */
                   7111: 
                   7112:   if ((code == NE || code == EQ)
                   7113:       && TREE_CODE (arg0) == BIT_AND_EXPR && integer_zerop (arg1)
                   7114:       && integer_pow2p (TREE_OPERAND (arg0, 1))
1.1.1.4 ! root     7115:       && TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT)
1.1       root     7116:     {
                   7117:       int bitnum = exact_log2 (INTVAL (expand_expr (TREE_OPERAND (arg0, 1),
1.1.1.4 ! root     7118:                                                    NULL_RTX, VOIDmode, 0)));
1.1       root     7119: 
                   7120:       if (subtarget == 0 || GET_CODE (subtarget) != REG
                   7121:          || GET_MODE (subtarget) != operand_mode
                   7122:          || ! safe_from_p (subtarget, TREE_OPERAND (arg0, 0)))
                   7123:        subtarget = 0;
                   7124: 
                   7125:       op0 = expand_expr (TREE_OPERAND (arg0, 0), subtarget, VOIDmode, 0);
                   7126: 
                   7127:       if (bitnum != 0)
                   7128:        op0 = expand_shift (RSHIFT_EXPR, GET_MODE (op0), op0,
                   7129:                            size_int (bitnum), target, 1);
                   7130: 
                   7131:       if (GET_MODE (op0) != mode)
                   7132:        op0 = convert_to_mode (mode, op0, 1);
                   7133: 
                   7134:       if (bitnum != TYPE_PRECISION (type) - 1)
                   7135:        op0 = expand_and (op0, const1_rtx, target);
                   7136: 
1.1.1.3   root     7137:       if ((code == EQ && ! invert) || (code == NE && invert))
1.1       root     7138:        op0 = expand_binop (mode, xor_optab, op0, const1_rtx, target, 0,
                   7139:                            OPTAB_LIB_WIDEN);
                   7140: 
                   7141:       return op0;
                   7142:     }
                   7143: 
                   7144:   /* Now see if we are likely to be able to do this.  Return if not.  */
                   7145:   if (! can_compare_p (operand_mode))
                   7146:     return 0;
                   7147:   icode = setcc_gen_code[(int) code];
                   7148:   if (icode == CODE_FOR_nothing
                   7149:       || (only_cheap && insn_operand_mode[(int) icode][0] != mode))
                   7150:     {
                   7151:       /* We can only do this if it is one of the special cases that
                   7152:         can be handled without an scc insn.  */
                   7153:       if ((code == LT && integer_zerop (arg1))
                   7154:          || (! only_cheap && code == GE && integer_zerop (arg1)))
                   7155:        ;
                   7156:       else if (BRANCH_COST >= 0
                   7157:               && ! only_cheap && (code == NE || code == EQ)
                   7158:               && TREE_CODE (type) != REAL_TYPE
                   7159:               && ((abs_optab->handlers[(int) operand_mode].insn_code
                   7160:                    != CODE_FOR_nothing)
                   7161:                   || (ffs_optab->handlers[(int) operand_mode].insn_code
                   7162:                       != CODE_FOR_nothing)))
                   7163:        ;
                   7164:       else
                   7165:        return 0;
                   7166:     }
                   7167:       
                   7168:   preexpand_calls (exp);
                   7169:   if (subtarget == 0 || GET_CODE (subtarget) != REG
                   7170:       || GET_MODE (subtarget) != operand_mode
                   7171:       || ! safe_from_p (subtarget, arg1))
                   7172:     subtarget = 0;
                   7173: 
                   7174:   op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
1.1.1.4 ! root     7175:   op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
1.1       root     7176: 
                   7177:   if (target == 0)
                   7178:     target = gen_reg_rtx (mode);
                   7179: 
1.1.1.4 ! root     7180:   /* Pass copies of OP0 and OP1 in case they contain a QUEUED.  This is safe
        !          7181:      because, if the emit_store_flag does anything it will succeed and
        !          7182:      OP0 and OP1 will not be used subsequently.  */
        !          7183: 
        !          7184:   result = emit_store_flag (target, code,
        !          7185:                            queued_subexp_p (op0) ? copy_rtx (op0) : op0,
        !          7186:                            queued_subexp_p (op1) ? copy_rtx (op1) : op1,
        !          7187:                            operand_mode, unsignedp, 1);
1.1       root     7188: 
                   7189:   if (result)
1.1.1.3   root     7190:     {
                   7191:       if (invert)
                   7192:        result = expand_binop (mode, xor_optab, result, const1_rtx,
                   7193:                               result, 0, OPTAB_LIB_WIDEN);
                   7194:       return result;
                   7195:     }
1.1       root     7196: 
                   7197:   /* If this failed, we have to do this with set/compare/jump/set code.  */
                   7198:   if (target == 0 || GET_CODE (target) != REG
                   7199:       || reg_mentioned_p (target, op0) || reg_mentioned_p (target, op1))
                   7200:     target = gen_reg_rtx (GET_MODE (target));
                   7201: 
1.1.1.3   root     7202:   emit_move_insn (target, invert ? const0_rtx : const1_rtx);
1.1.1.4 ! root     7203:   result = compare_from_rtx (op0, op1, code, unsignedp,
        !          7204:                             operand_mode, NULL_RTX, 0);
1.1       root     7205:   if (GET_CODE (result) == CONST_INT)
1.1.1.3   root     7206:     return (((result == const0_rtx && ! invert)
                   7207:             || (result != const0_rtx && invert))
                   7208:            ? const0_rtx : const1_rtx);
1.1       root     7209: 
                   7210:   label = gen_label_rtx ();
                   7211:   if (bcc_gen_fctn[(int) code] == 0)
                   7212:     abort ();
                   7213: 
                   7214:   emit_jump_insn ((*bcc_gen_fctn[(int) code]) (label));
1.1.1.3   root     7215:   emit_move_insn (target, invert ? const1_rtx : const0_rtx);
1.1       root     7216:   emit_label (label);
                   7217: 
                   7218:   return target;
                   7219: }
                   7220: 
                   7221: /* Generate a tablejump instruction (used for switch statements).  */
                   7222: 
                   7223: #ifdef HAVE_tablejump
                   7224: 
                   7225: /* INDEX is the value being switched on, with the lowest value
                   7226:    in the table already subtracted.
1.1.1.3   root     7227:    MODE is its expected mode (needed if INDEX is constant).
1.1       root     7228:    RANGE is the length of the jump table.
                   7229:    TABLE_LABEL is a CODE_LABEL rtx for the table itself.
                   7230: 
                   7231:    DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
                   7232:    index value is out of range.  */
                   7233: 
                   7234: void
1.1.1.2   root     7235: do_tablejump (index, mode, range, table_label, default_label)
1.1       root     7236:      rtx index, range, table_label, default_label;
1.1.1.2   root     7237:      enum machine_mode mode;
1.1       root     7238: {
                   7239:   register rtx temp, vector;
                   7240: 
1.1.1.3   root     7241:   /* Do an unsigned comparison (in the proper mode) between the index
                   7242:      expression and the value which represents the length of the range.
                   7243:      Since we just finished subtracting the lower bound of the range
                   7244:      from the index expression, this comparison allows us to simultaneously
                   7245:      check that the original index expression value is both greater than
                   7246:      or equal to the minimum value of the range and less than or equal to
                   7247:      the maximum value of the range.  */
1.1.1.2   root     7248: 
1.1.1.4 ! root     7249:   emit_cmp_insn (range, index, LTU, NULL_RTX, mode, 0, 0);
1.1       root     7250:   emit_jump_insn (gen_bltu (default_label));
1.1.1.3   root     7251: 
                   7252:   /* If index is in range, it must fit in Pmode.
                   7253:      Convert to Pmode so we can index with it.  */
                   7254:   if (mode != Pmode)
                   7255:     index = convert_to_mode (Pmode, index, 1);
                   7256: 
1.1       root     7257:   /* If flag_force_addr were to affect this address
                   7258:      it could interfere with the tricky assumptions made
                   7259:      about addresses that contain label-refs,
                   7260:      which may be valid only very near the tablejump itself.  */
                   7261:   /* ??? The only correct use of CASE_VECTOR_MODE is the one inside the
                   7262:      GET_MODE_SIZE, because this indicates how large insns are.  The other
                   7263:      uses should all be Pmode, because they are addresses.  This code
                   7264:      could fail if addresses and insns are not the same size.  */
                   7265:   index = memory_address_noforce
                   7266:     (CASE_VECTOR_MODE,
                   7267:      gen_rtx (PLUS, Pmode,
                   7268:              gen_rtx (MULT, Pmode, index,
1.1.1.4 ! root     7269:                       GEN_INT (GET_MODE_SIZE (CASE_VECTOR_MODE))),
1.1       root     7270:              gen_rtx (LABEL_REF, Pmode, table_label)));
                   7271:   temp = gen_reg_rtx (CASE_VECTOR_MODE);
                   7272:   vector = gen_rtx (MEM, CASE_VECTOR_MODE, index);
                   7273:   RTX_UNCHANGING_P (vector) = 1;
                   7274:   convert_move (temp, vector, 0);
                   7275: 
                   7276:   emit_jump_insn (gen_tablejump (temp, table_label));
                   7277: 
                   7278: #ifndef CASE_VECTOR_PC_RELATIVE
                   7279:   /* If we are generating PIC code or if the table is PC-relative, the
                   7280:      table and JUMP_INSN must be adjacent, so don't output a BARRIER.  */
                   7281:   if (! flag_pic)
                   7282:     emit_barrier ();
                   7283: #endif
                   7284: }
                   7285: 
                   7286: #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.