Annotation of gcc/expr.c, revision 1.1.1.15

1.1       root        1: /* Convert tree expression to rtl instructions, for GNU compiler.
1.1.1.2   root        2:    Copyright (C) 1988 Free Software Foundation, Inc.
1.1       root        3: 
                      4: This file is part of GNU CC.
                      5: 
1.1.1.15! root        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 1, or (at your option)
        !             9: any later version.
        !            10: 
1.1       root       11: GNU CC is distributed in the hope that it will be useful,
1.1.1.15! root       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.  */
1.1       root       19: 
                     20: 
                     21: #include "config.h"
                     22: #include "rtl.h"
                     23: #include "tree.h"
1.1.1.2   root       24: #include "flags.h"
1.1       root       25: #include "insn-flags.h"
                     26: #include "insn-codes.h"
                     27: #include "expr.h"
1.1.1.2   root       28: #include "insn-config.h"
                     29: #include "recog.h"
                     30: #include "varargs.h"
                     31: 
                     32: /* Decide whether a function's arguments should be processed
                     33:    from first to last or from last to first.  */
                     34: 
                     35: #ifdef STACK_GROWS_DOWNWARD
                     36: #ifdef PUSH_ROUNDING
                     37: #define PUSH_ARGS_REVERSED     /* If it's last to first */
                     38: #endif
                     39: #endif
                     40: 
                     41: /* Like STACK_BOUNDARY but in units of bytes, not bits.  */
                     42: #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
1.1       root       43: 
                     44: /* If this is nonzero, we do not bother generating VOLATILE
                     45:    around volatile memory references, and we are willing to
                     46:    output indirect addresses.  If cse is to follow, we reject
                     47:    indirect addresses so a useful potential cse is generated;
                     48:    if it is used only once, instruction combination will produce
                     49:    the same indirect address eventually.  */
                     50: int cse_not_expected;
                     51: 
                     52: /* Nonzero to generate code for all the subroutines within an
                     53:    expression before generating the upper levels of the expression.
                     54:    Nowadays this is never zero.  */
                     55: int do_preexpand_calls = 1;
                     56: 
                     57: /* Number of units that we should eventually pop off the stack.
                     58:    These are the arguments to function calls that have already returned.  */
                     59: int pending_stack_adjust;
                     60: 
                     61: /* Total size of arguments already pushed for function calls that
1.1.1.6   root       62:    have not happened yet.  When this is nonzero,
1.1       root       63:    args passed to function calls must be popped right away
1.1.1.6   root       64:    to ensure contiguity of argument lists for future calls.
                     65: 
                     66:    This can also be temporarily incremented for various other reasons
                     67:    to inhibit deferring of pops.  */
1.1.1.2   root       68: static int current_args_size;
1.1       root       69: 
1.1.1.6   root       70: #define NO_DEFER_POP current_args_size += 1
                     71: #define OK_DEFER_POP current_args_size -= 1
                     72: 
1.1.1.13  root       73: /* A list of all cleanups which belong to the arguments of
1.1.1.8   root       74:    function calls being expanded by expand_call.  */
                     75: static tree cleanups_of_this_call;
                     76: 
1.1.1.2   root       77: /* Nonzero means current function may call alloca.  */
                     78: int may_call_alloca;
                     79: 
                     80: rtx store_expr ();
                     81: static void store_constructor ();
                     82: static rtx store_field ();
1.1       root       83: static rtx expand_call ();
1.1.1.2   root       84: static void emit_call_1 ();
                     85: static rtx prepare_call_address ();
                     86: static rtx expand_builtin ();
1.1       root       87: static rtx compare ();
1.1.1.2   root       88: static rtx compare_constants ();
1.1       root       89: static rtx compare1 ();
                     90: static rtx do_store_flag ();
                     91: static void preexpand_calls ();
1.1.1.2   root       92: static rtx expand_increment ();
                     93: static void move_by_pieces_1 ();
1.1.1.4   root       94: static int move_by_pieces_ninsns ();
1.1.1.2   root       95: static void init_queue ();
1.1.1.9   root       96: static void store_one_arg ();
                     97: static rtx target_for_arg ();
1.1.1.2   root       98: 
                     99: void do_pending_stack_adjust ();
1.1       root      100: 
                    101: /* MOVE_RATIO is the number of move instructions that is better than
                    102:    a block move.  */
                    103: 
1.1.1.10  root      104: #ifndef MOVE_RATIO
                    105: #if defined (HAVE_movstrqi) || defined (HAVE_movstrhi) || defined (HAVE_movstrsi)
1.1       root      106: #define MOVE_RATIO 2
                    107: #else
1.1.1.10  root      108: /* A value of around 6 would minimize code size; infinity would minimize
                    109:    execution time.  */
                    110: #define MOVE_RATIO 15
                    111: #endif
1.1       root      112: #endif
                    113: 
                    114: /* Table indexed by tree code giving 1 if the code is for a
                    115:    comparison operation, or anything that is most easily
                    116:    computed with a conditional branch.
                    117: 
                    118:    We include tree.def to give it the proper length.
                    119:    The contents thus created are irrelevant.
                    120:    The real contents are initialized in init_comparisons.  */
                    121: 
1.1.1.2   root      122: #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) 0,
1.1       root      123: 
                    124: static char comparison_code[] = {
                    125: #include "tree.def"
                    126: };
                    127: #undef DEFTREECODE
                    128: 
1.1.1.2   root      129: /* This is run once per compilation.  */
                    130: 
                    131: void
1.1       root      132: init_comparisons ()
                    133: {
                    134:   comparison_code[(int) EQ_EXPR] = 1;
                    135:   comparison_code[(int) NE_EXPR] = 1;
                    136:   comparison_code[(int) LT_EXPR] = 1;
                    137:   comparison_code[(int) GT_EXPR] = 1;
                    138:   comparison_code[(int) LE_EXPR] = 1;
                    139:   comparison_code[(int) GE_EXPR] = 1;
                    140: }
1.1.1.2   root      141: 
                    142: /* This is run at the start of compiling a function.  */
                    143: 
                    144: void
                    145: init_expr ()
                    146: {
                    147:   init_queue ();
                    148:   may_call_alloca = 0;
                    149: }
1.1       root      150: 
                    151: /* Manage the queue of increment instructions to be output
                    152:    for POSTINCREMENT_EXPR expressions, etc.  */
                    153: 
                    154: static rtx pending_chain;
                    155: 
                    156: /* Queue up to increment (or change) VAR later.  BODY says how:
                    157:    BODY should be the same thing you would pass to emit_insn
                    158:    to increment right away.  It will go to emit_insn later on.
                    159: 
                    160:    The value is a QUEUED expression to be used in place of VAR
1.1.1.2   root      161:    where you want to guarantee the pre-incrementation value of VAR.  */
1.1       root      162: 
                    163: static rtx
                    164: enqueue_insn (var, body)
                    165:      rtx var, body;
                    166: {
                    167:   pending_chain = gen_rtx (QUEUED, GET_MODE (var),
                    168:                           var, 0, 0, body, pending_chain);
                    169:   return pending_chain;
                    170: }
                    171: 
                    172: /* Use protect_from_queue to convert a QUEUED expression
                    173:    into something that you can put immediately into an instruction.
                    174:    If the queued incrementation has not happened yet,
                    175:    protect_from_queue returns the variable itself.
                    176:    If the incrementation has happened, protect_from_queue returns a temp
                    177:    that contains a copy of the old value of the variable.
                    178: 
                    179:    Any time an rtx which might possibly be a QUEUED is to be put
                    180:    into an instruction, it must be passed through protect_from_queue first.
                    181:    QUEUED expressions are not meaningful in instructions.
                    182: 
                    183:    Do not pass a value through protect_from_queue and then hold
                    184:    on to it for a while before putting it in an instruction!
                    185:    If the queue is flushed in between, incorrect code will result.  */
                    186: 
                    187: rtx
                    188: protect_from_queue (x, modify)
                    189:      register rtx x;
                    190:      int modify;
                    191: {
                    192:   register RTX_CODE code = GET_CODE (x);
                    193:   if (code != QUEUED)
                    194:     {
                    195:       /* A special hack for read access to (MEM (QUEUED ...))
                    196:         to facilitate use of autoincrement.
                    197:         Make a copy of the contents of the memory location
                    198:         rather than a copy of the address.  */
                    199:       if (code == MEM && GET_CODE (XEXP (x, 0)) == QUEUED && !modify)
                    200:        {
                    201:          register rtx y = XEXP (x, 0);
                    202:          XEXP (x, 0) = QUEUED_VAR (y);
                    203:          if (QUEUED_INSN (y))
                    204:            {
                    205:              register rtx temp = gen_reg_rtx (GET_MODE (x));
                    206:              emit_insn_before (gen_move_insn (temp, x),
                    207:                                QUEUED_INSN (y));
                    208:              return temp;
                    209:            }
                    210:          return x;
                    211:        }
                    212:       /* Otherwise, recursively protect the subexpressions of all
                    213:         the kinds of rtx's that can contain a QUEUED.  */
                    214:       if (code == MEM)
                    215:        XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0);
                    216:       else if (code == PLUS || code == MULT)
                    217:        {
                    218:          XEXP (x, 0) = protect_from_queue (XEXP (x, 0), 0);
                    219:          XEXP (x, 1) = protect_from_queue (XEXP (x, 1), 0);
                    220:        }
                    221:       return x;
                    222:     }
                    223:   /* If the increment has not happened, use the variable itself.  */
                    224:   if (QUEUED_INSN (x) == 0)
                    225:     return QUEUED_VAR (x);
                    226:   /* If the increment has happened and a pre-increment copy exists,
                    227:      use that copy.  */
                    228:   if (QUEUED_COPY (x) != 0)
                    229:     return QUEUED_COPY (x);
                    230:   /* The increment has happened but we haven't set up a pre-increment copy.
                    231:      Set one up now, and use it.  */
                    232:   QUEUED_COPY (x) = gen_reg_rtx (GET_MODE (QUEUED_VAR (x)));
                    233:   emit_insn_before (gen_move_insn (QUEUED_COPY (x), QUEUED_VAR (x)),
                    234:                    QUEUED_INSN (x));
                    235:   return QUEUED_COPY (x);
                    236: }
                    237: 
1.1.1.2   root      238: /* Return nonzero if X contains a QUEUED expression:
1.1.1.15! root      239:    if it contains anything that will be altered by a queued increment.
        !           240:    We handle only combinations of MEM, PLUS, MINUS and MULT operators
        !           241:    since memory addresses generally contain only those.  */
1.1.1.2   root      242: 
                    243: static int
                    244: queued_subexp_p (x)
                    245:      rtx x;
                    246: {
                    247:   register enum rtx_code code = GET_CODE (x);
                    248:   switch (code)
                    249:     {
                    250:     case QUEUED:
                    251:       return 1;
                    252:     case MEM:
                    253:       return queued_subexp_p (XEXP (x, 0));
                    254:     case MULT:
                    255:     case PLUS:
                    256:     case MINUS:
                    257:       return queued_subexp_p (XEXP (x, 0))
                    258:        || queued_subexp_p (XEXP (x, 1));
                    259:     }
                    260:   return 0;
                    261: }
                    262: 
                    263: /* Perform all the pending incrementations.  */
1.1       root      264: 
                    265: void
                    266: emit_queue ()
                    267: {
                    268:   register rtx p;
                    269:   while (p = pending_chain)
                    270:     {
                    271:       QUEUED_INSN (p) = emit_insn (QUEUED_BODY (p));
                    272:       pending_chain = QUEUED_NEXT (p);
                    273:     }
                    274: }
                    275: 
1.1.1.2   root      276: static void
1.1       root      277: init_queue ()
                    278: {
                    279:   if (pending_chain)
                    280:     abort ();
                    281: }
                    282: 
                    283: /* Copy data from FROM to TO, where the machine modes are not the same.
                    284:    Both modes may be integer, or both may be floating.
                    285:    UNSIGNEDP should be nonzero if FROM is an unsigned type.
                    286:    This causes zero-extension instead of sign-extension.  */
                    287: 
                    288: void
                    289: convert_move (to, from, unsignedp)
                    290:      register rtx to, from;
                    291:      int unsignedp;
                    292: {
                    293:   enum machine_mode to_mode = GET_MODE (to);
                    294:   enum machine_mode from_mode = GET_MODE (from);
                    295:   int to_real = to_mode == SFmode || to_mode == DFmode;
                    296:   int from_real = from_mode == SFmode || from_mode == DFmode;
                    297:   int extending = (int) to_mode > (int) from_mode;
                    298: 
                    299:   to = protect_from_queue (to, 1);
                    300:   from = protect_from_queue (from, 0);
                    301: 
                    302:   if (to_real != from_real)
                    303:     abort ();
                    304: 
1.1.1.2   root      305:   if (to_mode == from_mode
                    306:       || (from_mode == VOIDmode && CONSTANT_P (from)))
1.1       root      307:     {
                    308:       emit_move_insn (to, from);
                    309:       return;
                    310:     }
                    311: 
                    312:   if (to_real)
                    313:     {
                    314: #ifdef HAVE_extendsfdf2
                    315:       if (HAVE_extendsfdf2 && extending)
                    316:        {
1.1.1.2   root      317:          emit_unop_insn (CODE_FOR_extendsfdf2, to, from, UNKNOWN);
1.1       root      318:          return;
                    319:        }
                    320: #endif
                    321: #ifdef HAVE_truncdfsf2
                    322:       if (HAVE_truncdfsf2 && ! extending)
                    323:        {
1.1.1.2   root      324:          emit_unop_insn (CODE_FOR_truncdfsf2, to, from, UNKNOWN);
1.1       root      325:          return;
                    326:        }
                    327: #endif
                    328:       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, (extending
1.1.1.13  root      329:                                                      ? "__extendsfdf2"
                    330:                                                      : "__truncdfsf2")),
1.1.1.2   root      331:                         GET_MODE (to), 1,
                    332:                         from,  (extending ? SFmode : DFmode));
                    333:       emit_move_insn (to, hard_libcall_value (GET_MODE (to)));
1.1       root      334:       return;
                    335:     }
                    336: 
1.1.1.2   root      337:   /* Now both modes are integers.  */
                    338: 
1.1       root      339:   if (to_mode == DImode)
                    340:     {
                    341:       if (unsignedp)
                    342:        {
1.1.1.14  root      343: #ifdef HAVE_zero_extendsidi2
                    344:          if (HAVE_zero_extendsidi2 && from_mode == SImode)
                    345:            emit_unop_insn (CODE_FOR_zero_extendsidi2, to, from, ZERO_EXTEND);
                    346:          else
                    347: #endif
                    348: #ifdef HAVE_zero_extendhidi2
                    349:          if (HAVE_zero_extendhidi2 && from_mode == HImode)
                    350:            emit_unop_insn (CODE_FOR_zero_extendhidi2, to, from, ZERO_EXTEND);
                    351:          else
                    352: #endif
                    353: #ifdef HAVE_zero_extendqidi2
                    354:          if (HAVE_zero_extendqidi2 && from_mode == QImode)
                    355:            emit_unop_insn (CODE_FOR_zero_extendqidi2, to, from, ZERO_EXTEND);
                    356:          else
                    357: #endif
                    358: #ifdef HAVE_zero_extendsidi2
                    359:          if (HAVE_zero_extendsidi2)
                    360:            {
                    361:              convert_move (gen_lowpart (SImode, to), from, unsignedp);
1.1.1.15! root      362:              emit_unop_insn (CODE_FOR_zero_extendsidi2, to,
        !           363:                              gen_lowpart (SImode, to), ZERO_EXTEND);
1.1.1.14  root      364:            }
                    365:          else
                    366: #endif
                    367:            {
                    368:              emit_insn (gen_rtx (CLOBBER, VOIDmode, to));
                    369:              convert_move (gen_lowpart (SImode, to), from, unsignedp);
                    370:              emit_clr_insn (gen_highpart (SImode, to));
                    371:            }
1.1       root      372:        }
1.1.1.5   root      373: #ifdef HAVE_extendsidi2
1.1.1.14  root      374:       else if (HAVE_extendsidi2 && from_mode == SImode)
                    375:        emit_unop_insn (CODE_FOR_extendsidi2, to, from, SIGN_EXTEND);
                    376: #endif
                    377: #ifdef HAVE_extendhidi2
                    378:       else if (HAVE_extendhidi2 && from_mode == HImode)
                    379:        emit_unop_insn (CODE_FOR_extendhidi2, to, from, SIGN_EXTEND);
                    380: #endif
                    381: #ifdef HAVE_extendqidi2
                    382:       else if (HAVE_extendqidi2 && from_mode == QImode)
                    383:        emit_unop_insn (CODE_FOR_extendqidi2, to, from, SIGN_EXTEND);
                    384: #endif
                    385: #ifdef HAVE_extendsidi2
1.1.1.5   root      386:       else if (HAVE_extendsidi2)
1.1.1.14  root      387:        {
                    388:          convert_move (gen_lowpart (SImode, to), from, unsignedp);
                    389:          emit_unop_insn (CODE_FOR_extendsidi2, to, to, SIGN_EXTEND);
                    390:        }
1.1.1.5   root      391: #endif
1.1.1.2   root      392: #ifdef HAVE_slt
                    393:       else if (HAVE_slt && insn_operand_mode[(int) CODE_FOR_slt][0] == SImode)
1.1       root      394:        {
1.1.1.5   root      395:          emit_insn (gen_rtx (CLOBBER, VOIDmode, to));
1.1       root      396:          convert_move (gen_lowpart (SImode, to), from, unsignedp);
1.1.1.2   root      397:          emit_insn (gen_slt (gen_highpart (SImode, to)));
1.1       root      398:        }
                    399: #endif
                    400:       else
                    401:        {
                    402:          register rtx label = gen_label_rtx ();
                    403: 
1.1.1.5   root      404:          emit_insn (gen_rtx (CLOBBER, VOIDmode, to));
1.1       root      405:          emit_clr_insn (gen_highpart (SImode, to));
                    406:          convert_move (gen_lowpart (SImode, to), from, unsignedp);
                    407:          emit_cmp_insn (gen_lowpart (SImode, to),
                    408:                         gen_rtx (CONST_INT, VOIDmode, 0),
1.1.1.14  root      409:                         0, 0, 0);
1.1.1.6   root      410:          NO_DEFER_POP;
1.1       root      411:          emit_jump_insn (gen_bge (label));
                    412:          expand_unop (SImode, one_cmpl_optab,
                    413:                       gen_highpart (SImode, to), gen_highpart (SImode, to),
                    414:                       1);
                    415:          emit_label (label);
1.1.1.6   root      416:          OK_DEFER_POP;
1.1       root      417:        }
                    418:       return;
                    419:     }
                    420: 
                    421:   if (from_mode == DImode)
                    422:     {
                    423:       convert_move (to, gen_lowpart (SImode, from), 0);
                    424:       return;
                    425:     }
                    426: 
                    427:   /* Now follow all the conversions between integers
                    428:      no more than a word long.  */
                    429: 
1.1.1.2   root      430:   /* For truncation, usually we can just refer to FROM in a narrower mode.  */
                    431:   if (GET_MODE_BITSIZE (to_mode) < GET_MODE_BITSIZE (from_mode)
                    432:       && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (to_mode),
                    433:                                GET_MODE_BITSIZE (from_mode))
                    434:       && ((GET_CODE (from) == MEM
                    435:           && ! mode_dependent_address_p (XEXP (from, 0)))
                    436:          || GET_CODE (from) == REG))
                    437:     {
                    438:       emit_move_insn (to, gen_lowpart (to_mode, from));
                    439:       return;
                    440:     }
                    441: 
1.1       root      442:   if (to_mode == SImode && from_mode == HImode)
                    443:     {
                    444:       if (unsignedp)
                    445:        {
                    446: #ifdef HAVE_zero_extendhisi2
                    447:          if (HAVE_zero_extendhisi2)
1.1.1.2   root      448:            emit_unop_insn (CODE_FOR_zero_extendhisi2, to, from, ZERO_EXTEND);
1.1       root      449:          else
                    450: #endif
                    451:            abort ();
                    452:        }
                    453:       else
                    454:        {
                    455: #ifdef HAVE_extendhisi2
                    456:          if (HAVE_extendhisi2)
1.1.1.2   root      457:            emit_unop_insn (CODE_FOR_extendhisi2, to, from, SIGN_EXTEND);
1.1       root      458:          else
                    459: #endif
                    460:            abort ();
                    461:        }
                    462:       return;
                    463:     }
                    464: 
                    465:   if (to_mode == SImode && from_mode == QImode)
                    466:     {
                    467:       if (unsignedp)
                    468:        {
                    469: #ifdef HAVE_zero_extendqisi2
                    470:          if (HAVE_zero_extendqisi2)
                    471:            {
1.1.1.2   root      472:              emit_unop_insn (CODE_FOR_zero_extendqisi2, to, from, ZERO_EXTEND);
1.1       root      473:              return;
                    474:            }
                    475: #endif
                    476: #if defined (HAVE_zero_extendqihi2) && defined (HAVE_extendhisi2)
                    477:          if (HAVE_zero_extendqihi2 && HAVE_extendhisi2)
                    478:            {
                    479:              register rtx temp = gen_reg_rtx (HImode);
1.1.1.2   root      480:              emit_unop_insn (CODE_FOR_zero_extendqihi2, temp, from, ZERO_EXTEND);
                    481:              emit_unop_insn (CODE_FOR_extendhisi2, to, temp, SIGN_EXTEND);
1.1       root      482:              return;
                    483:            }
                    484: #endif
                    485:        }
                    486:       else
                    487:        {
                    488: #ifdef HAVE_extendqisi2
                    489:          if (HAVE_extendqisi2)
                    490:            {
1.1.1.2   root      491:              emit_unop_insn (CODE_FOR_extendqisi2, to, from, SIGN_EXTEND);
1.1       root      492:              return;
                    493:            }
                    494: #endif
                    495: #if defined (HAVE_extendqihi2) && defined (HAVE_extendhisi2)
                    496:          if (HAVE_extendqihi2 && HAVE_extendhisi2)
                    497:            {
                    498:              register rtx temp = gen_reg_rtx (HImode);
1.1.1.2   root      499:              emit_unop_insn (CODE_FOR_extendqihi2, temp, from, SIGN_EXTEND);
                    500:              emit_unop_insn (CODE_FOR_extendhisi2, to, temp, SIGN_EXTEND);
1.1       root      501:              return;
                    502:            }
                    503: #endif
                    504:        }
                    505:       abort ();
                    506:     }
                    507: 
                    508:   if (to_mode == HImode && from_mode == QImode)
                    509:     {
                    510:       if (unsignedp)
                    511:        {
                    512: #ifdef HAVE_zero_extendqihi2
                    513:          if (HAVE_zero_extendqihi2)
                    514:            {
1.1.1.2   root      515:              emit_unop_insn (CODE_FOR_zero_extendqihi2, to, from, ZERO_EXTEND);
1.1       root      516:              return;
                    517:            }
                    518: #endif
                    519:        }
                    520:       else
                    521:        {
                    522: #ifdef HAVE_extendqihi2
                    523:          if (HAVE_extendqihi2)
                    524:            {
1.1.1.2   root      525:              emit_unop_insn (CODE_FOR_extendqihi2, to, from, SIGN_EXTEND);
1.1       root      526:              return;
                    527:            }
                    528: #endif
                    529:        }
                    530:       abort ();
                    531:     }
                    532: 
                    533:   /* Now we are truncating an integer to a smaller one.
                    534:      If the result is a temporary, we might as well just copy it,
                    535:      since only the low-order part of the result needs to be valid
                    536:      and it is valid with no change.  */
                    537: 
                    538:   if (GET_CODE (to) == REG)
                    539:     {
                    540:       if (GET_CODE (from) == REG)
                    541:        {
                    542:          emit_move_insn (to, gen_lowpart (GET_MODE (to), from));
                    543:          return;
                    544:        }
1.1.1.2   root      545:       else if (GET_CODE (from) == SUBREG)
                    546:        {
                    547:          from = copy_rtx (from);
                    548:          /* This is safe since FROM is not more than one word.  */
                    549:          PUT_MODE (from, GET_MODE (to));
                    550:          emit_move_insn (to, from);
                    551:          return;
                    552:        }
1.1       root      553: #ifndef BYTES_BIG_ENDIAN
                    554:       else if (GET_CODE (from) == MEM)
                    555:        {
                    556:          register rtx addr = XEXP (from, 0);
1.1.1.2   root      557:          if (memory_address_p (GET_MODE (to), addr))
1.1       root      558:            {
                    559:              emit_move_insn (to, gen_rtx (MEM, GET_MODE (to), addr));
                    560:              return;
                    561:            }
                    562:        }
                    563: #endif /* not BYTES_BIG_ENDIAN */
                    564:     }
                    565: 
                    566:   if (from_mode == SImode && to_mode == HImode)
                    567:     {
                    568: #ifdef HAVE_truncsihi2
                    569:       if (HAVE_truncsihi2)
                    570:        {
1.1.1.2   root      571:          emit_unop_insn (CODE_FOR_truncsihi2, to, from, UNKNOWN);
1.1       root      572:          return;
                    573:        }
                    574: #endif
                    575:       abort ();
                    576:     }
                    577: 
                    578:   if (from_mode == SImode && to_mode == QImode)
                    579:     {
                    580: #ifdef HAVE_truncsiqi2
                    581:       if (HAVE_truncsiqi2)
                    582:        {
1.1.1.2   root      583:          emit_unop_insn (CODE_FOR_truncsiqi2, to, from, UNKNOWN);
1.1       root      584:          return;
                    585:        }
                    586: #endif
                    587:       abort ();
                    588:     }
                    589: 
                    590:   if (from_mode == HImode && to_mode == QImode)
                    591:     {
                    592: #ifdef HAVE_trunchiqi2
                    593:       if (HAVE_trunchiqi2)
                    594:        {
1.1.1.2   root      595:          emit_unop_insn (CODE_FOR_trunchiqi2, to, from, UNKNOWN);
1.1       root      596:          return;
                    597:        }
                    598: #endif
                    599:       abort ();
                    600:     }
1.1.1.2   root      601: 
                    602:   /* Mode combination is not recognized.  */
                    603:   abort ();
1.1       root      604: }
                    605: 
                    606: /* Return an rtx for a value that would result
                    607:    from converting X to mode MODE.
                    608:    Both X and MODE may be floating, or both integer.
                    609:    UNSIGNEDP is nonzero if X is an unsigned value.
                    610:    This can be done by referring to a part of X in place
                    611:    or by copying to a new temporary with conversion.  */
                    612: 
                    613: rtx
                    614: convert_to_mode (mode, x, unsignedp)
                    615:      enum machine_mode mode;
                    616:      rtx x;
                    617:      int unsignedp;
                    618: {
                    619:   register rtx temp;
                    620:   if (mode == GET_MODE (x))
                    621:     return x;
1.1.1.2   root      622:   if (integer_mode_p (mode)
                    623:       && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (x)))
1.1       root      624:     return gen_lowpart (mode, x);
                    625:   temp = gen_reg_rtx (mode);
                    626:   convert_move (temp, x, unsignedp);
                    627:   return temp;
                    628: }
1.1.1.2   root      629: 
                    630: int
                    631: integer_mode_p (mode)
                    632:      enum machine_mode mode;
                    633: {
                    634:   return (int) mode > (int) VOIDmode && (int) mode <= (int) TImode;
                    635: }
1.1       root      636: 
                    637: /* Generate several move instructions to copy LEN bytes
1.1.1.2   root      638:    from block FROM to block TO.  (These are MEM rtx's with BLKmode).
                    639:    The caller must pass FROM and TO
1.1       root      640:     through protect_from_queue before calling.
                    641:    ALIGN (in bytes) is maximum alignment we can assume.  */
                    642: 
                    643: struct move_by_pieces
                    644: {
                    645:   rtx to;
1.1.1.2   root      646:   rtx to_addr;
1.1       root      647:   int autinc_to;
                    648:   int explicit_inc_to;
                    649:   rtx from;
1.1.1.2   root      650:   rtx from_addr;
1.1       root      651:   int autinc_from;
                    652:   int explicit_inc_from;
                    653:   int len;
                    654:   int offset;
                    655:   int reverse;
                    656: };
                    657: 
                    658: static void
1.1.1.2   root      659: move_by_pieces (to, from, len, align)
1.1       root      660:      rtx to, from;
                    661:      int len, align;
                    662: {
                    663:   struct move_by_pieces data;
1.1.1.2   root      664:   rtx to_addr = XEXP (to, 0), from_addr = XEXP (from, 0);
1.1       root      665: 
                    666:   data.offset = 0;
1.1.1.2   root      667:   data.to_addr = to_addr;
                    668:   data.from_addr = from_addr;
1.1       root      669:   data.to = to;
                    670:   data.from = from;
1.1.1.2   root      671:   data.autinc_to
                    672:     = (GET_CODE (to_addr) == PRE_INC || GET_CODE (to_addr) == PRE_DEC
                    673:        || GET_CODE (to_addr) == POST_INC || GET_CODE (to_addr) == POST_DEC);
                    674:   data.autinc_from
                    675:     = (GET_CODE (from_addr) == PRE_INC || GET_CODE (from_addr) == PRE_DEC
                    676:        || GET_CODE (from_addr) == POST_INC
                    677:        || GET_CODE (from_addr) == POST_DEC);
1.1       root      678: 
                    679:   data.explicit_inc_from = 0;
                    680:   data.explicit_inc_to = 0;
1.1.1.2   root      681:   data.reverse
                    682:     = (GET_CODE (to_addr) == PRE_DEC || GET_CODE (to_addr) == POST_DEC);
1.1       root      683:   if (data.reverse) data.offset = len;
                    684:   data.len = len;
                    685: 
                    686:   /* If copying requires more than two move insns,
                    687:      copy addresses to registers (to make displacements shorter)
                    688:      and use post-increment if available.  */
                    689:   if (!(data.autinc_from && data.autinc_to)
                    690:       && move_by_pieces_ninsns (len, align) > 2)
                    691:     {
                    692: #ifdef HAVE_PRE_DECREMENT
                    693:       if (data.reverse && ! data.autinc_from)
                    694:        {
1.1.1.2   root      695:          data.from_addr = copy_addr_to_reg (plus_constant (from_addr, len));
1.1       root      696:          data.autinc_from = 1;
                    697:          data.explicit_inc_from = -1;
                    698:        }
                    699: #endif
                    700: #ifdef HAVE_POST_INCREMENT
                    701:       if (! data.autinc_from)
                    702:        {
1.1.1.2   root      703:          data.from_addr = copy_addr_to_reg (from_addr);
1.1       root      704:          data.autinc_from = 1;
                    705:          data.explicit_inc_from = 1;
                    706:        }
                    707: #endif
1.1.1.2   root      708:       if (!data.autinc_from && CONSTANT_P (from_addr))
                    709:        data.from_addr = copy_addr_to_reg (from_addr);
1.1       root      710: #ifdef HAVE_PRE_DECREMENT
                    711:       if (data.reverse && ! data.autinc_to)
                    712:        {
1.1.1.2   root      713:          data.to_addr = copy_addr_to_reg (plus_constant (to_addr, len));
1.1       root      714:          data.autinc_to = 1;
                    715:          data.explicit_inc_to = -1;
                    716:        }
                    717: #endif
                    718: #ifdef HAVE_POST_INCREMENT
                    719:       if (! data.reverse && ! data.autinc_to)
                    720:        {
1.1.1.2   root      721:          data.to_addr = copy_addr_to_reg (to_addr);
1.1       root      722:          data.autinc_to = 1;
                    723:          data.explicit_inc_to = 1;
                    724:        }
                    725: #endif
1.1.1.2   root      726:       if (!data.autinc_to && CONSTANT_P (to_addr))
                    727:        data.to_addr = copy_addr_to_reg (to_addr);
1.1       root      728:     }
                    729: 
                    730: #ifdef STRICT_ALIGNMENT
1.1.1.2   root      731:   if (align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
1.1       root      732:     align = MOVE_MAX;
                    733: #else
                    734:   align = MOVE_MAX;
                    735: #endif
                    736: 
                    737: #ifdef HAVE_movti
                    738:   if (HAVE_movti && align >= GET_MODE_SIZE (TImode))
                    739:     move_by_pieces_1 (gen_movti, TImode, &data);
                    740: #endif
                    741: #ifdef HAVE_movdi
                    742:   if (HAVE_movdi && align >= GET_MODE_SIZE (DImode))
                    743:     move_by_pieces_1 (gen_movdi, DImode, &data);
                    744: #endif
1.1.1.2   root      745: #ifdef HAVE_movsi
1.1       root      746:   if (align >= GET_MODE_SIZE (SImode))
                    747:     move_by_pieces_1 (gen_movsi, SImode, &data);
1.1.1.2   root      748: #endif
                    749: #ifdef HAVE_movhi
                    750:   if (HAVE_movhi && align >= GET_MODE_SIZE (HImode))
1.1       root      751:     move_by_pieces_1 (gen_movhi, HImode, &data);
1.1.1.2   root      752: #endif
                    753: #ifdef HAVE_movqi
1.1       root      754:   move_by_pieces_1 (gen_movqi, QImode, &data);
1.1.1.2   root      755: #else
                    756:   movqi instruction required in machine description
                    757: #endif
1.1       root      758: }
                    759: 
                    760: /* Return number of insns required to move L bytes by pieces.
                    761:    ALIGN (in bytes) is maximum alignment we can assume.  */
                    762: 
1.1.1.2   root      763: static int
1.1       root      764: move_by_pieces_ninsns (l, align)
                    765:      unsigned int l;
                    766:      int align;
                    767: {
                    768:   register int n_insns = 0;
                    769: 
                    770: #ifdef STRICT_ALIGNMENT
1.1.1.2   root      771:   if (align > MOVE_MAX || align >= BIGGEST_ALIGNMENT / BITS_PER_UNIT)
1.1       root      772:     align = MOVE_MAX;
                    773: #else
                    774:   align = MOVE_MAX;
                    775: #endif
                    776: 
                    777: #ifdef HAVE_movti
                    778:   if (HAVE_movti && align >= GET_MODE_SIZE (TImode))
                    779:     n_insns += l / GET_MODE_SIZE (TImode), l %= GET_MODE_SIZE (TImode);
                    780: #endif
                    781: #ifdef HAVE_movdi
                    782:   if (HAVE_movdi && align >= GET_MODE_SIZE (DImode))
                    783:     n_insns += l / GET_MODE_SIZE (DImode), l %= GET_MODE_SIZE (DImode);
                    784: #endif
1.1.1.2   root      785: #ifdef HAVE_movsi
1.1       root      786:   if (HAVE_movsi && align >= GET_MODE_SIZE (SImode))
                    787:     n_insns += l / GET_MODE_SIZE (SImode), l %= GET_MODE_SIZE (SImode);
1.1.1.2   root      788: #endif
                    789: #ifdef HAVE_movhi
1.1       root      790:   if (HAVE_movhi && align >= GET_MODE_SIZE (HImode))
                    791:     n_insns += l / GET_MODE_SIZE (HImode), l %= GET_MODE_SIZE (HImode);
1.1.1.2   root      792: #endif
1.1       root      793:   n_insns += l;
                    794: 
                    795:   return n_insns;
                    796: }
                    797: 
                    798: /* Subroutine of move_by_pieces.  Move as many bytes as appropriate
                    799:    with move instructions for mode MODE.  GENFUN is the gen_... function
                    800:    to make a move insn for that mode.  DATA has all the other info.  */
                    801: 
1.1.1.2   root      802: static void
1.1       root      803: move_by_pieces_1 (genfun, mode, data)
                    804:      rtx (*genfun) ();
                    805:      enum machine_mode mode;
                    806:      struct move_by_pieces *data;
                    807: {
                    808:   register int size = GET_MODE_SIZE (mode);
                    809:   register rtx to1, from1;
                    810: 
                    811:   while (data->len >= size)
                    812:     {
1.1.1.2   root      813:       if (data->reverse) data->offset -= size;
1.1       root      814: 
1.1.1.13  root      815:       to1 = (data->autinc_to
                    816:             ? gen_rtx (MEM, mode, data->to_addr)
                    817:             : change_address (data->to, mode,
                    818:                               plus_constant (data->to_addr, data->offset)));
                    819:       from1 =
                    820:        (data->autinc_from
                    821:         ? gen_rtx (MEM, mode, data->from_addr)
                    822:         : change_address (data->from, mode,
                    823:                           plus_constant (data->from_addr, data->offset)));
1.1       root      824: 
                    825: #ifdef HAVE_PRE_DECREMENT
                    826:       if (data->explicit_inc_to < 0)
1.1.1.2   root      827:        emit_insn (gen_sub2_insn (data->to_addr,
1.1       root      828:                                  gen_rtx (CONST_INT, VOIDmode, size)));
                    829:       if (data->explicit_inc_from < 0)
1.1.1.2   root      830:        emit_insn (gen_sub2_insn (data->from_addr,
1.1       root      831:                                  gen_rtx (CONST_INT, VOIDmode, size)));
                    832: #endif
                    833: 
1.1.1.5   root      834:       emit_insn ((*genfun) (to1, from1));
1.1       root      835: #ifdef HAVE_POST_INCREMENT
                    836:       if (data->explicit_inc_to > 0)
1.1.1.2   root      837:        emit_insn (gen_add2_insn (data->to_addr,
1.1       root      838:                                  gen_rtx (CONST_INT, VOIDmode, size)));
                    839:       if (data->explicit_inc_from > 0)
1.1.1.2   root      840:        emit_insn (gen_add2_insn (data->from_addr,
1.1       root      841:                                  gen_rtx (CONST_INT, VOIDmode, size)));
                    842: #endif
                    843: 
                    844:       if (! data->reverse) data->offset += size;
1.1.1.2   root      845: 
1.1       root      846:       data->len -= size;
                    847:     }
                    848: }
                    849: 
                    850: /* Emit code to move a block Y to a block X.
                    851:    This may be done with string-move instructions,
                    852:    with multiple scalar move instructions, or with a library call.
                    853: 
                    854:    Both X and Y must be MEM rtx's (perhaps inside VOLATILE)
                    855:    with mode BLKmode.
                    856:    SIZE is an rtx that says how long they are.
                    857:    ALIGN is the maximum alignment we can assume they have,
                    858:    measured in bytes.  */
                    859: 
                    860: static void
                    861: emit_block_move (x, y, size, align)
                    862:      rtx x, y;
                    863:      rtx size;
                    864:      int align;
                    865: {
                    866:   if (GET_MODE (x) != BLKmode)
                    867:     abort ();
                    868: 
                    869:   if (GET_MODE (y) != BLKmode)
                    870:     abort ();
                    871: 
                    872:   x = protect_from_queue (x, 1);
                    873:   y = protect_from_queue (y, 0);
                    874: 
1.1.1.2   root      875:   if (GET_CODE (x) != MEM)
1.1       root      876:     abort ();
1.1.1.2   root      877:   if (GET_CODE (y) != MEM)
1.1       root      878:     abort ();
                    879:   if (size == 0)
                    880:     abort ();
                    881: 
                    882:   if (GET_CODE (size) == CONST_INT
                    883:       && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)
                    884:          < MOVE_RATIO))
1.1.1.2   root      885:     move_by_pieces (x, y, INTVAL (size), align);
1.1       root      886:   else
                    887:     {
1.1.1.9   root      888:       /* Try the most limited insn first, because there's no point
                    889:         including more than one in the machine description unless
                    890:         the more limited one has some advantage.  */
                    891: #ifdef HAVE_movstrqi
                    892:       if (HAVE_movstrqi
                    893:          && GET_CODE (size) == CONST_INT
                    894:          && ((unsigned) INTVAL (size)
                    895:              < (1 << (GET_MODE_BITSIZE (QImode) - 1))))
1.1       root      896:        {
1.1.1.14  root      897:          emit_insn (gen_movstrqi (x, y, size,
                    898:                                   gen_rtx (CONST_INT, VOIDmode, align)));
1.1       root      899:          return;
                    900:        }
                    901: #endif
                    902: #ifdef HAVE_movstrhi
                    903:       if (HAVE_movstrhi
                    904:          && GET_CODE (size) == CONST_INT
                    905:          && ((unsigned) INTVAL (size)
1.1.1.5   root      906:              < (1 << (GET_MODE_BITSIZE (HImode) - 1))))
1.1       root      907:        {
1.1.1.14  root      908:          emit_insn (gen_movstrhi (x, y, size,
                    909:                                   gen_rtx (CONST_INT, VOIDmode, align)));
1.1       root      910:          return;
                    911:        }
                    912: #endif
1.1.1.9   root      913: #ifdef HAVE_movstrsi
                    914:       if (HAVE_movstrsi)
1.1.1.5   root      915:        {
1.1.1.14  root      916:          emit_insn (gen_movstrsi (x, y, size,
                    917:                                   gen_rtx (CONST_INT, VOIDmode, align)));
1.1.1.5   root      918:          return;
                    919:        }
                    920: #endif
1.1.1.2   root      921: 
                    922: #ifdef TARGET_MEM_FUNCTIONS
                    923:       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"),
                    924:                         VOIDmode, 3, XEXP (x, 0), Pmode,
                    925:                         XEXP (y, 0), Pmode,
                    926:                         size, Pmode);
                    927: #else
1.1       root      928:       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"),
1.1.1.2   root      929:                         VOIDmode, 3, XEXP (y, 0), Pmode,
                    930:                         XEXP (x, 0), Pmode,
1.1       root      931:                         size, Pmode);
1.1.1.2   root      932: #endif
                    933:     }
                    934: }
                    935: 
                    936: /* Copy all or part of a BLKmode value X into registers starting at REGNO.
                    937:    The number of registers to be filled is NREGS.  */
                    938: 
                    939: static void
                    940: move_block_to_reg (regno, x, nregs)
                    941:      int regno;
                    942:      rtx x;
                    943:      int nregs;
                    944: {
                    945:   int i;
                    946:   if (GET_CODE (x) == CONST_DOUBLE && x != dconst0_rtx)
                    947:     x = force_const_double_mem (x);
                    948:   for (i = 0; i < nregs; i++)
                    949:     {
                    950:       if (GET_CODE (x) == REG)
                    951:        emit_move_insn (gen_rtx (REG, SImode, regno + i),
                    952:                        gen_rtx (SUBREG, SImode, x, i));
                    953:       else if (x == dconst0_rtx)
                    954:        emit_move_insn (gen_rtx (REG, SImode, regno + i),
                    955:                        const0_rtx);
                    956:       else
                    957:        emit_move_insn (gen_rtx (REG, SImode, regno + i),
                    958:                        gen_rtx (MEM, SImode,
1.1.1.10  root      959:                                 memory_address (SImode,
                    960:                                                 plus_constant (XEXP (x, 0),
                    961:                                                                i * GET_MODE_SIZE (SImode)))));
1.1.1.2   root      962:     }
                    963: }
                    964: 
                    965: /* Copy all or part of a BLKmode value X out of registers starting at REGNO.
                    966:    The number of registers to be filled is NREGS.  */
                    967: 
                    968: void
                    969: move_block_from_reg (regno, x, nregs)
                    970:      int regno;
                    971:      rtx x;
                    972:      int nregs;
                    973: {
                    974:   int i;
                    975:   for (i = 0; i < nregs; i++)
                    976:     {
                    977:       if (GET_CODE (x) == REG)
                    978:        emit_move_insn (gen_rtx (SUBREG, SImode, x, i),
                    979:                        gen_rtx (REG, SImode, regno + i));
                    980:       else
                    981:        emit_move_insn (gen_rtx (MEM, SImode,
1.1.1.10  root      982:                                 memory_address (SImode,
                    983:                                                 plus_constant (XEXP (x, 0),
                    984:                                                                i * GET_MODE_SIZE (SImode)))),
1.1.1.2   root      985:                        gen_rtx (REG, SImode, regno + i));
1.1       root      986:     }
                    987: }
1.1.1.2   root      988: 
                    989: /* Mark NREGS consecutive regs, starting at REGNO, as being live now.  */
                    990: 
                    991: static void
                    992: use_regs (regno, nregs)
                    993:      int regno;
                    994:      int nregs;
                    995: {
                    996:   int i;
                    997:   for (i = 0; i < nregs; i++)
                    998:     emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, regno + i)));
                    999: }
1.1       root     1000: 
1.1.1.2   root     1001: /* Write zeros through the storage of OBJECT.
                   1002:    If OBJECT has BLKmode, SIZE is its length in bytes.  */
                   1003: 
                   1004: void
                   1005: clear_storage (object, size)
                   1006:      rtx object;
                   1007:      int size;
                   1008: {
                   1009:   if (GET_MODE (object) == BLKmode)
                   1010:     {
                   1011: #ifdef TARGET_MEM_FUNCTIONS
                   1012:       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memset"),
                   1013:                         VOIDmode, 3,
                   1014:                         XEXP (object, 0), Pmode, const0_rtx, Pmode,
                   1015:                         gen_rtx (CONST_INT, VOIDmode, size), Pmode);
                   1016: #else
                   1017:       emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bzero"),
                   1018:                         VOIDmode, 2,
                   1019:                         XEXP (object, 0), Pmode,
                   1020:                         gen_rtx (CONST_INT, VOIDmode, size), Pmode);
                   1021: #endif
                   1022:     }
                   1023:   else
1.1.1.13  root     1024:     emit_move_insn (object, const0_rtx);
1.1.1.2   root     1025: }
                   1026: 
1.1       root     1027: /* Generate code to copy Y into X.
                   1028:    Both Y and X must have the same mode, except that
                   1029:    Y can be a constant with VOIDmode.
1.1.1.2   root     1030:    This mode cannot be BLKmode; use emit_block_move for that.
1.1       root     1031: 
1.1.1.2   root     1032:    Return the last instruction emitted.  */
                   1033: 
                   1034: rtx
1.1       root     1035: emit_move_insn (x, y)
                   1036:      rtx x, y;
                   1037: {
                   1038:   enum machine_mode mode = GET_MODE (x);
                   1039:   x = protect_from_queue (x, 1);
                   1040:   y = protect_from_queue (y, 0);
                   1041: 
1.1.1.3   root     1042:   if ((CONSTANT_P (y) || GET_CODE (y) == CONST_DOUBLE)
                   1043:       && ! LEGITIMATE_CONSTANT_P (y))
1.1.1.10  root     1044:     {
                   1045:       y = force_const_mem (mode, y);
                   1046:       if (! memory_address_p (mode, y))
                   1047:        y = gen_rtx (MEM, mode, memory_address (mode, XEXP (y, 0)));
                   1048:     }
1.1.1.2   root     1049: 
1.1       root     1050:   if (mode == BLKmode)
                   1051:     abort ();
1.1.1.2   root     1052:   if (mov_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1.1.1.6   root     1053:     return
1.1.1.2   root     1054:       emit_insn (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
                   1055: #if 0
                   1056:   /* It turns out you get much better optimization (in cse and flow)
                   1057:      if you define movdi and movdf instruction patterns
                   1058:      even if they must turn into multiple assembler instructions.  */
1.1       root     1059:   else if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (SImode))
                   1060:     {
                   1061:       register int count = GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode);
                   1062:       register int i;
1.1.1.2   root     1063:       if (GET_CODE (y) == CONST_DOUBLE && y != dconst0_rtx)
                   1064:        y = force_const_double_mem (y);
1.1       root     1065:       for (i = 0; i < count; i++)
                   1066:        {
                   1067:          rtx x1, y1;
                   1068:          if (GET_CODE (x) == REG)
                   1069:            x1 = gen_rtx (SUBREG, SImode, x, i);
                   1070:          else
                   1071:            x1 = gen_rtx (MEM, SImode,
                   1072:                          memory_address (SImode,
                   1073:                                          plus_constant (XEXP (x, 0),
                   1074:                                                         i * GET_MODE_SIZE (SImode))));
                   1075:          if (GET_CODE (y) == REG)
                   1076:            y1 = gen_rtx (SUBREG, SImode, y, i);
1.1.1.2   root     1077:          else if (y == dconst0_rtx)
                   1078:            y1 = const0_rtx;
1.1       root     1079:          else
                   1080:            y1 = gen_rtx (MEM, SImode,
                   1081:                          memory_address (SImode,
                   1082:                                          plus_constant (XEXP (y, 0),
                   1083:                                                         i * GET_MODE_SIZE (SImode))));
                   1084:          emit_insn (gen_movsi (protect_from_queue (x1, 1), protect_from_queue (y1, 0)));
                   1085:        }
                   1086:     }
1.1.1.2   root     1087: #endif
1.1       root     1088:   else
                   1089:     abort ();
                   1090: }
                   1091: 
                   1092: /* Pushing data onto the stack.  */
                   1093: 
                   1094: /* Push a block of length SIZE (perhaps variable)
                   1095:    and return an rtx to address the beginning of the block.
1.1.1.4   root     1096:    Note that it is not possible for the value returned to be a QUEUED.
                   1097:    The value may be stack_pointer_rtx.
                   1098: 
1.1.1.7   root     1099:    The value we return does take account of STACK_POINTER_OFFSET.  */
1.1       root     1100: 
1.1.1.7   root     1101: rtx
1.1       root     1102: push_block (size)
                   1103:      rtx size;
                   1104: {
                   1105:   register rtx temp;
1.1.1.2   root     1106:   if (CONSTANT_P (size) || GET_CODE (size) == REG)
                   1107:     anti_adjust_stack (size);
                   1108:   else
                   1109:     anti_adjust_stack (copy_to_mode_reg (Pmode, size));
1.1.1.6   root     1110: 
1.1       root     1111: #ifdef STACK_GROWS_DOWNWARD
1.1.1.2   root     1112:   temp = stack_pointer_rtx;
1.1       root     1113: #else
                   1114:   temp = gen_rtx (PLUS, Pmode,
1.1.1.2   root     1115:                  stack_pointer_rtx,
1.1.1.11  root     1116:                  negate_rtx (Pmode, size));
1.1       root     1117:   if (GET_CODE (size) != CONST_INT)
                   1118:     temp = force_operand (temp, 0);
                   1119: #endif
1.1.1.7   root     1120: 
                   1121: #ifdef STACK_POINTER_OFFSET
                   1122:   temp = plus_constant (temp, STACK_POINTER_OFFSET);
                   1123: #endif /* STACK_POINTER_OFFSET */
                   1124: 
1.1       root     1125:   return memory_address (QImode, temp);
                   1126: }
                   1127: 
                   1128: static rtx
                   1129: gen_push_operand ()
                   1130: {
                   1131:   return gen_rtx (
                   1132: #ifdef STACK_GROWS_DOWNWARD
                   1133:                  PRE_DEC,
                   1134: #else
                   1135:                  PRE_INC,
                   1136: #endif
                   1137:                  Pmode,
1.1.1.2   root     1138:                  stack_pointer_rtx);
1.1       root     1139: }
                   1140: 
                   1141: /* Generate code to push X onto the stack, assuming it has mode MODE.
                   1142:    MODE is redundant except when X is a CONST_INT (since they don't
                   1143:    carry mode info).
                   1144:    SIZE is an rtx for the size of data to be copied (in bytes),
                   1145:    needed only if X is BLKmode.
1.1.1.13  root     1146: 
                   1147: 
                   1148: 
                   1149: 
                   1150: 
1.1.1.2   root     1151:    ALIGN (in bytes) is maximum alignment we can assume.
                   1152: 
                   1153:    If PARTIAL is nonzero, then copy that many of the first words
                   1154:    of X into registers starting with REG, and push the rest of X.
                   1155:    The amount of space pushed is decreased by PARTIAL words,
                   1156:    rounded *down* to a multiple of PARM_BOUNDARY.
                   1157:    REG must be a hard register in this case.
                   1158: 
                   1159:    EXTRA is the amount in bytes of extra space to leave next to this arg.
                   1160: 
                   1161:    On a machine that lacks real push insns, ARGS_ADDR is the address of
                   1162:    the bottom of the argument block for this call.  We use indexing off there
                   1163:    to store the arg.  On machines with push insns, ARGS_ADDR is 0.
                   1164: 
                   1165:    ARGS_SO_FAR is the size of args previously pushed for this call.  */
1.1       root     1166: 
                   1167: static void
1.1.1.2   root     1168: emit_push_insn (x, mode, size, align, partial, reg, extra, args_addr, args_so_far)
1.1       root     1169:      register rtx x;
                   1170:      enum machine_mode mode;
                   1171:      rtx size;
                   1172:      int align;
1.1.1.2   root     1173:      int partial;
                   1174:      rtx reg;
                   1175:      int extra;
                   1176:      rtx args_addr;
                   1177:      rtx args_so_far;
1.1       root     1178: {
                   1179:   rtx xinner;
1.1.1.6   root     1180:   enum direction stack_direction
                   1181: #ifdef STACK_GROWS_DOWNWARD
                   1182:     = downward;
                   1183: #else
                   1184:     = upward;
                   1185: #endif
                   1186: 
                   1187:   /* Decide where to pad the argument: `downward' for below,
                   1188:      `upward' for above, or `none' for don't pad it.
                   1189:      Default is below for small data on big-endian machines; else above.  */
                   1190:   enum direction where_pad = FUNCTION_ARG_PADDING (mode, size);
1.1       root     1191: 
                   1192:   xinner = x = protect_from_queue (x, 0);
                   1193: 
1.1.1.2   root     1194:   /* If part should go in registers, copy that part
                   1195:      into the appropriate registers.  */
                   1196:   if (partial > 0)
                   1197:     move_block_to_reg (REGNO (reg), x, partial);
                   1198: 
1.1.1.6   root     1199:   if (extra)
                   1200:     {
                   1201:       if (args_addr == 0)
                   1202:        {
                   1203:          /* Push padding now if padding above and stack grows down,
                   1204:             or if padding below and stack grows up.  */
                   1205:          if (where_pad != none && where_pad != stack_direction)
                   1206:            anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra));
                   1207:        }
                   1208:       else
                   1209:        {
                   1210:          /* If space already allocated, just adjust the address we use.  */
                   1211:          if (where_pad == downward)
                   1212:            args_so_far = plus_constant (args_so_far, extra);
                   1213:        }
                   1214:     }
1.1       root     1215: 
                   1216:   if (mode == BLKmode)
                   1217:     {
                   1218:       register rtx temp;
1.1.1.2   root     1219:       int used = partial * UNITS_PER_WORD;
                   1220:       int offset = used % (PARM_BOUNDARY / BITS_PER_UNIT);
                   1221: 
1.1.1.13  root     1222:       used -= offset;
1.1.1.2   root     1223: 
1.1       root     1224:       if (size == 0)
                   1225:        abort ();
                   1226: 
1.1.1.2   root     1227:       if (partial != 0)
                   1228:        xinner = change_address (xinner, BLKmode,
                   1229:                                 plus_constant (XEXP (xinner, 0), used));
                   1230: 
                   1231: #ifdef PUSH_ROUNDING
                   1232:       /* Do it with several push insns if that doesn't take lots of insns
                   1233:         and if there is no difficulty with push insns that skip bytes
                   1234:         on the stack for alignment purposes.  */
                   1235:       if (args_addr == 0
                   1236:          && GET_CODE (size) == CONST_INT
                   1237:          && args_addr == 0
                   1238:          && (move_by_pieces_ninsns ((unsigned) INTVAL (size) - used, align)
                   1239:              < MOVE_RATIO)
                   1240:          && PUSH_ROUNDING (INTVAL (size)) == INTVAL (size))
                   1241:        move_by_pieces (gen_rtx (MEM, BLKmode, gen_push_operand ()), xinner,
                   1242:                        INTVAL (size) - used, align);
1.1       root     1243:       else
1.1.1.2   root     1244: #endif /* PUSH_ROUNDING */
1.1       root     1245:        {
1.1.1.2   root     1246:          /* Otherwise make space on the stack and copy the data
                   1247:             to the address of that space.  */
                   1248: 
                   1249:          /* First deduct part put into registers from the size we need.  */
                   1250:          if (partial != 0)
                   1251:            {
                   1252:              if (GET_CODE (size) == CONST_INT)
                   1253:                size = gen_rtx (CONST_INT, VOIDmode, INTVAL (size) - used);
                   1254:              else
                   1255:                size = expand_binop (GET_MODE (size), sub_optab, size,
                   1256:                                     gen_rtx (CONST_INT, VOIDmode, used),
                   1257:                                     0, 0, OPTAB_LIB_WIDEN);
                   1258:            }
                   1259: 
                   1260:          /* Get the address of the stack space.  */
                   1261:          if (! args_addr)
                   1262:            temp = push_block (size);
                   1263:          else if (GET_CODE (args_so_far) == CONST_INT)
                   1264:            temp = memory_address (BLKmode,
                   1265:                                   plus_constant (args_addr,
1.1.1.13  root     1266:                                                  used + INTVAL (args_so_far)));
1.1.1.2   root     1267:          else
                   1268:            temp = memory_address (BLKmode,
                   1269:                                   plus_constant (gen_rtx (PLUS, Pmode,
                   1270:                                                           args_addr, args_so_far),
1.1.1.13  root     1271:                                                  used));
1.1.1.2   root     1272: 
                   1273: 
                   1274:          /* TEMP is the address of the block.  Copy the data there.  */
                   1275:          if (GET_CODE (size) == CONST_INT
                   1276:              && (move_by_pieces_ninsns ((unsigned) INTVAL (size), align)
                   1277:                  < MOVE_RATIO))
                   1278:            {
                   1279:              move_by_pieces (gen_rtx (MEM, BLKmode, temp), xinner,
                   1280:                              INTVAL (size), align);
                   1281:              return;
                   1282:            }
1.1.1.13  root     1283:          /* Try the most limited insn first, because there's no point
                   1284:             including more than one in the machine description unless
                   1285:             the more limited one has some advantage.  */
1.1.1.9   root     1286: #ifdef HAVE_movstrqi
                   1287:          if (HAVE_movstrqi
                   1288:              && GET_CODE (size) == CONST_INT
                   1289:              && ((unsigned) INTVAL (size)
                   1290:                  < (1 << (GET_MODE_BITSIZE (QImode) - 1))))
1.1       root     1291:            {
1.1.1.9   root     1292:              emit_insn (gen_movstrqi (gen_rtx (MEM, BLKmode, temp),
1.1.1.14  root     1293:                                       xinner, size,
                   1294:                                       gen_rtx (CONST_INT, VOIDmode, align)));
1.1       root     1295:              return;
                   1296:            }
                   1297: #endif
                   1298: #ifdef HAVE_movstrhi
                   1299:          if (HAVE_movstrhi
                   1300:              && GET_CODE (size) == CONST_INT
                   1301:              && ((unsigned) INTVAL (size)
1.1.1.5   root     1302:                  < (1 << (GET_MODE_BITSIZE (HImode) - 1))))
1.1       root     1303:            {
                   1304:              emit_insn (gen_movstrhi (gen_rtx (MEM, BLKmode, temp),
1.1.1.14  root     1305:                                       xinner, size,
                   1306:                                       gen_rtx (CONST_INT, VOIDmode, align)));
1.1       root     1307:              return;
                   1308:            }
                   1309: #endif
1.1.1.9   root     1310: #ifdef HAVE_movstrsi
                   1311:          if (HAVE_movstrsi)
1.1.1.5   root     1312:            {
1.1.1.14  root     1313:              emit_insn (gen_movstrsi (gen_rtx (MEM, BLKmode, temp),
                   1314:                                       xinner, size,
                   1315:                                       gen_rtx (CONST_INT, VOIDmode, align)));
1.1.1.5   root     1316:              return;
                   1317:            }
                   1318: #endif
1.1.1.2   root     1319: 
                   1320:          if (reg_mentioned_p (stack_pointer_rtx, temp))
                   1321:            {
1.1.1.15! root     1322:              /* Now that emit_library_call does force_operand
        !          1323:                 before pushing anything, preadjustment does not work.  */
        !          1324:              temp = copy_to_reg (temp);
        !          1325: #if 0
1.1.1.2   root     1326:              /* Correct TEMP so it holds what will be a description of
                   1327:                 the address to copy to, valid after one arg is pushed.  */
1.1.1.5   root     1328:              int xsize = GET_MODE_SIZE (Pmode);
                   1329: #ifdef PUSH_ROUNDING
                   1330:              xsize = PUSH_ROUNDING (xsize);
                   1331: #endif
                   1332:              xsize = ((xsize + PARM_BOUNDARY / BITS_PER_UNIT - 1)
                   1333:                       / (PARM_BOUNDARY / BITS_PER_UNIT)
                   1334:                       * (PARM_BOUNDARY / BITS_PER_UNIT));
1.1.1.8   root     1335: #ifdef TARGET_MEM_FUNCTIONS
                   1336:              /* If we are calling bcopy, we push one arg before TEMP.
                   1337:                 If calling memcpy, we push two.  */
                   1338:              xsize *= 2;
                   1339: #endif
1.1       root     1340: #ifdef STACK_GROWS_DOWNWARD
1.1.1.4   root     1341:              temp = plus_constant (temp, xsize);
1.1       root     1342: #else
1.1.1.6   root     1343:              temp = plus_constant (temp, -xsize);
1.1.1.15! root     1344: #endif /* not STACK_GROWS_DOWNWARD */
        !          1345: #endif /* 0 */
1.1.1.2   root     1346:            }
                   1347: 
                   1348:          /* Make current_args_size nonzero around the library call
                   1349:             to force it to pop the bcopy-arguments right away.  */
1.1.1.9   root     1350:          NO_DEFER_POP;
1.1.1.2   root     1351: #ifdef TARGET_MEM_FUNCTIONS
                   1352:          emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcpy"),
                   1353:                             VOIDmode, 3, temp, Pmode, XEXP (xinner, 0), Pmode,
                   1354:                             size, Pmode);
                   1355: #else
1.1       root     1356:          emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcopy"),
1.1.1.2   root     1357:                             VOIDmode, 3, XEXP (xinner, 0), Pmode, temp, Pmode,
1.1       root     1358:                             size, Pmode);
1.1.1.2   root     1359: #endif
1.1.1.9   root     1360:          OK_DEFER_POP;
1.1       root     1361:        }
                   1362:     }
1.1.1.2   root     1363:   else if (partial > 0)
1.1       root     1364:     {
1.1.1.14  root     1365:       /* Scalar partly in registers.  */
                   1366: 
1.1.1.2   root     1367:       int size = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
                   1368:       int i;
1.1.1.13  root     1369:       int not_stack;
1.1.1.6   root     1370:       /* # words of start of argument
1.1.1.2   root     1371:         that we must make space for but need not store.  */
                   1372:       int skip = partial % (PARM_BOUNDARY / BITS_PER_WORD);
                   1373:       int args_offset = INTVAL (args_so_far);
                   1374: 
                   1375:       /* If we make space by pushing it, we might as well push
                   1376:         the real data.  Otherwise, we can leave SKIP nonzero
                   1377:         and leave the space uninitialized.  */
                   1378:       if (args_addr == 0)
                   1379:        skip = 0;
                   1380: 
1.1.1.13  root     1381:       /* Now NOT_STACK gets the number of units that we don't need to
                   1382:         allocate on the stack.  */
                   1383:       not_stack = partial - skip;
1.1.1.2   root     1384: 
                   1385:       if (GET_CODE (x) == CONST_DOUBLE && x != dconst0_rtx)
                   1386:        x = force_const_double_mem (x);
                   1387: 
1.1.1.13  root     1388:       /* Loop over all the words allocated on the stack for this arg.  */
1.1.1.14  root     1389:       /* We can do it by words, because any scalar bigger than a word
                   1390:         has a size a multiple of a word.  */
1.1.1.2   root     1391: #ifndef PUSH_ARGS_REVERSED
1.1.1.13  root     1392:       for (i = not_stack; i < size; i++)
1.1.1.2   root     1393: #else
1.1.1.13  root     1394:       for (i = size - 1; i >= not_stack; i--)
1.1.1.2   root     1395: #endif
1.1.1.13  root     1396:        if (i >= not_stack + skip)
                   1397:          {
1.1.1.14  root     1398:            rtx wd;
                   1399:            rtx addr;
                   1400:            /* Get the next word of the value in WD.  */
1.1.1.13  root     1401:            if (GET_CODE (x) == MEM)
1.1.1.14  root     1402:              {
                   1403:                rtx addr = memory_address (SImode,
                   1404:                                           plus_constant (XEXP (x, 0),
                   1405:                                                          i * UNITS_PER_WORD));
                   1406:                /* Copy to a reg, since machine may lack
                   1407:                   memory-to-memory move insns.  */
                   1408:                wd = copy_to_reg (gen_rtx (MEM, SImode, addr));
                   1409:              }
1.1.1.13  root     1410:            else if (GET_CODE (x) == REG)
1.1.1.14  root     1411:              wd = gen_rtx (SUBREG, SImode, x, i);
1.1.1.13  root     1412:            else if (x == dconst0_rtx)
1.1.1.14  root     1413:              wd = const0_rtx;
1.1.1.13  root     1414:            else
                   1415:              abort ();
1.1.1.14  root     1416: 
                   1417:            emit_push_insn (wd,
                   1418:                            SImode, 0, align, 0, 0, 0, args_addr,
                   1419:                            gen_rtx (CONST_INT, VOIDmode,
                   1420:                                     args_offset + i * UNITS_PER_WORD));
                   1421: 
                   1422: 
1.1.1.13  root     1423:          }
1.1       root     1424:     }
                   1425:   else
1.1.1.2   root     1426:     {
                   1427:       rtx addr;
                   1428: #ifdef PUSH_ROUNDING
                   1429:       if (args_addr == 0)
                   1430:        addr = gen_push_operand ();
                   1431:       else
                   1432: #endif
                   1433:        if (GET_CODE (args_so_far) == CONST_INT)
                   1434:          addr
                   1435:            = memory_address (mode,
                   1436:                              plus_constant (args_addr, INTVAL (args_so_far)));
                   1437:       else
                   1438:        addr = memory_address (mode, gen_rtx (PLUS, Pmode, args_addr,
                   1439:                                              args_so_far));
                   1440: 
                   1441:       emit_move_insn (gen_rtx (MEM, mode, addr), x);
                   1442:     }
                   1443: 
1.1.1.6   root     1444:   if (extra && args_addr == 0 && where_pad == stack_direction)
1.1.1.2   root     1445:     anti_adjust_stack (gen_rtx (CONST_INT, VOIDmode, extra));
1.1       root     1446: }
                   1447: 
                   1448: /* Output a library call to function FUN (a SYMBOL_REF rtx)
1.1.1.2   root     1449:    for a value of mode OUTMODE
1.1       root     1450:    with NARGS different arguments, passed as alternating rtx values
                   1451:    and machine_modes to convert them to.
                   1452:    The rtx values should have been passed through protect_from_queue already.  */
                   1453: 
                   1454: void
1.1.1.2   root     1455: emit_library_call (va_alist)
                   1456:      va_dcl
1.1       root     1457: {
1.1.1.2   root     1458:   register va_list p;
1.1       root     1459:   register int args_size = 0;
                   1460:   register int argnum;
1.1.1.2   root     1461:   enum machine_mode outmode;
                   1462:   int nargs;
                   1463:   rtx fun;
                   1464:   rtx orgfun;
                   1465:   int inc;
                   1466:   int count;
                   1467:   rtx *regvec;
                   1468:   rtx argblock = 0;
                   1469:   CUMULATIVE_ARGS args_so_far;
                   1470:   struct arg { rtx value; enum machine_mode mode; };
                   1471:   struct arg *argvec;
                   1472:   int old_args_size = current_args_size;
1.1.1.15! root     1473:   int stack_padding = 0;
1.1.1.2   root     1474: 
                   1475:   va_start (p);
                   1476:   orgfun = fun = va_arg (p, rtx);
                   1477:   outmode = va_arg (p, enum machine_mode);
                   1478:   nargs = va_arg (p, int);
                   1479: 
                   1480:   regvec = (rtx *) alloca (nargs * sizeof (rtx));
                   1481: 
                   1482:   /* Copy all the libcall-arguments out of the varargs data
                   1483:      and into a vector ARGVEC.  */
                   1484:   argvec = (struct arg *) alloca (nargs * sizeof (struct arg));
                   1485:   for (count = 0; count < nargs; count++)
                   1486:     {
1.1.1.14  root     1487:       rtx val = va_arg (p, rtx);
                   1488:       enum machine_mode mode = va_arg (p, enum machine_mode);
                   1489: 
                   1490:       argvec[count].value = val;
                   1491: 
                   1492:       /* Convert the arg value to the mode the library wants.
                   1493:         Also make sure it is a reasonable operand
                   1494:         for a move or push insn.  */
                   1495:       /* ??? It is wrong to do it here; must do it earlier
                   1496:         where we know the signedness of the arg.  */
                   1497:       if (GET_MODE (val) != mode && GET_MODE (val) != VOIDmode)
                   1498:        {
                   1499:          val = gen_reg_rtx (mode);
                   1500:          convert_move (val, argvec[argnum].value, 0);
                   1501:        }
                   1502:       else if (GET_CODE (val) != REG && GET_CODE (val) != MEM
                   1503:               
                   1504:               && ! ((CONSTANT_P (val) || GET_CODE (val) == CONST_DOUBLE)
                   1505:                     && LEGITIMATE_CONSTANT_P (val)))
                   1506:        val = force_operand (val, 0);
                   1507: 
                   1508:       argvec[count].value = val;
                   1509:       argvec[count].mode = mode;
1.1.1.2   root     1510:     }
                   1511:   va_end (p);
                   1512: 
                   1513:   /* If we have no actual push instructions, make space for all the args
                   1514:      right now.  */
                   1515: #ifndef PUSH_ROUNDING
                   1516:   INIT_CUMULATIVE_ARGS (args_so_far, (tree)0);
                   1517:   for (count = 0; count < nargs; count++)
                   1518:     {
                   1519:       register enum machine_mode mode = argvec[count].mode;
                   1520:       register rtx reg;
                   1521:       register int partial;
                   1522: 
                   1523:       reg = FUNCTION_ARG (args_so_far, mode, 0, 1);
                   1524: #ifdef FUNCTION_ARG_PARTIAL_NREGS
                   1525:       partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, 0, 1);
                   1526: #else
                   1527:       partial = 0;
                   1528: #endif
                   1529:       if (reg == 0 || partial != 0)
                   1530:        args_size += GET_MODE_SIZE (mode);
                   1531:       if (partial != 0)
                   1532:        args_size -= partial * GET_MODE_SIZE (SImode);
                   1533:       FUNCTION_ARG_ADVANCE (args_so_far, mode, 0, 1);
                   1534:     }
                   1535: 
                   1536:   if (args_size != 0)
1.1.1.15! root     1537:     {
        !          1538: #ifdef STACK_ARGS_ADJUST
        !          1539:       stack_padding = STACK_ARGS_ADJUST (args_size);
        !          1540:       args_size += stack_padding;
1.1.1.2   root     1541: #endif
1.1.1.15! root     1542:       argblock
        !          1543:        = push_block (round_push (gen_rtx (CONST_INT, VOIDmode, args_size)));
        !          1544:     }
        !          1545: #endif /* no PUSH_ROUNDING */
1.1.1.2   root     1546: 
                   1547:   INIT_CUMULATIVE_ARGS (args_so_far, (tree)0);
                   1548: 
                   1549: #ifdef PUSH_ARGS_REVERSED
                   1550:   inc = -1;
                   1551:   argnum = nargs - 1;
1.1       root     1552: #else
1.1.1.2   root     1553:   inc = 1;
                   1554:   argnum = 0;
1.1       root     1555: #endif
1.1.1.15! root     1556:   args_size = stack_padding;
1.1.1.2   root     1557: 
                   1558:   for (count = 0; count < nargs; count++, argnum += inc)
1.1       root     1559:     {
1.1.1.2   root     1560:       register enum machine_mode mode = argvec[argnum].mode;
                   1561:       register rtx val = argvec[argnum].value;
                   1562:       rtx reg;
                   1563:       int partial;
                   1564:       int arg_size;
                   1565: 
                   1566:       reg = FUNCTION_ARG (args_so_far, mode, 0, 1);
                   1567:       regvec[argnum] = reg;
                   1568: #ifdef FUNCTION_ARG_PARTIAL_NREGS
                   1569:       partial = FUNCTION_ARG_PARTIAL_NREGS (args_so_far, mode, 0, 1);
                   1570: #else
                   1571:       partial = 0;
                   1572: #endif
                   1573: 
                   1574:       if (reg != 0 && partial == 0)
                   1575:        emit_move_insn (reg, val);
                   1576:       else
                   1577:        emit_push_insn (val, mode, 0, 0, partial, reg, 0, argblock,
                   1578:                        gen_rtx (CONST_INT, VOIDmode, args_size));
                   1579: 
                   1580:       /* Compute size of stack space used by this argument.  */
                   1581:       if (reg == 0 || partial != 0)
                   1582:        arg_size = GET_MODE_SIZE (mode);
                   1583:       else
                   1584:        arg_size = 0;
                   1585:       if (partial != 0)
                   1586:        arg_size
                   1587:          -= ((partial * UNITS_PER_WORD)
                   1588:              / (PARM_BOUNDARY / BITS_PER_UNIT)
                   1589:              * (PARM_BOUNDARY / BITS_PER_UNIT));
                   1590: 
                   1591:       args_size += arg_size;
1.1.1.9   root     1592:       NO_DEFER_POP;
1.1.1.2   root     1593:       FUNCTION_ARG_ADVANCE (args_so_far, mode, 0, 1);
1.1       root     1594:     }
                   1595: 
                   1596:   emit_queue ();
1.1.1.2   root     1597: 
                   1598:   fun = prepare_call_address (fun, 0);
                   1599: 
                   1600:   /* Any regs containing parms remain in use through the call.
                   1601:      ??? This is not quite correct, since it doesn't indicate
                   1602:      that they are in use immediately before the call insn.
                   1603:      Currently that doesn't matter since explicitly-used regs
                   1604:      won't be used for reloading.  But if the reloader becomes smarter,
                   1605:      this will have to change somehow.  */
                   1606:   for (count = 0; count < nargs; count++)
                   1607:     if (regvec[count] != 0)
                   1608:       emit_insn (gen_rtx (USE, VOIDmode, regvec[count]));
                   1609: 
                   1610: #ifdef STACK_BOUNDARY
                   1611:   args_size = (args_size + STACK_BYTES - 1) / STACK_BYTES * STACK_BYTES;
                   1612: #endif
                   1613: 
1.1.1.3   root     1614:   /* Don't allow popping to be deferred, since then
                   1615:      cse'ing of library calls could delete a call and leave the pop.  */
1.1.1.9   root     1616:   NO_DEFER_POP;
1.1.1.2   root     1617:   emit_call_1 (fun, get_identifier (XSTR (orgfun, 0)), args_size,
                   1618:               FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
                   1619:               outmode != VOIDmode ? hard_libcall_value (outmode) : 0,
1.1.1.3   root     1620:               old_args_size + 1);
1.1.1.9   root     1621:   OK_DEFER_POP;
1.1       root     1622: }
                   1623: 
                   1624: /* Expand an assignment that stores the value of FROM into TO.
1.1.1.2   root     1625:    If WANT_VALUE is nonzero, return an rtx for the value of TO.
                   1626:    (This may contain a QUEUED rtx.)
                   1627:    Otherwise, the returned value is not meaningful.
                   1628: 
                   1629:    SUGGEST_REG is no longer actually used.
                   1630:    It used to mean, copy the value through a register
                   1631:    and return that register, if that is possible.
                   1632:    But now we do this if WANT_VALUE.
                   1633: 
                   1634:    If the value stored is a constant, we return the constant.  */
1.1       root     1635: 
                   1636: rtx
1.1.1.2   root     1637: expand_assignment (to, from, want_value, suggest_reg)
1.1       root     1638:      tree to, from;
1.1.1.2   root     1639:      int want_value;
                   1640:      int suggest_reg;
1.1       root     1641: {
                   1642:   register rtx to_rtx = 0;
                   1643: 
                   1644:   /* Don't crash if the lhs of the assignment was erroneous.  */
                   1645: 
                   1646:   if (TREE_CODE (to) == ERROR_MARK)
                   1647:     return expand_expr (from, 0, VOIDmode, 0);
                   1648: 
                   1649:   /* Assignment of a structure component needs special treatment
1.1.1.2   root     1650:      if the structure component's rtx is not simply a MEM.
                   1651:      Assignment of an array element at a constant index
                   1652:      has the same problem.  */
                   1653: 
                   1654:   if (TREE_CODE (to) == COMPONENT_REF
                   1655:       || (TREE_CODE (to) == ARRAY_REF
                   1656:          && TREE_CODE (TREE_OPERAND (to, 1)) == INTEGER_CST
                   1657:          && TREE_CODE (TYPE_SIZE (TREE_TYPE (to))) == INTEGER_CST))
1.1       root     1658:     {
1.1.1.2   root     1659:       register enum machine_mode mode1;
                   1660:       int bitsize;
1.1       root     1661:       int volstruct = 0;
1.1.1.2   root     1662:       tree tem = to;
                   1663:       int bitpos = 0;
                   1664:       int unsignedp;
1.1       root     1665: 
1.1.1.2   root     1666:       if (TREE_CODE (to) == COMPONENT_REF)
1.1       root     1667:        {
                   1668:          tree field = TREE_OPERAND (to, 1);
1.1.1.2   root     1669:          bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field);
                   1670:          mode1 = DECL_MODE (TREE_OPERAND (to, 1));
                   1671:          unsignedp = TREE_UNSIGNED (field);
1.1       root     1672:        }
1.1.1.2   root     1673:       else
1.1       root     1674:        {
1.1.1.2   root     1675:          mode1 = TYPE_MODE (TREE_TYPE (to));
                   1676:          bitsize = GET_MODE_BITSIZE (mode1);
                   1677:          unsignedp = TREE_UNSIGNED (TREE_TYPE (to));
1.1       root     1678:        }
                   1679: 
1.1.1.2   root     1680:       /* Compute cumulative bit-offset for nested component-refs
                   1681:         and array-refs, and find the ultimate containing object.  */
1.1       root     1682: 
1.1.1.2   root     1683:       while (1)
1.1       root     1684:        {
1.1.1.2   root     1685:          if (TREE_CODE (tem) == COMPONENT_REF)
                   1686:            {
                   1687:              bitpos += DECL_OFFSET (TREE_OPERAND (tem, 1));
                   1688:              if (TREE_THIS_VOLATILE (tem))
                   1689:                volstruct = 1;
                   1690:            }
                   1691:          else if (TREE_CODE (tem) == ARRAY_REF
                   1692:                   && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
                   1693:                   && TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) == INTEGER_CST)
                   1694:            {
                   1695:              bitpos += (TREE_INT_CST_LOW (TREE_OPERAND (tem, 1))
                   1696:                         * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tem)))
                   1697:                         * TYPE_SIZE_UNIT (TREE_TYPE (tem)));
                   1698:            }
                   1699:          else
                   1700:            break;
                   1701:          tem = TREE_OPERAND (tem, 0);
1.1       root     1702:        }
                   1703: 
1.1.1.2   root     1704:       /* If we are going to use store_bit_field and extract_bit_field,
                   1705:         make sure to_rtx will be safe for multiple use.  */
                   1706:       if (mode1 == BImode && want_value)
                   1707:        tem = stabilize_reference (tem);
1.1       root     1708: 
1.1.1.2   root     1709:       to_rtx = expand_expr (tem, 0, VOIDmode, 0);
                   1710: 
                   1711:       return store_field (to_rtx, bitsize, bitpos, mode1, from,
1.1.1.10  root     1712:                          (want_value
                   1713:                           /* Spurious cast makes HPUX compiler happy.  */
                   1714:                           ? (enum machine_mode) TYPE_MODE (TREE_TYPE (to))
                   1715:                           : VOIDmode),
1.1.1.14  root     1716:                          unsignedp,
                   1717:                          TYPE_ALIGN (TREE_TYPE (to)));
1.1       root     1718:     }
                   1719: 
                   1720:   /* Ordinary treatment.  Expand TO to get a REG or MEM rtx.
                   1721:      Don't re-expand if it was expanded already (in COMPONENT_REF case).  */
                   1722: 
                   1723:   if (to_rtx == 0)
                   1724:     to_rtx = expand_expr (to, 0, VOIDmode, 0);
                   1725: 
                   1726:   /* Compute FROM and store the value in the rtx we got.  */
                   1727: 
1.1.1.2   root     1728:   return store_expr (from, to_rtx, want_value);
1.1       root     1729: }
                   1730: 
                   1731: /* Generate code for computing expression EXP,
1.1.1.2   root     1732:    and storing the value into TARGET.
                   1733:    Returns TARGET or an equivalent value.
                   1734:    TARGET may contain a QUEUED rtx.
1.1       root     1735: 
1.1.1.2   root     1736:    If SUGGEST_REG is nonzero, copy the value through a register
                   1737:    and return that register, if that is possible.
                   1738: 
                   1739:    If the value stored is a constant, we return the constant.  */
                   1740: 
                   1741: rtx
                   1742: store_expr (exp, target, suggest_reg)
1.1       root     1743:      register tree exp;
                   1744:      register rtx target;
1.1.1.2   root     1745:      int suggest_reg;
1.1       root     1746: {
1.1.1.2   root     1747:   register rtx temp;
                   1748:   int dont_return_target = 0;
                   1749: 
                   1750:   /* Copying a non-constant CONSTRUCTOR needs special treatment.  */
                   1751: 
                   1752:   if (TREE_CODE (exp) == CONSTRUCTOR && ! TREE_LITERAL (exp))
                   1753:     {
                   1754:       store_constructor (exp, target);
                   1755:       return target;
                   1756:     }
                   1757: 
                   1758:   if (suggest_reg && GET_CODE (target) == MEM && GET_MODE (target) != BLKmode)
                   1759:     /* If target is in memory and caller wants value in a register instead,
                   1760:        arrange that.  Pass TARGET as target for expand_expr so that,
                   1761:        if EXP is another assignment, SUGGEST_REG will be nonzero for it.
                   1762:        We know expand_expr will not use the target in that case.  */
                   1763:     {
                   1764:       temp = expand_expr (exp, cse_not_expected ? 0 : target,
                   1765:                          GET_MODE (target), 0);
                   1766:       if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
                   1767:        temp = copy_to_reg (temp);
                   1768:       dont_return_target = 1;
                   1769:     }
                   1770:   else if (queued_subexp_p (target))
                   1771:     /* If target contains a postincrement, it is not safe
                   1772:        to use as the returned value.  It would access the wrong
                   1773:        place by the time the queued increment gets output.
                   1774:        So copy the value through a temporary and use that temp
                   1775:        as the result.  */
                   1776:     {
                   1777:       temp = expand_expr (exp, 0, GET_MODE (target), 0);
                   1778:       if (GET_MODE (temp) != BLKmode && GET_MODE (temp) != VOIDmode)
                   1779:        temp = copy_to_reg (temp);
                   1780:       dont_return_target = 1;
                   1781:     }
                   1782:   else
                   1783:     {
                   1784:       temp = expand_expr (exp, target, GET_MODE (target), 0);
                   1785:       /* DO return TARGET if it's a specified hardware register.
                   1786:         expand_return relies on this.  */
                   1787:       if (!(target && GET_CODE (target) == REG
                   1788:            && REGNO (target) < FIRST_PSEUDO_REGISTER)
                   1789:          && (CONSTANT_P (temp) || GET_CODE (temp) == CONST_DOUBLE))
                   1790:        dont_return_target = 1;
                   1791:     }
                   1792: 
1.1.1.12  root     1793:   /* If value was not generated in the target, store it there.
                   1794:      Convert the value to TARGET's type first if nec.  */
1.1.1.2   root     1795: 
1.1       root     1796:   if (temp != target && TREE_CODE (exp) != ERROR_MARK)
                   1797:     {
                   1798:       target = protect_from_queue (target, 1);
                   1799:       if (GET_MODE (temp) != GET_MODE (target)
                   1800:          && GET_MODE (temp) != VOIDmode)
1.1.1.2   root     1801:        {
                   1802:          int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
                   1803:          if (dont_return_target)
1.1.1.12  root     1804:            {
                   1805:              /* In this case, we will return TEMP,
                   1806:                 so make sure it has the proper mode.
                   1807:                 But don't forget to store the value into TARGET.  */
                   1808:              temp = convert_to_mode (GET_MODE (target), temp, unsignedp);
                   1809:              emit_move_insn (target, temp);
                   1810:            }
1.1.1.2   root     1811:          else
                   1812:            convert_move (target, temp, unsignedp);
                   1813:        }
                   1814: 
1.1       root     1815:       else if (GET_MODE (temp) == BLKmode)
                   1816:        emit_block_move (target, temp, expr_size (exp),
                   1817:                         TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
                   1818:       else
                   1819:        emit_move_insn (target, temp);
                   1820:     }
1.1.1.2   root     1821:   if (dont_return_target)
                   1822:     return temp;
1.1       root     1823:   return target;
                   1824: }
                   1825: 
1.1.1.2   root     1826: /* Store the value of constructor EXP into the rtx TARGET.
                   1827:    TARGET is either a REG or a MEM.  */
1.1       root     1828: 
1.1.1.2   root     1829: static void
                   1830: store_constructor (exp, target)
                   1831:      tree exp;
                   1832:      rtx target;
1.1       root     1833: {
1.1.1.7   root     1834:   /* Don't try copying piece by piece into a hard register
                   1835:      since that is vulnerable to being clobbered by EXP.
                   1836:      Instead, construct in a pseudo register and then copy it all.  */
                   1837:   if (GET_CODE (target) == REG && REGNO (target) < FIRST_PSEUDO_REGISTER)
                   1838:     {
                   1839:       rtx temp = gen_reg_rtx (GET_MODE (target));
                   1840:       store_constructor (exp, temp);
                   1841:       emit_move_insn (target, temp);
                   1842:       return;
                   1843:     }
                   1844: 
1.1.1.2   root     1845:   if (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE)
1.1       root     1846:     {
1.1.1.2   root     1847:       register tree elt;
1.1       root     1848: 
1.1.1.2   root     1849:       /* If the constructor has fewer fields than the structure,
                   1850:         clear the whole structure first.  */
1.1       root     1851: 
1.1.1.2   root     1852:       if (list_length (CONSTRUCTOR_ELTS (exp))
                   1853:          != list_length (TYPE_FIELDS (TREE_TYPE (exp))))
                   1854:        clear_storage (target, int_size_in_bytes (TREE_TYPE (exp)));
                   1855:       else
                   1856:        /* Inform later passes that the old value is dead.  */
                   1857:        emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
                   1858: 
                   1859:       /* Store each element of the constructor into
                   1860:         the corresponding field of TARGET.  */
                   1861: 
                   1862:       for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
                   1863:        {
                   1864:          register tree field = TREE_PURPOSE (elt);
                   1865:          register enum machine_mode mode;
                   1866:          int bitsize;
                   1867:          int bitpos;
                   1868:          int unsignedp;
                   1869: 
                   1870:          bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field);
                   1871:          mode = DECL_MODE (field);
                   1872:          unsignedp = TREE_UNSIGNED (field);
                   1873: 
                   1874:          bitpos = DECL_OFFSET (field);
                   1875: 
                   1876:          store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt),
1.1.1.15! root     1877:                       /* The alignment of TARGET is
        !          1878:                          at least what its type requires.  */
        !          1879:                       VOIDmode, 0, TYPE_ALIGN (TREE_TYPE (exp)));
1.1.1.2   root     1880:        }
                   1881:     }
                   1882:   else if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
                   1883:     {
                   1884:       register tree elt;
                   1885:       register int i;
                   1886:       tree domain = TYPE_DOMAIN (TREE_TYPE (exp));
                   1887:       int minelt = TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain));
                   1888:       int maxelt = TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain));
                   1889:       tree elttype = TREE_TYPE (TREE_TYPE (exp));
                   1890: 
                   1891:       /* If the constructor has fewer fields than the structure,
                   1892:         clear the whole structure first.  */
                   1893: 
                   1894:       if (list_length (CONSTRUCTOR_ELTS (exp)) < maxelt - minelt + 1)
                   1895:        clear_storage (target, maxelt - minelt + 1);
                   1896:       else
                   1897:        /* Inform later passes that the old value is dead.  */
                   1898:        emit_insn (gen_rtx (CLOBBER, VOIDmode, target));
                   1899: 
                   1900:       /* Store each element of the constructor into
                   1901:         the corresponding element of TARGET, determined
                   1902:         by counting the elements.  */
                   1903:       for (elt = CONSTRUCTOR_ELTS (exp), i = 0;
                   1904:           elt;
                   1905:           elt = TREE_CHAIN (elt), i++)
                   1906:        {
                   1907:          register enum machine_mode mode;
                   1908:          int bitsize;
                   1909:          int bitpos;
                   1910:          int unsignedp;
                   1911: 
                   1912:          mode = TYPE_MODE (elttype);
                   1913:          bitsize = GET_MODE_BITSIZE (mode);
                   1914:          unsignedp = TREE_UNSIGNED (elttype);
                   1915: 
                   1916:          bitpos = (i * TREE_INT_CST_LOW (TYPE_SIZE (elttype))
                   1917:                    * TYPE_SIZE_UNIT (elttype));
                   1918: 
                   1919:          store_field (target, bitsize, bitpos, mode, TREE_VALUE (elt),
1.1.1.15! root     1920:                       /* The alignment of TARGET is
        !          1921:                          at least what its type requires.  */
        !          1922:                       VOIDmode, 0, TYPE_ALIGN (TREE_TYPE (exp)));
1.1.1.2   root     1923:        }
                   1924:     }
                   1925: }
                   1926: 
                   1927: /* Store the value of EXP (an expression tree)
                   1928:    into a subfield of TARGET which has mode MODE and occupies
                   1929:    BITSIZE bits, starting BITPOS bits from the start of TARGET.
                   1930: 
                   1931:    If VALUE_MODE is VOIDmode, return nothing in particular.
                   1932:    UNSIGNEDP is not used in this case.
                   1933: 
                   1934:    Otherwise, return an rtx for the value stored.  This rtx
                   1935:    has mode VALUE_MODE if that is convenient to do.
1.1.1.14  root     1936:    In this case, UNSIGNEDP must be nonzero if the value is an unsigned type.
                   1937: 
                   1938:    ALIGN is the alignment that TARGET is known to have, measured in bytes.  */
1.1.1.2   root     1939: 
                   1940: static rtx
1.1.1.14  root     1941: store_field (target, bitsize, bitpos, mode, exp, value_mode, unsignedp, align)
1.1.1.2   root     1942:      rtx target;
                   1943:      int bitsize, bitpos;
                   1944:      enum machine_mode mode;
                   1945:      tree exp;
                   1946:      enum machine_mode value_mode;
                   1947:      int unsignedp;
1.1.1.14  root     1948:      int align;
1.1.1.2   root     1949: {
                   1950:   /* If the structure is in a register or if the component
                   1951:      is a bit field, we cannot use addressing to access it.
                   1952:      Use bit-field techniques or SUBREG to store in it.  */
                   1953: 
                   1954:   if (mode == BImode || GET_CODE (target) == REG
                   1955:       || GET_CODE (target) == SUBREG)
                   1956:     {
                   1957:       store_bit_field (target, bitsize, bitpos,
                   1958:                       mode,
1.1.1.14  root     1959:                       expand_expr (exp, 0, VOIDmode, 0),
                   1960:                       align);
1.1.1.2   root     1961:       if (value_mode != VOIDmode)
                   1962:        return extract_bit_field (target, bitsize, bitpos, unsignedp,
1.1.1.14  root     1963:                                  0, value_mode, 0, align);
1.1.1.2   root     1964:       return const0_rtx;
                   1965:     }
                   1966:   else
                   1967:     {
                   1968:       rtx addr = XEXP (target, 0);
                   1969:       rtx to_rtx;
                   1970: 
                   1971:       /* If a value is wanted, it must be the lhs;
                   1972:         so make the address stable for multiple use.  */
                   1973: 
                   1974:       if (value_mode != VOIDmode && GET_CODE (addr) != REG
                   1975:          && ! CONSTANT_ADDRESS_P (addr))
                   1976:        addr = copy_to_reg (addr);
                   1977: 
                   1978:       /* Now build a reference to just the desired component.  */
                   1979: 
                   1980:       to_rtx = change_address (target, mode,
                   1981:                               plus_constant (addr,
                   1982:                                              (bitpos / BITS_PER_UNIT)));
1.1.1.10  root     1983:       MEM_IN_STRUCT_P (to_rtx) = 1;
1.1.1.2   root     1984: 
                   1985:       return store_expr (exp, to_rtx, value_mode != VOIDmode);
                   1986:     }
                   1987: }
                   1988: 
                   1989: /* Given an rtx VALUE that may contain additions and multiplications,
                   1990:    return an equivalent value that just refers to a register or memory.
                   1991:    This is done by generating instructions to perform the arithmetic
                   1992:    and returning a pseudo-register containing the value.  */
                   1993: 
                   1994: rtx
                   1995: force_operand (value, target)
                   1996:      rtx value, target;
                   1997: {
                   1998:   register optab binoptab = 0;
                   1999:   register rtx op2;
                   2000:   /* Use subtarget as the target for operand 0 of a binary operation.  */
                   2001:   register rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
                   2002: 
                   2003:   if (GET_CODE (value) == PLUS)
                   2004:     binoptab = add_optab;
                   2005:   else if (GET_CODE (value) == MINUS)
                   2006:     binoptab = sub_optab;
                   2007:   else if (GET_CODE (value) == MULT)
                   2008:     {
                   2009:       op2 = XEXP (value, 1);
                   2010:       if (!CONSTANT_P (op2)
                   2011:          && !(GET_CODE (op2) == REG && op2 != subtarget))
                   2012:        subtarget = 0;
                   2013:       return expand_mult (GET_MODE (value),
                   2014:                          force_operand (XEXP (value, 0), subtarget),
                   2015:                          force_operand (op2, 0),
                   2016:                          target, 0);
                   2017:     }
                   2018: 
                   2019:   if (binoptab)
                   2020:     {
                   2021:       op2 = XEXP (value, 1);
                   2022:       if (!CONSTANT_P (op2)
                   2023:          && !(GET_CODE (op2) == REG && op2 != subtarget))
                   2024:        subtarget = 0;
                   2025:       if (binoptab == sub_optab
                   2026:          && GET_CODE (op2) == CONST_INT && INTVAL (op2) < 0)
                   2027:        {
                   2028:          binoptab = add_optab;
                   2029:          op2 = gen_rtx (CONST_INT, VOIDmode, - INTVAL (op2));
                   2030:        }
                   2031:       return expand_binop (GET_MODE (value), binoptab,
                   2032:                           force_operand (XEXP (value, 0), subtarget),
                   2033:                           force_operand (op2, 0),
                   2034:                           target, 0, OPTAB_LIB_WIDEN);
                   2035:       /* We give UNSIGNEP = 0 to expand_binop
                   2036:         because the only operations we are expanding here are signed ones.  */
                   2037:     }
                   2038:   return value;
                   2039: }
                   2040: 
                   2041: /* expand_expr: generate code for computing expression EXP.
1.1.1.14  root     2042:    An rtx for the computed value is returned.  The value is never null.
                   2043:    In the case of a void EXP, const0_rtx is returned.
1.1.1.2   root     2044: 
                   2045:    The value may be stored in TARGET if TARGET is nonzero.
1.1       root     2046:    TARGET is just a suggestion; callers must assume that
                   2047:    the rtx returned may not be the same as TARGET.
                   2048: 
1.1.1.2   root     2049:    If TARGET is CONST0_RTX, it means that the value will be ignored.
                   2050: 
1.1       root     2051:    If TMODE is not VOIDmode, it suggests generating the
                   2052:    result in mode TMODE.  But this is done only when convenient.
                   2053:    Otherwise, TMODE is ignored and the value generated in its natural mode.
                   2054:    TMODE is just a suggestion; callers must assume that
                   2055:    the rtx returned may not have mode TMODE.
                   2056: 
1.1.1.2   root     2057:    If MODIFIER is EXPAND_SUM then when EXP is an addition
1.1       root     2058:    we can return an rtx of the form (MULT (REG ...) (CONST_INT ...))
                   2059:    or a nest of (PLUS ...) and (MINUS ...) where the terms are
                   2060:    products as above, or REG or MEM, or constant.
1.1.1.2   root     2061:    Ordinarily in such cases we would output mul or add instructions
                   2062:    and then return a pseudo reg containing the sum.
                   2063: 
                   2064:    If MODIFIER is EXPAND_CONST_ADDRESS then it is ok to return
                   2065:    a MEM rtx whose address is a constant that isn't a legitimate address.  */
1.1       root     2066: 
                   2067: /* Subroutine of expand_expr:
1.1.1.13  root     2068:    save the non-copied parts (LIST) of an expr (LHS), and return a list
                   2069:    which can restore these values to their previous values,
                   2070:    should something modify their storage.  */
                   2071: static tree
                   2072: save_noncopied_parts (lhs, list)
                   2073:      tree lhs;
                   2074:      tree list;
                   2075: {
                   2076:   tree tail;
                   2077:   tree parts = 0;
                   2078: 
                   2079:   for (tail = list; tail; tail = TREE_CHAIN (tail))
                   2080:     if (TREE_CODE (TREE_VALUE (tail)) == TREE_LIST)
                   2081:       parts = chainon (parts, save_noncopied_parts (TREE_VALUE (tail)));
                   2082:     else
                   2083:       {
                   2084:        tree part = TREE_VALUE (tail);
                   2085:        tree part_type = TREE_TYPE (part);
                   2086:        parts = tree_cons (save_expr (build_component_ref (lhs, part, parts, 0)),
                   2087:                           build_nt (RTL_EXPR, 0, (tree) assign_stack_local (TYPE_MODE (part_type), int_size_in_bytes (part_type))),
                   2088:                           parts);
                   2089:        store_expr (TREE_PURPOSE (parts), RTL_EXPR_RTL (TREE_VALUE (parts)), 0);
                   2090:       }
                   2091:   return parts;
                   2092: }
                   2093: 
                   2094: /* Subroutine of expand_expr:
1.1       root     2095:    return the target to use when recursively expanding
                   2096:    the first operand of an arithmetic operation.  */
                   2097: 
                   2098: static rtx
                   2099: validate_subtarget (subtarget, otherop)
                   2100:      rtx subtarget;
                   2101:      tree otherop;
                   2102: {
                   2103:   if (TREE_LITERAL (otherop))
                   2104:     return subtarget;
                   2105:   if (TREE_CODE (otherop) == VAR_DECL
                   2106:       && DECL_RTL (otherop) != subtarget)
                   2107:     return subtarget;
                   2108:   return 0;
                   2109: }
                   2110: 
                   2111: rtx
1.1.1.2   root     2112: expand_expr (exp, target, tmode, modifier)
1.1       root     2113:      register tree exp;
                   2114:      rtx target;
                   2115:      enum machine_mode tmode;
1.1.1.2   root     2116:      enum expand_modifier modifier;
1.1       root     2117: {
                   2118:   register rtx op0, op1, temp;
                   2119:   tree type = TREE_TYPE (exp);
                   2120:   register enum machine_mode mode = TYPE_MODE (type);
                   2121:   register enum tree_code code = TREE_CODE (exp);
1.1.1.2   root     2122:   optab this_optab;
1.1       root     2123:   int negate_1;
                   2124:   /* Use subtarget as the target for operand 0 of a binary operation.  */
                   2125:   rtx subtarget = (target != 0 && GET_CODE (target) == REG ? target : 0);
1.1.1.2   root     2126:   rtx original_target = target;
                   2127:   int ignore = target == const0_rtx;
                   2128: 
1.1.1.7   root     2129:   /* Don't use hard regs as subtargets, because the combiner
                   2130:      can only handle pseudo regs.  */
                   2131:   if (subtarget && REGNO (subtarget) < FIRST_PSEUDO_REGISTER)
                   2132:     subtarget = 0;
                   2133: 
1.1.1.2   root     2134:   if (ignore) target = 0, original_target = 0;
1.1       root     2135: 
                   2136:   /* If will do cse, generate all results into registers
                   2137:      since 1) that allows cse to find more things
                   2138:      and 2) otherwise cse could produce an insn the machine
                   2139:      cannot support.  */
                   2140: 
                   2141:   if (! cse_not_expected && mode != BLKmode)
                   2142:     target = subtarget;
                   2143: 
1.1.1.2   root     2144:   /* No sense saving up arithmetic to be done
                   2145:      if it's all in the wrong mode to form part of an address.
                   2146:      And force_operand won't know whether to sign-extend or zero-extend.  */
                   2147: 
                   2148:   if (mode != Pmode && modifier == EXPAND_SUM)
1.1.1.6   root     2149:     modifier = EXPAND_NORMAL;
1.1.1.2   root     2150: 
1.1       root     2151:   switch (code)
                   2152:     {
1.1.1.4   root     2153:     case PARM_DECL:
                   2154:       if (DECL_RTL (exp) == 0)
                   2155:        {
                   2156:          error_with_decl (exp, "prior parameter's size depends on `%s'");
                   2157:          return const0_rtx;
                   2158:        }
                   2159: 
1.1       root     2160:     case FUNCTION_DECL:
                   2161:     case VAR_DECL:
                   2162:     case RESULT_DECL:
                   2163:       if (DECL_RTL (exp) == 0)
                   2164:        abort ();
1.1.1.14  root     2165:       /* This is the case of an array whose size is to be determined
                   2166:         from its initializer, while the initializer is still being parsed.
                   2167:         See expand_decl.  */
                   2168:       if (GET_CODE (DECL_RTL (exp)) == MEM
                   2169:          && GET_CODE (XEXP (DECL_RTL (exp), 0)) == REG)
                   2170:        return change_address (DECL_RTL (exp), BLKmode,
                   2171:                               XEXP (DECL_RTL (exp), 0));
1.1.1.2   root     2172:       if (GET_CODE (DECL_RTL (exp)) == MEM
                   2173:          && modifier != EXPAND_CONST_ADDRESS)
                   2174:        {
                   2175:          /* DECL_RTL probably contains a constant address.
                   2176:             On RISC machines where a constant address isn't valid,
                   2177:             make some insns to get that address into a register.  */
1.1.1.7   root     2178:          if (!memory_address_p (DECL_MODE (exp), XEXP (DECL_RTL (exp), 0))
                   2179:              || (flag_force_addr
                   2180:                  && CONSTANT_ADDRESS_P (XEXP (DECL_RTL (exp), 0))))
1.1.1.2   root     2181:            return change_address (DECL_RTL (exp), VOIDmode,
                   2182:                                   copy_rtx (XEXP (DECL_RTL (exp), 0)));
                   2183:        }
1.1       root     2184:       return DECL_RTL (exp);
                   2185: 
                   2186:     case INTEGER_CST:
1.1.1.7   root     2187:       if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_INT)
                   2188:        return gen_rtx (CONST_INT, VOIDmode, TREE_INT_CST_LOW (exp));
1.1.1.8   root     2189:       /* Generate immediate CONST_DOUBLE
1.1.1.7   root     2190:         which will be turned into memory by reload if necessary.  */
1.1.1.8   root     2191:       return immed_double_const (TREE_INT_CST_LOW (exp),
                   2192:                                 TREE_INT_CST_HIGH (exp),
                   2193:                                 mode);
1.1       root     2194: 
                   2195:     case CONST_DECL:
                   2196:       return expand_expr (DECL_INITIAL (exp), target, VOIDmode, 0);
                   2197: 
                   2198:     case REAL_CST:
1.1.1.7   root     2199:       /* If optimized, generate immediate CONST_DOUBLE
                   2200:         which will be turned into memory by reload if necessary.  */
1.1       root     2201:       if (!cse_not_expected)
                   2202:        return immed_real_const (exp);
                   2203:     case COMPLEX_CST:
                   2204:     case STRING_CST:
1.1.1.8   root     2205:       if (! TREE_CST_RTL (exp))
                   2206:        output_constant_def (exp);
                   2207: 
                   2208:       /* TREE_CST_RTL probably contains a constant address.
                   2209:         On RISC machines where a constant address isn't valid,
                   2210:         make some insns to get that address into a register.  */
                   2211:       if (GET_CODE (TREE_CST_RTL (exp)) == MEM
                   2212:          && modifier != EXPAND_CONST_ADDRESS
                   2213:          && !memory_address_p (mode, XEXP (TREE_CST_RTL (exp), 0)))
                   2214:        return change_address (TREE_CST_RTL (exp), VOIDmode,
                   2215:                               copy_rtx (XEXP (TREE_CST_RTL (exp), 0)));
1.1       root     2216:       return TREE_CST_RTL (exp);
                   2217: 
                   2218:     case SAVE_EXPR:
                   2219:       if (SAVE_EXPR_RTL (exp) == 0)
                   2220:        {
1.1.1.5   root     2221:          rtx reg = gen_reg_rtx (mode);
                   2222:          SAVE_EXPR_RTL (exp) = reg;
                   2223:          store_expr (TREE_OPERAND (exp, 0), reg, 0);
                   2224:          if (!optimize)
                   2225:            save_expr_regs = gen_rtx (EXPR_LIST, VOIDmode, reg,
                   2226:                                      save_expr_regs);
1.1       root     2227:        }
1.1.1.2   root     2228:       /* Don't let the same rtl node appear in two places.  */
1.1       root     2229:       return SAVE_EXPR_RTL (exp);
                   2230: 
1.1.1.2   root     2231:     case RTL_EXPR:
1.1.1.10  root     2232:       if (RTL_EXPR_SEQUENCE (exp) == const0_rtx)
                   2233:        abort ();
                   2234:       emit_insns (RTL_EXPR_SEQUENCE (exp));
                   2235:       RTL_EXPR_SEQUENCE (exp) = const0_rtx;
1.1.1.2   root     2236:       return RTL_EXPR_RTL (exp);
                   2237: 
                   2238:     case CONSTRUCTOR:
                   2239:       /* All elts simple constants => refer to a constant in memory.  */
                   2240:       if (TREE_STATIC (exp))
                   2241:        /* For aggregate types with non-BLKmode modes,
                   2242:           this should ideally construct a CONST_INT.  */
1.1.1.14  root     2243:        {
                   2244:          rtx constructor = output_constant_def (exp);
                   2245:          if (! memory_address_p (GET_MODE (constructor),
                   2246:                                  XEXP (constructor, 0)))
                   2247:            constructor = change_address (constructor, VOIDmode,
                   2248:                                          XEXP (constructor, 0));
                   2249:          return constructor;
                   2250:        }
1.1.1.2   root     2251: 
                   2252:       if (ignore)
                   2253:        {
                   2254:          tree elt;
                   2255:          for (elt = CONSTRUCTOR_ELTS (exp); elt; elt = TREE_CHAIN (elt))
                   2256:            expand_expr (TREE_VALUE (elt), const0_rtx, VOIDmode, 0);
                   2257:          return const0_rtx;
                   2258:        }
                   2259:       else
                   2260:        {
                   2261:          if (target == 0)
                   2262:            target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
                   2263:                              get_structure_value_addr (expr_size (exp)));
                   2264:          store_expr (exp, target, 0);
                   2265:          return target;
                   2266:        }
                   2267: 
1.1       root     2268:     case INDIRECT_REF:
                   2269:       {
                   2270:        tree exp1 = TREE_OPERAND (exp, 0);
                   2271:        tree exp2;
                   2272: 
                   2273:        /* A SAVE_EXPR as the address in an INDIRECT_EXPR is generated
                   2274:           for  *PTR += ANYTHING  where PTR is put inside the SAVE_EXPR.
                   2275:           This code has the same general effect as simply doing
                   2276:           expand_expr on the save expr, except that the expression PTR
                   2277:           is computed for use as a memory address.  This means different
                   2278:           code, suitable for indexing, may be generated.  */
                   2279:        if (TREE_CODE (exp1) == SAVE_EXPR
                   2280:            && SAVE_EXPR_RTL (exp1) == 0
                   2281:            && TREE_CODE (exp2 = TREE_OPERAND (exp1, 0)) != ERROR_MARK
                   2282:            && TYPE_MODE (TREE_TYPE (exp1)) == Pmode
                   2283:            && TYPE_MODE (TREE_TYPE (exp2)) == Pmode)
                   2284:          {
1.1.1.2   root     2285:            temp = expand_expr (TREE_OPERAND (exp1, 0), 0, VOIDmode, EXPAND_SUM);
1.1       root     2286:            op0 = memory_address (mode, temp);
                   2287:            op0 = copy_all_regs (op0);
                   2288:            SAVE_EXPR_RTL (exp1) = op0;
                   2289:          }
                   2290:        else
                   2291:          {
1.1.1.2   root     2292:            op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, EXPAND_SUM);
1.1       root     2293:            op0 = memory_address (mode, op0);
                   2294:          }
                   2295:       }
                   2296:       temp = gen_rtx (MEM, mode, op0);
1.1.1.2   root     2297:       /* If address was computed by addition,
                   2298:         mark this as an element of an aggregate.  */
                   2299:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == PLUS_EXPR
                   2300:          || (TREE_CODE (TREE_OPERAND (exp, 0)) == SAVE_EXPR
                   2301:              && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == PLUS_EXPR))
1.1.1.10  root     2302:        MEM_IN_STRUCT_P (temp) = 1;
1.1.1.13  root     2303:       MEM_VOLATILE_P (temp) = TREE_THIS_VOLATILE (exp) || flag_volatile;
1.1.1.10  root     2304:       RTX_UNCHANGING_P (temp) = TREE_READONLY (exp);
1.1.1.2   root     2305:       return temp;
                   2306: 
                   2307:     case ARRAY_REF:
                   2308:       if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
                   2309:          || TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) != INTEGER_CST)
                   2310:        {
                   2311:          /* Nonconstant array index or nonconstant element size.
                   2312:             Generate the tree for *(&array+index) and expand that,
                   2313:             except do it in a language-independent way
                   2314:             and don't complain about non-lvalue arrays.
                   2315:             `mark_addressable' should already have been called
                   2316:             for any array for which this case will be reached.  */
                   2317: 
                   2318:          tree array_adr = build (ADDR_EXPR, TYPE_POINTER_TO (type),
                   2319:                                  TREE_OPERAND (exp, 0));
                   2320:          tree index = TREE_OPERAND (exp, 1);
                   2321:          tree elt;
                   2322: 
                   2323:          /* Convert the integer argument to a type the same size as a pointer
                   2324:             so the multiply won't overflow spuriously.  */
                   2325:          if (TYPE_PRECISION (TREE_TYPE (index)) != POINTER_SIZE)
                   2326:            index = convert (type_for_size (POINTER_SIZE, 0), index);
                   2327: 
                   2328:          /* The array address isn't volatile even if the array is.  */
                   2329:          TREE_VOLATILE (array_adr) = 0;
                   2330: 
                   2331:          elt = build (INDIRECT_REF, type,
                   2332:                       fold (build (PLUS_EXPR, TYPE_POINTER_TO (type),
                   2333:                                    array_adr,
                   2334:                                    fold (build (MULT_EXPR,
                   2335:                                                 TYPE_POINTER_TO (type),
                   2336:                                                 index, size_in_bytes (type))))));
                   2337: 
                   2338:          return expand_expr (elt, target, tmode, modifier);
                   2339:        }
1.1.1.13  root     2340: 
                   2341:       /* If this is a constant index into a constant array,
                   2342:         just get the value from the array.  */
                   2343:       if (TREE_READONLY (TREE_OPERAND (exp, 0))
                   2344:          && ! TREE_VOLATILE (TREE_OPERAND (exp, 0))
                   2345:          && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == ARRAY_TYPE
                   2346:          && TREE_LITERAL (TREE_OPERAND (exp, 1))
                   2347:          && TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL
1.1.1.15! root     2348:          && DECL_INITIAL (TREE_OPERAND (exp, 0))
        !          2349:          && TREE_CODE (DECL_INITIAL (TREE_OPERAND (exp, 0))) != ERROR_MARK)
1.1.1.13  root     2350:        {
                   2351:          tree index = fold (TREE_OPERAND (exp, 1));
                   2352:          if (TREE_CODE (index) == INTEGER_CST)
                   2353:            {
                   2354:              int i = TREE_INT_CST_LOW (index);
                   2355:              tree init = CONSTRUCTOR_ELTS (DECL_INITIAL (TREE_OPERAND (exp, 0)));
                   2356: 
                   2357:              while (init && i--)
                   2358:                init = TREE_CHAIN (init);
                   2359:              if (init)
                   2360:                return expand_expr (fold (TREE_VALUE (init)), target, tmode, modifier);
                   2361:            }
                   2362:        }
1.1.1.2   root     2363:       /* Treat array-ref with constant index as a component-ref.  */
1.1       root     2364: 
                   2365:     case COMPONENT_REF:
                   2366:       {
1.1.1.2   root     2367:        register enum machine_mode mode1;
1.1       root     2368:        int volstruct = 0;
1.1.1.2   root     2369:        int bitsize;
                   2370:        tree tem = exp;
                   2371:        int bitpos = 0;
                   2372:        int unsignedp;
1.1       root     2373: 
1.1.1.2   root     2374:        if (TREE_CODE (exp) == COMPONENT_REF)
1.1       root     2375:          {
                   2376:            tree field = TREE_OPERAND (exp, 1);
1.1.1.2   root     2377:            bitsize = TREE_INT_CST_LOW (DECL_SIZE (field)) * DECL_SIZE_UNIT (field);
                   2378:            mode1 = DECL_MODE (TREE_OPERAND (exp, 1));
                   2379:            unsignedp = TREE_UNSIGNED (field);
1.1       root     2380:          }
1.1.1.2   root     2381:        else
1.1       root     2382:          {
1.1.1.2   root     2383:            mode1 = TYPE_MODE (TREE_TYPE (exp));
                   2384:            bitsize = GET_MODE_BITSIZE (mode1);
                   2385:            unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
1.1       root     2386:          }
                   2387: 
1.1.1.2   root     2388:        /* Compute cumulative bit-offset for nested component-refs
                   2389:           and array-refs, and find the ultimate containing object.  */
                   2390: 
                   2391:        while (1)
1.1       root     2392:          {
1.1.1.2   root     2393:            if (TREE_CODE (tem) == COMPONENT_REF)
                   2394:              {
                   2395:                bitpos += DECL_OFFSET (TREE_OPERAND (tem, 1));
                   2396:                if (TREE_THIS_VOLATILE (tem))
                   2397:                  volstruct = 1;
                   2398:              }
                   2399:            else if (TREE_CODE (tem) == ARRAY_REF
                   2400:                     && TREE_CODE (TREE_OPERAND (tem, 1)) == INTEGER_CST
                   2401:                     && TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) == INTEGER_CST)
                   2402:              {
                   2403:                bitpos += (TREE_INT_CST_LOW (TREE_OPERAND (tem, 1))
                   2404:                           * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (tem)))
                   2405:                           * TYPE_SIZE_UNIT (TREE_TYPE (tem)));
                   2406:              }
                   2407:            else
                   2408:              break;
                   2409:            tem = TREE_OPERAND (tem, 0);
1.1       root     2410:          }
                   2411: 
1.1.1.2   root     2412:        op0 = expand_expr (tem, 0, VOIDmode,
                   2413:                           (modifier == EXPAND_CONST_ADDRESS
                   2414:                            ? modifier : EXPAND_NORMAL));
1.1       root     2415: 
1.1.1.2   root     2416:        if (mode1 == BImode || GET_CODE (op0) == REG
                   2417:            || GET_CODE (op0) == SUBREG)
                   2418:          {
                   2419:            return extract_bit_field (op0, bitsize, bitpos, unsignedp,
1.1.1.14  root     2420:                                      target, mode, tmode,
                   2421:                                      TYPE_ALIGN (TREE_TYPE (tem)));
1.1.1.2   root     2422:          }
                   2423:        /* Get a reference to just this component.  */
                   2424:        if (modifier == EXPAND_CONST_ADDRESS)
                   2425:          op0 = gen_rtx (MEM, mode1, plus_constant (XEXP (op0, 0),
                   2426:                                                    (bitpos / BITS_PER_UNIT)));
                   2427:        else
                   2428:          op0 = change_address (op0, mode1,
                   2429:                                plus_constant (XEXP (op0, 0),
                   2430:                                               (bitpos / BITS_PER_UNIT)));
1.1.1.10  root     2431:        MEM_IN_STRUCT_P (op0) = 1;
1.1.1.15! root     2432:        MEM_VOLATILE_P (op0) |= volstruct;
1.1.1.2   root     2433:        /* If OP0 is in the shared structure-value stack slot,
                   2434:           and it is not BLKmode, copy it into a register.
                   2435:           The shared slot may be clobbered at any time by another call.
                   2436:           BLKmode is safe because our caller will either copy the value away
                   2437:           or take another component and come back here.  */
                   2438:        if (mode != BLKmode
                   2439:            && TREE_CODE (TREE_OPERAND (exp, 0)) == CALL_EXPR
                   2440:            && TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == BLKmode)
                   2441:          op0 = copy_to_reg (op0);
                   2442:        if (mode == mode1 || mode1 == BLKmode || mode1 == tmode)
                   2443:          return op0;
                   2444:        if (target == 0)
                   2445:          target = gen_reg_rtx (tmode != VOIDmode ? tmode : mode);
                   2446:        convert_move (target, op0, unsignedp);
                   2447:        return target;
1.1       root     2448:       }
                   2449: 
                   2450:       /* Intended for a reference to a buffer of a file-object in Pascal.
                   2451:         But it's not certain that a special tree code will really be
                   2452:         necessary for these.  INDIRECT_REF might work for them.  */
                   2453:     case BUFFER_REF:
                   2454:       abort ();
                   2455: 
1.1.1.13  root     2456:     case WITH_CLEANUP_EXPR:
                   2457:       RTL_EXPR_RTL (TREE_OPERAND (exp, 1))
                   2458:        = expand_expr (TREE_OPERAND (exp, 0), target, tmode, modifier);
                   2459:       cleanups_of_this_call = tree_cons (0, TREE_OPERAND (exp, 2), cleanups_of_this_call);
                   2460:       return RTL_EXPR_RTL (TREE_OPERAND (exp, 1));
                   2461: 
1.1       root     2462:     case CALL_EXPR:
1.1.1.2   root     2463:       /* Check for a built-in function.  */
                   2464:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
                   2465:          && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == FUNCTION_DECL
1.1.1.5   root     2466:          && (DECL_FUNCTION_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
                   2467:              != NOT_BUILT_IN))
1.1.1.2   root     2468:        return expand_builtin (exp, target, subtarget, tmode);
1.1       root     2469:       /* If this call was expanded already by preexpand_calls,
                   2470:         just return the result we got.  */
                   2471:       if (CALL_EXPR_RTL (exp) != 0)
                   2472:        return CALL_EXPR_RTL (exp);
1.1.1.2   root     2473:       return expand_call (exp, target, ignore);
1.1       root     2474: 
                   2475:     case NOP_EXPR:
                   2476:     case CONVERT_EXPR:
1.1.1.7   root     2477:     case REFERENCE_EXPR:
1.1.1.2   root     2478:       if (TREE_CODE (type) == VOID_TYPE || ignore)
1.1       root     2479:        {
1.1.1.2   root     2480:          expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, modifier);
1.1       root     2481:          return const0_rtx;
                   2482:        }
                   2483:       if (mode == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0))))
1.1.1.2   root     2484:        return expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, modifier);
1.1       root     2485:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, mode, 0);
1.1.1.2   root     2486:       if (GET_MODE (op0) == mode || GET_MODE (op0) == VOIDmode)
1.1       root     2487:        return op0;
1.1.1.2   root     2488:       if (flag_force_mem && GET_CODE (op0) == MEM)
                   2489:        op0 = copy_to_reg (op0);
1.1       root     2490:       if (target == 0)
                   2491:        target = gen_reg_rtx (mode);
1.1.1.2   root     2492:       convert_move (target, op0, TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0))));
1.1       root     2493:       return target;
                   2494: 
                   2495:     case PLUS_EXPR:
                   2496:       preexpand_calls (exp);
1.1.1.2   root     2497:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
                   2498:          && modifier == EXPAND_SUM)
1.1       root     2499:        {
1.1.1.2   root     2500:          op1 = expand_expr (TREE_OPERAND (exp, 1), subtarget, VOIDmode, EXPAND_SUM);
1.1       root     2501:          op1 = plus_constant (op1, TREE_INT_CST_LOW (TREE_OPERAND (exp, 0)));
1.1.1.2   root     2502:          return op1;
1.1       root     2503:        }
                   2504:       negate_1 = 1;
                   2505:     plus_minus:
1.1.1.2   root     2506:       if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
                   2507:          && modifier == EXPAND_SUM)
1.1       root     2508:        {
1.1.1.2   root     2509:          op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM);
1.1       root     2510:          op0 = plus_constant (op0,
                   2511:                               negate_1 * TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)));
1.1.1.2   root     2512:          return op0;
1.1       root     2513:        }
                   2514:       this_optab = add_optab;
1.1.1.2   root     2515:       if (modifier != EXPAND_SUM) goto binop;
1.1       root     2516:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
1.1.1.2   root     2517:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM);
                   2518:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, EXPAND_SUM);
1.1       root     2519:       /* Put a sum last, to simplify what follows.  */
                   2520: #ifdef OLD_INDEXING
                   2521:       if (GET_CODE (op1) == MULT)
                   2522:        {
                   2523:          temp = op0;
                   2524:          op0 = op1;
                   2525:          op1 = temp;
                   2526:        }
                   2527: #endif
                   2528: #ifndef OLD_INDEXING
                   2529:       /* Make sure any term that's a sum with a constant comes last.  */
                   2530:       if (GET_CODE (op0) == PLUS
1.1.1.2   root     2531:          && CONSTANT_P (XEXP (op0, 1)))
1.1       root     2532:        {
                   2533:          temp = op0;
                   2534:          op0 = op1;
                   2535:          op1 = temp;
                   2536:        }
                   2537:       /* If adding to a sum including a constant,
                   2538:         associate it to put the constant outside.  */
                   2539:       if (GET_CODE (op1) == PLUS
1.1.1.2   root     2540:          && CONSTANT_P (XEXP (op1, 1)))
1.1       root     2541:        {
                   2542:          op0 = gen_rtx (PLUS, mode, XEXP (op1, 0), op0);
                   2543:          if (GET_CODE (XEXP (op1, 1)) == CONST_INT)
                   2544:            return plus_constant (op0, INTVAL (XEXP (op1, 1)));
                   2545:          else
                   2546:            return gen_rtx (PLUS, mode, op0, XEXP (op1, 1));
                   2547:        }
                   2548: #endif
                   2549:       return gen_rtx (PLUS, mode, op0, op1);
                   2550: 
                   2551:     case MINUS_EXPR:
                   2552:       preexpand_calls (exp);
                   2553:       if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
                   2554:        {
1.1.1.10  root     2555:          int negated;
1.1.1.2   root     2556:          if (modifier == EXPAND_SUM)
                   2557:            {
                   2558:              negate_1 = -1;
                   2559:              goto plus_minus;
                   2560:            }
                   2561:          subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   2562:          op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1.1.10  root     2563:          negated = - TREE_INT_CST_LOW (TREE_OPERAND (exp, 1));
                   2564:          if (GET_MODE_BITSIZE (mode) < HOST_BITS_PER_INT)
                   2565:            negated &= (1 << GET_MODE_BITSIZE (mode)) - 1;
                   2566:          op1 = gen_rtx (CONST_INT, VOIDmode, negated);
1.1.1.2   root     2567:          this_optab = add_optab;
                   2568:          goto binop2;
1.1       root     2569:        }
                   2570:       this_optab = sub_optab;
                   2571:       goto binop;
                   2572: 
                   2573:     case MULT_EXPR:
                   2574:       preexpand_calls (exp);
                   2575:       /* If first operand is constant, swap them.
                   2576:         Thus the following special case checks need only
                   2577:         check the second operand.  */
                   2578:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST)
                   2579:        {
                   2580:          register tree t1 = TREE_OPERAND (exp, 0);
                   2581:          TREE_OPERAND (exp, 0) = TREE_OPERAND (exp, 1);
                   2582:          TREE_OPERAND (exp, 1) = t1;
                   2583:        }
                   2584: 
                   2585:       /* Attempt to return something suitable for generating an
                   2586:         indexed address, for machines that support that.  */
                   2587: 
1.1.1.2   root     2588:       if (modifier == EXPAND_SUM
1.1.1.6   root     2589:          && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
1.1       root     2590:        {
1.1.1.2   root     2591:          op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, EXPAND_SUM);
                   2592: 
                   2593:          /* Apply distributive law if OP0 is x+c.  */
                   2594:          if (GET_CODE (op0) == PLUS
                   2595:              && GET_CODE (XEXP (op0, 1)) == CONST_INT)
                   2596:            return gen_rtx (PLUS, mode,
                   2597:                            gen_rtx (MULT, mode, XEXP (op0, 0),
                   2598:                                     gen_rtx (CONST_INT, VOIDmode,
                   2599:                                              TREE_INT_CST_LOW (TREE_OPERAND (exp, 1)))),
                   2600:                            gen_rtx (CONST_INT, VOIDmode,
                   2601:                                     (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))
                   2602:                                      * INTVAL (XEXP (op0, 1)))));
                   2603: 
1.1       root     2604:          if (GET_CODE (op0) != REG)
1.1.1.2   root     2605:            op0 = force_operand (op0, 0);
                   2606:          if (GET_CODE (op0) != REG)
                   2607:            op0 = copy_to_mode_reg (mode, op0);
                   2608: 
1.1.1.6   root     2609:          return gen_rtx (MULT, mode, op0,
1.1       root     2610:                          gen_rtx (CONST_INT, VOIDmode,
                   2611:                                   TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))));
                   2612:        }
                   2613:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   2614:       /* Check for multiplying things that have been extended
                   2615:         from a narrower type.  If this machine supports multiplying
                   2616:         in that narrower type with a result in the desired type,
                   2617:         do it that way, and avoid the explicit type-conversion.  */
                   2618:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == NOP_EXPR
                   2619:          && TREE_CODE (TREE_TYPE (exp)) == INTEGER_TYPE
                   2620:          && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
                   2621:              < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))))
                   2622:          && ((TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
                   2623:               && int_fits_type_p (TREE_OPERAND (exp, 1),
1.1.1.2   root     2624:                                   TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
                   2625:               /* Don't use a widening multiply if a shift will do.  */
                   2626:               && exact_log2 (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))) < 0)
1.1       root     2627:              ||
                   2628:              (TREE_CODE (TREE_OPERAND (exp, 1)) == NOP_EXPR
                   2629:               && (TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
                   2630:                   ==
1.1.1.2   root     2631:                   TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))))
                   2632:               /* If both operands are extended, they must either both
                   2633:                  be zero-extended or both be sign-extended.  */
                   2634:               && (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 1), 0)))
                   2635:                   ==
                   2636:                   TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))))))
1.1       root     2637:        {
                   2638:          enum machine_mode innermode
                   2639:            = TYPE_MODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)));
1.1.1.2   root     2640:          this_optab = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)))
1.1       root     2641:                        ? umul_widen_optab : smul_widen_optab);
                   2642:          if ((int) innermode + 1 == (int) mode
1.1.1.2   root     2643:              && this_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
1.1       root     2644:            {
                   2645:              op0 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 0), 0),
                   2646:                                 0, VOIDmode, 0);
                   2647:              if (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
                   2648:                op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   2649:              else
                   2650:                op1 = expand_expr (TREE_OPERAND (TREE_OPERAND (exp, 1), 0),
                   2651:                                   0, VOIDmode, 0);
                   2652:              goto binop2;
                   2653:            }
                   2654:        }
                   2655:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   2656:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
1.1.1.2   root     2657:       return expand_mult (mode, op0, op1, target, TREE_UNSIGNED (type));
1.1       root     2658: 
                   2659:     case TRUNC_DIV_EXPR:
                   2660:     case FLOOR_DIV_EXPR:
                   2661:     case CEIL_DIV_EXPR:
                   2662:     case ROUND_DIV_EXPR:
                   2663:       preexpand_calls (exp);
                   2664:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
1.1.1.2   root     2665:       /* Possible optimization: compute the dividend with EXPAND_SUM
1.1       root     2666:         then if the divisor is constant can optimize the case
                   2667:         where some terms of the dividend have coeffs divisible by it.  */
                   2668:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   2669:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   2670:       return expand_divmod (0, code, mode, op0, op1, target,
1.1.1.2   root     2671:                            TREE_UNSIGNED (type));
1.1       root     2672: 
                   2673:     case RDIV_EXPR:
                   2674:       preexpand_calls (exp);
                   2675:       this_optab = flodiv_optab;
                   2676:       goto binop;
                   2677: 
                   2678:     case TRUNC_MOD_EXPR:
                   2679:     case FLOOR_MOD_EXPR:
                   2680:     case CEIL_MOD_EXPR:
                   2681:     case ROUND_MOD_EXPR:
                   2682:       preexpand_calls (exp);
                   2683:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   2684:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   2685:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   2686:       return expand_divmod (1, code, mode, op0, op1, target,
1.1.1.2   root     2687:                            TREE_UNSIGNED (type));
1.1       root     2688: #if 0
                   2689: #ifdef HAVE_divmoddisi4
                   2690:       if (GET_MODE (op0) != DImode)
                   2691:        {
                   2692:          temp = gen_reg_rtx (DImode);
                   2693:          convert_move (temp, op0, 0);
                   2694:          op0 = temp;
                   2695:          if (GET_MODE (op1) != SImode && GET_CODE (op1) != CONST_INT)
                   2696:            {
                   2697:              temp = gen_reg_rtx (SImode);
                   2698:              convert_move (temp, op1, 0);
                   2699:              op1 = temp;
                   2700:            }
                   2701:          temp = gen_reg_rtx (SImode);
                   2702:          if (target == 0)
                   2703:            target = gen_reg_rtx (SImode);
                   2704:          emit_insn (gen_divmoddisi4 (temp, protect_from_queue (op0, 0),
                   2705:                                      protect_from_queue (op1, 0),
                   2706:                                      protect_from_queue (target, 1)));
                   2707:          return target;
                   2708:        }
                   2709: #endif
                   2710: #endif
                   2711: 
                   2712:     case FIX_ROUND_EXPR:
                   2713:     case FIX_FLOOR_EXPR:
                   2714:     case FIX_CEIL_EXPR:
                   2715:       abort ();                        /* Not used for C.  */
                   2716: 
                   2717:     case FIX_TRUNC_EXPR:
                   2718:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   2719:       if (target == 0)
                   2720:        target = gen_reg_rtx (mode);
1.1.1.2   root     2721:       {
                   2722:        int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
                   2723:        if (mode == HImode || mode == QImode)
                   2724:          {
                   2725:            register rtx temp = gen_reg_rtx (SImode);
1.1.1.6   root     2726:            expand_fix (temp, op0, 0);
                   2727:            convert_move (target, temp, 0);
1.1.1.2   root     2728:          }
                   2729:        else
                   2730:          expand_fix (target, op0, unsignedp);
                   2731:       }
1.1       root     2732:       return target;
                   2733: 
                   2734:     case FLOAT_EXPR:
                   2735:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   2736:       if (target == 0)
                   2737:        target = gen_reg_rtx (mode);
1.1.1.2   root     2738:       {
                   2739:        int unsignedp = TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));
                   2740:        if (GET_MODE (op0) == HImode
                   2741:            || GET_MODE (op0) == QImode)
                   2742:          {
                   2743:            register rtx temp = gen_reg_rtx (SImode);
                   2744:            convert_move (temp, op0, unsignedp);
                   2745:            expand_float (target, temp, 0);
                   2746:          }
                   2747:        else
                   2748:          expand_float (target, op0, unsignedp);
                   2749:       }
1.1       root     2750:       return target;
                   2751: 
                   2752:     case NEGATE_EXPR:
                   2753:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   2754:       temp = expand_unop (mode, neg_optab, op0, target, 0);
                   2755:       if (temp == 0)
                   2756:        abort ();
                   2757:       return temp;
                   2758: 
                   2759:     case ABS_EXPR:
                   2760:       /* First try to do it with a special abs instruction.
                   2761:         If that does not win, use conditional jump and negate.  */
1.1.1.2   root     2762:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
1.1       root     2763:       temp = expand_unop (mode, abs_optab, op0, target, 0);
                   2764:       if (temp != 0)
                   2765:        return temp;
                   2766:       temp = gen_label_rtx ();
                   2767:       if (target == 0 || GET_CODE (target) != REG)
1.1.1.2   root     2768:        target = gen_reg_rtx (mode);
1.1       root     2769:       emit_move_insn (target, op0);
1.1.1.2   root     2770:       emit_cmp_insn (target,
                   2771:                     expand_expr (convert (TREE_TYPE (exp), integer_zero_node),
                   2772:                                  0, VOIDmode, 0),
1.1.1.14  root     2773:                     0, 0, 0);
1.1.1.6   root     2774:       NO_DEFER_POP;
1.1       root     2775:       emit_jump_insn (gen_bge (temp));
                   2776:       op0 = expand_unop (mode, neg_optab, target, target, 0);
                   2777:       if (op0 != target)
                   2778:        emit_move_insn (target, op0);
                   2779:       emit_label (temp);
1.1.1.6   root     2780:       OK_DEFER_POP;
1.1       root     2781:       return target;
                   2782: 
                   2783:     case MAX_EXPR:
                   2784:     case MIN_EXPR:
1.1.1.8   root     2785:       mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 1)));
1.1       root     2786:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   2787:       if (target == 0 || GET_CODE (target) != REG || target == op1)
1.1.1.2   root     2788:        target = gen_reg_rtx (mode);
1.1       root     2789:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   2790:       if (target != op0)
                   2791:        emit_move_insn (target, op0);
                   2792:       op0 = gen_label_rtx ();
                   2793:       if (code == MAX_EXPR)
1.1.1.2   root     2794:        temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))
                   2795:                ? compare1 (target, op1, GEU, LEU, 1, mode)
                   2796:                : compare1 (target, op1, GE, LE, 0, mode));
                   2797:       else
                   2798:        temp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1)))
                   2799:                ? compare1 (target, op1, LEU, GEU, 1, mode)
                   2800:                : compare1 (target, op1, LE, GE, 0, mode));
                   2801:       if (temp == const0_rtx)
                   2802:        emit_move_insn (target, op1);
                   2803:       else if (temp != const1_rtx)
                   2804:        {
1.1.1.13  root     2805:          if (bcc_gen_fctn[(int) GET_CODE (temp)] != 0)
                   2806:            emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (temp)]) (op0));
                   2807:          else
                   2808:            abort ();
1.1.1.2   root     2809:          emit_move_insn (target, op1);
                   2810:        }
                   2811:       emit_label (op0);
1.1       root     2812:       return target;
                   2813: 
                   2814: /* ??? Can optimize when the operand of this is a bitwise operation,
                   2815:    by using a different bitwise operation.  */
                   2816:     case BIT_NOT_EXPR:
                   2817:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   2818:       temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
                   2819:       if (temp == 0)
                   2820:        abort ();
                   2821:       return temp;
                   2822: 
1.1.1.2   root     2823:     case FFS_EXPR:
                   2824:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   2825:       temp = expand_unop (mode, ffs_optab, op0, target, 1);
                   2826:       if (temp == 0)
                   2827:        abort ();
                   2828:       return temp;
                   2829: 
1.1       root     2830: /* ??? Can optimize bitwise operations with one arg constant.
                   2831:    Pastel optimizes (a bitwise1 n) bitwise2 (a bitwise3 b)
                   2832:    and (a bitwise1 b) bitwise2 b (etc)
                   2833:    but that is probably not worth while.  */
                   2834: 
1.1.1.2   root     2835: /* BIT_AND_EXPR is for bitwise anding.
1.1       root     2836:    TRUTH_AND_EXPR is for anding two boolean values
                   2837:    when we want in all cases to compute both of them.
                   2838:    In general it is fastest to do TRUTH_AND_EXPR by
                   2839:    computing both operands as actual zero-or-1 values
                   2840:    and then bitwise anding.  In cases where there cannot
                   2841:    be any side effects, better code would be made by
                   2842:    treating TRUTH_AND_EXPR like TRUTH_ANDIF_EXPR;
                   2843:    but the question is how to recognize those cases.  */
                   2844: 
                   2845:     case TRUTH_AND_EXPR:
                   2846:     case BIT_AND_EXPR:
                   2847:       preexpand_calls (exp);
                   2848:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   2849:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   2850:       op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   2851:       return expand_bit_and (mode, op0, op1, target);
                   2852: 
                   2853: /* See comment above about TRUTH_AND_EXPR; it applies here too.  */
                   2854:     case TRUTH_OR_EXPR:
                   2855:     case BIT_IOR_EXPR:
                   2856:       preexpand_calls (exp);
                   2857:       this_optab = ior_optab;
                   2858:       goto binop;
                   2859: 
                   2860:     case BIT_XOR_EXPR:
                   2861:       preexpand_calls (exp);
                   2862:       this_optab = xor_optab;
                   2863:       goto binop;
                   2864: 
                   2865:     case LSHIFT_EXPR:
                   2866:     case RSHIFT_EXPR:
                   2867:     case LROTATE_EXPR:
                   2868:     case RROTATE_EXPR:
                   2869:       preexpand_calls (exp);
                   2870:       subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   2871:       op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   2872:       return expand_shift (code, mode, op0, TREE_OPERAND (exp, 1), target,
1.1.1.2   root     2873:                           TREE_UNSIGNED (type));
1.1       root     2874: 
                   2875: /* ??? cv's were used to effect here to combine additive constants
                   2876:    and to determine the answer when only additive constants differ.
                   2877:    Also, the addition of one can be handled by changing the condition.  */
                   2878:     case LT_EXPR:
                   2879:     case LE_EXPR:
                   2880:     case GT_EXPR:
                   2881:     case GE_EXPR:
                   2882:     case EQ_EXPR:
                   2883:     case NE_EXPR:
                   2884:       preexpand_calls (exp);
1.1.1.2   root     2885:       temp = do_store_flag (exp, target, mode);
1.1       root     2886:       if (temp != 0)
                   2887:        return temp;
1.1.1.2   root     2888:       /* For foo != 0, load foo, and if it is nonzero load 1 instead. */
                   2889:       if (code == NE_EXPR && integer_zerop (TREE_OPERAND (exp, 1))
                   2890:          && subtarget
                   2891:          && (GET_MODE (subtarget)
                   2892:              == TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
1.1       root     2893:        {
                   2894:          temp = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   2895:          if (temp != subtarget)
                   2896:            temp = copy_to_reg (temp);
                   2897:          op1 = gen_label_rtx ();
1.1.1.14  root     2898:          emit_cmp_insn (temp, const0_rtx, 0, TREE_UNSIGNED (type), 0);
1.1       root     2899:          emit_jump_insn (gen_beq (op1));
                   2900:          emit_move_insn (temp, const1_rtx);
                   2901:          emit_label (op1);
                   2902:          return temp;
                   2903:        }
                   2904:       /* If no set-flag instruction, must generate a conditional
                   2905:         store into a temporary variable.  Drop through
                   2906:         and handle this like && and ||.  */
                   2907: 
                   2908:     case TRUTH_ANDIF_EXPR:
                   2909:     case TRUTH_ORIF_EXPR:
                   2910:       temp = gen_reg_rtx (mode);
                   2911:       emit_clr_insn (temp);
                   2912:       op1 = gen_label_rtx ();
                   2913:       jumpifnot (exp, op1);
                   2914:       emit_0_to_1_insn (temp);
                   2915:       emit_label (op1);
                   2916:       return temp;
                   2917: 
                   2918:     case TRUTH_NOT_EXPR:
                   2919:       op0 = expand_expr (TREE_OPERAND (exp, 0), target, VOIDmode, 0);
                   2920:       /* The parser is careful to generate TRUTH_NOT_EXPR
                   2921:         only with operands that are always zero or one.  */
                   2922:       temp = expand_binop (mode, xor_optab, op0,
                   2923:                           gen_rtx (CONST_INT, mode, 1),
                   2924:                           target, 1, OPTAB_LIB_WIDEN);
                   2925:       if (temp == 0)
                   2926:        abort ();
                   2927:       return temp;
                   2928: 
                   2929:     case COMPOUND_EXPR:
1.1.1.2   root     2930:       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
1.1       root     2931:       emit_queue ();
                   2932:       return expand_expr (TREE_OPERAND (exp, 1), target, VOIDmode, 0);
                   2933: 
                   2934:     case COND_EXPR:
                   2935:       /* Note that COND_EXPRs whose type is a structure or union
                   2936:         are required to be constructed to contain assignments of
                   2937:         a temporary variable, so that we can evaluate them here
                   2938:         for side effect only.  If type is void, we must do likewise.  */
                   2939:       op0 = gen_label_rtx ();
                   2940:       op1 = gen_label_rtx ();
                   2941: 
1.1.1.2   root     2942:       if (mode == VOIDmode || ignore)
1.1       root     2943:        temp = 0;
                   2944:       else if (target)
                   2945:        temp = target;
1.1.1.2   root     2946:       else if (mode == BLKmode)
                   2947:        {
                   2948:          if (TYPE_SIZE (type) == 0 || ! TREE_LITERAL (TYPE_SIZE (type)))
                   2949:            abort ();
                   2950:          temp = assign_stack_local (BLKmode,
                   2951:                                     (TREE_INT_CST_LOW (TYPE_SIZE (type))
                   2952:                                      * TYPE_SIZE_UNIT (type)
                   2953:                                      + BITS_PER_UNIT - 1)
                   2954:                                     / BITS_PER_UNIT);
                   2955:        }
1.1       root     2956:       else
                   2957:        temp = gen_reg_rtx (mode);
                   2958: 
                   2959:       jumpifnot (TREE_OPERAND (exp, 0), op0);
1.1.1.6   root     2960:       NO_DEFER_POP;
1.1       root     2961:       if (temp != 0)
1.1.1.2   root     2962:        store_expr (TREE_OPERAND (exp, 1), temp, 0);
1.1       root     2963:       else
1.1.1.2   root     2964:        expand_expr (TREE_OPERAND (exp, 1), ignore ? const0_rtx : 0,
                   2965:                     VOIDmode, 0);
1.1       root     2966:       emit_queue ();
                   2967:       emit_jump_insn (gen_jump (op1));
                   2968:       emit_barrier ();
                   2969:       emit_label (op0);
                   2970:       if (temp != 0)
1.1.1.2   root     2971:        store_expr (TREE_OPERAND (exp, 2), temp, 0);
1.1       root     2972:       else
1.1.1.2   root     2973:        expand_expr (TREE_OPERAND (exp, 2), ignore ? const0_rtx : 0,
                   2974:                     VOIDmode, 0);
1.1       root     2975:       emit_queue ();
                   2976:       emit_label (op1);
1.1.1.6   root     2977:       OK_DEFER_POP;
1.1       root     2978:       return temp;
                   2979: 
                   2980:     case MODIFY_EXPR:
1.1.1.7   root     2981:       {
                   2982:        /* If lhs is complex, expand calls in rhs before computing it.
                   2983:           That's so we don't compute a pointer and save it over a call.
                   2984:           If lhs is simple, compute it first so we can give it as a
                   2985:           target if the rhs is just a call.  This avoids an extra temp and copy
                   2986:           and that prevents a partial-subsumption which makes bad code.
                   2987:           Actually we could treat component_ref's of vars like vars.  */
                   2988: 
                   2989:        tree lhs = TREE_OPERAND (exp, 0);
                   2990:        tree rhs = TREE_OPERAND (exp, 1);
1.1.1.13  root     2991:        tree noncopied_parts;
1.1.1.7   root     2992: 
                   2993:        if (TREE_CODE (lhs) != VAR_DECL
                   2994:            && TREE_CODE (lhs) != RESULT_DECL
                   2995:            && TREE_CODE (lhs) != PARM_DECL)
                   2996:          preexpand_calls (exp);
                   2997: 
1.1.1.13  root     2998:        noncopied_parts = save_noncopied_parts (lhs, TYPE_NONCOPIED_PARTS (TREE_TYPE (lhs)));
                   2999:        temp = expand_assignment (lhs, rhs, ! ignore, original_target != 0);
                   3000:        while (noncopied_parts != 0)
1.1.1.7   root     3001:          {
1.1.1.13  root     3002:            store_expr (TREE_VALUE (noncopied_parts),
                   3003:                        SAVE_EXPR_RTL (TREE_PURPOSE (noncopied_parts)), 0);
                   3004:            noncopied_parts = TREE_CHAIN (noncopied_parts);
1.1.1.7   root     3005:          }
1.1.1.13  root     3006:        return temp;
                   3007:       }
1.1       root     3008: 
                   3009:     case PREINCREMENT_EXPR:
                   3010:     case PREDECREMENT_EXPR:
1.1.1.2   root     3011:       return expand_increment (exp, 0);
1.1       root     3012: 
                   3013:     case POSTINCREMENT_EXPR:
                   3014:     case POSTDECREMENT_EXPR:
1.1.1.2   root     3015:       return expand_increment (exp, 1);
1.1       root     3016: 
                   3017:     case ADDR_EXPR:
1.1.1.2   root     3018:       op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode,
                   3019:                         EXPAND_CONST_ADDRESS);
1.1       root     3020:       if (GET_CODE (op0) != MEM)
                   3021:        abort ();
1.1.1.2   root     3022:       if (modifier == EXPAND_SUM)
1.1       root     3023:        return XEXP (op0, 0);
1.1.1.2   root     3024:       op0 = force_operand (XEXP (op0, 0), target);
                   3025:       if (flag_force_addr && GET_CODE (op0) != REG)
                   3026:        return force_reg (Pmode, op0);
                   3027:       return op0;
1.1       root     3028: 
                   3029:     case ENTRY_VALUE_EXPR:
                   3030:       abort ();
                   3031: 
                   3032:     case ERROR_MARK:
1.1.1.2   root     3033:       return const0_rtx;
1.1       root     3034: 
                   3035:     default:
                   3036:       abort ();
                   3037:     }
                   3038: 
                   3039:   /* Here to do an ordinary binary operator, generating an instruction
                   3040:      from the optab already placed in `this_optab'.  */
                   3041:  binop:
                   3042:   /* Detect things like x = y | (a == b)
                   3043:      and do them as (x = y), (a == b ? x |= 1 : 0), x.  */
                   3044:   /* First, get the comparison or conditional into the second arg.  */
                   3045:   if (comparison_code[(int) TREE_CODE (TREE_OPERAND (exp, 0))]
                   3046:       || (TREE_CODE (TREE_OPERAND (exp, 0)) == COND_EXPR
                   3047:          && (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 1))
                   3048:              || integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 0), 2)))))
                   3049:     {
                   3050:       if (this_optab == ior_optab || this_optab == add_optab
                   3051:          || this_optab == xor_optab)
                   3052:        {
                   3053:          tree exch = TREE_OPERAND (exp, 1);
                   3054:          TREE_OPERAND (exp, 1) = TREE_OPERAND (exp, 0);
                   3055:          TREE_OPERAND (exp, 0) = exch;
                   3056:        }
                   3057:     }
1.1.1.3   root     3058:   /* Optimize X + (Y ? Z : 0) by computing X and maybe adding Z.  */
1.1       root     3059:   if (comparison_code[(int) TREE_CODE (TREE_OPERAND (exp, 1))]
                   3060:       || (TREE_CODE (TREE_OPERAND (exp, 1)) == COND_EXPR
                   3061:          && (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 1))
                   3062:              || integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 2)))))
                   3063:     {
                   3064:       if (this_optab == ior_optab || this_optab == add_optab
                   3065:          || this_optab == xor_optab || this_optab == sub_optab
                   3066:          || this_optab == lshl_optab || this_optab == ashl_optab
                   3067:          || this_optab == lshr_optab || this_optab == ashr_optab
                   3068:          || this_optab == rotl_optab || this_optab == rotr_optab)
                   3069:        {
1.1.1.2   root     3070:          tree thenexp;
1.1       root     3071:          rtx thenv = 0;
                   3072: 
1.1.1.8   root     3073:          /* TARGET gets a reg in which we can perform the computation.
                   3074:             Use the specified target if it's a pseudo reg and safe.  */
                   3075:          target = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
1.1       root     3076:          if (target == 0) target = gen_reg_rtx (mode);
1.1.1.3   root     3077: 
                   3078:          /* Compute X into the target.  */
1.1.1.2   root     3079:          store_expr (TREE_OPERAND (exp, 0), target, 0);
1.1       root     3080:          op0 = gen_label_rtx ();
                   3081: 
1.1.1.3   root     3082:          /* If other operand is a comparison COMP, treat it as COMP ? 1 : 0 */
1.1       root     3083:          if (TREE_CODE (TREE_OPERAND (exp, 1)) != COND_EXPR)
                   3084:            {
                   3085:              do_jump (TREE_OPERAND (exp, 1), op0, 0);
                   3086:              thenv = const1_rtx;
                   3087:            }
                   3088:          else if (integer_zerop (TREE_OPERAND (TREE_OPERAND (exp, 1), 2)))
                   3089:            {
                   3090:              do_jump (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), op0, 0);
                   3091:              thenexp = TREE_OPERAND (TREE_OPERAND (exp, 1), 1);
                   3092:            }
                   3093:          else
                   3094:            {
                   3095:              do_jump (TREE_OPERAND (TREE_OPERAND (exp, 1), 0), 0, op0);
                   3096:              thenexp = TREE_OPERAND (TREE_OPERAND (exp, 1), 2);
                   3097:            }
                   3098: 
                   3099:          if (thenv == 0)
                   3100:            thenv = expand_expr (thenexp, 0, VOIDmode, 0);
                   3101: 
1.1.1.3   root     3102:          /* THENV is now Z, the value to operate on, as an rtx.
                   3103:             We have already tested that Y isn't zero, so do the operation.  */
                   3104: 
1.1       root     3105:          if (this_optab == rotl_optab || this_optab == rotr_optab)
                   3106:            temp = expand_binop (mode, this_optab, target, thenv, target,
                   3107:                                 -1, OPTAB_LIB);
                   3108:          else if (this_optab == lshl_optab || this_optab == lshr_optab)
                   3109:            temp = expand_binop (mode, this_optab, target, thenv, target,
                   3110:                                 1, OPTAB_LIB_WIDEN);
                   3111:          else
                   3112:            temp = expand_binop (mode, this_optab, target, thenv, target,
                   3113:                                 0, OPTAB_LIB_WIDEN);
                   3114:          if (target != temp)
                   3115:            emit_move_insn (target, temp);
                   3116: 
1.1.1.6   root     3117:          do_pending_stack_adjust ();
1.1       root     3118:          emit_label (op0);
                   3119:          return target;
                   3120:        }
                   3121:     }
                   3122:   subtarget = validate_subtarget (subtarget, TREE_OPERAND (exp, 1));
                   3123:   op0 = expand_expr (TREE_OPERAND (exp, 0), subtarget, VOIDmode, 0);
                   3124:   op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   3125:  binop2:
                   3126:   temp = expand_binop (mode, this_optab, op0, op1, target,
1.1.1.2   root     3127:                       TREE_UNSIGNED (TREE_TYPE (exp)), OPTAB_LIB_WIDEN);
1.1       root     3128:   if (temp == 0)
                   3129:     abort ();
                   3130:   return temp;
                   3131: }
                   3132: 
1.1.1.2   root     3133: /* Expand an expression EXP that calls a built-in function,
                   3134:    with result going to TARGET if that's convenient
                   3135:    (and in mode MODE if that's convenient).
                   3136:    SUBTARGET may be used as the target for computing one of EXP's operands.  */
                   3137: 
                   3138: static rtx
                   3139: expand_builtin (exp, target, subtarget, mode)
                   3140:      tree exp;
                   3141:      rtx target;
                   3142:      rtx subtarget;
                   3143:      enum machine_mode mode;
                   3144: {
                   3145:   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
                   3146:   tree arglist = TREE_OPERAND (exp, 1);
                   3147:   rtx op0;
                   3148: 
                   3149:   switch (DECL_FUNCTION_CODE (fndecl))
                   3150:     {
                   3151:     case BUILT_IN_ABS:
                   3152:     case BUILT_IN_LABS:
                   3153:     case BUILT_IN_FABS:
                   3154:       /* build_function_call changes these into ABS_EXPR.  */
                   3155:       abort ();
                   3156: 
1.1.1.14  root     3157:     case BUILT_IN_SAVEREGS:
                   3158:       {
                   3159:        /* When this function is called, it means that registers must be
                   3160:           saved on entry to this function.  So we migrate the
                   3161:           call to the first insn of this function.  */
                   3162:        rtx last = get_last_insn ();
                   3163:        /* Now really call the function.  `expand_call' does not call
                   3164:           expand_builtin, so there is no danger of infinite recursion here.  */
                   3165:        expand_call (exp, target, 1);
                   3166:        reorder_insns (last, get_last_insn (), get_insns ());
                   3167:       }
                   3168:       
1.1.1.2   root     3169:     case BUILT_IN_ALLOCA:
1.1.1.10  root     3170:       if (arglist == 0
                   3171:          /* Arg could be non-integer if user redeclared this fcn wrong.  */
                   3172:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
1.1.1.2   root     3173:        return const0_rtx;
                   3174:       frame_pointer_needed = 1;
                   3175:       /* Compute the argument.  */
                   3176:       op0 = expand_expr (TREE_VALUE (arglist), 0, VOIDmode, 0);
                   3177:       if (! CONSTANT_P (op0))
                   3178:        {
                   3179:          op0 = force_reg (GET_MODE (op0), op0);
                   3180:          if (GET_MODE (op0) != Pmode)
1.1.1.12  root     3181:            op0 = convert_to_mode (Pmode, op0, 1);
1.1.1.2   root     3182:        }
                   3183:       /* Push that much space (rounding it up).  */
1.1.1.3   root     3184:       do_pending_stack_adjust ();
1.1.1.8   root     3185: 
                   3186: #ifdef STACK_POINTER_OFFSET
1.1.1.9   root     3187:       /* If we will have to round the result down (which is up
                   3188:         if stack grows down), make sure we have extra space so the
                   3189:         user still gets at least as much space as he asked for.  */
1.1.1.8   root     3190:       if ((STACK_POINTER_OFFSET + STACK_BYTES - 1) / STACK_BYTES
                   3191:          != STACK_POINTER_OFFSET / STACK_BYTES)
                   3192:        op0 = plus_constant (op0, STACK_BYTES);
                   3193: #endif
                   3194: 
1.1.1.4   root     3195: #ifdef STACK_GROWS_DOWNWARD
1.1.1.2   root     3196:       anti_adjust_stack (round_push (op0));
1.1.1.4   root     3197: #endif
1.1.1.2   root     3198:       /* Return a copy of current stack ptr, in TARGET if possible.  */
                   3199:       if (target)
                   3200:        emit_move_insn (target, stack_pointer_rtx);
                   3201:       else
                   3202:        target = copy_to_reg (stack_pointer_rtx);
1.1.1.4   root     3203: #ifdef STACK_POINTER_OFFSET
                   3204:       /* If the contents of the stack pointer reg are offset from the
                   3205:         actual top-of-stack address, add the offset here.  */
1.1.1.6   root     3206:       if (GET_CODE (target) == REG)
1.1.1.8   root     3207:        emit_insn (gen_add2_insn (target,
                   3208:                                  gen_rtx (CONST_INT, VOIDmode,
                   3209:                                           (STACK_POINTER_OFFSET + STACK_BYTES - 1) / STACK_BYTES * STACK_BYTES)));
1.1.1.6   root     3210:       else
                   3211:        {
                   3212:          rtx temp =
                   3213:            expand_binop (GET_MODE (target), add_optab, target,
1.1.1.8   root     3214:                          gen_rtx (CONST_INT, VOIDmode,
                   3215:                                   (STACK_POINTER_OFFSET + STACK_BYTES - 1) / STACK_BYTES * STACK_BYTES),
1.1.1.6   root     3216:                          target,
                   3217:                          1, OPTAB_DIRECT);
                   3218:          if (temp == 0) abort ();
                   3219:          if (temp != target)
                   3220:            emit_move_insn (target, temp);
                   3221:        }
1.1.1.4   root     3222: #endif
                   3223: #ifndef STACK_GROWS_DOWNWARD
                   3224:       anti_adjust_stack (round_push (op0));
                   3225: #endif
1.1.1.2   root     3226:       return target;
                   3227: 
                   3228:     case BUILT_IN_FFS:
1.1.1.10  root     3229:       if (arglist == 0
                   3230:          /* Arg could be non-integer if user redeclared this fcn wrong.  */
                   3231:          || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != INTEGER_TYPE)
1.1.1.2   root     3232:        return const0_rtx;
                   3233: 
                   3234:       /* Compute the argument.  */
                   3235:       op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
                   3236:       /* Compute ffs, into TARGET if possible.
                   3237:         Set TARGET to wherever the result comes back.  */
                   3238:       target = expand_unop (mode, ffs_optab, op0, target, 1);
                   3239:       if (target == 0)
                   3240:        abort ();
                   3241:       return target;
                   3242: 
                   3243:     default:
                   3244:       abort ();
                   3245:     }
                   3246: }
                   3247: 
                   3248: /* Expand code for a post- or pre- increment or decrement
                   3249:    and return the RTX for the result.
                   3250:    POST is 1 for postinc/decrements and 0 for preinc/decrements.  */
                   3251: 
                   3252: static rtx
                   3253: expand_increment (exp, post)
                   3254:      register tree exp;
                   3255:      int post;
                   3256: {
                   3257:   register rtx op0, op1;
                   3258:   register rtx temp;
                   3259:   register tree incremented = TREE_OPERAND (exp, 0);
                   3260:   optab this_optab = add_optab;
                   3261:   int icode;
                   3262:   enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
                   3263:   int op0_is_copy = 0;
                   3264: 
                   3265:   /* Stabilize any component ref that might need to be
                   3266:      evaluated more than once below.  */
                   3267:   if (TREE_CODE (incremented) == COMPONENT_REF
                   3268:       && (TREE_CODE (TREE_OPERAND (incremented, 0)) != INDIRECT_REF
                   3269:          || DECL_MODE (TREE_OPERAND (exp, 1)) == BImode))
                   3270:     incremented = stabilize_reference (incremented);
                   3271: 
                   3272:   /* Compute the operands as RTX.
                   3273:      Note whether OP0 is the actual lvalue or a copy of it:
                   3274:      I believe it is a copy iff it is a register and insns were
                   3275:      generated in computing it.  */
                   3276:   temp = get_last_insn ();
                   3277:   op0 = expand_expr (incremented, 0, VOIDmode, 0);
                   3278:   if (temp != get_last_insn ())
                   3279:     op0_is_copy = (GET_CODE (op0) == REG || GET_CODE (op0) == SUBREG);
                   3280:   op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   3281: 
                   3282:   /* Decide whether incrementing or decrementing.  */
                   3283:   if (TREE_CODE (exp) == POSTDECREMENT_EXPR
                   3284:       || TREE_CODE (exp) == PREDECREMENT_EXPR)
                   3285:     this_optab = sub_optab;
                   3286: 
                   3287:   /* If OP0 is not the actual lvalue, but rather a copy in a register,
                   3288:      then we cannot just increment OP0.  We must
                   3289:      therefore contrive to increment the original value.
                   3290:      Then we can return OP0 since it is a copy of the old value.  */
                   3291:   if (op0_is_copy)
                   3292:     {
                   3293:       /* This is the easiest way to increment the value wherever it is.
                   3294:         Problems with multiple evaluation of INCREMENTED
                   3295:         are prevented because either (1) it is a component_ref,
                   3296:         in which case it was stabilized above, or (2) it is an array_ref
                   3297:         with constant index in an array in a register, which is
                   3298:         safe to reevaluate.  */
                   3299:       tree newexp = build ((this_optab == add_optab
                   3300:                            ? PLUS_EXPR : MINUS_EXPR),
                   3301:                           TREE_TYPE (exp),
                   3302:                           incremented,
                   3303:                           TREE_OPERAND (exp, 1));
                   3304:       temp = expand_assignment (incremented, newexp, ! post, 0);
                   3305:       return post ? op0 : temp;
                   3306:     }
                   3307: 
                   3308:   /* Convert decrement by a constant into a negative increment.  */
                   3309:   if (this_optab == sub_optab
                   3310:       && GET_CODE (op1) == CONST_INT)
                   3311:     {
                   3312:       op1 = gen_rtx (CONST_INT, VOIDmode, - INTVAL (op1));
                   3313:       this_optab = add_optab;
                   3314:     }
                   3315: 
                   3316:   if (post)
                   3317:     {
                   3318:       /* We have a true reference to the value in OP0.
                   3319:         If there is an insn to add or subtract in this mode, queue it.  */
                   3320: 
                   3321:       /* I'm not sure this is still necessary.  */
                   3322:       op0 = stabilize (op0);
                   3323: 
                   3324:       icode = (int) this_optab->handlers[(int) mode].insn_code;
                   3325:       if (icode != (int) CODE_FOR_nothing
                   3326:          /* Make sure that OP0 is valid for operands 0 and 1
                   3327:             of the insn we want to queue.  */
                   3328:          && (*insn_operand_predicate[icode][0]) (op0, mode)
                   3329:          && (*insn_operand_predicate[icode][1]) (op0, mode))
                   3330:        {
                   3331:          if (! (*insn_operand_predicate[icode][2]) (op1, mode))
                   3332:            op1 = force_reg (mode, op1);
                   3333: 
                   3334:          return enqueue_insn (op0, GEN_FCN (icode) (op0, op0, op1));
                   3335:        }
                   3336:     }
                   3337: 
                   3338:   /* Preincrement, or we can't increment with one simple insn.  */
                   3339:   if (post)
                   3340:     /* Save a copy of the value before inc or dec, to return it later.  */
                   3341:     temp = copy_to_reg (op0);
                   3342:   else
                   3343:     /* Arrange to return the incremented value.  */
                   3344:     temp = op0;
                   3345: 
                   3346:   /* Increment however we can.  */
                   3347:   op1 = expand_binop (mode, this_optab, op0, op1, op0,
                   3348:                      0, OPTAB_LIB_WIDEN);
                   3349:   /* Make sure the value is stored into OP0.  */
                   3350:   if (op1 != op0)
                   3351:     emit_move_insn (op0, op1);
                   3352: 
                   3353:   return temp;
                   3354: }
                   3355: 
1.1       root     3356: /* Expand all function calls contained within EXP, innermost ones first.
                   3357:    But don't look within expressions that have sequence points.
                   3358:    For each CALL_EXPR, record the rtx for its value
1.1.1.2   root     3359:    in the CALL_EXPR_RTL field.
                   3360: 
                   3361:    Calls that return large structures for which a structure return
                   3362:    stack slot is needed are not preexpanded.  Preexpanding them loses
                   3363:    because if more than one were preexpanded they would try to use the
                   3364:    same stack slot.  */
1.1       root     3365: 
                   3366: static void
                   3367: preexpand_calls (exp)
                   3368:      tree exp;
                   3369: {
                   3370:   register int nops, i;
                   3371: 
                   3372:   if (! do_preexpand_calls)
                   3373:     return;
                   3374: 
1.1.1.2   root     3375:   /* Only expressions and references can contain calls.  */
                   3376: 
                   3377:   if (tree_code_type[(int) TREE_CODE (exp)][0] != 'e'
                   3378:       && tree_code_type[(int) TREE_CODE (exp)][0] != 'r')
                   3379:     return;
                   3380: 
1.1       root     3381:   switch (TREE_CODE (exp))
                   3382:     {
                   3383:     case CALL_EXPR:
1.1.1.2   root     3384:       /* Do nothing to built-in functions.  */
                   3385:       if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
                   3386:          && TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0)) == FUNCTION_DECL
1.1.1.5   root     3387:          && (DECL_FUNCTION_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
                   3388:              != NOT_BUILT_IN))
1.1.1.2   root     3389:        return;
                   3390:       if (CALL_EXPR_RTL (exp) == 0
                   3391:          && TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
                   3392:        CALL_EXPR_RTL (exp) = expand_call (exp, 0, 0);
1.1       root     3393:       return;
                   3394: 
                   3395:     case COMPOUND_EXPR:
                   3396:     case COND_EXPR:
                   3397:     case TRUTH_ANDIF_EXPR:
                   3398:     case TRUTH_ORIF_EXPR:
                   3399:       /* If we find one of these, then we can be sure
                   3400:         the adjust will be done for it (since it makes jumps).
                   3401:         Do it now, so that if this is inside an argument
                   3402:         of a function, we don't get the stack adjustment
                   3403:         after some other args have already been pushed.  */
                   3404:       do_pending_stack_adjust ();
                   3405:       return;
                   3406: 
1.1.1.2   root     3407:     case RTL_EXPR:
                   3408:       return;
                   3409: 
1.1       root     3410:     case SAVE_EXPR:
                   3411:       if (SAVE_EXPR_RTL (exp) != 0)
                   3412:        return;
                   3413:     }
                   3414: 
                   3415:   nops = tree_code_length[(int) TREE_CODE (exp)];
                   3416:   for (i = 0; i < nops; i++)
                   3417:     if (TREE_OPERAND (exp, i) != 0)
                   3418:       {
                   3419:        register int type = *tree_code_type[(int) TREE_CODE (TREE_OPERAND (exp, i))];
                   3420:        if (type == 'e' || type == 'r')
                   3421:          preexpand_calls (TREE_OPERAND (exp, i));
                   3422:       }
                   3423: }
                   3424: 
1.1.1.2   root     3425: /* Force FUNEXP into a form suitable for the address of a CALL,
                   3426:    and return that as an rtx.  Also load the static chain register
                   3427:    from either FUNEXP or CONTEXT.  */
1.1       root     3428: 
1.1.1.2   root     3429: static rtx
                   3430: prepare_call_address (funexp, context)
1.1       root     3431:      rtx funexp;
                   3432:      rtx context;
                   3433: {
                   3434:   funexp = protect_from_queue (funexp, 0);
1.1.1.2   root     3435:   if (context != 0)
1.1       root     3436:     context = protect_from_queue (context, 0);
                   3437: 
                   3438:   /* Function variable in language with nested functions.  */
                   3439:   if (GET_MODE (funexp) == EPmode)
                   3440:     {
1.1.1.2   root     3441:       emit_move_insn (static_chain_rtx, gen_highpart (Pmode, funexp));
                   3442:       funexp = memory_address (FUNCTION_MODE, gen_lowpart (Pmode, funexp));
                   3443:       emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
1.1       root     3444:     }
                   3445:   else
                   3446:     {
                   3447:       if (context != 0)
1.1.1.2   root     3448:        /* Unless function variable in C, or top level function constant */
                   3449:        emit_move_insn (static_chain_rtx, lookup_static_chain (context));
                   3450: 
                   3451:       /* Make a valid memory address and copy constants thru pseudo-regs,
                   3452:         but not for a constant address if -fno-function-cse.  */
                   3453:       if (GET_CODE (funexp) != SYMBOL_REF)
                   3454:        funexp = memory_address (FUNCTION_MODE, funexp);
                   3455:       else
1.1       root     3456:        {
1.1.1.2   root     3457: #ifndef NO_FUNCTION_CSE
1.1.1.6   root     3458:          if (optimize && ! flag_no_function_cse)
                   3459:            funexp = force_reg (Pmode, funexp);
1.1.1.2   root     3460: #endif
                   3461:        }
                   3462: 
                   3463:       if (context != 0)
                   3464:        emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
1.1       root     3465:     }
1.1.1.2   root     3466:   return funexp;
                   3467: }
                   3468: 
                   3469: /* Generate instructions to call function FUNEXP,
                   3470:    and optionally pop the results.
                   3471:    The CALL_INSN is the first insn generated.
                   3472: 
                   3473:    FUNTYPE is the data type of the function, or, for a library call,
                   3474:    the identifier for the name of the call.  This is given to the
                   3475:    macro RETURN_POPS_ARGS to determine whether this function pops its own args.
                   3476: 
1.1.1.6   root     3477:    STACK_SIZE is the number of bytes of arguments on the stack,
1.1.1.2   root     3478:    rounded up to STACK_BOUNDARY; zero if the size is variable.
                   3479:    This is both to put into the call insn and
                   3480:    to generate explicit popping code if necessary.
                   3481: 
                   3482:    NEXT_ARG_REG is the rtx that results from executing
                   3483:      FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1)
                   3484:    just after all the args have had their registers assigned.
                   3485:    This could be whatever you like, but normally it is the first
                   3486:    arg-register beyond those used for args in this call,
                   3487:    or 0 if all the arg-registers are used in this call.
                   3488:    It is passed on to `gen_call' so you can put this info in the call insn.
                   3489: 
                   3490:    VALREG is a hard register in which a value is returned,
                   3491:    or 0 if the call does not return a value.
                   3492: 
                   3493:    OLD_ARGS_SIZE is the value that `current_args_size' had before
                   3494:    the args to this call were processed.
                   3495:    We restore `current_args_size' to that value.  */
                   3496: 
                   3497: static void
                   3498: emit_call_1 (funexp, funtype, stack_size, next_arg_reg, valreg, old_args_size)
                   3499:      rtx funexp;
                   3500:      tree funtype;
                   3501:      int stack_size;
                   3502:      rtx next_arg_reg;
                   3503:      rtx valreg;
                   3504:      int old_args_size;
                   3505: {
                   3506:   rtx stack_size_rtx = gen_rtx (CONST_INT, VOIDmode, stack_size);
                   3507: 
                   3508:   if (valreg)
                   3509:     emit_call_insn (gen_call_value (valreg,
                   3510:                                    gen_rtx (MEM, FUNCTION_MODE, funexp),
                   3511:                                    stack_size_rtx, next_arg_reg));
                   3512:   else
                   3513:     emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, funexp),
                   3514:                              stack_size_rtx, next_arg_reg));
                   3515: 
                   3516:   current_args_size = old_args_size;
                   3517: 
1.1       root     3518:   /* If returning from the subroutine does not automatically pop the args,
                   3519:      we need an instruction to pop them sooner or later.
                   3520:      Perhaps do it now; perhaps just record how much space to pop later.  */
1.1.1.2   root     3521: 
                   3522:   if (! RETURN_POPS_ARGS (TREE_TYPE (funtype))
                   3523:       && stack_size != 0)
1.1       root     3524:     {
1.1.1.2   root     3525:       if (flag_defer_pop && current_args_size == 0)
                   3526:        pending_stack_adjust += stack_size;
1.1       root     3527:       else
1.1.1.3   root     3528:        adjust_stack (stack_size_rtx);
1.1       root     3529:     }
                   3530: }
                   3531: 
                   3532: /* At the start of a function, record that we have no previously-pushed
                   3533:    arguments waiting to be popped.  */
                   3534: 
1.1.1.2   root     3535: void
                   3536: init_pending_stack_adjust ()
1.1       root     3537: {
                   3538:   pending_stack_adjust = 0;
                   3539: }
                   3540: 
1.1.1.2   root     3541: /* When exiting from function, if safe, clear out any pending stack adjust
                   3542:    so the adjustment won't get done.  */
                   3543: 
                   3544: void
                   3545: clear_pending_stack_adjust ()
                   3546: {
                   3547: #ifdef EXIT_IGNORE_STACK
1.1.1.4   root     3548:   if (!flag_omit_frame_pointer && EXIT_IGNORE_STACK
1.1.1.10  root     3549:       && ! TREE_INLINE (current_function_decl)
                   3550:       && ! flag_inline_functions)
1.1.1.2   root     3551:     pending_stack_adjust = 0;
                   3552: #endif
                   3553: }
                   3554: 
1.1       root     3555: /* At start of function, initialize.  */
1.1.1.2   root     3556: void
1.1       root     3557: clear_current_args_size ()
                   3558: {
                   3559:   current_args_size = 0;
                   3560: }
                   3561: 
                   3562: /* Pop any previously-pushed arguments that have not been popped yet.  */
                   3563: 
1.1.1.2   root     3564: void
1.1       root     3565: do_pending_stack_adjust ()
                   3566: {
                   3567:   if (current_args_size == 0)
                   3568:     {
                   3569:       if (pending_stack_adjust != 0)
                   3570:        adjust_stack (gen_rtx (CONST_INT, VOIDmode, pending_stack_adjust));
                   3571:       pending_stack_adjust = 0;
                   3572:     }
                   3573: }
                   3574: 
                   3575: /* Generate all the code for a function call
                   3576:    and return an rtx for its value.
                   3577:    Store the value in TARGET (specified as an rtx) if convenient.
1.1.1.2   root     3578:    If the value is stored in TARGET then TARGET is returned.
                   3579:    If IGNORE is nonzero, then we ignore the value of the function call.  */
1.1       root     3580: 
1.1.1.9   root     3581: struct arg_data
                   3582: {
                   3583:   /* Tree node for this argument.  */
                   3584:   tree tree_value;
                   3585:   /* Precomputed RTL value, or 0 if it isn't precomputed.  */
                   3586:   rtx value;
                   3587:   /* Register to pass this argument in, or 0 if passed on stack.  */
                   3588:   rtx reg;
                   3589:   /* Number of registers to use.  0 means put the whole arg in registers.
                   3590:      Also 0 if not passed in registers.  */
                   3591:   int partial;
                   3592:   /* Offset of this argument from beginning of stack-args.  */
                   3593:   struct args_size offset;
                   3594:   /* Size of this argument on the stack, rounded up for any padding it gets,
                   3595:      parts of the argument passed in registers do not count.
                   3596:      If the FIRST_PARM_CALLER_OFFSET is negative, then register parms
                   3597:      are counted here as well.  */
                   3598:   struct args_size size;
                   3599:   /* Nonzero if this arg has already been stored.  */
                   3600:   int stored;
                   3601:   /* const0_rtx means should preallocate stack space for this arg.
                   3602:      Other non0 value is the stack slot, preallocated.
                   3603:      Used only for BLKmode.  */
                   3604:   rtx stack;
                   3605: };
                   3606: 
1.1       root     3607: static rtx
1.1.1.2   root     3608: expand_call (exp, target, ignore)
1.1       root     3609:      tree exp;
                   3610:      rtx target;
1.1.1.2   root     3611:      int ignore;
1.1       root     3612: {
1.1.1.8   root     3613:   /* List of actual parameters.  */
1.1       root     3614:   tree actparms = TREE_OPERAND (exp, 1);
1.1.1.8   root     3615:   /* RTX for the function to be called.  */
1.1.1.2   root     3616:   rtx funexp;
1.1.1.8   root     3617:   /* Data type of the function.  */
                   3618:   tree funtype;
                   3619:   /* Declaration of the function being called,
                   3620:      or 0 if the function is computed (not known by name).  */
                   3621:   tree fndecl = 0;
                   3622: 
                   3623:   /* Register in which non-BLKmode value will be returned,
                   3624:      or 0 if no value or if value is BLKmode.  */
                   3625:   rtx valreg;
                   3626:   /* Address where we should return a BLKmode value;
                   3627:      0 if value not BLKmode.  */
                   3628:   rtx structure_value_addr = 0;
                   3629:   /* Nonzero if that address is being passed by treating it as
                   3630:      an extra, implicit first parameter.  Otherwise,
                   3631:      it is passed by being copied directly into struct_value_rtx.  */
                   3632:   int structure_value_addr_parm = 0;
1.1.1.15! root     3633:   /* Nonzero if called function returns an aggregate in memory PCC style,
        !          3634:      by returning the address of where to find it.  */
        !          3635:   int pcc_struct_value = 0;
1.1.1.8   root     3636: 
                   3637:   /* Number of actual parameters in this call, including struct value addr.  */
                   3638:   int num_actuals;
                   3639:   /* Number of named args.  Args after this are anonymous ones
                   3640:      and they must all go on the stack.  */
                   3641:   int n_named_args;
                   3642: 
1.1.1.9   root     3643:   /* Vector of information about each argument.
                   3644:      Arguments are numbered in the order they will be pushed,
1.1.1.8   root     3645:      not the order they are written.  */
1.1.1.9   root     3646:   struct arg_data *args;
1.1.1.8   root     3647: 
                   3648:   /* Total size in bytes of all the stack-parms scanned so far.  */
                   3649:   struct args_size args_size;
1.1.1.9   root     3650:   /* Remember initial value of args_size.constant.  */
                   3651:   int starting_args_size;
                   3652:   /* Nonzero means count reg-parms' size in ARGS_SIZE.  */
                   3653:   int stack_count_regparms = 0;
1.1.1.15! root     3654:   /* Number of bytes of padding BELOW the first argument.  */
        !          3655:   int stack_padding = 0;
1.1.1.8   root     3656:   /* Data on reg parms scanned so far.  */
                   3657:   CUMULATIVE_ARGS args_so_far;
                   3658:   /* Nonzero if a reg parm has been scanned.  */
1.1.1.9   root     3659:   int reg_parm_seen;
                   3660:   /* Nonzero if we must avoid push-insns in the args for this call.  */
                   3661:   int must_preallocate;
1.1.1.8   root     3662:   /* 1 if scanning parms front to back, -1 if scanning back to front.  */
1.1.1.2   root     3663:   int inc;
1.1.1.8   root     3664:   /* Address of space preallocated for stack parms
                   3665:      (on machines that lack push insns), or 0 if space not preallocated.  */
                   3666:   rtx argblock = 0;
                   3667: 
                   3668:   /* Nonzero if it is plausible that this is a call to alloca.  */
                   3669:   int may_be_alloca;
                   3670:   /* Nonzero if this is a call to setjmp or a related function.  */
1.1.1.2   root     3671:   int is_setjmp;
1.1.1.8   root     3672:   /* Nonzero if this is a call to an inline function.  */
1.1.1.2   root     3673:   int is_integrable = 0;
1.1.1.8   root     3674:   /* Nonzero if this is a call to __builtin_new.  */
                   3675:   int is_builtin_new;
1.1.1.14  root     3676:   /* Nonzero if this is a call to a `const' function.  */
                   3677:   int is_const = 0;
1.1.1.8   root     3678: 
1.1.1.9   root     3679:   /* Nonzero if there are BLKmode args whose data types require them
                   3680:      to be passed in memory, not (even partially) in registers.  */
                   3681:   int BLKmode_parms_forced = 0;
                   3682:   /* The offset of the first BLKmode parameter which 
                   3683:      *must* be passed in memory.  */
                   3684:   int BLKmode_parms_first_offset = 0;
                   3685:   /* Total size of BLKmode parms which could usefully be preallocated.  */
                   3686:   int BLKmode_parms_sizes = 0;
                   3687: 
                   3688:   /* Amount stack was adjusted to protect BLKmode parameters
                   3689:      which are below the nominal "stack address" value.  */
                   3690:   rtx protected_stack = 0;
                   3691: 
1.1.1.14  root     3692:   /* The last insn before the things that are intrinsically part of the call.
                   3693:      The beginning reg-note goes on the insn after this one.  */
                   3694:   rtx insn_before;
                   3695: 
1.1.1.9   root     3696:   rtx old_stack_level = 0;
1.1.1.2   root     3697:   int old_pending_adj;
                   3698:   int old_current_args_size = current_args_size;
1.1.1.8   root     3699:   tree old_cleanups = cleanups_of_this_call;
1.1.1.2   root     3700: 
1.1.1.8   root     3701:   register tree p;
                   3702:   register int i;
1.1.1.2   root     3703: 
                   3704:   /* See if we can find a DECL-node for the actual function.
                   3705:      As a result, decide whether this is a call to an integrable function.  */
                   3706: 
1.1.1.8   root     3707:   p = TREE_OPERAND (exp, 0);
1.1.1.2   root     3708:   if (TREE_CODE (p) == ADDR_EXPR)
                   3709:     {
                   3710:       fndecl = TREE_OPERAND (p, 0);
                   3711:       if (TREE_CODE (fndecl) != FUNCTION_DECL)
                   3712:        fndecl = 0;
                   3713:       else
                   3714:        {
                   3715:          extern tree current_function_decl;
1.1       root     3716: 
1.1.1.2   root     3717:          if (fndecl != current_function_decl
                   3718:              && DECL_SAVED_INSNS (fndecl))
                   3719:            is_integrable = 1;
                   3720:          else
1.1.1.4   root     3721:            {
                   3722:              /* In case this function later becomes inlineable,
                   3723:                 record that there was already a non-inline call to it.  */
                   3724:              TREE_ADDRESSABLE (fndecl) = 1;
                   3725:              TREE_ADDRESSABLE (DECL_NAME (fndecl)) = 1;
                   3726:            }
1.1.1.14  root     3727: 
                   3728:          if (TREE_READONLY (fndecl) && ! TREE_THIS_VOLATILE (fndecl))
                   3729:            is_const = 1;
1.1.1.2   root     3730:        }
                   3731:     }
1.1       root     3732: 
1.1.1.2   root     3733:   /* Set up a place to return a structure.  */
1.1       root     3734: 
1.1.1.15! root     3735:   if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode
        !          3736:       || (flag_pcc_struct_return
        !          3737:          && (TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
        !          3738:              || TREE_CODE (TREE_TYPE (exp)) == UNION_TYPE)))
1.1       root     3739:     {
                   3740:       /* This call returns a big structure.  */
1.1.1.15! root     3741: #ifdef PCC_STATIC_STRUCT_RETURN
        !          3742:       if (flag_pcc_struct_return)
1.1.1.9   root     3743:        {
1.1.1.15! root     3744:          pcc_struct_value = 1;
        !          3745:          is_integrable = 0;  /* Easier than making that case work right.  */
1.1.1.9   root     3746:        }
1.1       root     3747:       else
1.1.1.15! root     3748: #endif
        !          3749:        {
        !          3750:          if (target)
        !          3751:            {
        !          3752:              structure_value_addr = XEXP (target, 0);
        !          3753:              if (reg_mentioned_p (stack_pointer_rtx, structure_value_addr))
        !          3754:                structure_value_addr = copy_to_reg (structure_value_addr);
        !          3755:            }
        !          3756:          else
        !          3757:            /* Make room on the stack to hold the value.  */
        !          3758:            structure_value_addr = get_structure_value_addr (expr_size (exp));
        !          3759:        }
1.1       root     3760:     }
                   3761: 
1.1.1.15! root     3762:   /* If called function is inline, try to integrate it.  */
        !          3763: 
1.1.1.2   root     3764:   if (is_integrable)
                   3765:     {
                   3766:       extern rtx expand_inline_function ();
                   3767:       rtx temp;
                   3768: 
                   3769:       temp = expand_inline_function (fndecl, actparms, target,
                   3770:                                     ignore, TREE_TYPE (exp),
                   3771:                                     structure_value_addr);
                   3772: 
1.1.1.8   root     3773:       /* If inlining succeeded, return.  */
                   3774:       if ((int) temp != -1)
1.1.1.2   root     3775:        return temp;
1.1.1.8   root     3776: 
                   3777:       /* If inlining failed, mark FNDECL as needing to be compiled
                   3778:         separately after all.  */
                   3779:       TREE_ADDRESSABLE (fndecl) = 1;
                   3780:       TREE_ADDRESSABLE (DECL_NAME (fndecl)) = 1;
1.1.1.2   root     3781:     }
                   3782: 
                   3783: #if 0
                   3784:   /* Unless it's a call to a specific function that isn't alloca,
                   3785:      if it has one argument, we must assume it might be alloca.  */
                   3786: 
                   3787:   may_be_alloca =
                   3788:     (!(fndecl != 0
                   3789:        && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
                   3790:                  "alloca"))
                   3791:      && actparms != 0
                   3792:      && TREE_CHAIN (actparms) == 0);
                   3793: #else
                   3794:   /* We assume that alloca will always be called by name.  It
                   3795:      makes no sense to pass it as a pointer-to-function to
                   3796:      anything that does not understand its behavior.  */
                   3797:   may_be_alloca =
1.1.1.9   root     3798:     (fndecl && (! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "alloca")
                   3799:                || ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)),
                   3800:                             "__builtin_alloca")));
1.1.1.2   root     3801: #endif
                   3802: 
                   3803:   /* See if this is a call to a function that can return more than once.  */
                   3804: 
                   3805:   is_setjmp
                   3806:     = (fndecl != 0
                   3807:        && (!strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "setjmp")
                   3808:           || !strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "_setjmp")));
                   3809: 
1.1.1.8   root     3810:   is_builtin_new
                   3811:     = (fndecl != 0
                   3812:        && (!strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "__builtin_new")));
                   3813: 
1.1.1.2   root     3814:   if (may_be_alloca)
                   3815:     {
                   3816:       frame_pointer_needed = 1;
                   3817:       may_call_alloca = 1;
                   3818:     }
                   3819: 
                   3820:   /* Don't let pending stack adjusts add up to too much.
                   3821:      Also, do all pending adjustments now
                   3822:      if there is any chance this might be a call to alloca.  */
                   3823: 
                   3824:   if (pending_stack_adjust >= 32
                   3825:       || (pending_stack_adjust > 0 && may_be_alloca))
                   3826:     do_pending_stack_adjust ();
                   3827: 
                   3828:   /* Operand 0 is a pointer-to-function; get the type of the function.  */
                   3829:   funtype = TREE_TYPE (TREE_OPERAND (exp, 0));
                   3830:   if (TREE_CODE (funtype) != POINTER_TYPE)
                   3831:     abort ();
                   3832:   funtype = TREE_TYPE (funtype);
                   3833: 
1.1.1.8   root     3834:   /* If the address for a structure value should be in memory,
                   3835:      and it would go in memory if treated as an extra parameter,
                   3836:      treat it that way.  */
1.1.1.6   root     3837:   if (structure_value_addr && GET_CODE (struct_value_rtx) == MEM)
1.1.1.8   root     3838:     {
                   3839:       rtx tem;
                   3840: 
                   3841:       INIT_CUMULATIVE_ARGS (args_so_far, funtype);
                   3842:       tem = FUNCTION_ARG (args_so_far, Pmode,
                   3843:                          build_pointer_type (TREE_TYPE (funtype)), 1);
1.1.1.10  root     3844:       if (tem != 0 && GET_CODE (tem) == MEM)
1.1.1.8   root     3845:        {
                   3846:          actparms = tree_cons (error_mark_node,
                   3847:                                build (SAVE_EXPR,
                   3848:                                       type_for_size (GET_MODE_BITSIZE (Pmode), 0),
                   3849:                                       0,
                   3850:                                       force_reg (Pmode, structure_value_addr)),
                   3851:                                actparms);
                   3852:          structure_value_addr_parm = 1;
                   3853:        }
                   3854:     }
1.1.1.6   root     3855: 
1.1.1.2   root     3856:   /* Count the arguments and set NUM_ACTUALS.  */
1.1       root     3857:   for (p = actparms, i = 0; p; p = TREE_CHAIN (p)) i++;
                   3858:   num_actuals = i;
1.1.1.2   root     3859: 
                   3860:   /* Compute number of named args.
                   3861:      This may actually be 1 too large, but that happens
                   3862:      only in the case when all args are named, so no trouble results.  */
                   3863:   if (TYPE_ARG_TYPES (funtype) != 0)
                   3864:     n_named_args = list_length (TYPE_ARG_TYPES (funtype));
                   3865:   else
                   3866:     /* If we know nothing, treat all args as named.  */
                   3867:     n_named_args = num_actuals;
                   3868: 
1.1.1.9   root     3869:   /* Make a vector to hold all the information about each arg.  */
                   3870:   args = (struct arg_data *) alloca (num_actuals * sizeof (struct arg_data));
                   3871:   bzero (args, num_actuals * sizeof (struct arg_data));
                   3872: 
                   3873:   args_size.constant = 0;
                   3874:   args_size.var = 0;
                   3875: #ifdef FIRST_PARM_CALLER_OFFSET
                   3876:   args_size.constant = FIRST_PARM_CALLER_OFFSET (fntype);
                   3877:   stack_count_regparms = 1;
                   3878: #endif
                   3879:   starting_args_size = args_size.constant;
1.1.1.2   root     3880: 
                   3881:   /* In this loop, we consider args in the order they are written.
1.1.1.9   root     3882:      We fill up ARGS from the front of from the back if necessary
                   3883:      so that in any case the first arg to be pushed ends up at the front.  */
1.1       root     3884: 
1.1.1.2   root     3885: #ifdef PUSH_ARGS_REVERSED
                   3886:   i = num_actuals - 1, inc = -1;
1.1       root     3887:   /* In this case, must reverse order of args
1.1.1.2   root     3888:      so that we compute and push the last arg first.  */
1.1       root     3889: #else
1.1.1.2   root     3890:   i = 0, inc = 1;
                   3891: #endif
                   3892: 
                   3893:   INIT_CUMULATIVE_ARGS (args_so_far, funtype);
                   3894: 
                   3895:   for (p = actparms; p; p = TREE_CHAIN (p), i += inc)
                   3896:     {
                   3897:       tree type = TREE_TYPE (TREE_VALUE (p));
1.1.1.9   root     3898:       args[i].tree_value = TREE_VALUE (p);
                   3899:       args[i].offset = args_size;
1.1.1.2   root     3900: 
1.1.1.15! root     3901:       if (type == error_mark_node
        !          3902:          || TYPE_SIZE (type) == 0)
1.1.1.2   root     3903:        continue;
                   3904: 
                   3905:       /* Decide where to pass this arg.  */
1.1.1.9   root     3906:       /* args[i].reg is nonzero if all or part is passed in registers.
                   3907:         args[i].partial is nonzero if part but not all is passed in registers,
1.1.1.2   root     3908:          and the exact value says how many words are passed in registers.  */
                   3909: 
                   3910:       if (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
1.1.1.6   root     3911:          && args_size.var == 0
                   3912:          /* error_mark_node here is a flag for the fake argument
                   3913:             for a structure value address.  */
                   3914:          && TREE_PURPOSE (p) != error_mark_node)
1.1.1.2   root     3915:        {
1.1.1.9   root     3916:          args[i].reg = FUNCTION_ARG (args_so_far, TYPE_MODE (type), type,
                   3917:                                      i < n_named_args);
1.1.1.2   root     3918: #ifdef FUNCTION_ARG_PARTIAL_NREGS
1.1.1.9   root     3919:          args[i].partial
                   3920:            = FUNCTION_ARG_PARTIAL_NREGS (args_so_far,
                   3921:                                          TYPE_MODE (type), type,
                   3922:                                          i < n_named_args);
1.1.1.2   root     3923: #endif
                   3924:        }
                   3925: 
1.1.1.9   root     3926:       /* Compute the stack-size of this argument.  */
1.1.1.2   root     3927: 
1.1.1.9   root     3928:       if (args[i].reg != 0 && args[i].partial == 0
                   3929:          && ! stack_count_regparms)
                   3930:        /* On most machines, don't count stack space for a register arg.  */
1.1.1.2   root     3931:        ;
                   3932:       else if (TYPE_MODE (type) != BLKmode)
                   3933:        {
                   3934:          register int size;
                   3935: 
                   3936:          size = GET_MODE_SIZE (TYPE_MODE (type));
                   3937:          /* Compute how much space the push instruction will push.
                   3938:             On many machines, pushing a byte will advance the stack
                   3939:             pointer by a halfword.  */
                   3940: #ifdef PUSH_ROUNDING
                   3941:          size = PUSH_ROUNDING (size);
1.1       root     3942: #endif
1.1.1.2   root     3943:          /* Compute how much space the argument should get:
1.1.1.6   root     3944:             maybe pad to a multiple of the alignment for arguments.  */
                   3945:          if (none == FUNCTION_ARG_PADDING (TYPE_MODE (type), (rtx)0))
1.1.1.9   root     3946:            args[i].size.constant = size;
1.1.1.6   root     3947:          else
1.1.1.9   root     3948:            args[i].size.constant
1.1.1.6   root     3949:              = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
                   3950:                  / (PARM_BOUNDARY / BITS_PER_UNIT))
                   3951:                 * (PARM_BOUNDARY / BITS_PER_UNIT));
1.1.1.2   root     3952:        }
                   3953:       else
                   3954:        {
                   3955:          register tree size = size_in_bytes (type);
                   3956: 
                   3957:          /* A nonscalar.  Round its size up to a multiple
1.1.1.9   root     3958:             of PARM_BOUNDARY bits, unless it is not supposed to be padded.  */
1.1.1.6   root     3959:          if (none
                   3960:              != FUNCTION_ARG_PADDING (TYPE_MODE (type),
                   3961:                                       expand_expr (size, 0, VOIDmode, 0)))
                   3962:            size = convert_units (convert_units (size, BITS_PER_UNIT,
                   3963:                                                 PARM_BOUNDARY),
                   3964:                                  PARM_BOUNDARY, BITS_PER_UNIT);
1.1.1.9   root     3965:          ADD_PARM_SIZE (args[i].size, size);
                   3966: 
                   3967:          /* Certain data types may not be passed in registers
                   3968:             (eg C++ classes with constructors).
                   3969:             Also, BLKmode parameters initialized from CALL_EXPRs
                   3970:             are treated specially, if it is a win to do so.  */
                   3971:          if (TREE_CODE (TREE_VALUE (p)) == CALL_EXPR
1.1.1.13  root     3972:              || TREE_ADDRESSABLE (type))
1.1.1.9   root     3973:            {
1.1.1.13  root     3974:              if (TREE_ADDRESSABLE (type))
1.1.1.9   root     3975:                BLKmode_parms_forced = 1;
                   3976:              /* This is a marker for such a parameter.  */
                   3977:              args[i].stack = const0_rtx;
                   3978:              BLKmode_parms_sizes += TREE_INT_CST_LOW (size);
                   3979: 
                   3980:              /* If this parm's location is "below" the nominal stack pointer,
                   3981:                 note to decrement the stack pointer while it is computed.  */
                   3982: #ifdef FIRST_PARM_CALLER_OFFSET
                   3983:              if (BLKmode_parms_first_offset == 0)
                   3984:                BLKmode_parms_first_offset
                   3985:                  /* If parameter's offset is variable, assume the worst.  */
                   3986:                  = (args[i].offset.var
                   3987:                     ? FIRST_PARM_CALLER_OFFSET (fntype)
                   3988:                     : args[i].offset.constant);
                   3989: #endif
                   3990:            }
1.1.1.2   root     3991:        }
1.1.1.9   root     3992: 
1.1.1.2   root     3993:       /* If a part of the arg was put into registers,
                   3994:         don't include that part in the amount pushed.  */
1.1.1.9   root     3995:       if (! stack_count_regparms)
                   3996:        args[i].size.constant
                   3997:          -= ((args[i].partial * UNITS_PER_WORD)
                   3998:              / (PARM_BOUNDARY / BITS_PER_UNIT)
                   3999:              * (PARM_BOUNDARY / BITS_PER_UNIT));
1.1.1.2   root     4000: 
1.1.1.9   root     4001:       /* Update ARGS_SIZE, the total stack space for args so far.  */
1.1.1.2   root     4002: 
1.1.1.9   root     4003:       args_size.constant += args[i].size.constant;
                   4004:       if (args[i].size.var)
1.1.1.2   root     4005:        {
1.1.1.9   root     4006:          ADD_PARM_SIZE (args_size, args[i].size.var);
1.1.1.2   root     4007:        }
1.1.1.9   root     4008: 
                   4009:       /* Increment ARGS_SO_FAR, which has info about which arg-registers
                   4010:         have been used, etc.  */
                   4011: 
                   4012:       FUNCTION_ARG_ADVANCE (args_so_far, TYPE_MODE (type), type,
                   4013:                            i < n_named_args);
1.1.1.2   root     4014:     }
                   4015: 
1.1.1.9   root     4016:   /* If we would have to push a partially-in-regs parm
                   4017:      before other stack parms, preallocate stack space instead.  */
                   4018:   must_preallocate = 0;
                   4019:   {
                   4020:     int partial_seen = 0;
                   4021:     for (i = 0; i < num_actuals; i++)
                   4022:       {
                   4023:        if (args[i].partial > 0)
                   4024:          partial_seen = 1;
                   4025:        else if (partial_seen && args[i].reg == 0)
                   4026:          must_preallocate = 1;
                   4027:       }
                   4028:   }
                   4029: 
1.1.1.14  root     4030:   /* Precompute all register parameters.  It isn't safe to compute anything
                   4031:      once we have started filling any specific hard regs.
                   4032:      If this function call is cse'able, precompute all the parameters.  */
                   4033: 
                   4034:   reg_parm_seen = 0;
                   4035:   for (i = 0; i < num_actuals; i++)
                   4036:     if (args[i].reg != 0 || is_const)
                   4037:       {
1.1.1.15! root     4038:        int j;
        !          4039:        int struct_value_lossage = 0;
        !          4040: 
        !          4041:        /* First, see if this is a precomputed struct-returning function call
        !          4042:           and other subsequent parms are also such.  */
        !          4043:        if (TYPE_MODE (TREE_TYPE (args[i].tree_value)) == BLKmode
        !          4044:            && TREE_CODE (args[i].tree_value) == CALL_EXPR)
        !          4045:          for (j = i + 1; j < num_actuals; j++)
        !          4046:            if (TYPE_MODE (TREE_TYPE (args[j].tree_value)) == BLKmode
        !          4047:                && TREE_CODE (args[j].tree_value) == CALL_EXPR
        !          4048:                && args[j].reg != 0 || is_const)
        !          4049:              {
        !          4050:                /* We have two precomputed structure-values call expressions
        !          4051:                   in our parm list.  Both of them would normally use
        !          4052:                   the structure-value block.  To avoid the conflict,
        !          4053:                   compute this parm with a different temporary block.  */
        !          4054:                int size = int_size_in_bytes (TREE_TYPE (args[i].tree_value));
        !          4055:                rtx structval = assign_stack_local (BLKmode, size);
        !          4056:                args[i].value = expand_expr (args[i].tree_value, structval,
        !          4057:                                             VOIDmode, 0);
        !          4058:                struct_value_lossage = 1;
        !          4059:                break;
        !          4060:              }
        !          4061:        if (!struct_value_lossage)
        !          4062:          args[i].value = expand_expr (args[i].tree_value, 0, VOIDmode, 0);
        !          4063: 
1.1.1.14  root     4064:        if (args[i].reg != 0)
                   4065:          reg_parm_seen = 1;
1.1.1.15! root     4066: 
1.1.1.14  root     4067:        if (GET_CODE (args[i].value) != MEM
                   4068:            && ! CONSTANT_P (args[i].value)
                   4069:            && GET_CODE (args[i].value) != CONST_DOUBLE)
                   4070:          args[i].value
                   4071:            = force_reg (TYPE_MODE (TREE_TYPE (args[i].tree_value)),
                   4072:                         args[i].value);
                   4073:        /* ANSI doesn't require a sequence point here,
                   4074:           but PCC has one, so this will avoid some problems.  */
                   4075:        emit_queue ();
                   4076:       }
                   4077: 
                   4078:   /* Get the function to call, in the form of RTL, if it is a constant.  */
                   4079:   if (fndecl && is_const)
                   4080:     {
                   4081:       /* Get a SYMBOL_REF rtx for the function address.  */
                   4082:       funexp = XEXP (DECL_RTL (fndecl), 0);
                   4083: 
                   4084: #ifndef NO_FUNCTION_CSE
                   4085:       /* Pass the address through a pseudoreg, if desired,
                   4086:         before the "beginning" of the library call.
                   4087:         So this insn isn't "part of" the library call, in case that
                   4088:         is deleted, or cse'd.  */
                   4089:       if (! flag_no_function_cse)
                   4090:        funexp = copy_to_mode_reg (Pmode, funexp);
                   4091: #endif
                   4092:     }
                   4093: 
                   4094:   /* Now we are about to start emitting insns that can be deleted
                   4095:      if the libcall is deleted.  */
                   4096:   insn_before = get_last_insn ();
                   4097: 
1.1.1.9   root     4098:   /* If we have no actual push instructions, or shouldn't use them,
                   4099:      or we need a variable amount of space, make space for all args right now.
                   4100:      Round the needed size up to multiple of STACK_BOUNDARY.  */
1.1.1.2   root     4101: 
                   4102:   if (args_size.var != 0)
                   4103:     {
                   4104:       old_stack_level = copy_to_mode_reg (Pmode, stack_pointer_rtx);
                   4105:       old_pending_adj = pending_stack_adjust;
1.1.1.15! root     4106: #ifdef STACK_ARGS_ADJUST
        !          4107:       stack_padding = STACK_ARGS_ADJUST (args_size.constant);
        !          4108:       args_size.constant += stack_padding;
        !          4109: #endif
1.1.1.2   root     4110:       argblock = push_block (round_push (ARGS_SIZE_RTX (args_size)));
                   4111:     }
1.1.1.9   root     4112:   else if (args_size.constant > 0)
1.1.1.2   root     4113:     {
                   4114:       int needed = args_size.constant;
                   4115: 
1.1.1.15! root     4116: #ifdef STACK_ARGS_ADJUST
        !          4117:       stack_padding = STACK_ARGS_ADJUST (needed);
        !          4118:       needed += stack_padding;
        !          4119: #endif
1.1.1.2   root     4120: #ifdef STACK_BOUNDARY
                   4121:       needed = (needed + STACK_BYTES - 1) / STACK_BYTES * STACK_BYTES;
                   4122: #endif
1.1.1.15! root     4123:       args_size.constant = needed;
1.1.1.2   root     4124: 
1.1.1.9   root     4125:       if (
1.1.1.2   root     4126: #ifndef PUSH_ROUNDING
1.1.1.9   root     4127:          1  /* Always preallocate if no push insns.  */
                   4128: #else
                   4129:          must_preallocate || BLKmode_parms_forced
                   4130:          || BLKmode_parms_sizes > (args_size.constant >> 1)
                   4131: #endif
                   4132:          )
1.1.1.2   root     4133:        {
1.1.1.9   root     4134:          /* Try to reuse some or all of the pending_stack_adjust
                   4135:             to get this space.  Maybe we can avoid any pushing.  */
                   4136:          if (needed > pending_stack_adjust)
                   4137:            {
                   4138:              needed -= pending_stack_adjust;
                   4139:              pending_stack_adjust = 0;
                   4140:            }
                   4141:          else
                   4142:            {
                   4143:              pending_stack_adjust -= needed;
                   4144:              needed = 0;
                   4145:            }
                   4146:          argblock = push_block (gen_rtx (CONST_INT, VOIDmode, needed));
1.1.1.2   root     4147:        }
                   4148:     }
1.1.1.13  root     4149: #ifndef PUSH_ROUNDING
                   4150:   else if (BLKmode_parms_forced)
                   4151:     {
                   4152:       /* If we have reg-parms that need to be temporarily on the stack,
                   4153:         set up an arg block address even though there is no space
                   4154:         to be allocated for it.  */
                   4155:       argblock = push_block (const0_rtx);
                   4156:     }
                   4157: #endif
1.1.1.2   root     4158: 
1.1.1.15! root     4159: #ifdef STACK_ARGS_ADJUST
        !          4160:   /* If stack needs padding below the args, increase all arg offsets
        !          4161:      so the args are stored above the padding.  */
        !          4162:   if (stack_padding)
        !          4163:     for (i = 0; i < num_actuals; i++)
        !          4164:       args[i].offset.constant += stack_padding;
        !          4165: #endif
        !          4166: 
1.1.1.9   root     4167:   /* Don't try to defer pops if preallocating, not even from the first arg,
                   4168:      since ARGBLOCK probably refers to the SP.  */
                   4169:   if (argblock)
                   4170:     NO_DEFER_POP;
                   4171: 
                   4172: #ifdef STACK_GROWS_DOWNWARD
                   4173:   /* If any BLKmode parms need to be preallocated in space
                   4174:      below the nominal stack-pointer address, we need to adjust the
                   4175:      stack pointer so that this location is temporarily above it.
                   4176:      This ensures that computation won't clobber that space.  */
                   4177:   if (BLKmode_parms_first_offset < 0 && argblock != 0)
                   4178:     {
                   4179:       int needed = -BLKmode_parms_first_offset;
                   4180:       argblock = copy_to_reg (argblock);
                   4181: 
                   4182: #ifdef STACK_BOUNDARY
                   4183:       needed = (needed + STACK_BYTES - 1) / STACK_BYTES * STACK_BYTES;
                   4184: #endif
                   4185:       protected_stack = gen_rtx (CONST_INT, VOIDmode, needed);
                   4186:       anti_adjust_stack (protected_stack);
                   4187:     }
                   4188: #endif /* STACK_GROWS_DOWNWARD */
                   4189: 
1.1.1.2   root     4190:   /* Get the function to call, in the form of RTL.  */
                   4191:   if (fndecl)
                   4192:     /* Get a SYMBOL_REF rtx for the function address.  */
                   4193:     funexp = XEXP (DECL_RTL (fndecl), 0);
                   4194:   else
                   4195:     /* Generate an rtx (probably a pseudo-register) for the address.  */
1.1.1.4   root     4196:     {
                   4197:       funexp = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   4198:       emit_queue ();
                   4199:     }
1.1.1.2   root     4200: 
1.1.1.9   root     4201:   /* Now compute and store all non-register parms.
                   4202:      These come before register parms, since they can require block-moves,
                   4203:      which could clobber the registers used for register parms.
                   4204:      Parms which have partial registers are not stored here,
                   4205:      but we do preallocate space here if they want that.  */
1.1.1.2   root     4206: 
1.1       root     4207:   for (i = 0; i < num_actuals; i++)
                   4208:     {
1.1.1.9   root     4209:       /* Preallocate the stack space for a parm if appropriate
                   4210:         so it can be computed directly in the stack space.  */
                   4211:       if (args[i].stack != 0 && argblock != 0)
                   4212:        args[i].stack = target_for_arg (TREE_TYPE (args[i].tree_value),
                   4213:                                        ARGS_SIZE_RTX (args[i].size),
                   4214:                                        argblock, args[i].offset);
1.1       root     4215:       else
1.1.1.9   root     4216:        args[i].stack = 0;
1.1       root     4217: 
1.1.1.15! root     4218:       if (args[i].reg == 0
        !          4219:          && TYPE_SIZE (TREE_TYPE (args[i].tree_value)) != 0)
1.1.1.9   root     4220:        store_one_arg (&args[i], argblock, may_be_alloca);
                   4221:     }
1.1       root     4222: 
1.1.1.9   root     4223:   /* Now store any partially-in-registers parm.
                   4224:      This is the last place a block-move can happen.  */
                   4225:   if (reg_parm_seen)
                   4226:     for (i = 0; i < num_actuals; i++)
                   4227:       if (args[i].partial != 0)
                   4228:        store_one_arg (&args[i], argblock, may_be_alloca);
1.1       root     4229: 
1.1.1.9   root     4230:   if (protected_stack != 0)
                   4231:     adjust_stack (protected_stack);
1.1       root     4232: 
1.1.1.9   root     4233:   /* Pass the function the address in which to return a structure value.  */
                   4234:   if (structure_value_addr && ! structure_value_addr_parm)
                   4235:     emit_move_insn (struct_value_rtx, force_reg (Pmode, structure_value_addr));
1.1       root     4236: 
1.1.1.9   root     4237:   /* Now set up any wholly-register parms.  They were computed already.  */
                   4238:   if (reg_parm_seen)
                   4239:     for (i = 0; i < num_actuals; i++)
                   4240:       if (args[i].reg != 0 && args[i].partial == 0)
                   4241:        store_one_arg (&args[i], argblock, may_be_alloca);
1.1       root     4242: 
                   4243:   /* Perform postincrements before actually calling the function.  */
                   4244:   emit_queue ();
                   4245: 
1.1.1.2   root     4246:   /* All arguments and registers used for the call must be set up by now!  */
1.1       root     4247: 
1.1.1.2   root     4248:   /* ??? Other languages need a nontrivial second argument (static chain).  */
                   4249:   funexp = prepare_call_address (funexp, 0);
                   4250: 
                   4251:   /* Mark all register-parms as living through the call.
                   4252:      ??? This is not quite correct, since it doesn't indicate
                   4253:      that they are in use immediately before the call insn.
                   4254:      Currently that doesn't matter since explicitly-used regs
                   4255:      won't be used for reloading.  But if the reloader becomes smarter,
                   4256:      this will have to change somehow.  */
                   4257:   for (i = 0; i < num_actuals; i++)
1.1.1.9   root     4258:     if (args[i].reg != 0)
1.1.1.2   root     4259:       {
1.1.1.9   root     4260:        if (args[i].partial > 0)
                   4261:          use_regs (REGNO (args[i].reg), args[i].partial);
                   4262:        else if (GET_MODE (args[i].reg) == BLKmode)
                   4263:          use_regs (REGNO (args[i].reg),
1.1.1.10  root     4264:                    (int_size_in_bytes (TREE_TYPE (args[i].tree_value))
1.1.1.2   root     4265:                     / UNITS_PER_WORD));
                   4266:        else
1.1.1.9   root     4267:          emit_insn (gen_rtx (USE, VOIDmode, args[i].reg));
1.1.1.2   root     4268:       }
                   4269: 
1.1.1.9   root     4270:   if (structure_value_addr && GET_CODE (struct_value_rtx) == REG)
1.1.1.2   root     4271:     emit_insn (gen_rtx (USE, VOIDmode, struct_value_rtx));
                   4272: 
                   4273:   /* Figure out the register where the value, if any, will come back.  */
                   4274:   valreg = 0;
                   4275:   if (TYPE_MODE (TREE_TYPE (exp)) != VOIDmode
                   4276:       && TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
                   4277:     valreg = hard_function_value (TREE_TYPE (exp), fndecl);
                   4278: 
                   4279:   /* Generate the actual call instruction.  */
1.1.1.9   root     4280:   if (args_size.constant < 0)
                   4281:     args_size.constant = 0;
1.1.1.2   root     4282:   emit_call_1 (funexp, funtype, args_size.constant,
                   4283:               FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1),
                   4284:               valreg, old_current_args_size);
1.1       root     4285: 
                   4286: /* ???  Nothing has been done here to record control flow
                   4287:    when contained functions can do nonlocal gotos.  */
                   4288: 
1.1.1.2   root     4289:   /* For calls to `setjmp', etc., inform flow.c it should complain
                   4290:      if nonvolatile values are live.  */
                   4291: 
                   4292:   if (is_setjmp)
1.1.1.11  root     4293:     {
                   4294:       emit_note (IDENTIFIER_POINTER (DECL_NAME (fndecl)), NOTE_INSN_SETJMP);
                   4295:       current_function_calls_setjmp = 1;
                   4296:     }
1.1.1.2   root     4297: 
1.1.1.14  root     4298:   /* Notice functions that cannot return.
                   4299:      If optimizing, insns emitted below will be dead.
                   4300:      If not optimizing, they will exist, which is useful
                   4301:      if the user uses the `return' command in the debugger.  */
                   4302: 
                   4303:   if (fndecl && TREE_THIS_VOLATILE (fndecl))
                   4304:     emit_barrier ();
                   4305: 
1.1.1.8   root     4306:   /* For calls to __builtin_new, note that it can never return 0.
                   4307:      This is because a new handler will be called, and 0 it not
                   4308:      among the numbers it is supposed to return.  */
                   4309: #if 0
                   4310:   if (is_builtin_new)
                   4311:     emit_note (IDENTIFIER_POINTER (DECL_NAME (fndecl)), NOTE_INSN_BUILTIN_NEW);
                   4312: #endif
1.1.1.2   root     4313: 
1.1       root     4314:   /* If value type not void, return an rtx for the value.  */
                   4315: 
1.1.1.13  root     4316:   /* If there are cleanups to be called, don't use a hard reg as target.  */
                   4317:   if (cleanups_of_this_call != old_cleanups
                   4318:       && target && REG_P (target)
                   4319:       && REGNO (target) < FIRST_PSEUDO_REGISTER)
                   4320:     target = 0;
                   4321: 
1.1.1.2   root     4322:   if (TYPE_MODE (TREE_TYPE (exp)) == VOIDmode
                   4323:       || ignore)
1.1       root     4324:     {
1.1.1.14  root     4325:       target = const0_rtx;
1.1       root     4326:     }
1.1.1.8   root     4327:   else if (structure_value_addr)
                   4328:     {
                   4329:       if (target == 0)
                   4330:        target = gen_rtx (MEM, BLKmode,
                   4331:                          memory_address (BLKmode, structure_value_addr));
                   4332:     }
1.1.1.15! root     4333:   else if (pcc_struct_value)
        !          4334:     {
        !          4335:       if (target != 0)
        !          4336:        {
        !          4337:          valreg = hard_function_value (build_pointer_type (TREE_TYPE (exp)),
        !          4338:                                        fndecl);
        !          4339:          target = gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
        !          4340:                            copy_to_reg (valreg));
        !          4341:        }
        !          4342:       else if (TYPE_MODE (TREE_TYPE (exp)) != BLKmode)
        !          4343:        emit_move_insn (target, gen_rtx (MEM, TYPE_MODE (TREE_TYPE (exp)),
        !          4344:                                         copy_to_reg (valreg)));
        !          4345:       else
        !          4346:        emit_block_move (target, gen_rtx (MEM, BLKmode, copy_to_reg (valreg)),
        !          4347:                         expr_size (exp),
        !          4348:                         TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
        !          4349:     }
1.1.1.8   root     4350:   else if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)))
1.1       root     4351:     {
1.1.1.2   root     4352:       if (!rtx_equal_p (target, valreg))
                   4353:        emit_move_insn (target, valreg);
                   4354:       else
                   4355:        /* This tells expand_inline_function to copy valreg to its target.  */
                   4356:        emit_insn (gen_rtx (USE, VOIDmode, valreg));
1.1       root     4357:     }
1.1.1.8   root     4358:   else
                   4359:     target = copy_to_reg (valreg);
                   4360: 
1.1.1.9   root     4361:   /* Perform all cleanups needed for the arguments of this call
                   4362:      (i.e. destructors in C++).  */
                   4363:   while (cleanups_of_this_call != old_cleanups)
                   4364:     {
                   4365:       expand_expr (TREE_VALUE (cleanups_of_this_call), 0, VOIDmode, 0);
                   4366:       cleanups_of_this_call = TREE_CHAIN (cleanups_of_this_call);
                   4367:     }
                   4368: 
1.1.1.8   root     4369:   /* If size of args is variable, restore saved stack-pointer value.  */
                   4370: 
1.1.1.9   root     4371:   if (old_stack_level)
1.1.1.8   root     4372:     {
                   4373:       emit_move_insn (stack_pointer_rtx, old_stack_level);
                   4374:       pending_stack_adjust = old_pending_adj;
                   4375:     }
                   4376: 
1.1.1.14  root     4377:   /* If call is cse'able, make appropriate pair of reg-notes around it.  */
                   4378:   if (is_const)
                   4379:     {
                   4380:       rtx insn_first = NEXT_INSN (insn_before);
                   4381:       rtx insn_last = get_last_insn ();
                   4382:       rtx note = 0;
                   4383: 
                   4384:       /* Construct an "equal form" for the value
                   4385:         which mentions all the arguments in order
                   4386:         as well as the function name.  */
                   4387:       for (i = 0; i < num_actuals; i++)
                   4388:        if (args[i].reg != 0 || is_const)
                   4389:          note = gen_rtx (EXPR_LIST, VOIDmode, args[i].value, note);
                   4390:       note = gen_rtx (EXPR_LIST, VOIDmode, XEXP (DECL_RTL (fndecl), 0), note);
                   4391: 
                   4392:       REG_NOTES (insn_last)
                   4393:        = gen_rtx (EXPR_LIST, REG_EQUAL, note,
                   4394:                   gen_rtx (INSN_LIST, REG_RETVAL, insn_first,
                   4395:                            REG_NOTES (insn_last)));
                   4396:       REG_NOTES (insn_first)
                   4397:        = gen_rtx (INSN_LIST, REG_LIBCALL, insn_last,
                   4398:                   REG_NOTES (insn_first));
                   4399:     }
                   4400: 
1.1.1.9   root     4401:   return target;
                   4402: }
                   4403: 
                   4404: /* Return an rtx which represents a suitable home on the stack
                   4405:    given TYPE, the type of the argument looking for a home.
                   4406:    This is called only for BLKmode arguments.
                   4407: 
                   4408:    SIZE is the size needed for this target.
                   4409:    ARGS_ADDR is the address of the bottom of the argument block for this call.
                   4410:    OFFSET describes this parameter's offset into ARGS_ADDR.  It is meaningless
                   4411:    if this machine uses push insns.  */
                   4412: 
                   4413: static rtx
                   4414: target_for_arg (type, size, args_addr, offset)
                   4415:      tree type;
                   4416:      rtx size;
                   4417:      rtx args_addr;
                   4418:      struct args_size offset;
                   4419: {
                   4420:   rtx target;
                   4421:   rtx offset_rtx = ARGS_SIZE_RTX (offset);
                   4422: 
                   4423:   /* We do not call memory_address if possible,
                   4424:      because we want to address as close to the stack
                   4425:      as possible.  For non-variable sized arguments,
                   4426:      this will be stack-pointer relative addressing.  */
                   4427:   if (GET_CODE (offset_rtx) == CONST_INT)
                   4428:     target = plus_constant (args_addr, INTVAL (offset_rtx));
                   4429:   else
1.1.1.8   root     4430:     {
1.1.1.9   root     4431:       /* I have no idea how to guarantee that this
                   4432:         will work in the presence of register parameters.  */
                   4433:       target = gen_rtx (PLUS, Pmode, args_addr, offset_rtx);
                   4434:       target = memory_address (QImode, target);
1.1.1.8   root     4435:     }
1.1.1.9   root     4436: 
                   4437:   return gen_rtx (MEM, BLKmode, target);
                   4438: }
                   4439: 
                   4440: /* Store a single argument for a function call
                   4441:    into the register or memory area where it must be passed.
                   4442:    *ARG describes the argument value and where to pass it.
                   4443:    ARGBLOCK is the address of the stack-block for all the arguments,
                   4444:    or 0 on a machine where arguemnts are pushed individually.
                   4445:    MAY_BE_ALLOCA nonzero says this could be a call to `alloca'
                   4446:    so must be careful about how the stack is used.  */
                   4447: 
                   4448: static void
                   4449: store_one_arg (arg, argblock, may_be_alloca)
                   4450:      struct arg_data *arg;
                   4451:      rtx argblock;
                   4452:      int may_be_alloca;
                   4453: {
                   4454:   register tree pval = arg->tree_value;
                   4455:   int used = 0;
                   4456: 
                   4457:   if (TREE_CODE (pval) == ERROR_MARK)
                   4458:     return;
                   4459: 
                   4460:   if (arg->reg != 0 && arg->partial == 0)
                   4461:     {
                   4462:       /* Being passed entirely in a register.  */
                   4463:       if (arg->value != 0)
                   4464:        {
                   4465:          if (GET_MODE (arg->value) == BLKmode)
                   4466:            move_block_to_reg (REGNO (arg->reg), arg->value,
                   4467:                               (int_size_in_bytes (TREE_TYPE (pval))
                   4468:                                / UNITS_PER_WORD));
                   4469:          else
                   4470:            emit_move_insn (arg->reg, arg->value);
                   4471:        }
                   4472:       else
                   4473:        store_expr (pval, arg->reg, 0);
                   4474: 
                   4475:       /* Don't allow anything left on stack from computation
                   4476:         of argument to alloca.  */
                   4477:       if (may_be_alloca)
                   4478:        do_pending_stack_adjust ();
                   4479:     }
                   4480:   else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode)
                   4481:     {
                   4482:       register int size;
                   4483:       rtx tem;
                   4484: 
                   4485:       /* Argument is a scalar, not entirely passed in registers.
                   4486:         (If part is passed in registers, arg->partial says how much
                   4487:         and emit_push_insn will take care of putting it there.)
                   4488:         
                   4489:         Push it, and if its size is less than the
                   4490:         amount of space allocated to it,
                   4491:         also bump stack pointer by the additional space.
                   4492:         Note that in C the default argument promotions
                   4493:         will prevent such mismatches.  */
                   4494: 
                   4495:       used = size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (pval)));
                   4496:       /* Compute how much space the push instruction will push.
                   4497:         On many machines, pushing a byte will advance the stack
                   4498:         pointer by a halfword.  */
                   4499: #ifdef PUSH_ROUNDING
                   4500:       size = PUSH_ROUNDING (size);
                   4501: #endif
                   4502:       /* Compute how much space the argument should get:
                   4503:         round up to a multiple of the alignment for arguments.  */
                   4504:       if (none != FUNCTION_ARG_PADDING (TYPE_MODE (TREE_TYPE (pval)), (rtx)0))
                   4505:        used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)
                   4506:                 / (PARM_BOUNDARY / BITS_PER_UNIT))
                   4507:                * (PARM_BOUNDARY / BITS_PER_UNIT));
                   4508: 
                   4509:       tem = arg->value;
                   4510:       if (tem == 0)
                   4511:        {
                   4512:          tem = expand_expr (pval, 0, VOIDmode, 0);
                   4513:          /* ANSI doesn't require a sequence point here,
                   4514:             but PCC has one, so this will avoid some problems.  */
                   4515:          emit_queue ();
                   4516:        }
                   4517: 
                   4518:       /* Don't allow anything left on stack from computation
                   4519:         of argument to alloca.  */
                   4520:       if (may_be_alloca)
                   4521:        do_pending_stack_adjust ();
                   4522: 
                   4523:       emit_push_insn (tem, TYPE_MODE (TREE_TYPE (pval)), 0, 0,
                   4524:                      arg->partial, arg->reg, used - size,
                   4525:                      argblock, ARGS_SIZE_RTX (arg->offset));
                   4526:     }
                   4527:   else if (arg->stack != 0)
                   4528:     {
1.1.1.14  root     4529:       /* BLKmode parm, not entirely passed in registers,
                   4530:         and with space already allocated.  */
                   4531: 
                   4532:       tree sizetree = size_in_bytes (TREE_TYPE (pval));
                   4533:       /* Round the size up to multiple of PARM_BOUNDARY bits.  */
                   4534:       tree s1 = convert_units (sizetree, BITS_PER_UNIT, PARM_BOUNDARY);
                   4535:       tree s2 = convert_units (s1, PARM_BOUNDARY, BITS_PER_UNIT);
                   4536: 
                   4537:       /* Find out if the parm needs padding, and whether above or below.  */
                   4538:       enum direction where_pad
                   4539:        = FUNCTION_ARG_PADDING (TYPE_MODE (TREE_TYPE (pval)),
                   4540:                                expand_expr (sizetree, 0, VOIDmode, 0));
                   4541: 
                   4542:       /* If it is padded below, adjust the stack address
                   4543:         upward over the padding.  */
                   4544: 
                   4545:       if (where_pad == downward)
                   4546:        {
                   4547:          rtx offset_rtx;
                   4548:          rtx address = XEXP (arg->stack, 0);
                   4549:          struct args_size stack_offset;
                   4550: 
                   4551:          stack_offset.constant = 0;
                   4552:          stack_offset.var = 0;
                   4553: 
                   4554:          /* Compute amount of padding.  */
                   4555:          ADD_PARM_SIZE (stack_offset, s2);
                   4556:          SUB_PARM_SIZE (stack_offset, sizetree);
                   4557:          offset_rtx = ARGS_SIZE_RTX (stack_offset);
                   4558: 
                   4559:          /* Adjust the address to store at.  */
                   4560:          if (GET_CODE (offset_rtx) == CONST_INT)
                   4561:            address = plus_constant (address, INTVAL (offset_rtx));
                   4562:          else
                   4563:            {
                   4564:              address = gen_rtx (PLUS, Pmode, address, offset_rtx);
                   4565:              address = memory_address (QImode, address);
                   4566:            }
                   4567:          arg->stack = change_address (arg->stack, VOIDmode, address);
                   4568:        }
                   4569: 
1.1.1.12  root     4570:       /* ARG->stack probably refers to the stack-pointer.  If so,
                   4571:         stabilize it, in case stack-pointer changes during evaluation.  */
                   4572:       if (reg_mentioned_p (stack_pointer_rtx, arg->stack))
                   4573:        arg->stack = change_address (arg->stack, VOIDmode,
                   4574:                                     copy_to_reg (XEXP (arg->stack, 0)));
1.1.1.9   root     4575:       /* BLKmode argument that should go in a prespecified stack location.  */
                   4576:       if (arg->value == 0)
                   4577:        /* Not yet computed => compute it there.  */
                   4578:        /* ??? This should be changed to tell expand_expr
                   4579:           that it can store directly in the target.  */
                   4580:        arg->value = store_expr (arg->tree_value, arg->stack, 0);
                   4581:       else if (arg->value != arg->stack)
                   4582:        /* It was computed somewhere, but not where we wanted.
                   4583:           For example, the value may have come from an official
                   4584:           local variable or parameter.  In that case, expand_expr
                   4585:           does not fill our suggested target.  */
                   4586:        emit_block_move (arg->stack, arg->value, ARGS_SIZE_RTX (arg->size),
1.1.1.10  root     4587:                         TYPE_ALIGN (TREE_TYPE (pval)) / BITS_PER_UNIT);
1.1.1.9   root     4588: 
                   4589:       /* Now, if this value wanted to be partly in registers,
                   4590:         move the value from the stack to the registers
                   4591:         that are supposed to hold the values.  */
                   4592:       if (arg->partial > 0)
                   4593:        move_block_to_reg (REGNO (arg->reg), arg->stack, arg->partial);
                   4594:     }
                   4595:   else
                   4596:     {
1.1.1.14  root     4597:       /* BLKmode, at least partly to be pushed.  */
                   4598: 
1.1.1.9   root     4599:       register rtx tem
                   4600:        = arg->value ? arg->value : expand_expr (pval, 0, VOIDmode, 0);
                   4601:       register int excess;
                   4602:       rtx size_rtx;
                   4603: 
                   4604:       /* Pushing a nonscalar.
                   4605:         If part is passed in registers, arg->partial says how much
                   4606:         and emit_push_insn will take care of putting it there.  */
                   4607: 
                   4608:       /* Round its size up to a multiple
                   4609:         of the allocation unit for arguments.  */
                   4610: 
                   4611:       if (arg->size.var != 0)
                   4612:        {
                   4613:          excess = 0;
                   4614:          size_rtx = ARGS_SIZE_RTX (arg->size);
                   4615:        }
                   4616:       else
                   4617:        {
                   4618:          register tree size = size_in_bytes (TREE_TYPE (pval));
                   4619:          /* PUSH_ROUNDING has no effect on us, because
                   4620:             emit_push_insn for BLKmode is careful to avoid it.  */
                   4621:          excess = arg->size.constant - TREE_INT_CST_LOW (size);
                   4622:          size_rtx = expand_expr (size, 0, VOIDmode, 0);
                   4623:        }
                   4624: 
                   4625:       if (arg->stack)
                   4626:        abort ();
                   4627: 
                   4628:       emit_push_insn (tem, TYPE_MODE (TREE_TYPE (pval)), size_rtx,
                   4629:                      TYPE_ALIGN (TREE_TYPE (pval)) / BITS_PER_UNIT,
                   4630:                      arg->partial, arg->reg, excess, argblock,
                   4631:                      ARGS_SIZE_RTX (arg->offset));
                   4632:     }
                   4633: 
                   4634:   /* Once we have pushed something, pops can't safely
                   4635:      be deferred during the rest of the arguments.  */
                   4636:   NO_DEFER_POP;
1.1       root     4637: }
                   4638: 
                   4639: /* Expand conditional expressions.  */
                   4640: 
                   4641: /* Generate code to evaluate EXP and jump to LABEL if the value is zero.
                   4642:    LABEL is an rtx of code CODE_LABEL, in this function and all the
                   4643:    functions here.  */
                   4644: 
1.1.1.2   root     4645: void
1.1       root     4646: jumpifnot (exp, label)
                   4647:      tree exp;
                   4648:      rtx label;
                   4649: {
                   4650:   do_jump (exp, label, 0);
                   4651: }
                   4652: 
                   4653: /* Generate code to evaluate EXP and jump to LABEL if the value is nonzero.  */
                   4654: 
1.1.1.2   root     4655: void
1.1       root     4656: jumpif (exp, label)
                   4657:      tree exp;
                   4658:      rtx label;
                   4659: {
                   4660:   do_jump (exp, 0, label);
                   4661: }
                   4662: 
                   4663: /* Generate code to evaluate EXP and jump to IF_FALSE_LABEL if
                   4664:    the result is zero, or IF_TRUE_LABEL if the result is one.
                   4665:    Either of IF_FALSE_LABEL and IF_TRUE_LABEL may be zero,
                   4666:    meaning fall through in that case.
                   4667: 
                   4668:    This function is responsible for optimizing cases such as
                   4669:    &&, || and comparison operators in EXP.  */
                   4670: 
1.1.1.2   root     4671: void
1.1       root     4672: do_jump (exp, if_false_label, if_true_label)
                   4673:      tree exp;
                   4674:      rtx if_false_label, if_true_label;
                   4675: {
                   4676:   register enum tree_code code = TREE_CODE (exp);
                   4677:   /* Some cases need to create a label to jump to
                   4678:      in order to properly fall through.
                   4679:      These cases set DROP_THROUGH_LABEL nonzero.  */
                   4680:   rtx drop_through_label = 0;
                   4681:   rtx temp;
                   4682:   rtx comparison = 0;
                   4683: 
                   4684:   emit_queue ();
                   4685: 
                   4686:   switch (code)
                   4687:     {
                   4688:     case ERROR_MARK:
                   4689:       break;
                   4690: 
                   4691:     case INTEGER_CST:
                   4692:       temp = integer_zerop (exp) ? if_false_label : if_true_label;
                   4693:       if (temp)
                   4694:        emit_jump (temp);
                   4695:       break;
                   4696: 
                   4697:     case ADDR_EXPR:
                   4698:       /* The address of something can never be zero.  */
                   4699:       if (if_true_label)
                   4700:        emit_jump (if_true_label);
                   4701:       break;
1.1.1.6   root     4702: 
1.1       root     4703:     case NOP_EXPR:
                   4704:       do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
                   4705:       break;
                   4706: 
                   4707:     case TRUTH_NOT_EXPR:
                   4708:       do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
                   4709:       break;
                   4710: 
                   4711:     case TRUTH_ANDIF_EXPR:
                   4712:       if (if_false_label == 0)
                   4713:        if_false_label = drop_through_label = gen_label_rtx ();
                   4714:       do_jump (TREE_OPERAND (exp, 0), if_false_label, 0);
                   4715:       do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
                   4716:       break;
                   4717: 
                   4718:     case TRUTH_ORIF_EXPR:
                   4719:       if (if_true_label == 0)
                   4720:        if_true_label = drop_through_label = gen_label_rtx ();
                   4721:       do_jump (TREE_OPERAND (exp, 0), 0, if_true_label);
                   4722:       do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
                   4723:       break;
                   4724: 
                   4725:     case COMPOUND_EXPR:
1.1.1.2   root     4726:       expand_expr (TREE_OPERAND (exp, 0), const0_rtx, VOIDmode, 0);
1.1       root     4727:       emit_queue ();
                   4728:       do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
                   4729:       break;
                   4730: 
                   4731:     case COND_EXPR:
                   4732:       {
                   4733:        register rtx label1 = gen_label_rtx ();
                   4734:        drop_through_label = gen_label_rtx ();
                   4735:        do_jump (TREE_OPERAND (exp, 0), label1, 0);
                   4736:        /* Now the THEN-expression.  */
                   4737:        do_jump (TREE_OPERAND (exp, 1),
                   4738:                 if_false_label ? if_false_label : drop_through_label,
                   4739:                 if_true_label ? if_true_label : drop_through_label);
                   4740:        emit_label (label1);
                   4741:        /* Now the ELSE-expression.  */
                   4742:        do_jump (TREE_OPERAND (exp, 2),
                   4743:                 if_false_label ? if_false_label : drop_through_label,
                   4744:                 if_true_label ? if_true_label : drop_through_label);
                   4745:       }
                   4746:       break;
                   4747: 
                   4748:     case EQ_EXPR:
                   4749:       comparison = compare (exp, EQ, EQ, EQ, EQ);
                   4750:       break;
                   4751: 
                   4752:     case NE_EXPR:
                   4753:       comparison = compare (exp, NE, NE, NE, NE);
                   4754:       break;
                   4755: 
                   4756:     case LT_EXPR:
                   4757:       comparison = compare (exp, LT, LTU, GT, GTU);
                   4758:       break;
                   4759: 
                   4760:     case LE_EXPR:
                   4761:       comparison = compare (exp, LE, LEU, GE, GEU);
                   4762:       break;
                   4763: 
                   4764:     case GT_EXPR:
                   4765:       comparison = compare (exp, GT, GTU, LT, LTU);
                   4766:       break;
                   4767: 
                   4768:     case GE_EXPR:
                   4769:       comparison = compare (exp, GE, GEU, LE, LEU);
                   4770:       break;
                   4771: 
                   4772:     default:
                   4773:       temp = expand_expr (exp, 0, VOIDmode, 0);
1.1.1.2   root     4774:       /* Copy to register to avoid generating bad insns by cse
                   4775:         from (set (mem ...) (arithop))  (set (cc0) (mem ...)).  */
                   4776:       if (!cse_not_expected && GET_CODE (temp) == MEM)
                   4777:        temp = copy_to_reg (temp);
1.1       root     4778:       do_pending_stack_adjust ();
1.1.1.2   root     4779:       {
                   4780:        rtx zero;
                   4781:        if (GET_MODE (temp) == SFmode)
                   4782:          zero = fconst0_rtx;
                   4783:        else if (GET_MODE (temp) == DFmode)
                   4784:          zero = dconst0_rtx;
                   4785:        else
                   4786:          zero = const0_rtx;
1.1       root     4787: 
1.1.1.2   root     4788:        if (GET_CODE (temp) == CONST_INT)
                   4789:          comparison = compare_constants (NE, 0,
                   4790:                                          INTVAL (temp), 0, BITS_PER_WORD);
                   4791:        else if (GET_MODE (temp) != VOIDmode)
                   4792:          comparison = compare1 (temp, zero, NE, NE, 0, GET_MODE (temp));
                   4793:        else
                   4794:          abort ();
                   4795:       }
1.1       root     4796:     }
                   4797: 
1.1.1.2   root     4798:   /* Do any postincrements in the expression that was tested.  */
                   4799:   emit_queue ();
                   4800: 
1.1       root     4801:   /* If COMPARISON is nonzero here, it is an rtx that can be substituted
                   4802:      straight into a conditional jump instruction as the jump condition.
                   4803:      Otherwise, all the work has been done already.  */
                   4804: 
1.1.1.2   root     4805:   if (comparison == const1_rtx)
                   4806:     {
                   4807:       if (if_true_label)
                   4808:        emit_jump (if_true_label);
                   4809:     }
                   4810:   else if (comparison == const0_rtx)
                   4811:     {
                   4812:       if (if_false_label)
                   4813:        emit_jump (if_false_label);
                   4814:     }
                   4815:   else if (comparison)
                   4816:     {
                   4817:       if (if_true_label)
                   4818:        {
1.1.1.13  root     4819:          if (bcc_gen_fctn[(int) GET_CODE (comparison)] != 0)
                   4820:            emit_jump_insn ((*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_true_label));
                   4821:          else
                   4822:            abort ();
                   4823: 
1.1.1.2   root     4824:          if (if_false_label)
                   4825:            emit_jump (if_false_label);
                   4826:        }
                   4827:       else if (if_false_label)
                   4828:        {
1.1.1.13  root     4829:          rtx pat;
                   4830: 
                   4831:          if (bcc_gen_fctn[(int) GET_CODE (comparison)] == 0)
                   4832:            abort ();
                   4833: 
                   4834:          pat = (*bcc_gen_fctn[(int) GET_CODE (comparison)]) (if_false_label);
                   4835:          /* Now invert the sense of the jump by exchanging the two arms
                   4836:             of each IF_THEN_ELSE.  Note that inverting the condition
                   4837:             would be incorrect for IEEE floating point with nans!  */
1.1.1.14  root     4838:          if (GET_CODE (pat) == SEQUENCE)
                   4839:            {
                   4840:              int i;
                   4841:              /* We can invert a sequence if the only jump is at the end.  */
                   4842:              for (i = 0; i < XVECLEN (pat, 0) - 1; i++)
                   4843:                if (GET_CODE (XVECEXP (pat, 0, i)) == JUMP_INSN)
                   4844:                  abort ();
                   4845:              invert_exp (PATTERN (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1)));
                   4846:            }
                   4847:          else
                   4848:            invert_exp (pat, 0, 0);
                   4849: 
1.1.1.13  root     4850:          emit_jump_insn (pat);
1.1.1.2   root     4851:        }
                   4852:     }
1.1       root     4853: 
                   4854:   if (drop_through_label)
                   4855:     emit_label (drop_through_label);
                   4856: }
                   4857: 
1.1.1.2   root     4858: /* Compare two integer constant rtx's, OP0 and OP1.
                   4859:    The comparison operation is OPERATION.
                   4860:    Return an rtx representing the value 1 or 0.
                   4861:    WIDTH is the width in bits that is significant.  */
                   4862: 
                   4863: static rtx
                   4864: compare_constants (operation, unsignedp, op0, op1, width)
                   4865:      enum rtx_code operation;
                   4866:      int unsignedp;
                   4867:      int op0, op1;
                   4868:      int width;
                   4869: {
                   4870:   int val;
                   4871: 
                   4872:   /* Sign-extend or zero-extend the operands to a full word
                   4873:      from an initial width of WIDTH bits.  */
                   4874:   if (width < HOST_BITS_PER_INT)
                   4875:     {
                   4876:       op0 &= (1 << width) - 1;
                   4877:       op1 &= (1 << width) - 1;
                   4878: 
                   4879:       if (! unsignedp)
                   4880:        {
                   4881:          if (op0 & (1 << (width - 1)))
                   4882:            op0 |= ((-1) << width);
                   4883:          if (op1 & (1 << (width - 1)))
                   4884:            op1 |= ((-1) << width);
                   4885:        }
                   4886:     }
                   4887: 
                   4888:   switch (operation)
                   4889:     {
                   4890:     case EQ:
                   4891:       val = op0 == op1;
                   4892:       break;
                   4893: 
                   4894:     case NE:
                   4895:       val = op0 != op1;
                   4896:       break;
                   4897: 
                   4898:     case GT:
                   4899:     case GTU:
                   4900:       val = op0 > op1;
                   4901:       break;
                   4902: 
                   4903:     case LT:
                   4904:     case LTU:
                   4905:       val = op0 < op1;
                   4906:       break;
                   4907: 
                   4908:     case GE:
                   4909:     case GEU:
                   4910:       val = op0 >= op1;
                   4911:       break;
                   4912: 
                   4913:     case LE:
                   4914:     case LEU:
                   4915:       val = op0 <= op1;
                   4916:     }
                   4917: 
                   4918:   return val ? const1_rtx : const0_rtx;
                   4919: }
                   4920: 
1.1       root     4921: /* Generate code for a comparison expression EXP
                   4922:    (including code to compute the values to be compared)
                   4923:    and set (CC0) according to the result.
                   4924:    SIGNED_FORWARD should be the rtx operation for this comparison for
                   4925:    signed data; UNSIGNED_FORWARD, likewise for use if data is unsigned.
                   4926:    SIGNED_REVERSE and UNSIGNED_REVERSE are used if it is desirable
                   4927:    to interchange the operands for the compare instruction.
                   4928: 
                   4929:    We force a stack adjustment unless there are currently
                   4930:    things pushed on the stack that aren't yet used.  */
                   4931: 
                   4932: static rtx
                   4933: compare (exp, signed_forward, unsigned_forward,
                   4934:         signed_reverse, unsigned_reverse)
                   4935:      register tree exp;
                   4936:      enum rtx_code signed_forward, unsigned_forward;
                   4937:      enum rtx_code signed_reverse, unsigned_reverse;
                   4938: {
1.1.1.2   root     4939: 
1.1       root     4940:   register rtx op0 = expand_expr (TREE_OPERAND (exp, 0), 0, VOIDmode, 0);
                   4941:   register rtx op1 = expand_expr (TREE_OPERAND (exp, 1), 0, VOIDmode, 0);
                   4942:   register enum machine_mode mode = GET_MODE (op0);
                   4943:   int unsignedp;
                   4944: 
                   4945:   /* If one operand is 0, make it the second one.  */
                   4946: 
                   4947:   if (op0 == const0_rtx || op0 == fconst0_rtx || op0 == dconst0_rtx)
                   4948:     {
                   4949:       rtx tem = op0;
                   4950:       op0 = op1;
                   4951:       op1 = tem;
                   4952:       signed_forward = signed_reverse;
                   4953:       unsigned_forward = unsigned_reverse;
                   4954:     }
                   4955: 
1.1.1.2   root     4956:   if (flag_force_mem)
1.1       root     4957:     {
                   4958:       op0 = force_not_mem (op0);
                   4959:       op1 = force_not_mem (op1);
                   4960:     }
                   4961: 
                   4962:   do_pending_stack_adjust ();
                   4963: 
1.1.1.2   root     4964:   unsignedp = (TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)))
                   4965:               || TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 1))));
                   4966: 
                   4967:   if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT)
                   4968:     return compare_constants (signed_forward, unsignedp,
                   4969:                              INTVAL (op0), INTVAL (op1),
                   4970:                              GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)))));
1.1       root     4971: 
                   4972:   emit_cmp_insn (op0, op1,
                   4973:                 (mode == BLKmode) ? expr_size (TREE_OPERAND (exp, 0)) : 0,
1.1.1.14  root     4974:                 unsignedp,
                   4975:                 TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
1.1       root     4976: 
                   4977:   return gen_rtx ((unsignedp ? unsigned_forward : signed_forward),
                   4978:                  VOIDmode, cc0_rtx, const0_rtx);
                   4979: }
                   4980: 
                   4981: /* Like compare but expects the values to compare as two rtx's.
                   4982:    The decision as to signed or unsigned comparison must be made by the caller.
                   4983:    BLKmode is not allowed.  */
                   4984: 
                   4985: static rtx
1.1.1.2   root     4986: compare1 (op0, op1, forward_op, reverse_op, unsignedp, mode)
1.1       root     4987:      register rtx op0, op1;
                   4988:      enum rtx_code forward_op, reverse_op;
                   4989:      int unsignedp;
1.1.1.2   root     4990:      enum machine_mode mode;
1.1       root     4991: {
                   4992:   /* If one operand is 0, make it the second one.  */
                   4993: 
                   4994:   if (op0 == const0_rtx || op0 == fconst0_rtx || op0 == dconst0_rtx)
                   4995:     {
                   4996:       rtx tem = op0;
                   4997:       op0 = op1;
                   4998:       op1 = tem;
                   4999:       forward_op = reverse_op;
                   5000:     }
                   5001: 
1.1.1.2   root     5002:   if (flag_force_mem)
1.1       root     5003:     {
                   5004:       op0 = force_not_mem (op0);
                   5005:       op1 = force_not_mem (op1);
                   5006:     }
                   5007: 
                   5008:   do_pending_stack_adjust ();
                   5009: 
1.1.1.2   root     5010:   if (GET_CODE (op0) == CONST_INT && GET_CODE (op1) == CONST_INT)
                   5011:     return compare_constants (forward_op, unsignedp,
                   5012:                              INTVAL (op0), INTVAL (op1),
                   5013:                              GET_MODE_BITSIZE (mode));
                   5014: 
1.1.1.14  root     5015:   emit_cmp_insn (op0, op1, 0, unsignedp, 0);
1.1       root     5016: 
                   5017:   return gen_rtx (forward_op, VOIDmode, cc0_rtx, const0_rtx);
                   5018: }
                   5019: 
                   5020: /* Generate code to calculate EXP using a store-flag instruction
                   5021:    and return an rtx for the result.
                   5022:    If TARGET is nonzero, store the result there if convenient.
                   5023: 
                   5024:    Return zero if there is no suitable set-flag instruction
                   5025:    available on this machine.  */
                   5026: 
                   5027: static rtx
1.1.1.2   root     5028: do_store_flag (exp, target, mode)
1.1       root     5029:      tree exp;
                   5030:      rtx target;
1.1.1.2   root     5031:      enum machine_mode mode;
1.1       root     5032: {
                   5033:   register enum tree_code code = TREE_CODE (exp);
                   5034:   register rtx comparison = 0;
1.1.1.2   root     5035:   enum machine_mode compare_mode;
1.1       root     5036: 
                   5037:   switch (code)
                   5038:     {
1.1.1.2   root     5039: #ifdef HAVE_seq
1.1       root     5040:     case EQ_EXPR:
1.1.1.2   root     5041:       if (HAVE_seq)
                   5042:        {
                   5043:          comparison = compare (exp, EQ, EQ, EQ, EQ);
                   5044:          compare_mode = insn_operand_mode[(int) CODE_FOR_seq][0];
                   5045:        }
1.1       root     5046:       break;
                   5047: #endif
                   5048: 
1.1.1.2   root     5049: #ifdef HAVE_sne
1.1       root     5050:     case NE_EXPR:
1.1.1.2   root     5051:       if (HAVE_sne)
                   5052:        {
                   5053:          comparison = compare (exp, NE, NE, NE, NE);
                   5054:          compare_mode = insn_operand_mode[(int) CODE_FOR_sne][0];
                   5055:        }
1.1       root     5056:       break;
                   5057: #endif
                   5058: 
1.1.1.2   root     5059: #if defined (HAVE_slt) && defined (HAVE_sltu) && defined (HAVE_sgt) && defined (HAVE_sgtu)
1.1       root     5060:     case LT_EXPR:
1.1.1.2   root     5061:       if (HAVE_slt && HAVE_sltu && HAVE_sgt && HAVE_sgtu)
                   5062:        {
                   5063:          comparison = compare (exp, LT, LTU, GT, GTU);
                   5064:          compare_mode = insn_operand_mode[(int) CODE_FOR_slt][0];
                   5065:        }
1.1       root     5066:       break;
                   5067: 
                   5068:     case GT_EXPR:
1.1.1.2   root     5069:       if (HAVE_slt && HAVE_sltu && HAVE_sgt && HAVE_sgtu)
                   5070:        {
                   5071:          comparison = compare (exp, GT, GTU, LT, LTU);
                   5072:          compare_mode = insn_operand_mode[(int) CODE_FOR_slt][0];
                   5073:        }
1.1       root     5074:       break;
                   5075: #endif
                   5076: 
1.1.1.2   root     5077: #if defined (HAVE_sle) && defined (HAVE_sleu) && defined (HAVE_sge) && defined (HAVE_sgeu)
1.1       root     5078:     case LE_EXPR:
1.1.1.2   root     5079:       if (HAVE_sle && HAVE_sleu && HAVE_sge && HAVE_sgeu)
                   5080:        {
                   5081:          comparison = compare (exp, LE, LEU, GE, GEU);
                   5082:          compare_mode = insn_operand_mode[(int) CODE_FOR_sle][0];
                   5083:        }
1.1       root     5084:       break;
                   5085: 
                   5086:     case GE_EXPR:
1.1.1.2   root     5087:       if (HAVE_sle && HAVE_sleu && HAVE_sge && HAVE_sgeu)
                   5088:        {
                   5089:          comparison = compare (exp, GE, GEU, LE, LEU);
                   5090:          compare_mode = insn_operand_mode[(int) CODE_FOR_sle][0];
                   5091:        }
1.1       root     5092:       break;
                   5093: #endif
                   5094:     }
                   5095:   if (comparison == 0)
                   5096:     return 0;
                   5097: 
1.1.1.2   root     5098:   if (target == 0 || GET_MODE (target) != mode
                   5099:       || (mode != compare_mode && GET_CODE (target) != REG))
                   5100:     target = gen_reg_rtx (mode);
                   5101: 
                   5102:   /* Store the comparison in its proper mode.  */
1.1.1.13  root     5103:   if (GET_CODE (comparison) == CONST_INT)
                   5104:     emit_move_insn (target, comparison);
                   5105:   else if (GET_MODE (target) != compare_mode)
                   5106:     emit_insn ((*setcc_gen_fctn[(int) GET_CODE (comparison)])
                   5107:               (gen_rtx (SUBREG, compare_mode, target, 0)));
1.1.1.2   root     5108:   else
1.1.1.13  root     5109:     emit_insn ((*setcc_gen_fctn[(int) GET_CODE (comparison)]) (target));
1.1.1.2   root     5110: 
                   5111: #if STORE_FLAG_VALUE != 1
                   5112:   expand_bit_and (mode, target, const1_rtx, target);
                   5113: #endif
1.1       root     5114:   return target;
                   5115: }
                   5116: 
                   5117: /* Generate a tablejump instruction (used for switch statements).  */
                   5118: 
                   5119: #ifdef HAVE_tablejump
                   5120: 
                   5121: /* INDEX is the value being switched on, with the lowest value
                   5122:    in the table already subtracted.
                   5123:    RANGE is the length of the jump table.
                   5124:    TABLE_LABEL is a CODE_LABEL rtx for the table itself.
1.1.1.2   root     5125: 
1.1       root     5126:    DEFAULT_LABEL is a CODE_LABEL rtx to jump to if the
                   5127:    index value is out of range.  */
                   5128: 
                   5129: void
                   5130: do_tablejump (index, range, table_label, default_label)
                   5131:      rtx index, range, table_label, default_label;
                   5132: {
                   5133:   register rtx temp;
                   5134: 
1.1.1.14  root     5135:   emit_cmp_insn (range, index, 0, 0, 0);
1.1.1.2   root     5136:   emit_jump_insn (gen_bltu (default_label));
1.1.1.4   root     5137:   /* If flag_force_addr were to affect this address
                   5138:      it could interfere with the tricky assumptions made
                   5139:      about addresses that contain label-refs,
                   5140:      which may be valid only very near the tablejump itself.  */
                   5141:   index = memory_address_noforce
                   5142:     (CASE_VECTOR_MODE,
                   5143:      gen_rtx (PLUS, Pmode,
                   5144:              gen_rtx (MULT, Pmode, index,
                   5145:                       gen_rtx (CONST_INT, VOIDmode,
                   5146:                                GET_MODE_SIZE (CASE_VECTOR_MODE))),
                   5147:              gen_rtx (LABEL_REF, VOIDmode, table_label)));
1.1       root     5148:   temp = gen_reg_rtx (CASE_VECTOR_MODE);
                   5149:   convert_move (temp, gen_rtx (MEM, CASE_VECTOR_MODE, index), 0);
                   5150: 
1.1.1.2   root     5151:   emit_jump_insn (gen_tablejump (temp, table_label));
1.1       root     5152: }
                   5153: 
1.1.1.2   root     5154: #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.