Annotation of gcc/expr.c, revision 1.1.1.9

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