Annotation of gcc/expr.c, revision 1.1.1.7

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