Annotation of gcc/expr.c, revision 1.1.1.23

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